Merge pull request #30754 from deepeshgarg007/round_off_account_cost_center
fix: First preference to parent cost center rather than round off cost center
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 4453783..3f1998a 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -99,7 +99,7 @@
if doctype == "Budget":
add_dimension_to_budget_doctype(df.copy(), doc)
else:
- create_custom_field(doctype, df)
+ create_custom_field(doctype, df, ignore_validate=True)
count += 1
@@ -115,7 +115,7 @@
}
)
- create_custom_field("Budget", df)
+ create_custom_field("Budget", df, ignore_validate=True)
property_setter = frappe.db.exists("Property Setter", "Budget-budget_against-options")
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 9a35a24..417611f 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -18,7 +18,6 @@
"automatically_fetch_payment_terms",
"column_break_17",
"enable_common_party_accounting",
- "enable_discount_accounting",
"report_setting_section",
"use_custom_cash_flow",
"deferred_accounting_settings_section",
@@ -274,13 +273,6 @@
},
{
"default": "0",
- "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
- "fieldname": "enable_discount_accounting",
- "fieldtype": "Check",
- "label": "Enable Discount Accounting"
- },
- {
- "default": "0",
"description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
"fieldname": "enable_common_party_accounting",
"fieldtype": "Check",
@@ -354,7 +346,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2022-02-04 12:32:36.805652",
+ "modified": "2022-04-08 14:45:06.796418",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
index 8354981..3b125a2 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
@@ -28,7 +28,6 @@
self.validate_stale_days()
self.enable_payment_schedule_in_print()
- self.toggle_discount_accounting_fields()
self.validate_pending_reposts()
def validate_stale_days(self):
@@ -52,74 +51,6 @@
validate_fields_for_doctype=False,
)
- def toggle_discount_accounting_fields(self):
- enable_discount_accounting = cint(self.enable_discount_accounting)
-
- for doctype in ["Sales Invoice Item", "Purchase Invoice Item"]:
- make_property_setter(
- doctype,
- "discount_account",
- "hidden",
- not (enable_discount_accounting),
- "Check",
- validate_fields_for_doctype=False,
- )
- if enable_discount_accounting:
- make_property_setter(
- doctype,
- "discount_account",
- "mandatory_depends_on",
- "eval: doc.discount_amount",
- "Code",
- validate_fields_for_doctype=False,
- )
- else:
- make_property_setter(
- doctype,
- "discount_account",
- "mandatory_depends_on",
- "",
- "Code",
- validate_fields_for_doctype=False,
- )
-
- for doctype in ["Sales Invoice", "Purchase Invoice"]:
- make_property_setter(
- doctype,
- "additional_discount_account",
- "hidden",
- not (enable_discount_accounting),
- "Check",
- validate_fields_for_doctype=False,
- )
- if enable_discount_accounting:
- make_property_setter(
- doctype,
- "additional_discount_account",
- "mandatory_depends_on",
- "eval: doc.discount_amount",
- "Code",
- validate_fields_for_doctype=False,
- )
- else:
- make_property_setter(
- doctype,
- "additional_discount_account",
- "mandatory_depends_on",
- "",
- "Code",
- validate_fields_for_doctype=False,
- )
-
- make_property_setter(
- "Item",
- "default_discount_account",
- "hidden",
- not (enable_discount_accounting),
- "Check",
- validate_fields_for_doctype=False,
- )
-
def validate_pending_reposts(self):
if self.acc_frozen_upto:
check_pending_reposting(self.acc_frozen_upto)
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 96779d7..0f617b5 100644
--- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -5,7 +5,10 @@
import frappe
from frappe import _, msgprint
from frappe.model.document import Document
-from frappe.utils import flt, fmt_money, getdate, nowdate
+from frappe.query_builder.custom import ConstantColumn
+from frappe.utils import flt, fmt_money, getdate
+
+import erpnext
form_grid_templates = {"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"}
@@ -76,6 +79,52 @@
as_dict=1,
)
+ loan_disbursement = frappe.qb.DocType("Loan Disbursement")
+
+ loan_disbursements = (
+ frappe.qb.from_(loan_disbursement)
+ .select(
+ ConstantColumn("Loan Disbursement").as_("payment_document"),
+ loan_disbursement.name.as_("payment_entry"),
+ loan_disbursement.disbursed_amount.as_("credit"),
+ ConstantColumn(0).as_("debit"),
+ loan_disbursement.reference_number.as_("cheque_number"),
+ loan_disbursement.reference_date.as_("cheque_date"),
+ loan_disbursement.disbursement_date.as_("posting_date"),
+ loan_disbursement.applicant.as_("against_account"),
+ )
+ .where(loan_disbursement.docstatus == 1)
+ .where(loan_disbursement.disbursement_date >= self.from_date)
+ .where(loan_disbursement.disbursement_date <= self.to_date)
+ .where(loan_disbursement.clearance_date.isnull())
+ .where(loan_disbursement.disbursement_account.isin([self.bank_account, self.account]))
+ .orderby(loan_disbursement.disbursement_date)
+ .orderby(loan_disbursement.name, frappe.qb.desc)
+ ).run(as_dict=1)
+
+ loan_repayment = frappe.qb.DocType("Loan Repayment")
+
+ loan_repayments = (
+ frappe.qb.from_(loan_repayment)
+ .select(
+ ConstantColumn("Loan Repayment").as_("payment_document"),
+ loan_repayment.name.as_("payment_entry"),
+ loan_repayment.amount_paid.as_("debit"),
+ ConstantColumn(0).as_("credit"),
+ loan_repayment.reference_number.as_("cheque_number"),
+ loan_repayment.reference_date.as_("cheque_date"),
+ loan_repayment.applicant.as_("against_account"),
+ loan_repayment.posting_date,
+ )
+ .where(loan_repayment.docstatus == 1)
+ .where(loan_repayment.clearance_date.isnull())
+ .where(loan_repayment.posting_date >= self.from_date)
+ .where(loan_repayment.posting_date <= self.to_date)
+ .where(loan_repayment.payment_account.isin([self.bank_account, self.account]))
+ .orderby(loan_repayment.posting_date)
+ .orderby(loan_repayment.name, frappe.qb.desc)
+ ).run(as_dict=1)
+
pos_sales_invoices, pos_purchase_invoices = [], []
if self.include_pos_transactions:
pos_sales_invoices = frappe.db.sql(
@@ -114,20 +163,29 @@
entries = sorted(
list(payment_entries)
- + list(journal_entries + list(pos_sales_invoices) + list(pos_purchase_invoices)),
- key=lambda k: k["posting_date"] or getdate(nowdate()),
+ + list(journal_entries)
+ + list(pos_sales_invoices)
+ + list(pos_purchase_invoices)
+ + list(loan_disbursements)
+ + list(loan_repayments),
+ key=lambda k: getdate(k["posting_date"]),
)
self.set("payment_entries", [])
self.total_amount = 0.0
+ default_currency = erpnext.get_default_currency()
for d in entries:
row = self.append("payment_entries", {})
amount = flt(d.get("debit", 0)) - flt(d.get("credit", 0))
+ if not d.get("account_currency"):
+ d.account_currency = default_currency
+
formatted_amount = fmt_money(abs(amount), 2, d.account_currency)
d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr"))
+ d.posting_date = getdate(d.posting_date)
d.pop("credit")
d.pop("debit")
diff --git a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
index 706fbbe..c1e55f6 100644
--- a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
+++ b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
@@ -1,9 +1,96 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-# import frappe
import unittest
+import frappe
+from frappe.utils import add_months, getdate
+
+from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
+from erpnext.loan_management.doctype.loan.test_loan import (
+ create_loan,
+ create_loan_accounts,
+ create_loan_type,
+ create_repayment_entry,
+ make_loan_disbursement_entry,
+)
+
class TestBankClearance(unittest.TestCase):
- pass
+ @classmethod
+ def setUpClass(cls):
+ make_bank_account()
+ create_loan_accounts()
+ create_loan_masters()
+ add_transactions()
+
+ # Basic test case to test if bank clearance tool doesn't break
+ # Detailed test can be added later
+ def test_bank_clearance(self):
+ bank_clearance = frappe.get_doc("Bank Clearance")
+ bank_clearance.account = "_Test Bank Clearance - _TC"
+ bank_clearance.from_date = add_months(getdate(), -1)
+ bank_clearance.to_date = getdate()
+ bank_clearance.get_payment_entries()
+ self.assertEqual(len(bank_clearance.payment_entries), 3)
+
+
+def make_bank_account():
+ if not frappe.db.get_value("Account", "_Test Bank Clearance - _TC"):
+ frappe.get_doc(
+ {
+ "doctype": "Account",
+ "account_type": "Bank",
+ "account_name": "_Test Bank Clearance",
+ "company": "_Test Company",
+ "parent_account": "Bank Accounts - _TC",
+ }
+ ).insert()
+
+
+def create_loan_masters():
+ create_loan_type(
+ "Clearance Loan",
+ 2000000,
+ 13.5,
+ 25,
+ 0,
+ 5,
+ "Cash",
+ "_Test Bank Clearance - _TC",
+ "_Test Bank Clearance - _TC",
+ "Loan Account - _TC",
+ "Interest Income Account - _TC",
+ "Penalty Income Account - _TC",
+ )
+
+
+def add_transactions():
+ make_payment_entry()
+ make_loan()
+
+
+def make_loan():
+ loan = create_loan(
+ "_Test Customer",
+ "Clearance Loan",
+ 280000,
+ "Repay Over Number of Periods",
+ 20,
+ applicant_type="Customer",
+ )
+ loan.submit()
+ make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=getdate())
+ repayment_entry = create_repayment_entry(loan.name, "_Test Customer", getdate(), loan.loan_amount)
+ repayment_entry.save()
+ repayment_entry.submit()
+
+
+def make_payment_entry():
+ pi = make_purchase_invoice(supplier="_Test Supplier", qty=1, rate=690)
+ pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank Clearance - _TC")
+ pe.reference_no = "Conrad Oct 18"
+ pe.reference_date = "2018-10-24"
+ pe.insert()
+ pe.submit()
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index e37900b..a1d86e2 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -669,7 +669,7 @@
exchange_rate_map, net_rate_map = get_purchase_document_details(self)
enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
provisional_accounting_for_non_stock_items = cint(
frappe.db.get_value(
@@ -1159,7 +1159,7 @@
# tax table gl entries
valuation_tax = {}
enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
for tax in self.get("taxes"):
@@ -1252,7 +1252,7 @@
def enable_discount_accounting(self):
if not hasattr(self, "_enable_discount_accounting"):
self._enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
return self._enable_discount_accounting
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 59bd637..30d26ac 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -5,6 +5,7 @@
import unittest
import frappe
+from frappe.tests.utils import change_settings
from frappe.utils import add_days, cint, flt, getdate, nowdate, today
import erpnext
@@ -336,8 +337,8 @@
self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
+ @change_settings("Buying Settings", {"enable_discount_accounting": 1})
def test_purchase_invoice_with_discount_accounting_enabled(self):
- enable_discount_accounting()
discount_account = create_account(
account_name="Discount Account",
@@ -353,10 +354,10 @@
]
check_gl_entries(self, pi.name, expected_gle, nowdate())
- enable_discount_accounting(enable=0)
+ @change_settings("Buying Settings", {"enable_discount_accounting": 1})
def test_additional_discount_for_purchase_invoice_with_discount_accounting_enabled(self):
- enable_discount_accounting()
+
additional_discount_account = create_account(
account_name="Discount Account",
parent_account="Indirect Expenses - _TC",
@@ -1588,12 +1589,6 @@
accounts_settings.save()
-def enable_discount_accounting(enable=1):
- accounts_settings = frappe.get_doc("Accounts Settings")
- accounts_settings.enable_discount_accounting = enable
- accounts_settings.save()
-
-
def make_purchase_invoice(**args):
pi = frappe.new_doc("Purchase Invoice")
args = frappe._dict(args)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 5b7f1ce..f0880c1 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1051,7 +1051,7 @@
def make_tax_gl_entries(self, gl_entries):
enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
for tax in self.get("taxes"):
@@ -1097,7 +1097,7 @@
def make_item_gl_entries(self, gl_entries):
# income account gl entries
enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
for item in self.get("items"):
@@ -1276,7 +1276,7 @@
def enable_discount_accounting(self):
if not hasattr(self, "_enable_discount_accounting"):
self._enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
+ frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
return self._enable_discount_accounting
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index b22ec44..f2a696d 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -7,6 +7,7 @@
import frappe
from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.model.naming import make_autoname
+from frappe.tests.utils import change_settings
from frappe.utils import add_days, flt, getdate, nowdate
import erpnext
@@ -2707,12 +2708,8 @@
sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC"
)
+ @change_settings("Selling Settings", {"enable_discount_accounting": 1})
def test_sales_invoice_with_discount_accounting_enabled(self):
- from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
- enable_discount_accounting,
- )
-
- enable_discount_accounting()
discount_account = create_account(
account_name="Discount Account",
@@ -2728,14 +2725,10 @@
]
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
- enable_discount_accounting(enable=0)
+ @change_settings("Selling Settings", {"enable_discount_accounting": 1})
def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled(self):
- from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
- enable_discount_accounting,
- )
- enable_discount_accounting()
additional_discount_account = create_account(
account_name="Discount Account",
parent_account="Indirect Expenses - _TC",
@@ -2766,7 +2759,6 @@
]
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
- enable_discount_accounting(enable=0)
def test_asset_depreciation_on_sale_with_pro_rata(self):
"""
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 50321ba..89a9448 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -20,6 +20,7 @@
"maintain_same_rate",
"allow_multiple_items",
"bill_for_rejected_quantity_in_purchase_invoice",
+ "enable_discount_accounting",
"subcontract",
"backflush_raw_materials_of_subcontract_based_on",
"column_break_11",
@@ -133,6 +134,13 @@
{
"fieldname": "column_break_12",
"fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
+ "fieldname": "enable_discount_accounting",
+ "fieldtype": "Check",
+ "label": "Enable Discount Accounting for Buying"
}
],
"icon": "fa fa-cog",
@@ -140,7 +148,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2022-01-27 17:57:58.367048",
+ "modified": "2022-04-14 15:56:42.340223",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py
index 5507254..c52b59e 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.py
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.py
@@ -5,10 +5,15 @@
import frappe
+from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.model.document import Document
+from frappe.utils import cint
class BuyingSettings(Document):
+ def on_update(self):
+ self.toggle_discount_accounting_fields()
+
def validate(self):
for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
frappe.db.set_default(key, self.get(key, ""))
@@ -21,3 +26,60 @@
self.get("supp_master_name") == "Naming Series",
hide_name_field=False,
)
+
+ def toggle_discount_accounting_fields(self):
+ enable_discount_accounting = cint(self.enable_discount_accounting)
+
+ make_property_setter(
+ "Purchase Invoice Item",
+ "discount_account",
+ "hidden",
+ not (enable_discount_accounting),
+ "Check",
+ validate_fields_for_doctype=False,
+ )
+ if enable_discount_accounting:
+ make_property_setter(
+ "Purchase Invoice Item",
+ "discount_account",
+ "mandatory_depends_on",
+ "eval: doc.discount_amount",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+ else:
+ make_property_setter(
+ "Purchase Invoice Item",
+ "discount_account",
+ "mandatory_depends_on",
+ "",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+
+ make_property_setter(
+ "Purchase Invoice",
+ "additional_discount_account",
+ "hidden",
+ not (enable_discount_accounting),
+ "Check",
+ validate_fields_for_doctype=False,
+ )
+ if enable_discount_accounting:
+ make_property_setter(
+ "Purchase Invoice",
+ "additional_discount_account",
+ "mandatory_depends_on",
+ "eval: doc.discount_amount",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+ else:
+ make_property_setter(
+ "Purchase Invoice",
+ "additional_discount_account",
+ "mandatory_depends_on",
+ "",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index f20df09..78645e0 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1079,9 +1079,14 @@
return amount, base_amount
def make_discount_gl_entries(self, gl_entries):
- enable_discount_accounting = cint(
- frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
- )
+ if self.doctype == "Purchase Invoice":
+ enable_discount_accounting = cint(
+ frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
+ )
+ elif self.doctype == "Sales Invoice":
+ enable_discount_accounting = cint(
+ frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
+ )
if enable_discount_accounting:
if self.doctype == "Purchase Invoice":
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d163ca5..d6c44cb 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -365,4 +365,5 @@
erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances
erpnext.patches.v13_0.create_gst_custom_fields_in_quotation
erpnext.patches.v13_0.copy_custom_field_filters_to_website_item
+erpnext.patches.v14_0.discount_accounting_separation
erpnext.patches.v14_0.delete_employee_transfer_property_doctype
diff --git a/erpnext/patches/v14_0/discount_accounting_separation.py b/erpnext/patches/v14_0/discount_accounting_separation.py
new file mode 100644
index 0000000..fd49805
--- /dev/null
+++ b/erpnext/patches/v14_0/discount_accounting_separation.py
@@ -0,0 +1,9 @@
+import frappe
+
+
+def execute():
+ doc = frappe.get_doc("Accounts Settings")
+ discount_account = doc.enable_discount_accounting
+ if discount_account:
+ for doctype in ["Buying Settings", "Selling Settings"]:
+ frappe.db.set_value(doctype, doctype, "enable_discount_accounting", 1, update_modified=False)
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index a3abe86..0f73c5f 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -553,6 +553,7 @@
+ flt(value_details["CgstVal"])
+ flt(value_details["SgstVal"])
+ flt(value_details["IgstVal"])
+ + flt(value_details["CesVal"])
+ flt(value_details["OthChrg"])
+ flt(value_details["RndOffAmt"])
- flt(value_details["Discount"])
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 7c4a3f6..005e24c 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -27,7 +27,8 @@
"column_break_5",
"allow_multiple_items",
"allow_against_multiple_purchase_orders",
- "hide_tax_id"
+ "hide_tax_id",
+ "enable_discount_accounting"
],
"fields": [
{
@@ -164,6 +165,13 @@
"fieldname": "editable_bundle_item_rates",
"fieldtype": "Check",
"label": "Calculate Product Bundle Price based on Child Items' Rates"
+ },
+ {
+ "default": "0",
+ "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account",
+ "fieldname": "enable_discount_accounting",
+ "fieldtype": "Check",
+ "label": "Enable Discount Accounting for Selling"
}
],
"icon": "fa fa-cog",
@@ -171,7 +179,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2022-02-04 15:41:59.939261",
+ "modified": "2022-04-14 16:01:29.405642",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py
index 29e4712..6c09894 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.py
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.py
@@ -14,6 +14,7 @@
def on_update(self):
self.toggle_hide_tax_id()
self.toggle_editable_rate_for_bundle_items()
+ self.toggle_discount_accounting_fields()
def validate(self):
for key in [
@@ -58,3 +59,60 @@
"Check",
validate_fields_for_doctype=False,
)
+
+ def toggle_discount_accounting_fields(self):
+ enable_discount_accounting = cint(self.enable_discount_accounting)
+
+ make_property_setter(
+ "Sales Invoice Item",
+ "discount_account",
+ "hidden",
+ not (enable_discount_accounting),
+ "Check",
+ validate_fields_for_doctype=False,
+ )
+ if enable_discount_accounting:
+ make_property_setter(
+ "Sales Invoice Item",
+ "discount_account",
+ "mandatory_depends_on",
+ "eval: doc.discount_amount",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+ else:
+ make_property_setter(
+ "Sales Invoice Item",
+ "discount_account",
+ "mandatory_depends_on",
+ "",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+
+ make_property_setter(
+ "Sales Invoice",
+ "additional_discount_account",
+ "hidden",
+ not (enable_discount_accounting),
+ "Check",
+ validate_fields_for_doctype=False,
+ )
+ if enable_discount_accounting:
+ make_property_setter(
+ "Sales Invoice",
+ "additional_discount_account",
+ "mandatory_depends_on",
+ "eval: doc.discount_amount",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
+ else:
+ make_property_setter(
+ "Sales Invoice",
+ "additional_discount_account",
+ "mandatory_depends_on",
+ "",
+ "Code",
+ validate_fields_for_doctype=False,
+ )
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index b4fac82..5850ec7 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -2,12 +2,12 @@
# See license.txt
import json
-from datetime import timedelta
from uuid import uuid4
import frappe
from frappe.core.page.permission_manager.permission_manager import reset
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
+from frappe.query_builder.functions import CombineDatetime
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, today
from frappe.utils.data import add_to_date
@@ -1126,6 +1126,63 @@
# original amount
self.assertEqual(50, _get_stock_credit(final_consumption))
+ def test_tie_breaking(self):
+ frappe.flags.dont_execute_stock_reposts = True
+ self.addCleanup(frappe.flags.pop, "dont_execute_stock_reposts")
+
+ item = make_item().name
+ warehouse = "_Test Warehouse - _TC"
+
+ posting_date = "2022-01-01"
+ posting_time = "00:00:01"
+ sle = frappe.qb.DocType("Stock Ledger Entry")
+
+ def ordered_qty_after_transaction():
+ return (
+ frappe.qb.from_(sle)
+ .select("qty_after_transaction")
+ .where((sle.item_code == item) & (sle.warehouse == warehouse) & (sle.is_cancelled == 0))
+ .orderby(CombineDatetime(sle.posting_date, sle.posting_time))
+ .orderby(sle.creation)
+ ).run(pluck=True)
+
+ first = make_stock_entry(
+ item_code=item,
+ to_warehouse=warehouse,
+ qty=10,
+ posting_time=posting_time,
+ posting_date=posting_date,
+ do_not_submit=True,
+ )
+ second = make_stock_entry(
+ item_code=item,
+ to_warehouse=warehouse,
+ qty=1,
+ posting_date=posting_date,
+ posting_time=posting_time,
+ do_not_submit=True,
+ )
+
+ first.submit()
+ second.submit()
+
+ self.assertEqual([10, 11], ordered_qty_after_transaction())
+
+ first.cancel()
+ self.assertEqual([1], ordered_qty_after_transaction())
+
+ backdated = make_stock_entry(
+ item_code=item,
+ to_warehouse=warehouse,
+ qty=1,
+ posting_date="2021-01-01",
+ posting_time=posting_time,
+ )
+ self.assertEqual([1, 2], ordered_qty_after_transaction())
+
+ backdated.cancel()
+ self.assertEqual([1], ordered_qty_after_transaction())
+
def create_repack_entry(**args):
args = frappe._dict(args)