def test_purchase_invoice_with_advance(self): from erpnext.accounts.doctype.journal_entry.test_journal_entry \ import test_records as jv_test_records from erpnext.accounts.utils import get_balance_on_voucher jv = frappe.copy_doc(jv_test_records[1]) jv.insert() jv.submit() pi = frappe.copy_doc(test_records[0]) pi.disable_rounded_total = 1 pi.allocate_advances_automatically = 0 pi.append( "advances", { "reference_type": "Journal Entry", "reference_name": jv.name, "advance_amount": 400, "allocated_amount": 300, "remarks": jv.remark }) pi.insert() self.assertEqual(pi.outstanding_amount, 1212.30) pi.disable_rounded_total = 0 pi.get("payment_schedule")[0].payment_amount = 1512.0 pi.save() pi.submit() pi.load_from_db() self.assertEqual(pi.outstanding_amount, 1212.0) self.assertEqual( get_balance_on_voucher(pi.doctype, pi.name, "Supplier", pi.supplier, pi.credit_to), 1212.0) self.assertEqual( get_balance_on_voucher(jv.doctype, jv.name, "Supplier", pi.supplier, pi.credit_to), -100.0) self.assertTrue( frappe.db.sql( """select name from `tabJournal Entry Account` where reference_type='Purchase Invoice' and reference_name=%s and debit_in_account_currency=300""", pi.name)) pi.cancel() self.assertFalse( frappe.db.sql( """select name from `tabJournal Entry Account` where reference_type='Purchase Invoice' and reference_name=%s""", pi.name)) self.assertEqual( get_balance_on_voucher(jv.doctype, jv.name, "Supplier", pi.supplier, pi.credit_to), -400.0)
def test_debit_note(self): from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry from erpnext.accounts.utils import get_balance_on_voucher pi = make_purchase_invoice(item_code="_Test Item", qty=(5 * -1), rate=500, is_return=1) outstanding_amount = get_balance_on_voucher(pi.doctype, pi.name, "Supplier", pi.supplier, "Creditors - _TC") self.assertEqual(pi.outstanding_amount, outstanding_amount) pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC") pe.reference_no = "1" pe.reference_date = nowdate() pe.paid_from_account_currency = pi.currency pe.paid_to_account_currency = pi.currency pe.source_exchange_rate = 1 pe.target_exchange_rate = 1 pe.paid_amount = pi.grand_total * -1 pe.insert() pe.submit() pi_doc = frappe.get_doc('Purchase Invoice', pi.name) self.assertEqual(pi_doc.outstanding_amount, 0)
def update_outstanding_amt(voucher_type, voucher_no, account, party_type, party, on_cancel=False): # Update outstanding amt on against voucher dr_or_cr = None if voucher_type in [ "Sales Invoice", "Purchase Invoice", "Landed Cost Voucher", "Fees", "Expense Claim" ]: fieldname = "outstanding_amount" elif voucher_type == "Employee Advance": fieldname = "balance_amount" dr_or_cr = "debit_in_account_currency - credit_in_account_currency" else: return bal = get_balance_on_voucher(voucher_type, voucher_no, party_type, party, account, dr_or_cr=dr_or_cr) ref_doc = frappe.get_doc(voucher_type, voucher_no) ref_doc.db_set(fieldname, bal) ref_doc.set_status(update=True)
def update_outstanding_amt(voucher_type, voucher_no, account, party_type, party, on_cancel=False): # Update outstanding amt on against voucher if voucher_type in [ "Sales Invoice", "Purchase Invoice", "Landed Cost Voucher", "Fees" ]: bal = get_balance_on_voucher(voucher_type, voucher_no, party_type, party, account) ref_doc = frappe.get_doc(voucher_type, voucher_no) ref_doc.db_set('outstanding_amount', bal) ref_doc.set_status(update=True)
def get_outstanding(args): if not frappe.has_permission("Account"): frappe.msgprint(_("No Permission"), raise_exception=1) if isinstance(args, string_types): args = json.loads(args) company_currency = erpnext.get_company_currency(args.get("company")) if args.get("doctype") == "Journal Entry": against_jv_amount = get_balance_on_voucher("Journal Entry", args.get("docname"), args.get("party_type"), args.get("party"), args.get("account"), dr_or_cr="debit_in_account_currency - credit_in_account_currency") amount_field = "credit_in_account_currency" if against_jv_amount >= 0 else "debit_in_account_currency" return { amount_field: abs(against_jv_amount) } elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice"): party_type = "Customer" if args.get("doctype") == "Sales Invoice" else "Supplier" invoice = frappe.db.get_value(args["doctype"], args["docname"], ["outstanding_amount", "conversion_rate", scrub(party_type)] + (["letter_of_credit"] if args.get("doctype") == "Purchase Invoice" else []), as_dict=1) if invoice.get("letter_of_credit"): party_type = "Letter of Credit" exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1 if args["doctype"] == "Sales Invoice": amount_field = "credit_in_account_currency" \ if flt(invoice.outstanding_amount) > 0 else "debit_in_account_currency" else: amount_field = "debit_in_account_currency" \ if flt(invoice.outstanding_amount) > 0 else "credit_in_account_currency" return { amount_field: abs(flt(invoice.outstanding_amount)), "exchange_rate": exchange_rate, "party_type": party_type, "party": invoice.get(scrub(party_type)) }
def validate_jv_party_references(self): for reference_name, acc_amounts in iteritems(self.jv_party_references): for (account, party_type, party), amount in iteritems(acc_amounts): if amount == 0: continue if amount > 0: bal_dr_or_cr = "credit_in_account_currency - debit_in_account_currency" dr_or_cr = "credit" else: bal_dr_or_cr = "debit_in_account_currency - credit_in_account_currency" dr_or_cr = "debit" jv_balance = get_balance_on_voucher("Journal Entry", reference_name, party_type, party, account, bal_dr_or_cr) if jv_balance <= 0: frappe.throw(_("Journal Entry {0} does not have any {1} outstanding balance for party {2}") .format(reference_name, dr_or_cr, party)) else: amount = abs(amount) if amount > jv_balance: frappe.throw(_("Referenced amount {0} to Journal Entry {1} for party {2} is greater than the outstanding balance {3}") .format(amount, reference_name, party, jv_balance))
def test_jv_payable_advance_payment_voucher_balance(self): # Advance payment payment_jv = make_journal_entry("_Test Payable - _TC", "_Test Account Shipping Charges - _TC", 500, save=False) payment_jv.get("accounts")[0].update({ "party_type": "Supplier", "party": "_Test Supplier" }) payment_jv.insert() payment_jv.submit() payment_balance = get_balance_on_voucher(payment_jv.doctype, payment_jv.name, "Supplier", "_Test Supplier", "_Test Payable - _TC") self.assertEqual(payment_balance, -500) # Attempt to allocate an advance payment against another advance payment payment_jv2 = make_journal_entry( "_Test Payable - _TC", "_Test Account Shipping Charges - _TC", 100, save=False) payment_jv2.get("accounts")[0].update({ "party_type": "Supplier", "party": "_Test Supplier", "reference_type": payment_jv.doctype, "reference_name": payment_jv.name }) self.assertRaises(frappe.ValidationError, payment_jv2.insert) # Partial return of advance payment return_jv1 = make_journal_entry("_Test Bank - _TC", "_Test Payable - _TC", 150, save=False) return_jv1.get("accounts")[1].update({ "party_type": "Supplier", "party": "_Test Supplier", "reference_type": payment_jv.doctype, "reference_name": payment_jv.name }) return_jv1.insert() return_jv1.submit() return_balance = get_balance_on_voucher(return_jv1.doctype, return_jv1.name, "Supplier", "_Test Supplier", "_Test Payable - _TC") self.assertEqual(return_balance, 0) payment_balance = get_balance_on_voucher(payment_jv.doctype, payment_jv.name, "Supplier", "_Test Supplier", "_Test Payable - _TC") self.assertEqual(payment_balance, -350) # Attempt to return more than advance payment balance return_jv2 = make_journal_entry("_Test Bank - _TC", "_Test Payable - _TC", 1000, save=False) return_jv2.get("accounts")[1].update({ "party_type": "Supplier", "party": "_Test Supplier", "reference_type": payment_jv.doctype, "reference_name": payment_jv.name }) self.assertRaises(frappe.ValidationError, return_jv2.insert) # Return for the remaining balance of advance payment return_jv3 = make_journal_entry("_Test Bank - _TC", "_Test Payable - _TC", 350, save=False) return_jv3.get("accounts")[1].update({ "party_type": "Supplier", "party": "_Test Supplier", "reference_type": payment_jv.doctype, "reference_name": payment_jv.name }) return_jv3.insert() return_jv3.submit() payment_balance = get_balance_on_voucher(payment_jv.doctype, payment_jv.name, "Supplier", "_Test Supplier", "_Test Payable - _TC") self.assertEqual(payment_balance, 0) # Cancel a payment return_jv1.cancel() payment_balance = get_balance_on_voucher(payment_jv.doctype, payment_jv.name, "Supplier", "_Test Supplier", "_Test Payable - _TC") self.assertEqual(payment_balance, -150)
def test_jv_receivable_voucher_balance(self): # Receivable entry receivable_jv = make_journal_entry("_Test Receivable - _TC", "Sales - _TC", 500, save=False) receivable_jv.get("accounts")[0].update({ "party_type": "Customer", "party": "_Test Customer" }) receivable_jv.insert() receivable_jv.submit() receivable_balance = get_balance_on_voucher(receivable_jv.doctype, receivable_jv.name, "Customer", "_Test Customer", "_Test Receivable - _TC") self.assertEqual(receivable_balance, 500) # Attempt to allocate a receivable entry against another receivable entry receivable_jv2 = make_journal_entry("_Test Receivable - _TC", "Sales - _TC", 100, save=False) receivable_jv2.get("accounts")[0].update({ "party_type": "Customer", "party": "_Test Customer", "reference_type": receivable_jv.doctype, "reference_name": receivable_jv.name }) self.assertRaises(frappe.ValidationError, receivable_jv2.insert) # Partial payment against receivable entry payment_jv1 = make_journal_entry("_Test Bank - _TC", "_Test Receivable - _TC", 150, save=False) payment_jv1.get("accounts")[1].update({ "party_type": "Customer", "party": "_Test Customer", "reference_type": receivable_jv.doctype, "reference_name": receivable_jv.name }) payment_jv1.insert() payment_jv1.submit() payment_balance = get_balance_on_voucher(payment_jv1.doctype, payment_jv1.name, "Customer", "_Test Customer", "_Test Receivable - _TC") self.assertEqual(payment_balance, 0) receivable_balance = get_balance_on_voucher(receivable_jv.doctype, receivable_jv.name, "Customer", "_Test Customer", "_Test Receivable - _TC") self.assertEqual(receivable_balance, 350) # Attempt to over allocate payment against receivable entry payment_jv2 = make_journal_entry("_Test Bank - _TC", "_Test Receivable - _TC", 1000, save=False) payment_jv2.get("accounts")[1].update({ "party_type": "Customer", "party": "_Test Customer", "reference_type": receivable_jv.doctype, "reference_name": receivable_jv.name }) self.assertRaises(frappe.ValidationError, payment_jv2.insert) # Payment for the remaining balance of receivable entry payment_jv3 = make_journal_entry("_Test Bank - _TC", "_Test Receivable - _TC", 350, save=False) payment_jv3.get("accounts")[1].update({ "party_type": "Customer", "party": "_Test Customer", "reference_type": receivable_jv.doctype, "reference_name": receivable_jv.name }) payment_jv3.insert() payment_jv3.submit() receivable_balance = get_balance_on_voucher(receivable_jv.doctype, receivable_jv.name, "Customer", "_Test Customer", "_Test Receivable - _TC") self.assertEqual(receivable_balance, 0) # Cancel a payment payment_jv1.cancel() receivable_balance = get_balance_on_voucher(receivable_jv.doctype, receivable_jv.name, "Customer", "_Test Customer", "_Test Receivable - _TC") self.assertEqual(receivable_balance, 150)
def test_reconcile_advance_journal_entries(self): self.assertFalse( get_advance_journal_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True)) # Test records jv_simple = make_payment_jv(self.customer, 100) jv_multiple_rows = make_payment_jv(self.customer, 300, unallocated_rows=3) jv_half_returned = make_payment_jv(self.customer, 200) _jv_return = make_payment_jv(self.customer, 0, jv_half_returned.doctype, jv_half_returned.name, -100) _jv_receivable = make_payment_jv(self.customer, -100) jv_half_allocated = make_payment_jv(self.customer, 100, _jv_receivable.doctype, _jv_receivable.name, 100) so = make_sales_order(self.customer) jv_against_so = make_payment_jv(self.customer, 100, so.doctype, so.name, 100) # Test get_advance_journal_entries advances = get_advance_journal_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True) advance_vouchers = {} for d in advances: advance_vouchers.setdefault(d.reference_name, []) advance_vouchers[d.reference_name].append(d) self.assertEqual(len(advance_vouchers[jv_simple.name]), 1) self.assertEqual(advance_vouchers[jv_simple.name][0].amount, 100) self.assertEqual(len(advance_vouchers[jv_multiple_rows.name]), 1) self.assertEqual(advance_vouchers[jv_multiple_rows.name][0].amount, 300) self.assertEqual(len(advance_vouchers[jv_half_returned.name]), 1) self.assertEqual(advance_vouchers[jv_half_returned.name][0].amount, 100) self.assertEqual(len(advance_vouchers[jv_half_allocated.name]), 1) self.assertEqual(advance_vouchers[jv_half_allocated.name][0].amount, 100) self.assertEqual(len(advance_vouchers[jv_against_so.name]), 2) self.assertEqual(advance_vouchers[jv_against_so.name][0].amount, 100) self.assertEqual(advance_vouchers[jv_against_so.name][0].reference_row, jv_against_so.accounts[2].name) self.assertEqual(advance_vouchers[jv_against_so.name][1].amount, 100) # Test reconcile_against_document jv_receivable = make_payment_jv(self.customer, -5000) # Full allocation lst = [ frappe._dict({ 'voucher_type': jv_simple.doctype, 'voucher_no': jv_simple.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 100, 'allocated_amount': 100 }) ] reconcile_against_document(lst) self.assertEqual( get_balance_on_voucher(jv_receivable.doctype, jv_receivable.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 4900) self.assertTrue( frappe.db.sql( """select name from `tabJournal Entry Account` where name=%s and reference_name=%s and credit_in_account_currency=%s and docstatus=1 """, [jv_simple.accounts[1].name, jv_receivable.name, 100])) # Multiple row partial allocation lst = [ frappe._dict({ 'voucher_type': jv_multiple_rows.doctype, 'voucher_no': jv_multiple_rows.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 300, 'allocated_amount': 230 }) ] reconcile_against_document(lst) self.assertEqual( get_balance_on_voucher(jv_receivable.doctype, jv_receivable.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 4670) self.assertTrue( frappe.db.sql( """select count(*) from `tabJournal Entry Account` where parent=%s and reference_name=%s and party_type='Customer' and party=%s and account='_Test Receivable - _TC' and credit_in_account_currency=%s and docstatus=1 having count(*) = 2 """, [jv_multiple_rows.name, jv_receivable.name, self.customer.name, 100])) self.assertTrue( frappe.db.sql( """select name from `tabJournal Entry Account` where parent=%s and reference_name=%s and party_type='Customer' and party=%s and account='_Test Receivable - _TC' and credit_in_account_currency=%s and docstatus=1 """, [jv_multiple_rows.name, jv_receivable.name, self.customer.name, 30])) self.assertTrue( frappe.db.sql( """select name from `tabJournal Entry Account` where parent=%s and party_type='Customer' and party=%s and ifnull(reference_name, '') = '' and account='_Test Receivable - _TC' and credit_in_account_currency=%s and docstatus=1 """, [jv_multiple_rows.name, self.customer.name, 70])) # Attempt to over allocate a partially returned/knocked-off jv lst = [ frappe._dict({ 'voucher_type': jv_half_returned.doctype, 'voucher_no': jv_half_returned.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 200, 'allocated_amount': 200 }) ] self.assertRaises(frappe.ValidationError, reconcile_against_document, lst) # Attempt to over allocate a partially allocated jv lst = [ frappe._dict({ 'voucher_type': jv_half_allocated.doctype, 'voucher_no': jv_half_allocated.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 200, 'allocated_amount': 200 }) ] self.assertRaises(frappe.ValidationError, reconcile_against_document, lst) # Sales Order advance reallocation lst = [ frappe._dict({ 'voucher_type': jv_against_so.doctype, 'voucher_no': jv_against_so.name, 'voucher_detail_no': jv_against_so.accounts[2].name, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 100, 'allocated_amount': 100 }) ] reconcile_against_document(lst) self.assertEqual( get_balance_on_voucher(jv_receivable.doctype, jv_receivable.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 4570) self.assertEqual( get_balance_on_voucher(so.doctype, so.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 0) self.assertEqual( frappe.db.get_value("Sales Order", so.name, "advance_paid"), 0) self.assertTrue( frappe.db.sql( """select name from `tabJournal Entry Account` where name=%s and reference_name=%s and credit_in_account_currency=%s and docstatus=1 """, [jv_against_so.accounts[2].name, jv_receivable.name, 100])) # Test get_advance_payment_entries after reconciliation advances = get_advance_journal_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True) advance_vouchers = {} for d in advances: advance_vouchers.setdefault(d.reference_name, []) advance_vouchers[d.reference_name].append(d) self.assertFalse(advance_vouchers.get(jv_simple.name)) self.assertEqual(len(advance_vouchers[jv_multiple_rows.name]), 1) self.assertEqual(advance_vouchers[jv_multiple_rows.name][0].amount, 70) self.assertEqual(len(advance_vouchers[jv_against_so.name]), 1) self.assertEqual(advance_vouchers[jv_against_so.name][0].amount, 100)
def test_reconcile_advance_payment_entries(self): self.assertFalse( get_advance_payment_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True)) # Test records _jv_receivable = make_payment_jv(self.customer, -100) so = make_sales_order(self.customer) pe_against_so = make_payment_entry(self.customer, 100, so.doctype, so.name, 100) pe_unallocated = make_payment_entry(self.customer, 100) pe_half_allocated = make_payment_entry(self.customer, 100, _jv_receivable.doctype, _jv_receivable.name, 100) # Test get_advance_payment_entries advances = get_advance_payment_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True) advance_vouchers = {} for d in advances: advance_vouchers.setdefault(d.reference_name, []) advance_vouchers[d.reference_name].append(d) self.assertEqual(len(advance_vouchers[pe_against_so.name]), 2) self.assertEqual(advance_vouchers[pe_against_so.name][0].reference_row, pe_against_so.references[0].name) self.assertEqual(advance_vouchers[pe_against_so.name][0].amount, 100) self.assertEqual(advance_vouchers[pe_against_so.name][1].amount, 100) self.assertEqual(len(advance_vouchers[pe_unallocated.name]), 1) self.assertEqual(advance_vouchers[pe_unallocated.name][0].amount, 100) self.assertEqual(len(advance_vouchers[pe_half_allocated.name]), 1) self.assertEqual(advance_vouchers[pe_half_allocated.name][0].amount, 100) # Test reconcile_against_document jv_receivable = make_payment_jv(self.customer, -5000) # Full allocation lst = [ frappe._dict({ 'voucher_type': pe_unallocated.doctype, 'voucher_no': pe_unallocated.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 100, 'allocated_amount': 100 }) ] reconcile_against_document(lst) self.assertEqual( get_balance_on_voucher(jv_receivable.doctype, jv_receivable.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 4900) self.assertTrue( frappe.db.sql( """select name from `tabPayment Entry Reference` where parent=%s and reference_name=%s and allocated_amount=%s and docstatus=1 """, [pe_unallocated.name, jv_receivable.name, 100])) self.assertEqual( frappe.get_value("Payment Entry", pe_unallocated.name, "unallocated_amount"), 0) # Attempt to over allocate a partially allocated pe lst = [ frappe._dict({ 'voucher_type': pe_half_allocated.doctype, 'voucher_no': pe_half_allocated.name, 'voucher_detail_no': None, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 200, 'allocated_amount': 200 }) ] self.assertRaises(frappe.ValidationError, reconcile_against_document, lst) # Sales Order advance reallocation lst = [ frappe._dict({ 'voucher_type': pe_against_so.doctype, 'voucher_no': pe_against_so.name, 'voucher_detail_no': pe_against_so.references[0].name, 'against_voucher_type': jv_receivable.doctype, 'against_voucher': jv_receivable.name, 'account': "_Test Receivable - _TC", 'party_type': "Customer", 'party': self.customer.name, 'dr_or_cr': "credit_in_account_currency", 'unadjusted_amount': 100, 'allocated_amount': 100 }) ] reconcile_against_document(lst) self.assertEqual( get_balance_on_voucher(jv_receivable.doctype, jv_receivable.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 4800) self.assertEqual( get_balance_on_voucher(so.doctype, so.name, "Customer", self.customer.name, "_Test Receivable - _TC"), 0) self.assertEqual( frappe.db.get_value("Sales Order", so.name, "advance_paid"), 0) self.assertTrue( frappe.db.sql( """select name from `tabPayment Entry Reference` where parent=%s and reference_name=%s and allocated_amount=%s and docstatus=1 """, [pe_unallocated.name, jv_receivable.name, 100])) self.assertEqual( frappe.get_value("Payment Entry", pe_against_so.name, "unallocated_amount"), 100) # Test get_advance_payment_entries after reconciliation advances = get_advance_payment_entries(self.customer.doctype, self.customer.name, "_Test Receivable - _TC", "Sales Order", against_all_orders=True) advance_vouchers = {} for d in advances: advance_vouchers.setdefault(d.reference_name, []) advance_vouchers[d.reference_name].append(d) self.assertFalse(advance_vouchers.get(pe_unallocated.name)) self.assertEqual(len(advance_vouchers[pe_against_so.name]), 1) self.assertEqual(advance_vouchers[pe_against_so.name][0].amount, 100)
def get_outstanding(args): if not frappe.has_permission("Account"): frappe.msgprint(_("No Permission"), raise_exception=1) if isinstance(args, string_types): args = json.loads(args) company_currency = erpnext.get_company_currency(args.get("company")) if args.get("doctype") == "Journal Entry": against_jv_amount = get_balance_on_voucher("Journal Entry", args.get("docname"), args.get("party_type"), args.get("party"), args.get("account"), dr_or_cr="debit_in_account_currency - credit_in_account_currency") amount_field = "credit_in_account_currency" if against_jv_amount >= 0 else "debit_in_account_currency" return { amount_field: abs(against_jv_amount) } elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice", "Landed Cost Voucher"): fields = ["outstanding_amount", "conversion_rate"] if args.get("doctype") == "Landed Cost Voucher": party_type = "Supplier" party_field = 'party' fields.append('party_type') else: party_type = "Customer" if args.get("doctype") == "Sales Invoice" else "Supplier" party_field = scrub(party_type) account_field = "debit_to" if args.get("doctype") == "Sales Invoice" else "credit_to" fields.append(account_field) fields.append(party_field) if args.get("doctype") == "Purchase Invoice": fields.append('letter_of_credit') invoice = frappe.db.get_value(args["doctype"], args["docname"], fields, as_dict=1) if invoice.get("party_type"): party_type = invoice.get("party_type") if invoice.get("letter_of_credit"): party_type = "Letter of Credit" exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1 if args["doctype"] == "Sales Invoice": amount_field = "credit_in_account_currency" \ if flt(invoice.outstanding_amount) > 0 else "debit_in_account_currency" else: amount_field = "debit_in_account_currency" \ if flt(invoice.outstanding_amount) > 0 else "credit_in_account_currency" return { amount_field: abs(flt(invoice.outstanding_amount)), "exchange_rate": exchange_rate, "party_type": party_type, "party": invoice.get(party_field), "account": invoice.get(account_field) } elif args.get("doctype") in ("Employee Advance", "Expense Claim"): account_field = 'advance_account' if args.get("doctype") == "Employee Advance" else "payable_account" balance_field = 'balance_amount' if args.get("doctype") == "Employee Advance" else "outstanding_amount" details = frappe.db.get_value(args["doctype"], args["docname"], ['employee', account_field, balance_field], as_dict=1) balance_amount = details.get(balance_field) if args.get("doctype") == "Expense Claim" \ else -1 * flt(details.get(balance_field)) amount_field = "debit_in_account_currency" \ if flt(balance_amount) > 0 else "credit_in_account_currency" return { amount_field: abs(balance_amount), "party_type": "Employee", "party": details.get("employee"), "account": details.get(account_field), }
def get_reference_details(reference_doctype, reference_name, party_account_currency, party_type, party, account): total_amount = outstanding_amount = bill_no = None exchange_rate = 1 ref_doc = frappe.get_doc(reference_doctype, reference_name) company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company) if reference_doctype == "Fees": total_amount = ref_doc.get("grand_total") exchange_rate = 1 outstanding_amount = ref_doc.get("outstanding_amount") elif reference_doctype == "Landed Cost Voucher": total_amount = ref_doc.get("total_taxes_and_charges") exchange_rate = ref_doc.get("conversion_rate") outstanding_amount = ref_doc.get("outstanding_amount") elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1: total_amount = ref_doc.get("total_amount") if ref_doc.multi_currency: exchange_rate = get_average_party_exchange_rate_on_journal_entry(reference_name, party_type, party, account) else: exchange_rate = 1 outstanding_amount = get_balance_on_voucher("Journal Entry", reference_name, party_type, party, account) elif reference_doctype != "Journal Entry": if party_account_currency == company_currency: if ref_doc.doctype == "Expense Claim": total_amount = ref_doc.total_sanctioned_amount elif ref_doc.doctype == "Employee Advance": total_amount = ref_doc.advance_amount else: total_amount = ref_doc.base_grand_total exchange_rate = 1 else: total_amount = ref_doc.grand_total # Get the exchange rate from the original ref doc # or get it based on the posting date of the ref doc exchange_rate = ref_doc.get("conversion_rate") or \ get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) if reference_doctype in ("Sales Invoice", "Purchase Invoice"): outstanding_amount = ref_doc.get("outstanding_amount") bill_no = ref_doc.get("bill_no") elif reference_doctype == "Expense Claim": outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) \ - flt(ref_doc.get("total_amount+reimbursed")) - flt(ref_doc.get("total_advance_amount")) elif reference_doctype == "Employee Advance": outstanding_amount = ref_doc.advance_amount - flt(ref_doc.paid_amount) else: outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid) else: # Get the exchange rate based on the posting date of the ref doc exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) return frappe._dict({ "due_date": ref_doc.get("due_date"), "total_amount": total_amount, "outstanding_amount": outstanding_amount, "exchange_rate": exchange_rate, "bill_no": bill_no })