def reconcile(self):
        """
			Links booking and payment voucher
			1. cancel payment voucher
			2. split into multiple rows if partially adjusted, assign against voucher
			3. submit payment voucher
		"""
        if not self.voucher_no or not frappe.db.sql(
                """select name from `tab%s`
				where name = %s""" % (self.voucher_type, '%s'), self.voucher_no):
            frappe.throw(_("Please select valid Voucher No to proceed"))

        lst = []
        for d in self.get('ir_payment_details'):
            if flt(d.amt_to_be_reconciled) > 0:
                args = {
                    'voucher_no': d.voucher_no,
                    'voucher_detail_no': d.voucher_detail_no,
                    'against_voucher_type': self.voucher_type,
                    'against_voucher': self.voucher_no,
                    'account': self.account,
                    'is_advance': 'No',
                    # 'dr_or_cr' :  self.account_type=='debit' and 'credit' or 'debit',
                    'unadjusted_amt': flt(d.amt_due),
                    'allocated_amt': flt(d.amt_to_be_reconciled)
                }

                lst.append(args)

        if lst:
            from erpnext.accounts.utils import reconcile_against_document
            reconcile_against_document(lst)
            msgprint(_("Successfully allocated"))
        else:
            msgprint(_("No amount allocated"), raise_exception=1)
    def reconcile(self):
        self.validate_allocation()
        dr_or_cr = ("credit_in_account_currency"
                    if erpnext.get_party_account_type(self.party_type)
                    == 'Receivable' else "debit_in_account_currency")

        entry_list = []
        dr_or_cr_notes = []
        for row in self.get('allocation'):
            reconciled_entry = []
            if row.invoice_number and row.allocated_amount:
                if row.reference_type in ['Sales Invoice', 'Purchase Invoice']:
                    reconciled_entry = dr_or_cr_notes
                else:
                    reconciled_entry = entry_list

                reconciled_entry.append(self.get_payment_details(
                    row, dr_or_cr))

        if entry_list:
            reconcile_against_document(entry_list)

        if dr_or_cr_notes:
            reconcile_dr_cr_note(dr_or_cr_notes, self.company)

        msgprint(_("Successfully Reconciled"))
        self.get_unreconciled_entries()
Example #3
0
	def update_payment_entry(self, payment):
		lst = []
		invoices = payment.invoices.strip().split(',')
		if (len(invoices) == 0): return
		amount = float(abs(payment.amount))
		for invoice_entry in invoices:
			if (not invoice_entry.strip()): continue
			invs = invoice_entry.split('|')
			invoice_type, invoice = invs[0], invs[1]
			outstanding_amount = frappe.get_value(invoice_type, invoice, 'outstanding_amount')

			lst.append(frappe._dict({
				'voucher_type': payment.reference_type,
				'voucher_no' : payment.reference_name,
				'against_voucher_type' : invoice_type,
				'against_voucher'  : invoice,
				'account' : payment.account,
				'party_type': payment.party_type,
				'party': frappe.get_value("Payment Entry", payment.reference_name, "party"),
				'unadjusted_amount' : float(amount),
				'allocated_amount' : min(outstanding_amount, amount)
			}))
			amount -= outstanding_amount
		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			try:
				reconcile_against_document(lst)
			except:
				frappe.throw(_("Exception occurred while reconciling {0}".format(payment.reference_name)))
Example #4
0
	def update_against_document_in_jv(self):
		"""
			Links invoice and advance voucher:
				1. cancel advance voucher
				2. split into multiple rows if partially adjusted, assign against voucher
				3. submit advance voucher
		"""

		if self.doctype == "Sales Invoice":
			party_type = "Customer"
			party = self.customer
			party_account = self.debit_to
			dr_or_cr = "credit_in_account_currency"
		elif self.doctype == "Purchase Invoice":
			party_type = "Letter of Credit" if self.letter_of_credit else "Supplier"
			party = self.letter_of_credit if self.letter_of_credit else self.supplier
			party_account = self.credit_to
			dr_or_cr = "debit_in_account_currency"
		else:
			party_type = self.party_type
			party = self.party
			party_account = self.credit_to
			dr_or_cr = "debit_in_account_currency"

		if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
			invoice_amounts = {
				'exchange_rate': (self.conversion_rate
								  if self.party_account_currency != self.company_currency else 1),
				'grand_total': (self.base_grand_total
								if self.party_account_currency == self.company_currency else self.grand_total)
			}
		else:
			invoice_amounts = {
				'exchange_rate': 1,
				'grand_total': self.grand_total
			}

		lst = []
		for d in self.get('advances'):
			if flt(d.allocated_amount) > 0:
				args = frappe._dict({
					'voucher_type': d.reference_type,
					'voucher_no': d.reference_name,
					'voucher_detail_no': d.reference_row,
					'against_voucher_type': self.doctype,
					'against_voucher': self.name,
					'account': party_account,
					'party_type': party_type,
					'party': party,
					'dr_or_cr': dr_or_cr,
					'unadjusted_amount': flt(d.advance_amount),
					'allocated_amount': flt(d.allocated_amount),
					'outstanding_amount': self.outstanding_amount
				})
				args.update(invoice_amounts)
				lst.append(args)

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
	def reconcile(self):
		for e in self.get('payments'):
			e.invoice_type = None
			if e.invoice_number and " | " in e.invoice_number:
				e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")

		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = ("credit_in_account_currency"
			if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")

		lst = []
		for e in self.get('payments'):
			if e.invoice_number and e.allocated_amount:
				lst.append(frappe._dict({
					'voucher_type': e.reference_type,
					'voucher_no' : e.reference_name,
					'voucher_detail_no' : e.reference_row,
					'against_voucher_type' : e.invoice_type,
					'against_voucher'  : e.invoice_number,
					'account' : self.receivable_payable_account,
					'party_type': self.party_type,
					'party': self.party,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amount' : flt(e.amount),
					'allocated_amount' : flt(e.allocated_amount)
				}))

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)

			msgprint(_("Successfully Reconciled"))
			self.get_unreconciled_entries()
