mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 23:19:20 +00:00
Merge pull request #43255 from frappe/version-14-hotfix
chore: release v14
This commit is contained in:
@@ -22,8 +22,10 @@ class TestCostCenterAllocation(unittest.TestCase):
|
|||||||
cost_centers = [
|
cost_centers = [
|
||||||
"Main Cost Center 1",
|
"Main Cost Center 1",
|
||||||
"Main Cost Center 2",
|
"Main Cost Center 2",
|
||||||
|
"Main Cost Center 3",
|
||||||
"Sub Cost Center 1",
|
"Sub Cost Center 1",
|
||||||
"Sub Cost Center 2",
|
"Sub Cost Center 2",
|
||||||
|
"Sub Cost Center 3",
|
||||||
]
|
]
|
||||||
for cc in cost_centers:
|
for cc in cost_centers:
|
||||||
create_cost_center(cost_center_name=cc, company="_Test Company")
|
create_cost_center(cost_center_name=cc, company="_Test Company")
|
||||||
@@ -36,7 +38,7 @@ class TestCostCenterAllocation(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Cash - _TC", "Sales - _TC", 100, cost_center="Main Cost Center 1 - _TC", submit=True
|
"Cash - _TC", "Sales - _TC", 100, cost_center="Main Cost Center 1 - _TC", submit=True
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_values = [["Sub Cost Center 1 - _TC", 0.0, 60], ["Sub Cost Center 2 - _TC", 0.0, 40]]
|
expected_values = [["Sub Cost Center 1 - _TC", 0.0, 60], ["Sub Cost Center 2 - _TC", 0.0, 40]]
|
||||||
@@ -120,7 +122,7 @@ class TestCostCenterAllocation(unittest.TestCase):
|
|||||||
def test_valid_from_based_on_existing_gle(self):
|
def test_valid_from_based_on_existing_gle(self):
|
||||||
# GLE posted against Sub Cost Center 1 on today
|
# GLE posted against Sub Cost Center 1 on today
|
||||||
jv = make_journal_entry(
|
jv = make_journal_entry(
|
||||||
"_Test Cash - _TC",
|
"Cash - _TC",
|
||||||
"Sales - _TC",
|
"Sales - _TC",
|
||||||
100,
|
100,
|
||||||
cost_center="Main Cost Center 1 - _TC",
|
cost_center="Main Cost Center 1 - _TC",
|
||||||
@@ -141,6 +143,53 @@ class TestCostCenterAllocation(unittest.TestCase):
|
|||||||
|
|
||||||
jv.cancel()
|
jv.cancel()
|
||||||
|
|
||||||
|
def test_multiple_cost_center_allocation_on_same_main_cost_center(self):
|
||||||
|
coa1 = create_cost_center_allocation(
|
||||||
|
"_Test Company",
|
||||||
|
"Main Cost Center 3 - _TC",
|
||||||
|
{"Sub Cost Center 1 - _TC": 30, "Sub Cost Center 2 - _TC": 30, "Sub Cost Center 3 - _TC": 40},
|
||||||
|
valid_from=add_days(today(), -5),
|
||||||
|
)
|
||||||
|
|
||||||
|
coa2 = create_cost_center_allocation(
|
||||||
|
"_Test Company",
|
||||||
|
"Main Cost Center 3 - _TC",
|
||||||
|
{"Sub Cost Center 1 - _TC": 50, "Sub Cost Center 2 - _TC": 50},
|
||||||
|
valid_from=add_days(today(), -1),
|
||||||
|
)
|
||||||
|
|
||||||
|
jv = make_journal_entry(
|
||||||
|
"Cash - _TC",
|
||||||
|
"Sales - _TC",
|
||||||
|
100,
|
||||||
|
cost_center="Main Cost Center 3 - _TC",
|
||||||
|
posting_date=today(),
|
||||||
|
submit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
expected_values = {"Sub Cost Center 1 - _TC": 50, "Sub Cost Center 2 - _TC": 50}
|
||||||
|
|
||||||
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
|
gl_entries = (
|
||||||
|
frappe.qb.from_(gle)
|
||||||
|
.select(gle.cost_center, gle.debit, gle.credit)
|
||||||
|
.where(gle.voucher_type == "Journal Entry")
|
||||||
|
.where(gle.voucher_no == jv.name)
|
||||||
|
.where(gle.account == "Sales - _TC")
|
||||||
|
.orderby(gle.cost_center)
|
||||||
|
).run(as_dict=1)
|
||||||
|
|
||||||
|
self.assertTrue(gl_entries)
|
||||||
|
|
||||||
|
for gle in gl_entries:
|
||||||
|
self.assertTrue(gle.cost_center in expected_values)
|
||||||
|
self.assertEqual(gle.debit, 0)
|
||||||
|
self.assertEqual(gle.credit, expected_values[gle.cost_center])
|
||||||
|
|
||||||
|
coa1.cancel()
|
||||||
|
coa2.cancel()
|
||||||
|
jv.cancel()
|
||||||
|
|
||||||
|
|
||||||
def create_cost_center_allocation(
|
def create_cost_center_allocation(
|
||||||
company,
|
company,
|
||||||
|
|||||||
@@ -1365,6 +1365,79 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
expected_out_str = json.dumps(sorted(expected_pl_entries, key=json.dumps))
|
expected_out_str = json.dumps(sorted(expected_pl_entries, key=json.dumps))
|
||||||
self.assertEqual(out_str, expected_out_str)
|
self.assertEqual(out_str, expected_out_str)
|
||||||
|
|
||||||
|
@change_settings("Accounts Settings", {"delete_linked_ledger_entries": 1})
|
||||||
|
def test_delete_linked_exchange_gain_loss_journal(self):
|
||||||
|
from erpnext.accounts.doctype.account.test_account import create_account
|
||||||
|
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import (
|
||||||
|
make_customer,
|
||||||
|
)
|
||||||
|
|
||||||
|
debtors = create_account(
|
||||||
|
account_name="Debtors USD",
|
||||||
|
parent_account="Accounts Receivable - _TC",
|
||||||
|
company="_Test Company",
|
||||||
|
account_currency="USD",
|
||||||
|
account_type="Receivable",
|
||||||
|
)
|
||||||
|
|
||||||
|
# create a customer
|
||||||
|
customer = make_customer(customer="_Test Party USD")
|
||||||
|
cust_doc = frappe.get_doc("Customer", customer)
|
||||||
|
cust_doc.default_currency = "USD"
|
||||||
|
test_account_details = {
|
||||||
|
"company": "_Test Company",
|
||||||
|
"account": debtors,
|
||||||
|
}
|
||||||
|
cust_doc.append("accounts", test_account_details)
|
||||||
|
cust_doc.save()
|
||||||
|
|
||||||
|
# create a sales invoice
|
||||||
|
si = create_sales_invoice(
|
||||||
|
customer=customer,
|
||||||
|
currency="USD",
|
||||||
|
conversion_rate=83.970000000,
|
||||||
|
debit_to=debtors,
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
si.party_account_currency = "USD"
|
||||||
|
si.save()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
# create a payment entry for the invoice
|
||||||
|
pe = get_payment_entry("Sales Invoice", si.name)
|
||||||
|
pe.reference_no = "1"
|
||||||
|
pe.reference_date = frappe.utils.nowdate()
|
||||||
|
pe.paid_amount = 100
|
||||||
|
pe.source_exchange_rate = 90
|
||||||
|
pe.append(
|
||||||
|
"deductions",
|
||||||
|
{
|
||||||
|
"account": "_Test Exchange Gain/Loss - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"amount": 2710,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
pe.save()
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
# check creation of journal entry
|
||||||
|
jv = frappe.get_all(
|
||||||
|
"Journal Entry Account",
|
||||||
|
{"reference_type": pe.doctype, "reference_name": pe.name, "docstatus": 1},
|
||||||
|
pluck="parent",
|
||||||
|
)
|
||||||
|
self.assertTrue(jv)
|
||||||
|
|
||||||
|
# check cancellation of payment entry and journal entry
|
||||||
|
pe.cancel()
|
||||||
|
self.assertTrue(pe.docstatus == 2)
|
||||||
|
self.assertTrue(frappe.db.get_value("Journal Entry", {"name": jv[0]}, "docstatus") == 2)
|
||||||
|
|
||||||
|
# check deletion of payment entry and journal entry
|
||||||
|
pe.delete()
|
||||||
|
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, pe.doctype, pe.name)
|
||||||
|
self.assertRaises(frappe.DoesNotExistError, frappe.get_doc, "Journal Entry", jv[0])
|
||||||
|
|
||||||
|
|
||||||
def create_payment_entry(**args):
|
def create_payment_entry(**args):
|
||||||
payment_entry = frappe.new_doc("Payment Entry")
|
payment_entry = frappe.new_doc("Payment Entry")
|
||||||
|
|||||||
@@ -419,7 +419,8 @@
|
|||||||
"depends_on": "eval:doc.rate_or_discount==\"Rate\"",
|
"depends_on": "eval:doc.rate_or_discount==\"Rate\"",
|
||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Rate"
|
"label": "Rate",
|
||||||
|
"options": "currency"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@@ -647,7 +648,7 @@
|
|||||||
"icon": "fa fa-gift",
|
"icon": "fa fa-gift",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-05-17 13:16:34.496704",
|
"modified": "2024-09-16 18:14:51.314765",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Pricing Rule",
|
"name": "Pricing Rule",
|
||||||
@@ -709,4 +710,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"states": [],
|
||||||
"title_field": "title"
|
"title_field": "title"
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase, change_settings
|
||||||
|
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
@@ -14,7 +15,7 @@ from erpnext.stock.doctype.item.test_item import make_item
|
|||||||
from erpnext.stock.get_item_details import get_item_details
|
from erpnext.stock.get_item_details import get_item_details
|
||||||
|
|
||||||
|
|
||||||
class TestPricingRule(unittest.TestCase):
|
class TestPricingRule(FrappeTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
delete_existing_pricing_rules()
|
delete_existing_pricing_rules()
|
||||||
setup_pricing_rule_data()
|
setup_pricing_rule_data()
|
||||||
|
|||||||
@@ -1265,6 +1265,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
|
"no_copy": 1,
|
||||||
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nPartly Paid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
|
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nPartly Paid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
@@ -1610,7 +1611,7 @@
|
|||||||
"idx": 204,
|
"idx": 204,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-07-25 19:42:36.931278",
|
"modified": "2024-09-11 12:59:19.130593",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice",
|
"name": "Purchase Invoice",
|
||||||
|
|||||||
@@ -179,50 +179,53 @@ def process_gl_map(gl_map, merge_entries=True, precision=None):
|
|||||||
|
|
||||||
|
|
||||||
def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None):
|
def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None):
|
||||||
cost_center_allocation = get_cost_center_allocation_data(gl_map[0]["company"], gl_map[0]["posting_date"])
|
|
||||||
if not cost_center_allocation:
|
|
||||||
return gl_map
|
|
||||||
|
|
||||||
new_gl_map = []
|
new_gl_map = []
|
||||||
for d in gl_map:
|
for d in gl_map:
|
||||||
cost_center = d.get("cost_center")
|
cost_center = d.get("cost_center")
|
||||||
|
|
||||||
# Validate budget against main cost center
|
# Validate budget against main cost center
|
||||||
validate_expense_against_budget(d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision))
|
validate_expense_against_budget(d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision))
|
||||||
|
cost_center_allocation = get_cost_center_allocation_data(
|
||||||
if cost_center and cost_center_allocation.get(cost_center):
|
gl_map[0]["company"], gl_map[0]["posting_date"], cost_center
|
||||||
for sub_cost_center, percentage in cost_center_allocation.get(cost_center, {}).items():
|
)
|
||||||
gle = copy.deepcopy(d)
|
if not cost_center_allocation:
|
||||||
gle.cost_center = sub_cost_center
|
|
||||||
for field in ("debit", "credit", "debit_in_account_currency", "credit_in_account_currency"):
|
|
||||||
gle[field] = flt(flt(d.get(field)) * percentage / 100, precision)
|
|
||||||
new_gl_map.append(gle)
|
|
||||||
else:
|
|
||||||
new_gl_map.append(d)
|
new_gl_map.append(d)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for sub_cost_center, percentage in cost_center_allocation:
|
||||||
|
gle = copy.deepcopy(d)
|
||||||
|
gle.cost_center = sub_cost_center
|
||||||
|
for field in ("debit", "credit", "debit_in_account_currency", "credit_in_account_currency"):
|
||||||
|
gle[field] = flt(flt(d.get(field)) * percentage / 100, precision)
|
||||||
|
new_gl_map.append(gle)
|
||||||
|
|
||||||
return new_gl_map
|
return new_gl_map
|
||||||
|
|
||||||
|
|
||||||
def get_cost_center_allocation_data(company, posting_date):
|
def get_cost_center_allocation_data(company, posting_date, cost_center):
|
||||||
par = frappe.qb.DocType("Cost Center Allocation")
|
cost_center_allocation = frappe.db.get_value(
|
||||||
child = frappe.qb.DocType("Cost Center Allocation Percentage")
|
"Cost Center Allocation",
|
||||||
|
{
|
||||||
|
"docstatus": 1,
|
||||||
|
"company": company,
|
||||||
|
"valid_from": ("<=", posting_date),
|
||||||
|
"main_cost_center": cost_center,
|
||||||
|
},
|
||||||
|
pluck="name",
|
||||||
|
order_by="valid_from desc",
|
||||||
|
)
|
||||||
|
|
||||||
records = (
|
if not cost_center_allocation:
|
||||||
frappe.qb.from_(par)
|
return []
|
||||||
.inner_join(child)
|
|
||||||
.on(par.name == child.parent)
|
|
||||||
.select(par.main_cost_center, child.cost_center, child.percentage)
|
|
||||||
.where(par.docstatus == 1)
|
|
||||||
.where(par.company == company)
|
|
||||||
.where(par.valid_from <= posting_date)
|
|
||||||
.orderby(par.valid_from, order=frappe.qb.desc)
|
|
||||||
).run(as_dict=True)
|
|
||||||
|
|
||||||
cc_allocation = frappe._dict()
|
records = frappe.db.get_all(
|
||||||
for d in records:
|
"Cost Center Allocation Percentage",
|
||||||
cc_allocation.setdefault(d.main_cost_center, frappe._dict()).setdefault(d.cost_center, d.percentage)
|
{"parent": cost_center_allocation},
|
||||||
|
["cost_center", "percentage"],
|
||||||
|
as_list=True,
|
||||||
|
)
|
||||||
|
|
||||||
return cc_allocation
|
return records
|
||||||
|
|
||||||
|
|
||||||
def merge_similar_entries(gl_map, precision=None):
|
def merge_similar_entries(gl_map, precision=None):
|
||||||
|
|||||||
@@ -703,40 +703,74 @@ def cancel_exchange_gain_loss_journal(
|
|||||||
Cancel Exchange Gain/Loss for Sales/Purchase Invoice, if they have any.
|
Cancel Exchange Gain/Loss for Sales/Purchase Invoice, if they have any.
|
||||||
"""
|
"""
|
||||||
if parent_doc.doctype in ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]:
|
if parent_doc.doctype in ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]:
|
||||||
journals = frappe.db.get_all(
|
gain_loss_journals = get_linked_exchange_gain_loss_journal(
|
||||||
"Journal Entry Account",
|
referenced_dt=parent_doc.doctype, referenced_dn=parent_doc.name, je_docstatus=1
|
||||||
filters={
|
|
||||||
"reference_type": parent_doc.doctype,
|
|
||||||
"reference_name": parent_doc.name,
|
|
||||||
"docstatus": 1,
|
|
||||||
},
|
|
||||||
fields=["parent"],
|
|
||||||
as_list=1,
|
|
||||||
)
|
)
|
||||||
|
for doc in gain_loss_journals:
|
||||||
if journals:
|
gain_loss_je = frappe.get_doc("Journal Entry", doc)
|
||||||
gain_loss_journals = frappe.db.get_all(
|
if referenced_dt and referenced_dn:
|
||||||
"Journal Entry",
|
references = [(x.reference_type, x.reference_name) for x in gain_loss_je.accounts]
|
||||||
filters={
|
if (
|
||||||
"name": ["in", [x[0] for x in journals]],
|
len(references) == 2
|
||||||
"voucher_type": "Exchange Gain Or Loss",
|
and (referenced_dt, referenced_dn) in references
|
||||||
"docstatus": 1,
|
and (parent_doc.doctype, parent_doc.name) in references
|
||||||
},
|
):
|
||||||
as_list=1,
|
# only cancel JE generated against parent_doc and referenced_dn
|
||||||
)
|
|
||||||
for doc in gain_loss_journals:
|
|
||||||
gain_loss_je = frappe.get_doc("Journal Entry", doc[0])
|
|
||||||
if referenced_dt and referenced_dn:
|
|
||||||
references = [(x.reference_type, x.reference_name) for x in gain_loss_je.accounts]
|
|
||||||
if (
|
|
||||||
len(references) == 2
|
|
||||||
and (referenced_dt, referenced_dn) in references
|
|
||||||
and (parent_doc.doctype, parent_doc.name) in references
|
|
||||||
):
|
|
||||||
# only cancel JE generated against parent_doc and referenced_dn
|
|
||||||
gain_loss_je.cancel()
|
|
||||||
else:
|
|
||||||
gain_loss_je.cancel()
|
gain_loss_je.cancel()
|
||||||
|
else:
|
||||||
|
gain_loss_je.cancel()
|
||||||
|
|
||||||
|
|
||||||
|
def delete_exchange_gain_loss_journal(
|
||||||
|
parent_doc: dict | object, referenced_dt: str | None = None, referenced_dn: str | None = None
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Delete Exchange Gain/Loss for Sales/Purchase Invoice, if they have any.
|
||||||
|
"""
|
||||||
|
if parent_doc.doctype in ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]:
|
||||||
|
gain_loss_journals = get_linked_exchange_gain_loss_journal(
|
||||||
|
referenced_dt=parent_doc.doctype, referenced_dn=parent_doc.name, je_docstatus=2
|
||||||
|
)
|
||||||
|
for doc in gain_loss_journals:
|
||||||
|
gain_loss_je = frappe.get_doc("Journal Entry", doc)
|
||||||
|
if referenced_dt and referenced_dn:
|
||||||
|
references = [(x.reference_type, x.reference_name) for x in gain_loss_je.accounts]
|
||||||
|
if (
|
||||||
|
len(references) == 2
|
||||||
|
and (referenced_dt, referenced_dn) in references
|
||||||
|
and (parent_doc.doctype, parent_doc.name) in references
|
||||||
|
):
|
||||||
|
# only delete JE generated against parent_doc and referenced_dn
|
||||||
|
gain_loss_je.delete()
|
||||||
|
else:
|
||||||
|
gain_loss_je.delete()
|
||||||
|
|
||||||
|
|
||||||
|
def get_linked_exchange_gain_loss_journal(referenced_dt: str, referenced_dn: str, je_docstatus: int) -> list:
|
||||||
|
"""
|
||||||
|
Get all the linked exchange gain/loss journal entries for a given document.
|
||||||
|
"""
|
||||||
|
gain_loss_journals = []
|
||||||
|
if journals := frappe.db.get_all(
|
||||||
|
"Journal Entry Account",
|
||||||
|
{
|
||||||
|
"reference_type": referenced_dt,
|
||||||
|
"reference_name": referenced_dn,
|
||||||
|
"docstatus": je_docstatus,
|
||||||
|
},
|
||||||
|
pluck="parent",
|
||||||
|
):
|
||||||
|
gain_loss_journals = frappe.db.get_all(
|
||||||
|
"Journal Entry",
|
||||||
|
{
|
||||||
|
"name": ["in", journals],
|
||||||
|
"voucher_type": "Exchange Gain Or Loss",
|
||||||
|
"is_system_generated": 1,
|
||||||
|
"docstatus": je_docstatus,
|
||||||
|
},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
return gain_loss_journals
|
||||||
|
|
||||||
|
|
||||||
def cancel_common_party_journal(self):
|
def cancel_common_party_journal(self):
|
||||||
|
|||||||
@@ -326,11 +326,16 @@ class AccountsController(TransactionBase):
|
|||||||
repost_doc.save(ignore_permissions=True)
|
repost_doc.save(ignore_permissions=True)
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
|
from erpnext.accounts.utils import delete_exchange_gain_loss_journal
|
||||||
|
|
||||||
self._remove_references_in_repost_doctypes()
|
self._remove_references_in_repost_doctypes()
|
||||||
self._remove_references_in_unreconcile()
|
self._remove_references_in_unreconcile()
|
||||||
|
|
||||||
# delete sl and gl entries on deletion of transaction
|
# delete sl and gl entries on deletion of transaction
|
||||||
if frappe.db.get_single_value("Accounts Settings", "delete_linked_ledger_entries"):
|
if frappe.db.get_single_value("Accounts Settings", "delete_linked_ledger_entries"):
|
||||||
|
# delete linked exchange gain/loss journal
|
||||||
|
delete_exchange_gain_loss_journal(self)
|
||||||
|
|
||||||
ple = frappe.qb.DocType("Payment Ledger Entry")
|
ple = frappe.qb.DocType("Payment Ledger Entry")
|
||||||
frappe.qb.from_(ple).delete().where(
|
frappe.qb.from_(ple).delete().where(
|
||||||
(ple.voucher_type == self.doctype) & (ple.voucher_no == self.name)
|
(ple.voucher_type == self.doctype) & (ple.voucher_no == self.name)
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ class SellingController(StockController):
|
|||||||
if self.doctype in ["Sales Order", "Quotation"]:
|
if self.doctype in ["Sales Order", "Quotation"]:
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
item.gross_profit = flt(
|
item.gross_profit = flt(
|
||||||
((item.base_rate - flt(item.valuation_rate)) * item.stock_qty),
|
((flt(item.stock_uom_rate) - flt(item.valuation_rate)) * item.stock_qty),
|
||||||
self.precision("amount", item),
|
self.precision("amount", item),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -385,28 +385,14 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
placeholder: discount ? discount + "%" : __("Enter discount percentage."),
|
placeholder: discount ? discount + "%" : __("Enter discount percentage."),
|
||||||
input_class: "input-xs",
|
input_class: "input-xs",
|
||||||
onchange: function () {
|
onchange: function () {
|
||||||
if (flt(this.value) != 0) {
|
this.value = flt(this.value);
|
||||||
frappe.model.set_value(
|
frappe.model.set_value(
|
||||||
frm.doc.doctype,
|
frm.doc.doctype,
|
||||||
frm.doc.name,
|
frm.doc.name,
|
||||||
"additional_discount_percentage",
|
"additional_discount_percentage",
|
||||||
flt(this.value)
|
flt(this.value)
|
||||||
);
|
);
|
||||||
me.hide_discount_control(this.value);
|
me.hide_discount_control(this.value);
|
||||||
} else {
|
|
||||||
frappe.model.set_value(
|
|
||||||
frm.doc.doctype,
|
|
||||||
frm.doc.name,
|
|
||||||
"additional_discount_percentage",
|
|
||||||
0
|
|
||||||
);
|
|
||||||
me.$add_discount_elem.css({
|
|
||||||
border: "1px dashed var(--gray-500)",
|
|
||||||
padding: "var(--padding-sm) var(--padding-md)",
|
|
||||||
});
|
|
||||||
me.$add_discount_elem.html(`${me.get_discount_icon()} ${__("Add Discount")}`);
|
|
||||||
me.discount_field = undefined;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
parent: this.$add_discount_elem.find(".add-discount-field"),
|
parent: this.$add_discount_elem.find(".add-discount-field"),
|
||||||
@@ -417,9 +403,13 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hide_discount_control(discount) {
|
hide_discount_control(discount) {
|
||||||
if (!discount) {
|
if (!flt(discount)) {
|
||||||
this.$add_discount_elem.css({ padding: "0px", border: "none" });
|
this.$add_discount_elem.css({
|
||||||
this.$add_discount_elem.html(`<div class="add-discount-field"></div>`);
|
border: "1px dashed var(--gray-500)",
|
||||||
|
padding: "var(--padding-sm) var(--padding-md)",
|
||||||
|
});
|
||||||
|
this.$add_discount_elem.html(`${this.get_discount_icon()} ${__("Add Discount")}`);
|
||||||
|
this.discount_field = undefined;
|
||||||
} else {
|
} else {
|
||||||
this.$add_discount_elem.css({
|
this.$add_discount_elem.css({
|
||||||
border: "1px dashed var(--dark-green-500)",
|
border: "1px dashed var(--dark-green-500)",
|
||||||
@@ -1044,6 +1034,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
this.highlight_checkout_btn(false);
|
this.highlight_checkout_btn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.hide_discount_control(frm.doc.additional_discount_percentage);
|
||||||
this.update_totals_section(frm);
|
this.update_totals_section(frm);
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user