mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-12 11:25:09 +00:00
fix: correct payment terms fetching and recalculation logic
This commit is contained in:
@@ -2590,10 +2590,12 @@ class AccountsController(TransactionBase):
|
|||||||
prev_doc = self.get("items")[0].get("purchase_order")
|
prev_doc = self.get("items")[0].get("purchase_order")
|
||||||
prev_doctype = "Purchase Order"
|
prev_doctype = "Purchase Order"
|
||||||
prev_doctype_name = "purchase_order"
|
prev_doctype_name = "purchase_order"
|
||||||
else:
|
elif self.doctype == "Sales Order":
|
||||||
prev_doc = self.get("items")[0].get("prevdoc_docname")
|
prev_doc = self.get("items")[0].get("prevdoc_docname")
|
||||||
prev_doctype = "Quotation"
|
prev_doctype = "Quotation"
|
||||||
prev_doctype_name = "prevdoc_docname"
|
prev_doctype_name = "prevdoc_docname"
|
||||||
|
else:
|
||||||
|
return None, None, None
|
||||||
return prev_doc, prev_doctype, prev_doctype_name
|
return prev_doc, prev_doctype, prev_doctype_name
|
||||||
|
|
||||||
def linked_order_has_payment_terms(self, po_or_so, fieldname, doctype):
|
def linked_order_has_payment_terms(self, po_or_so, fieldname, doctype):
|
||||||
@@ -2690,7 +2692,9 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
d.validate_from_to_dates("discount_date", "due_date")
|
d.validate_from_to_dates("discount_date", "due_date")
|
||||||
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
if self.doctype in ["Sales Order", "Quotation"] and getdate(d.due_date) < getdate(
|
||||||
|
self.transaction_date
|
||||||
|
):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(
|
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(
|
||||||
d.idx
|
d.idx
|
||||||
|
|||||||
@@ -441,12 +441,11 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, ar
|
|||||||
filtered_items = args.get("filtered_children", [])
|
filtered_items = args.get("filtered_children", [])
|
||||||
child_filter = d.name in filtered_items if filtered_items else True
|
child_filter = d.name in filtered_items if filtered_items else True
|
||||||
return child_filter
|
return child_filter
|
||||||
|
|
||||||
automatically_fetch_payment_terms = cint(
|
automatically_fetch_payment_terms = cint(
|
||||||
frappe.get_single_value("Accounts Settings", "automatically_fetch_payment_terms")
|
frappe.get_single_value("Accounts Settings", "automatically_fetch_payment_terms")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
doclist = get_mapped_doc(
|
doclist = get_mapped_doc(
|
||||||
"Quotation",
|
"Quotation",
|
||||||
source_name,
|
source_name,
|
||||||
@@ -464,7 +463,6 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, ar
|
|||||||
},
|
},
|
||||||
"Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "reset_value": True},
|
"Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "reset_value": True},
|
||||||
"Sales Team": {"doctype": "Sales Team", "add_if_empty": True},
|
"Sales Team": {"doctype": "Sales Team", "add_if_empty": True},
|
||||||
"Payment Schedule": {"doctype": "Payment Schedule", "add_if_empty": True},
|
|
||||||
},
|
},
|
||||||
target_doc,
|
target_doc,
|
||||||
set_missing_values,
|
set_missing_values,
|
||||||
|
|||||||
@@ -174,12 +174,11 @@ class TestQuotation(FrappeTestCase):
|
|||||||
quotation.insert()
|
quotation.insert()
|
||||||
|
|
||||||
self.assertTrue(quotation.payment_schedule)
|
self.assertTrue(quotation.payment_schedule)
|
||||||
|
|
||||||
@change_settings(
|
@change_settings(
|
||||||
"Accounts Settings",
|
"Accounts Settings",
|
||||||
{"automatically_fetch_payment_terms": 1},
|
{"automatically_fetch_payment_terms": 1},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_make_sales_order_terms_copied(self):
|
def test_make_sales_order_terms_copied(self):
|
||||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||||
|
|
||||||
@@ -322,7 +321,11 @@ class TestQuotation(FrappeTestCase):
|
|||||||
|
|
||||||
@change_settings(
|
@change_settings(
|
||||||
"Accounts Settings",
|
"Accounts Settings",
|
||||||
{"add_taxes_from_item_tax_template": 0, "add_taxes_from_taxes_and_charges_template": 0,"automatically_fetch_payment_terms": 1,},
|
{
|
||||||
|
"add_taxes_from_item_tax_template": 0,
|
||||||
|
"add_taxes_from_taxes_and_charges_template": 0,
|
||||||
|
"automatically_fetch_payment_terms": 1,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
def test_make_sales_order_with_terms(self):
|
def test_make_sales_order_with_terms(self):
|
||||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||||
@@ -1065,7 +1068,7 @@ class TestQuotation(FrappeTestCase):
|
|||||||
|
|
||||||
quotation.reload()
|
quotation.reload()
|
||||||
self.assertEqual(quotation.status, "Open")
|
self.assertEqual(quotation.status, "Open")
|
||||||
|
|
||||||
@change_settings(
|
@change_settings(
|
||||||
"Accounts Settings",
|
"Accounts Settings",
|
||||||
{"automatically_fetch_payment_terms": 1},
|
{"automatically_fetch_payment_terms": 1},
|
||||||
@@ -1117,7 +1120,6 @@ class TestQuotation(FrappeTestCase):
|
|||||||
self.assertEqual(sales_order.payment_schedule[1].payment_amount, 5000)
|
self.assertEqual(sales_order.payment_schedule[1].payment_amount, 5000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test_records = frappe.get_test_records("Quotation")
|
test_records = frappe.get_test_records("Quotation")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1669,7 +1669,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fetch_from": "customer.is_internal_customer",
|
|
||||||
"fieldname": "ignore_default_payment_terms_template",
|
"fieldname": "ignore_default_payment_terms_template",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
@@ -1681,7 +1680,7 @@
|
|||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-03-06 15:03:35.717402",
|
"modified": "2026-03-06 15:33:49.059029",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
|||||||
@@ -52,13 +52,16 @@ class SalesOrder(SellingController):
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from frappe.types import DF
|
||||||
|
|
||||||
from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule
|
from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule
|
||||||
from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail
|
from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail
|
||||||
from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import SalesTaxesandCharges
|
from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import (
|
||||||
|
SalesTaxesandCharges,
|
||||||
|
)
|
||||||
from erpnext.selling.doctype.sales_order_item.sales_order_item import SalesOrderItem
|
from erpnext.selling.doctype.sales_order_item.sales_order_item import SalesOrderItem
|
||||||
from erpnext.selling.doctype.sales_team.sales_team import SalesTeam
|
from erpnext.selling.doctype.sales_team.sales_team import SalesTeam
|
||||||
from erpnext.stock.doctype.packed_item.packed_item import PackedItem
|
from erpnext.stock.doctype.packed_item.packed_item import PackedItem
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
additional_discount_percentage: DF.Float
|
additional_discount_percentage: DF.Float
|
||||||
address_display: DF.SmallText | None
|
address_display: DF.SmallText | None
|
||||||
@@ -96,7 +99,9 @@ class SalesOrder(SellingController):
|
|||||||
customer_group: DF.Link | None
|
customer_group: DF.Link | None
|
||||||
customer_name: DF.Data | None
|
customer_name: DF.Data | None
|
||||||
delivery_date: DF.Date | None
|
delivery_date: DF.Date | None
|
||||||
delivery_status: DF.Literal["Not Delivered", "Fully Delivered", "Partly Delivered", "Closed", "Not Applicable"]
|
delivery_status: DF.Literal[
|
||||||
|
"Not Delivered", "Fully Delivered", "Partly Delivered", "Closed", "Not Applicable"
|
||||||
|
]
|
||||||
disable_rounded_total: DF.Check
|
disable_rounded_total: DF.Check
|
||||||
discount_amount: DF.Currency
|
discount_amount: DF.Currency
|
||||||
dispatch_address: DF.SmallText | None
|
dispatch_address: DF.SmallText | None
|
||||||
@@ -149,7 +154,17 @@ class SalesOrder(SellingController):
|
|||||||
shipping_rule: DF.Link | None
|
shipping_rule: DF.Link | None
|
||||||
skip_delivery_note: DF.Check
|
skip_delivery_note: DF.Check
|
||||||
source: DF.Link | None
|
source: DF.Link | None
|
||||||
status: DF.Literal["", "Draft", "On Hold", "To Deliver and Bill", "To Bill", "To Deliver", "Completed", "Cancelled", "Closed"]
|
status: DF.Literal[
|
||||||
|
"",
|
||||||
|
"Draft",
|
||||||
|
"On Hold",
|
||||||
|
"To Deliver and Bill",
|
||||||
|
"To Bill",
|
||||||
|
"To Deliver",
|
||||||
|
"Completed",
|
||||||
|
"Cancelled",
|
||||||
|
"Closed",
|
||||||
|
]
|
||||||
tax_category: DF.Link | None
|
tax_category: DF.Link | None
|
||||||
tax_id: DF.Data | None
|
tax_id: DF.Data | None
|
||||||
taxes: DF.Table[SalesTaxesandCharges]
|
taxes: DF.Table[SalesTaxesandCharges]
|
||||||
|
|||||||
Reference in New Issue
Block a user