Example #6
0
	def update_against_document_in_jv(self):
		"""
			Links invoice and advance voucher:
				1. cancel advance voucher
				2. split into multiple rows if partially adjusted, assign against voucher
				3. submit advance voucher
		"""

		lst = []
		for d in self.get('advances'):
			if flt(d.allocated_amount) > 0:
				args = {
					'voucher_no' : d.journal_entry,
					'voucher_detail_no' : d.jv_detail_no,
					'against_voucher_type' : 'Purchase Invoice',
					'against_voucher'  : self.name,
					'account' : self.credit_to,
					'party_type': 'Supplier',
					'party': self.supplier,
					'is_advance' : 'Yes',
					'dr_or_cr' : 'debit',
					'unadjusted_amt' : flt(d.advance_amount),
					'allocated_amt' : flt(d.allocated_amount)
				}
				lst.append(args)

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
Example #7
0
	def reconcile(self, args):
		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
		lst = []
		for e in self.get('payments'):
			if e.invoice_type and e.invoice_number and e.allocated_amount:
				lst.append({
					'voucher_no' : e.journal_entry,
					'voucher_detail_no' : e.voucher_detail_number,
					'against_voucher_type' : e.invoice_type,
					'against_voucher'  : e.invoice_number,
					'account' : self.receivable_payable_account,
					'party_type': self.party_type,
					'party': self.party,
					'is_advance' : e.is_advance,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amt' : flt(e.amount),
					'allocated_amt' : flt(e.allocated_amount)
				})

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
			msgprint(_("Successfully Reconciled"))
			self.get_unreconciled_entries()
	def update_payment_entry(self, payment):
		lst = []
		invoices = payment.invoices.strip().split(',')
		if (len(invoices) == 0): return
		amount = float(abs(payment.amount))
		for invoice_entry in invoices:
			if (not invoice_entry.strip()): continue
			invs = invoice_entry.split('|')
			invoice_type, invoice = invs[0], invs[1]
			outstanding_amount = frappe.get_value(invoice_type, invoice, 'outstanding_amount')

			lst.append(frappe._dict({
				'voucher_type': payment.reference_type,
				'voucher_no' : payment.reference_name,
				'against_voucher_type' : invoice_type,
				'against_voucher'  : invoice,
				'account' : payment.account,
				'party_type': payment.party_type,
				'party': frappe.get_value("Payment Entry", payment.reference_name, "party"),
				'unadjusted_amount' : float(amount),
				'allocated_amount' : min(outstanding_amount, amount)
			}))
			amount -= outstanding_amount
		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			try:
				reconcile_against_document(lst)
			except:
				frappe.throw("Exception occurred while reconciling {0}".format(payment.reference_name))
Example #9
0
	def reconcile(self, args):
		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
		lst = []
		for e in self.get('payments'):
			if e.invoice_type and e.invoice_number and e.allocated_amount:
				lst.append({
					'voucher_no' : e.journal_entry,
					'voucher_detail_no' : e.voucher_detail_number,
					'against_voucher_type' : e.invoice_type,
					'against_voucher'  : e.invoice_number,
					'account' : self.receivable_payable_account,
					'party_type': self.party_type,
					'party': self.party,
					'is_advance' : e.is_advance,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amt' : flt(e.amount),
					'allocated_amt' : flt(e.allocated_amount)
				})

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
			msgprint(_("Successfully Reconciled"))
			self.get_unreconciled_entries()
