<commit_before># Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import cint, cstr, flt, fmt_money, formatdate, getdate
from frappe import msgprint, _
from erpnext.setup.utils import get_company_currency

from erpnext.controllers.accounts_controller import AccountsController

class JournalVoucher(AccountsController):
	def __init__(self, arg1, arg2=None):
		super(JournalVoucher, self).__init__(arg1, arg2)
		self.master_type = {}
		self.credit_days_for = {}
		self.credit_days_global = -1
		self.is_approving_authority = -1

	def validate(self):
		if not self.is_opening:
			self.is_opening='No'
		self.clearance_date = None

		super(JournalVoucher, self).validate_date_with_fiscal_year()

		self.validate_cheque_info()
		self.validate_entries_for_advance()
		self.validate_debit_and_credit()
		self.validate_against_jv()
		self.validate_against_sales_invoice()
		self.validate_against_purchase_invoice()
		self.set_against_account()
		self.create_remarks()
		self.set_aging_date()
		self.set_print_format_fields()

	def on_submit(self):
		if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
			self.check_credit_days()
		self.make_gl_entries()
		self.check_credit_limit()

	def on_cancel(self):
		from erpnext.accounts.utils import remove_against_link_from_jv
		remove_against_link_from_jv(self.doctype, self.name, "against_jv")

		self.make_gl_entries(1)

	def validate_cheque_info(self):
		if self.voucher_type in ['Bank Voucher']:
			if not self.cheque_no or not self.cheque_date:
				msgprint(_("Reference No & Reference Date is required for {0}").format(self.voucher_type),
					raise_exception=1)

		if self.cheque_date and not self.cheque_no:
			msgprint(_("Reference No is mandatory if you entered Reference Date"), raise_exception=1)

	def validate_entries_for_advance(self):
		for d in self.get('entries'):
			if not d.is_advance and not d.against_voucher and \
					not d.against_invoice and not d.against_jv:
				master_type = frappe.db.get_value("Account", d.account, "master_type")
				if (master_type == 'Customer' and flt(d.credit) > 0) or \
						(master_type == 'Supplier' and flt(d.debit) > 0):
					msgprint(_("Please check 'Is Advance' against Account {0} if this is an advance entry.").format(d.account))

	def validate_against_jv(self):
		for d in self.get('entries'):
			if d.against_jv:
				if d.against_jv == self.name:
					frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))

				against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
					where account = %s and docstatus = 1 and parent = %s
					and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)

				if not against_entries:
					frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
						.format(d.against_jv, d.account))
				else:
					dr_or_cr = "debit" if d.credit > 0 else "credit"
					valid = False
					for jvd in against_entries:
						if flt(jvd[dr_or_cr]) > 0:
							valid = True
					if not valid:
						frappe.throw(_("Against Journal Voucher {0} does not have any unmatched {1} entry")
							.format(d.against_jv, dr_or_cr))

	def validate_against_sales_invoice(self):
		for d in self.get("entries"):
			if d.against_invoice:
				if d.debit > 0:
					frappe.throw(_("Row {0}: Debit entry can not be linked with a Sales Invoice")
						.format(d.idx))
				if frappe.db.get_value("Sales Invoice", d.against_invoice, "debit_to") != d.account:
					frappe.throw(_("Row {0}: Account does not match with \
						Sales Invoice Debit To account").format(d.idx, d.account))

	def validate_against_purchase_invoice(self):
		for d in self.get("entries"):
			if d.against_voucher:
				if flt(d.credit) > 0:
					frappe.throw(_("Row {0}: Credit entry can not be linked with a Purchase Invoice")
						.format(d.idx))
				if frappe.db.get_value("Purchase Invoice", d.against_voucher, "credit_to") != d.account:
					frappe.throw(_("Row {0}: Account does not match with \
						Purchase Invoice Credit To account").format(d.idx, d.account))

	def set_against_account(self):
		accounts_debited, accounts_credited = [], []
		for d in self.get("entries"):
			if flt(d.debit > 0): accounts_debited.append(d.account)
			if flt(d.credit) > 0: accounts_credited.append(d.account)

		for d in self.get("entries"):
			if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
			if flt(d.credit > 0): d.against_account = ", ".join(list(set(accounts_debited)))

	def validate_debit_and_credit(self):
		self.total_debit, self.total_credit, self.difference = 0, 0, 0

		for d in self.get("entries"):
			if d.debit and d.credit:
				frappe.throw(_("You cannot credit and debit same account at the same time"))

			self.total_debit = flt(self.total_debit) + flt(d.debit, self.precision("debit", "entries"))
			self.total_credit = flt(self.total_credit) + flt(d.credit, self.precision("credit", "entries"))

		self.difference = flt(self.total_debit, self.precision("total_debit")) - \
			flt(self.total_credit, self.precision("total_credit"))

		if self.difference:
			frappe.throw(_("Total Debit must be equal to Total Credit. The difference is {0}")
				.format(self.difference))

	def create_remarks(self):
		r = []
		if self.cheque_no:
			if self.cheque_date:
				r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
			else:
				msgprint(_("Please enter Reference date"), raise_exception=1)

		for d in self.get('entries'):
			if d.against_invoice and d.credit:
				currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
				r.append(_("{0} {1} against Invoice {1}").format(currency, fmt_money(flt(d.credit)), d.against_invoice))

			if d.against_voucher and d.debit:
				bill_no = frappe.db.sql("""select bill_no, bill_date, currency
					from `tabPurchase Invoice` where name=%s""", d.against_voucher)
				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
						not in ['na', 'not applicable', 'none']:
					r.append(_('{0} {1} against Bill {2} dated {3}').format(bill_no[0][2],
						fmt_money(flt(d.debit)), bill_no[0][0],
						bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))

		if self.user_remark:
			r.append(_("Note: {0}").format(self.user_remark))

		if r:
			self.remark = ("\n").join(r)
		else:
			frappe.msgprint(_("User Remarks is mandatory"), raise_exception=1)

	def set_aging_date(self):
		if self.is_opening != 'Yes':
			self.aging_date = self.posting_date
		else:
			# check account type whether supplier or customer
			exists = False
			for d in self.get('entries'):
				account_type = frappe.db.get_value("Account", d.account, "account_type")
				if account_type in ["Supplier", "Customer"]:
					exists = True
					break

			# If customer/supplier account, aging date is mandatory
			if exists and not self.aging_date:
				msgprint(_("Aging Date is mandatory for opening entry"), raise_exception=1)
			else:
				self.aging_date = self.posting_date

	def set_print_format_fields(self):
		for d in self.get('entries'):
			account_type, master_type = frappe.db.get_value("Account", d.account,
				["account_type", "master_type"])

			if master_type in ['Supplier', 'Customer']:
				if not self.pay_to_recd_from:
					self.pay_to_recd_from = frappe.db.get_value(master_type,
						' - '.join(d.account.split(' - ')[:-1]),
						master_type == 'Customer' and 'customer_name' or 'supplier_name')

			if account_type in ['Bank', 'Cash']:<commit_msg>Minor fix in Journal Voucher<commit_after># Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe

