mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-01 20:48:27 +00:00
Merge pull request #35330 from ruthra-kumar/cr_note_posts_gl_for_itself
refactor: cr/dr note should be standalone even when created from another invoice
This commit is contained in:
@@ -702,7 +702,50 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
pe2.submit()
|
pe2.submit()
|
||||||
|
|
||||||
# create return entry against si1
|
# create return entry against si1
|
||||||
create_sales_invoice(is_return=1, return_against=si1.name, qty=-1)
|
cr_note = create_sales_invoice(is_return=1, return_against=si1.name, qty=-1)
|
||||||
|
si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount")
|
||||||
|
|
||||||
|
# create JE(credit note) manually against si1 and cr_note
|
||||||
|
je = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Journal Entry",
|
||||||
|
"company": si1.company,
|
||||||
|
"voucher_type": "Credit Note",
|
||||||
|
"posting_date": nowdate(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
je.append(
|
||||||
|
"accounts",
|
||||||
|
{
|
||||||
|
"account": si1.debit_to,
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": si1.customer,
|
||||||
|
"debit": 0,
|
||||||
|
"credit": 100,
|
||||||
|
"debit_in_account_currency": 0,
|
||||||
|
"credit_in_account_currency": 100,
|
||||||
|
"reference_type": si1.doctype,
|
||||||
|
"reference_name": si1.name,
|
||||||
|
"cost_center": si1.items[0].cost_center,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
je.append(
|
||||||
|
"accounts",
|
||||||
|
{
|
||||||
|
"account": cr_note.debit_to,
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": cr_note.customer,
|
||||||
|
"debit": 100,
|
||||||
|
"credit": 0,
|
||||||
|
"debit_in_account_currency": 100,
|
||||||
|
"credit_in_account_currency": 0,
|
||||||
|
"reference_type": cr_note.doctype,
|
||||||
|
"reference_name": cr_note.name,
|
||||||
|
"cost_center": cr_note.items[0].cost_center,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
je.save().submit()
|
||||||
|
|
||||||
si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount")
|
si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount")
|
||||||
self.assertEqual(si1_outstanding, -100)
|
self.assertEqual(si1_outstanding, -100)
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ class TestPaymentLedgerEntry(FrappeTestCase):
|
|||||||
cr_note1.return_against = si3.name
|
cr_note1.return_against = si3.name
|
||||||
cr_note1 = cr_note1.save().submit()
|
cr_note1 = cr_note1.save().submit()
|
||||||
|
|
||||||
pl_entries = (
|
pl_entries_si3 = (
|
||||||
qb.from_(ple)
|
qb.from_(ple)
|
||||||
.select(
|
.select(
|
||||||
ple.voucher_type,
|
ple.voucher_type,
|
||||||
@@ -309,7 +309,24 @@ class TestPaymentLedgerEntry(FrappeTestCase):
|
|||||||
.run(as_dict=True)
|
.run(as_dict=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_values = [
|
pl_entries_cr_note1 = (
|
||||||
|
qb.from_(ple)
|
||||||
|
.select(
|
||||||
|
ple.voucher_type,
|
||||||
|
ple.voucher_no,
|
||||||
|
ple.against_voucher_type,
|
||||||
|
ple.against_voucher_no,
|
||||||
|
ple.amount,
|
||||||
|
ple.delinked,
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(ple.against_voucher_type == cr_note1.doctype) & (ple.against_voucher_no == cr_note1.name)
|
||||||
|
)
|
||||||
|
.orderby(ple.creation)
|
||||||
|
.run(as_dict=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
expected_values_for_si3 = [
|
||||||
{
|
{
|
||||||
"voucher_type": si3.doctype,
|
"voucher_type": si3.doctype,
|
||||||
"voucher_no": si3.name,
|
"voucher_no": si3.name,
|
||||||
@@ -317,18 +334,21 @@ class TestPaymentLedgerEntry(FrappeTestCase):
|
|||||||
"against_voucher_no": si3.name,
|
"against_voucher_no": si3.name,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"delinked": 0,
|
"delinked": 0,
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
# credit/debit notes post ledger entries against itself
|
||||||
|
expected_values_for_cr_note1 = [
|
||||||
{
|
{
|
||||||
"voucher_type": cr_note1.doctype,
|
"voucher_type": cr_note1.doctype,
|
||||||
"voucher_no": cr_note1.name,
|
"voucher_no": cr_note1.name,
|
||||||
"against_voucher_type": si3.doctype,
|
"against_voucher_type": cr_note1.doctype,
|
||||||
"against_voucher_no": si3.name,
|
"against_voucher_no": cr_note1.name,
|
||||||
"amount": -amount,
|
"amount": -amount,
|
||||||
"delinked": 0,
|
"delinked": 0,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.assertEqual(pl_entries[0], expected_values[0])
|
self.assertEqual(pl_entries_si3, expected_values_for_si3)
|
||||||
self.assertEqual(pl_entries[1], expected_values[1])
|
self.assertEqual(pl_entries_cr_note1, expected_values_for_cr_note1)
|
||||||
|
|
||||||
def test_je_against_inv_and_note(self):
|
def test_je_against_inv_and_note(self):
|
||||||
ple = self.ple
|
ple = self.ple
|
||||||
|
|||||||
@@ -186,15 +186,12 @@ class PaymentReconciliation(Document):
|
|||||||
self.common_filter_conditions.append(ple.account == self.receivable_payable_account)
|
self.common_filter_conditions.append(ple.account == self.receivable_payable_account)
|
||||||
|
|
||||||
self.get_return_invoices()
|
self.get_return_invoices()
|
||||||
return_invoices = [
|
|
||||||
x for x in self.return_invoices if x.return_against == None or x.return_against == ""
|
|
||||||
]
|
|
||||||
|
|
||||||
outstanding_dr_or_cr = []
|
outstanding_dr_or_cr = []
|
||||||
if return_invoices:
|
if self.return_invoices:
|
||||||
ple_query = QueryPaymentLedger()
|
ple_query = QueryPaymentLedger()
|
||||||
return_outstanding = ple_query.get_voucher_outstandings(
|
return_outstanding = ple_query.get_voucher_outstandings(
|
||||||
vouchers=return_invoices,
|
vouchers=self.return_invoices,
|
||||||
common_filter=self.common_filter_conditions,
|
common_filter=self.common_filter_conditions,
|
||||||
posting_date=self.ple_posting_date_filter,
|
posting_date=self.ple_posting_date_filter,
|
||||||
min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None,
|
min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None,
|
||||||
|
|||||||
@@ -86,8 +86,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.docstatus == 1 && doc.outstanding_amount != 0
|
if(doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) {
|
||||||
&& !(doc.is_return && doc.return_against) && !doc.on_hold) {
|
|
||||||
this.frm.add_custom_button(
|
this.frm.add_custom_button(
|
||||||
__('Payment'),
|
__('Payment'),
|
||||||
() => this.make_payment_entry(),
|
() => this.make_payment_entry(),
|
||||||
|
|||||||
@@ -628,9 +628,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"credit_in_account_currency": base_grand_total
|
"credit_in_account_currency": base_grand_total
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
else grand_total,
|
else grand_total,
|
||||||
"against_voucher": self.return_against
|
"against_voucher": self.name,
|
||||||
if cint(self.is_return) and self.return_against
|
|
||||||
else self.name,
|
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
"project": self.project,
|
"project": self.project,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
@@ -1644,12 +1642,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate():
|
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate():
|
||||||
self.status = "Unpaid"
|
self.status = "Unpaid"
|
||||||
# Check if outstanding amount is 0 due to debit note issued against invoice
|
# Check if outstanding amount is 0 due to debit note issued against invoice
|
||||||
elif (
|
elif self.is_return == 0 and frappe.db.get_value(
|
||||||
outstanding_amount <= 0
|
"Purchase Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1}
|
||||||
and self.is_return == 0
|
|
||||||
and frappe.db.get_value(
|
|
||||||
"Purchase Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1}
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self.status = "Debit Note Issued"
|
self.status = "Debit Note Issued"
|
||||||
elif self.is_return == 1:
|
elif self.is_return == 1:
|
||||||
|
|||||||
@@ -98,8 +98,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
|
|||||||
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
|
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.docstatus == 1 && doc.outstanding_amount!=0
|
if (doc.docstatus == 1 && doc.outstanding_amount!=0) {
|
||||||
&& !(cint(doc.is_return) && doc.return_against)) {
|
|
||||||
this.frm.add_custom_button(
|
this.frm.add_custom_button(
|
||||||
__('Payment'),
|
__('Payment'),
|
||||||
() => this.make_payment_entry(),
|
() => this.make_payment_entry(),
|
||||||
|
|||||||
@@ -1104,9 +1104,7 @@ class SalesInvoice(SellingController):
|
|||||||
"debit_in_account_currency": base_grand_total
|
"debit_in_account_currency": base_grand_total
|
||||||
if self.party_account_currency == self.company_currency
|
if self.party_account_currency == self.company_currency
|
||||||
else grand_total,
|
else grand_total,
|
||||||
"against_voucher": self.return_against
|
"against_voucher": self.name,
|
||||||
if cint(self.is_return) and self.return_against
|
|
||||||
else self.name,
|
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
"project": self.project,
|
"project": self.project,
|
||||||
@@ -1732,12 +1730,8 @@ class SalesInvoice(SellingController):
|
|||||||
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate():
|
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate():
|
||||||
self.status = "Unpaid"
|
self.status = "Unpaid"
|
||||||
# Check if outstanding amount is 0 due to credit note issued against invoice
|
# Check if outstanding amount is 0 due to credit note issued against invoice
|
||||||
elif (
|
elif self.is_return == 0 and frappe.db.get_value(
|
||||||
outstanding_amount <= 0
|
"Sales Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1}
|
||||||
and self.is_return == 0
|
|
||||||
and frappe.db.get_value(
|
|
||||||
"Sales Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1}
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self.status = "Credit Note Issued"
|
self.status = "Credit Note Issued"
|
||||||
elif self.is_return == 1:
|
elif self.is_return == 1:
|
||||||
|
|||||||
@@ -1500,8 +1500,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(party_credited, 1000)
|
self.assertEqual(party_credited, 1000)
|
||||||
|
|
||||||
# Check outstanding amount
|
# Check outstanding amount
|
||||||
self.assertFalse(si1.outstanding_amount)
|
self.assertEqual(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"), -1000)
|
||||||
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
|
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 2500)
|
||||||
|
|
||||||
def test_gle_made_when_asset_is_returned(self):
|
def test_gle_made_when_asset_is_returned(self):
|
||||||
create_asset_data()
|
create_asset_data()
|
||||||
|
|||||||
Reference in New Issue
Block a user