Example #10
0
	def reconcile(self, args):
		for e in self.get('payments'):
			e.invoice_type = None
			if e.invoice_number and " | " in e.invoice_number:
				e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")

		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = ("credit_in_account_currency"
			if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")

		lst = []
		dr_or_cr_notes = []
		for e in self.get('payments'):
			reconciled_entry = []
			if e.invoice_number and e.allocated_amount:
				if e.reference_type in ['Sales Invoice', 'Purchase Invoice']:
					reconciled_entry = dr_or_cr_notes
				else:
					reconciled_entry = lst

				reconciled_entry.append(self.get_payment_details(e, dr_or_cr))

		if lst:
			reconcile_against_document(lst)

		if dr_or_cr_notes:
			reconcile_dr_cr_note(dr_or_cr_notes, self.company)

		msgprint(_("Successfully Reconciled"))
		self.get_unreconciled_entries()
Example #11
0
	def update_against_document_in_jv(self):
		"""
			Links invoice and advance voucher:
				1. cancel advance voucher
				2. split into multiple rows if partially adjusted, assign against voucher
				3. submit advance voucher
		"""

		lst = []
		for d in self.get('advances'):
			if flt(d.allocated_amount) > 0:
				args = {
					'voucher_no' : d.journal_entry,
					'voucher_detail_no' : d.jv_detail_no,
					'against_voucher_type' : 'Purchase Invoice',
					'against_voucher'  : self.name,
					'account' : self.credit_to,
					'party_type': 'Supplier',
					'party': self.supplier,
					'is_advance' : 'Yes',
					'dr_or_cr' : 'debit_in_account_currency',
					'unadjusted_amt' : flt(d.advance_amount),
					'allocated_amt' : flt(d.allocated_amount)
				}
				lst.append(args)

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
    def reconcile(self, args):
        self.get_invoice_entries()
        self.validate_invoice()
        dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
        lst = []
        for e in self.get("payments"):
            if e.invoice_type and e.invoice_number and e.allocated_amount:
                lst.append(
                    {
                        "voucher_no": e.journal_entry,
                        "voucher_detail_no": e.voucher_detail_number,
                        "against_voucher_type": e.invoice_type,
                        "against_voucher": e.invoice_number,
                        "account": self.receivable_payable_account,
                        "party_type": self.party_type,
                        "party": self.party,
                        "is_advance": e.is_advance,
                        "dr_or_cr": dr_or_cr,
                        "unadjusted_amt": flt(e.amount),
                        "allocated_amt": flt(e.allocated_amount),
                    }
                )

        if lst:
            from erpnext.accounts.utils import reconcile_against_document

            reconcile_against_document(lst)
            msgprint(_("Successfully Reconciled"))
            self.get_unreconciled_entries()
Example #13
0
    def update_against_document_in_jv(self):
        """
			Links invoice and advance voucher:
				1. cancel advance voucher
				2. split into multiple rows if partially adjusted, assign against voucher
				3. submit advance voucher
		"""

        lst = []
        for d in self.get("advances"):
            if flt(d.allocated_amount) > 0:
                args = {
                    "voucher_no": d.journal_entry,
                    "voucher_detail_no": d.jv_detail_no,
                    "against_voucher_type": "Sales Invoice",
                    "against_voucher": self.name,
                    "account": self.debit_to,
                    "party_type": "Customer",
                    "party": self.customer,
                    "is_advance": "Yes",
                    "dr_or_cr": "credit_in_account_currency",
                    "unadjusted_amt": flt(d.advance_amount),
                    "allocated_amt": flt(d.allocated_amount),
                }
                lst.append(args)

        if lst:
            from erpnext.accounts.utils import reconcile_against_document

            reconcile_against_document(lst)
	def reconcile(self, args):
		for e in self.get('payments'):
			e.invoice_type = None
			if e.invoice_number and " | " in e.invoice_number:
				e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")

		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = "credit_in_account_currency" \
			if self.party_type == "Customer" else "debit_in_account_currency"
			
		lst = []
		for e in self.get('payments'):
			if e.invoice_number and e.allocated_amount:
				lst.append(frappe._dict({
					'voucher_type': e.reference_type,
					'voucher_no' : e.reference_name,
					'voucher_detail_no' : e.reference_row,
					'against_voucher_type' : e.invoice_type,
					'against_voucher'  : e.invoice_number,
					'account' : self.receivable_payable_account,
					'party_type': self.party_type,
					'party': self.party,
					'is_advance' : e.is_advance,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amount' : flt(e.amount),
					'allocated_amount' : flt(e.allocated_amount)
				}))
				
		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
			
			msgprint(_("Successfully Reconciled"))
			self.get_unreconciled_entries()
Example #15
0
	def reconcile(self):
		self.validate_mandatory()
		self.validate_allocated_amount()

		dr_or_cr = "credit" if self.total_amount > 0 else "debit"

		lst = []
		for d in self.get('against_entries'):
			if flt(d.allocated_amount) > 0:
				lst.append({
					'voucher_no' : d.voucher_no,
					'voucher_detail_no' : d.voucher_detail_no,
					'against_voucher_type' : self.voucher_type,
					'against_voucher'  : self.voucher_no,
					'account' : self.account,
					'is_advance' : d.is_advance,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amt' : flt(d.original_amount),
					'allocated_amt' : flt(d.allocated_amount)
				})

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
			self.get_voucher_details()
			self.get_against_entries()
			msgprint(_("Successfully allocated"))
Example #16
0
    def update_against_document_in_jv(self):
        """
			Links invoice and advance voucher:
				1. cancel advance voucher
				2. split into multiple rows if partially adjusted, assign against voucher
				3. submit advance voucher
		"""

        if self.doctype == "Sales Invoice":
            party_type = "Customer"
            party = self.customer
            party_account = self.debit_to
            dr_or_cr = "credit_in_account_currency"
        else:
            party_type = "Supplier"
            party = self.supplier
            party_account = self.credit_to
            dr_or_cr = "debit_in_account_currency"

        lst = []
        for d in self.get("advances"):
            if flt(d.allocated_amount) > 0:
                args = frappe._dict(
                    {
                        "voucher_type": d.reference_type,
                        "voucher_no": d.reference_name,
                        "voucher_detail_no": d.reference_row,
                        "against_voucher_type": self.doctype,
                        "against_voucher": self.name,
                        "account": party_account,
                        "party_type": party_type,
                        "party": party,
                        "is_advance": "Yes",
                        "dr_or_cr": dr_or_cr,
                        "unadjusted_amount": flt(d.advance_amount),
                        "allocated_amount": flt(d.allocated_amount),
                        "exchange_rate": (
                            self.conversion_rate if self.party_account_currency != self.company_currency else 1
                        ),
                        "grand_total": (
                            self.base_grand_total
                            if self.party_account_currency == self.company_currency
                            else self.grand_total
                        ),
                        "outstanding_amount": self.outstanding_amount,
                    }
                )
                lst.append(args)

        if lst:
            from erpnext.accounts.utils import reconcile_against_document

            reconcile_against_document(lst)
def adjust_je_against_dn(payments):
    """ Adjust Journal Entries against Debit Note """
    try:
        for pi, value in payments.iteritems():
            if len(value['vendor_credit']) == 1:
                for dn in value['vendor_credit']:
                    lst = []
                    quickbooks_journal_entry_id = dn.get('vendor_credit_id')
                    args = get_jv_voucher_detail_no(
                        quickbooks_journal_entry_id)
                    pi_name = frappe.db.get_value(
                        "Purchase Invoice", {
                            "quickbooks_purchase_invoice_id":
                            value.get('qb_pi_id'),
                            "outstanding_amount": ['!=', 0]
                        }, "name")
                    if args.get('voucher_detail_no') and args.get(
                            'unadjusted_amount') and pi_name:
                        invoice = frappe.get_doc("Purchase Invoice", pi_name)
                        lst.append(
                            frappe._dict(
                                reconcile_entry(
                                    args,
                                    "Purchase Invoice",
                                    pi_name,
                                    invoice,
                                    paid_amt=value.get('paid_amount'))))
                    if lst:
                        from erpnext.accounts.utils import reconcile_against_document
                        reconcile_against_document(lst)
                        frappe.db.commit()
            elif len(value['vendor_credit']) > 1:
                for dn in value['vendor_credit']:
                    lst1 = []
                    quickbooks_journal_entry_id = dn.get('vendor_credit_id')
                    args = get_jv_voucher_detail_no(
                        quickbooks_journal_entry_id)
                    pi_name = frappe.db.get_value(
                        "Purchase Invoice", {
                            "quickbooks_purchase_invoice_id":
                            value.get('qb_pi_id'),
                            "outstanding_amount": ['!=', 0]
                        }, "name")
                    if args.get('voucher_detail_no') and args.get(
                            'unadjusted_amount') and pi_name:
                        invoice = frappe.get_doc("Purchase Invoice", pi_name)
                        lst1.append(
                            frappe._dict(
                                reconcile_entry(
                                    args,
                                    "Purchase Invoice",
                                    pi_name,
                                    invoice,
                                    paid_amt=dn.get('paid_amount'))))
                    if lst1:
                        from erpnext.accounts.utils import reconcile_against_document
                        reconcile_against_document(lst1)
                        frappe.db.commit()
    except Exception, e:
        make_quickbooks_log(title=e.message,
                            status="Error",
                            method="adjust_je_against_dn",
                            message=frappe.get_traceback(),
                            request_data=payments,
                            exception=True)
    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)