from frappe.utils import cint, cstr, flt, fmt_money, formatdate, getdate
from frappe import msgprint, _
from erpnext.setup.utils import get_company_currency

from erpnext.controllers.accounts_controller import AccountsController

class JournalVoucher(AccountsController):
	def __init__(self, arg1, arg2=None):
		super(JournalVoucher, self).__init__(arg1, arg2)
		self.master_type = {}
		self.credit_days_for = {}
		self.credit_days_global = -1
		self.is_approving_authority = -1

	def validate(self):
		if not self.is_opening:
			self.is_opening='No'
		self.clearance_date = None

		super(JournalVoucher, self).validate_date_with_fiscal_year()

		self.validate_cheque_info()
		self.validate_entries_for_advance()
		self.validate_debit_and_credit()
		self.validate_against_jv()
		self.validate_against_sales_invoice()
		self.validate_against_purchase_invoice()
		self.set_against_account()
		self.create_remarks()
		self.set_aging_date()
		self.set_print_format_fields()

	def on_submit(self):
		if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
			self.check_credit_days()
		self.make_gl_entries()
		self.check_credit_limit()

	def on_cancel(self):
		from erpnext.accounts.utils import remove_against_link_from_jv
		remove_against_link_from_jv(self.doctype, self.name, "against_jv")

		self.make_gl_entries(1)

	def validate_cheque_info(self):
		if self.voucher_type in ['Bank Voucher']:
			if not self.cheque_no or not self.cheque_date:
				msgprint(_("Reference No & Reference Date is required for {0}").format(self.voucher_type),
					raise_exception=1)

		if self.cheque_date and not self.cheque_no:
			msgprint(_("Reference No is mandatory if you entered Reference Date"), raise_exception=1)

	def validate_entries_for_advance(self):
		for d in self.get('entries'):
			if not d.is_advance and not d.against_voucher and \
					not d.against_invoice and not d.against_jv:
				master_type = frappe.db.get_value("Account", d.account, "master_type")
				if (master_type == 'Customer' and flt(d.credit) > 0) or \
						(master_type == 'Supplier' and flt(d.debit) > 0):
					msgprint(_("Please check 'Is Advance' against Account {0} if this is an advance entry.").format(d.account))

	def validate_against_jv(self):
		for d in self.get('entries'):
			if d.against_jv:
				if d.against_jv == self.name:
					frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))

				against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
					where account = %s and docstatus = 1 and parent = %s
					and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)

				if not against_entries:
					frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
						.format(d.against_jv, d.account))
				else:
					dr_or_cr = "debit" if d.credit > 0 else "credit"
					valid = False
					for jvd in against_entries:
						if flt(jvd[dr_or_cr]) > 0:
							valid = True
					if not valid:
						frappe.throw(_("Against Journal Voucher {0} does not have any unmatched {1} entry")
							.format(d.against_jv, dr_or_cr))

	def validate_against_sales_invoice(self):
		for d in self.get("entries"):
			if d.against_invoice:
				if d.debit > 0:
					frappe.throw(_("Row {0}: Debit entry can not be linked with a Sales Invoice")
						.format(d.idx))
				if frappe.db.get_value("Sales Invoice", d.against_invoice, "debit_to") != d.account:
					frappe.throw(_("Row {0}: Account does not match with \
						Sales Invoice Debit To account").format(d.idx, d.account))

	def validate_against_purchase_invoice(self):
		for d in self.get("entries"):
			if d.against_voucher:
				if flt(d.credit) > 0:
					frappe.throw(_("Row {0}: Credit entry can not be linked with a Purchase Invoice")
						.format(d.idx))
				if frappe.db.get_value("Purchase Invoice", d.against_voucher, "credit_to") != d.account:
					frappe.throw(_("Row {0}: Account does not match with \
						Purchase Invoice Credit To account").format(d.idx, d.account))

	def set_against_account(self):
		accounts_debited, accounts_credited = [], []
		for d in self.get("entries"):
			if flt(d.debit > 0): accounts_debited.append(d.account)
			if flt(d.credit) > 0: accounts_credited.append(d.account)

		for d in self.get("entries"):
			if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
			if flt(d.credit > 0): d.against_account = ", ".join(list(set(accounts_debited)))

	def validate_debit_and_credit(self):
		self.total_debit, self.total_credit, self.difference = 0, 0, 0

		for d in self.get("entries"):
			if d.debit and d.credit:
				frappe.throw(_("You cannot credit and debit same account at the same time"))

			self.total_debit = flt(self.total_debit) + flt(d.debit, self.precision("debit", "entries"))
			self.total_credit = flt(self.total_credit) + flt(d.credit, self.precision("credit", "entries"))

		self.difference = flt(self.total_debit, self.precision("total_debit")) - \
			flt(self.total_credit, self.precision("total_credit"))

		if self.difference:
			frappe.throw(_("Total Debit must be equal to Total Credit. The difference is {0}")
				.format(self.difference))

	def create_remarks(self):
		r = []
		if self.cheque_no:
			if self.cheque_date:
				r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
			else:
				msgprint(_("Please enter Reference date"), raise_exception=1)

		for d in self.get('entries'):
			if d.against_invoice and d.credit:
				currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
				r.append(_("{0} {1} against Invoice {1}").format(currency, fmt_money(flt(d.credit)), d.against_invoice))

			if d.against_voucher and d.debit:
				bill_no = frappe.db.sql("""select bill_no, bill_date, currency
					from `tabPurchase Invoice` where name=%s""", d.against_voucher)
				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
						not in ['na', 'not applicable', 'none']:
					r.append(_('{0} {1} against Bill {2} dated {3}').format(bill_no[0][2],
						fmt_money(flt(d.debit)), bill_no[0][0],
						bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))

		if self.user_remark:
			r.append(_("Note: {0}").format(self.user_remark))

		if r:
			self.remark = ("\n").join(r)
		else:
			frappe.msgprint(_("User Remarks is mandatory"), raise_exception=1)

	def set_aging_date(self):
		if self.is_opening != 'Yes':
			self.aging_date = self.posting_date
		else:
			# check account type whether supplier or customer
			exists = False
			for d in self.get('entries'):
				account_type = frappe.db.get_value("Account", d.account, "account_type")
				if account_type in ["Supplier", "Customer"]:
					exists = True
					break

			# If customer/supplier account, aging date is mandatory
			if exists and not self.aging_date:
				msgprint(_("Aging Date is mandatory for opening entry"), raise_exception=1)
			else:
				self.aging_date = self.posting_date

	def set_print_format_fields(self):
		for d in self.get('entries'):
			result = frappe.db.get_value("Account", d.account,
				["account_type", "master_type"])

			if not result:
				continue

			account_type, master_type = result

			if master_type in ['Supplier', 'Customer']:
				if not self.pay_to_recd_from:
					self.pay_to_recd_from = frappe.db.get_value(master_type,
						' - '.join(d.account.split(' - ')[:-1]),
						master_type == 'Customer' and 'customer_name' or 'supplier_name')

			if account_type in ['Bank', 'Cash']:
{'fraction_non_alphanumeric': 0.13177235772357723, 'fraction_numerical': 0.008455284552845528, 'mean_word_length': 4.2263766145479265, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5323270', 'n_tokens_mistral': 6315, 'n_tokens_neox': 5373, 'n_words': 1285}