Merge branch 'develop' of https://github.com/frappe/erpnext into finance-book-filter

This commit is contained in:
Khushi Rawat
2024-09-13 13:26:45 +05:30
10 changed files with 519 additions and 361 deletions

View File

@@ -1791,6 +1791,79 @@ class TestPaymentEntry(FrappeTestCase):
# 'Is Opening' should always be 'No' for normal advance payments # 'Is Opening' should always be 'No' for normal advance payments
self.assertEqual(gl_with_opening_set, []) self.assertEqual(gl_with_opening_set, [])
@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")

View File

@@ -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()

View File

@@ -769,40 +769,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):

View File

@@ -346,12 +346,17 @@ 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()
self.remove_serial_and_batch_bundle() self.remove_serial_and_batch_bundle()
# 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)

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n" "Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: info@erpnext.com\n" "Report-Msgid-Bugs-To: info@erpnext.com\n"
"POT-Creation-Date: 2024-09-01 09:35+0000\n" "POT-Creation-Date: 2024-09-01 09:35+0000\n"
"PO-Revision-Date: 2024-09-07 18:35\n" "PO-Revision-Date: 2024-09-10 18:59\n"
"Last-Translator: info@erpnext.com\n" "Last-Translator: info@erpnext.com\n"
"Language-Team: Persian\n" "Language-Team: Persian\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -715,7 +715,7 @@ msgstr ""
#. Header text in the Stock Workspace #. Header text in the Stock Workspace
#: selling/workspace/selling/selling.json stock/workspace/stock/stock.json #: selling/workspace/selling/selling.json stock/workspace/stock/stock.json
msgid "<span class=\"h4\"><b>Quick Access</b></span>" msgid "<span class=\"h4\"><b>Quick Access</b></span>"
msgstr "" msgstr "<span class=\"h4\"><b>دسترسی سریع</b></span>"
#. Header text in the Assets Workspace #. Header text in the Assets Workspace
#. Header text in the Quality Workspace #. Header text in the Quality Workspace
@@ -748,7 +748,7 @@ msgstr ""
#. Header text in the Settings Workspace #. Header text in the Settings Workspace
#: setup/workspace/settings/settings.json #: setup/workspace/settings/settings.json
msgid "<span class=\"h4\"><b>Settings</b></span>" msgid "<span class=\"h4\"><b>Settings</b></span>"
msgstr "" msgstr "<span class=\"h4\"><b>تنظیمات</b></span>"
#. Header text in the Accounting Workspace #. Header text in the Accounting Workspace
#. Header text in the Payables Workspace #. Header text in the Payables Workspace
@@ -757,7 +757,7 @@ msgstr ""
#: accounts/workspace/payables/payables.json #: accounts/workspace/payables/payables.json
#: accounts/workspace/receivables/receivables.json #: accounts/workspace/receivables/receivables.json
msgid "<span class=\"h4\"><b>Shortcuts</b></span>" msgid "<span class=\"h4\"><b>Shortcuts</b></span>"
msgstr "" msgstr "<span class=\"h4\"><b>میانبرها</b></span>"
#. Header text in the Settings Workspace #. Header text in the Settings Workspace
#: setup/workspace/settings/settings.json #: setup/workspace/settings/settings.json
@@ -785,7 +785,7 @@ msgstr ""
#: quality_management/workspace/quality/quality.json #: quality_management/workspace/quality/quality.json
#: setup/workspace/home/home.json support/workspace/support/support.json #: setup/workspace/home/home.json support/workspace/support/support.json
msgid "<span class=\"h4\"><b>Your Shortcuts</b></span>" msgid "<span class=\"h4\"><b>Your Shortcuts</b></span>"
msgstr "" msgstr "<span class=\"h4\"><b>میانبرهای شما</b></span>"
#. Content of the 'html_19' (HTML) field in DocType 'Inventory Dimension' #. Content of the 'html_19' (HTML) field in DocType 'Inventory Dimension'
#: stock/doctype/inventory_dimension/inventory_dimension.json #: stock/doctype/inventory_dimension/inventory_dimension.json
@@ -1020,7 +1020,7 @@ msgstr "در بالا"
#: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html:99 #: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html:99
#: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:351 #: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:351
msgid "Above 120 Days" msgid "Above 120 Days"
msgstr "" msgstr "بالای 120 روز"
#. Name of a role #. Name of a role
#: setup/doctype/department/department.json #: setup/doctype/department/department.json
@@ -3632,7 +3632,7 @@ msgstr "گروهی از آیتم‌ها را در یک آیتم دیگر جمع
#: setup/setup_wizard/data/industry_type.txt:4 #: setup/setup_wizard/data/industry_type.txt:4
msgid "Agriculture" msgid "Agriculture"
msgstr "" msgstr "کشاورزی"
#. Name of a role #. Name of a role
#: assets/doctype/location/location.json #: assets/doctype/location/location.json
@@ -3646,7 +3646,7 @@ msgstr "کاربر کشاورزی"
#: setup/setup_wizard/data/industry_type.txt:5 #: setup/setup_wizard/data/industry_type.txt:5
msgid "Airline" msgid "Airline"
msgstr "" msgstr "شرکت هواپیمایی"
#. Label of the algorithm (Select) field in DocType 'Bisect Accounting #. Label of the algorithm (Select) field in DocType 'Bisect Accounting
#. Statements' #. Statements'
@@ -4914,7 +4914,7 @@ msgstr "قابل اجرا در حساب"
#. Label of the to_designation (Link) field in DocType 'Authorization Rule' #. Label of the to_designation (Link) field in DocType 'Authorization Rule'
#: setup/doctype/authorization_rule/authorization_rule.json #: setup/doctype/authorization_rule/authorization_rule.json
msgid "Applicable To (Designation)" msgid "Applicable To (Designation)"
msgstr "قابل اجرا برای (تعیین)" msgstr "قابل اجرا برای (نقش سازمانی)"
#. Label of the to_emp (Link) field in DocType 'Authorization Rule' #. Label of the to_emp (Link) field in DocType 'Authorization Rule'
#: setup/doctype/authorization_rule/authorization_rule.json #: setup/doctype/authorization_rule/authorization_rule.json
@@ -5158,7 +5158,7 @@ msgstr "درخواست برای سند"
#. Label of a Link in the CRM Workspace #. Label of a Link in the CRM Workspace
#: crm/doctype/appointment/appointment.json crm/workspace/crm/crm.json #: crm/doctype/appointment/appointment.json crm/workspace/crm/crm.json
msgid "Appointment" msgid "Appointment"
msgstr "وقت ملاقات" msgstr "قرار ملاقات"
#. Name of a DocType #. Name of a DocType
#: crm/doctype/appointment_booking_settings/appointment_booking_settings.json #: crm/doctype/appointment_booking_settings/appointment_booking_settings.json
@@ -7930,7 +7930,7 @@ msgstr "Biot"
#: setup/setup_wizard/data/industry_type.txt:9 #: setup/setup_wizard/data/industry_type.txt:9
msgid "Biotechnology" msgid "Biotechnology"
msgstr "" msgstr "بیوتکنولوژی"
#. Name of a DocType #. Name of a DocType
#: accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json #: accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json
@@ -8048,7 +8048,7 @@ msgstr "آبی"
#. Accounts' #. Accounts'
#: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json #: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
msgid "Body" msgid "Body"
msgstr "بدن" msgstr "بدنه"
#. Label of the body_text (Text Editor) field in DocType 'Dunning' #. Label of the body_text (Text Editor) field in DocType 'Dunning'
#. Label of the body_text (Text Editor) field in DocType 'Dunning Letter Text' #. Label of the body_text (Text Editor) field in DocType 'Dunning Letter Text'
@@ -9756,7 +9756,7 @@ msgstr "سفارش پرداخت / ارسال سفارش / سفارش جدید"
#: setup/setup_wizard/data/industry_type.txt:12 #: setup/setup_wizard/data/industry_type.txt:12
msgid "Chemical" msgid "Chemical"
msgstr "" msgstr "شیمیایی"
#. Option for the 'Salary Mode' (Select) field in DocType 'Employee' #. Option for the 'Salary Mode' (Select) field in DocType 'Employee'
#: setup/doctype/employee/employee.json #: setup/doctype/employee/employee.json
@@ -19255,7 +19255,7 @@ msgstr "لاگ درون‌بُرد برون‌بُرد"
#: setup/setup_wizard/operations/install_fixtures.py:286 #: setup/setup_wizard/operations/install_fixtures.py:286
msgid "External" msgid "External"
msgstr "" msgstr "بیرونی"
#. Label of the external_work_history (Table) field in DocType 'Employee' #. Label of the external_work_history (Table) field in DocType 'Employee'
#: setup/doctype/employee/employee.json #: setup/doctype/employee/employee.json
@@ -51167,7 +51167,7 @@ msgstr " شناسه مالیاتی:"
#: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:32 #: accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html:32
msgid "Tax Id: {0}" msgid "Tax Id: {0}"
msgstr "" msgstr "شناسه مالیاتی: {0}"
#. Label of a Card Break in the Accounting Workspace #. Label of a Card Break in the Accounting Workspace
#: accounts/workspace/accounting/accounting.json #: accounts/workspace/accounting/accounting.json
@@ -53861,7 +53861,7 @@ msgstr "تعداد کل پیش بینی شده"
#: buying/report/item_wise_purchase_history/item_wise_purchase_history.py:272 #: buying/report/item_wise_purchase_history/item_wise_purchase_history.py:272
msgid "Total Purchase Amount" msgid "Total Purchase Amount"
msgstr "" msgstr "کل مبلغ خرید"
#. Label of the total_purchase_cost (Currency) field in DocType 'Project' #. Label of the total_purchase_cost (Currency) field in DocType 'Project'
#: projects/doctype/project/project.json #: projects/doctype/project/project.json

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n" "Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: info@erpnext.com\n" "Report-Msgid-Bugs-To: info@erpnext.com\n"
"POT-Creation-Date: 2024-09-01 09:35+0000\n" "POT-Creation-Date: 2024-09-01 09:35+0000\n"
"PO-Revision-Date: 2024-09-07 18:35\n" "PO-Revision-Date: 2024-09-10 18:59\n"
"Last-Translator: info@erpnext.com\n" "Last-Translator: info@erpnext.com\n"
"Language-Team: Swedish\n" "Language-Team: Swedish\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -28131,7 +28131,7 @@ msgstr "Maskin"
#: public/js/plant_floor_visual/visual_plant.js:70 #: public/js/plant_floor_visual/visual_plant.js:70
msgid "Machine Type" msgid "Machine Type"
msgstr "Naskin Typ" msgstr "Maskin Typ"
#. Option for the 'Stop Reason' (Select) field in DocType 'Downtime Entry' #. Option for the 'Stop Reason' (Select) field in DocType 'Downtime Entry'
#: manufacturing/doctype/downtime_entry/downtime_entry.json #: manufacturing/doctype/downtime_entry/downtime_entry.json

File diff suppressed because it is too large Load Diff

View File

@@ -1268,6 +1268,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
"Purchase Receipt": ["purchase_order_item", "purchase_invoice_item", "purchase_receipt_item"], "Purchase Receipt": ["purchase_order_item", "purchase_invoice_item", "purchase_receipt_item"],
"Purchase Invoice": ["purchase_order_item", "pr_detail", "po_detail"], "Purchase Invoice": ["purchase_order_item", "pr_detail", "po_detail"],
"Sales Order": ["prevdoc_docname", "quotation_item"], "Sales Order": ["prevdoc_docname", "quotation_item"],
"Purchase Order": ["supplier_quotation_item"],
}; };
const mappped_fields = mapped_item_field_map[this.frm.doc.doctype] || []; const mappped_fields = mapped_item_field_map[this.frm.doc.doctype] || [];
@@ -1511,6 +1512,31 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
} }
} }
batch_no(frm, cdt, cdn) {
let row = locals[cdt][cdn];
if (row.use_serial_batch_fields && row.batch_no) {
var params = this._get_args(row);
params.batch_no = row.batch_no;
params.uom = row.uom;
frappe.call({
method: "erpnext.stock.get_item_details.get_batch_based_item_price",
args: {
params: params,
item_code: row.item_code,
},
callback: function(r) {
if (!r.exc && r.message) {
row.price_list_rate = r.message;
row.rate = r.message;
refresh_field("rate", row.name, row.parentfield);
refresh_field("price_list_rate", row.name, row.parentfield);
}
}
})
}
}
toggle_item_grid_columns(company_currency) { toggle_item_grid_columns(company_currency) {
const me = this; const me = this;
// toggle columns // toggle columns

View File

@@ -1,4 +1,4 @@
<div> <div>
<a href={{ route }}>{{ title }}</a> <a href={{ route }}>{{ title or name }}</a>
</div> </div>
<!-- this is a sample default list template --> <!-- this is a sample default list template -->

View File

@@ -10,7 +10,7 @@ from frappe.model import child_table_fields, default_fields
from frappe.model.meta import get_field_precision from frappe.model.meta import get_field_precision
from frappe.model.utils import get_fetch_values from frappe.model.utils import get_fetch_values
from frappe.query_builder.functions import IfNull, Sum from frappe.query_builder.functions import IfNull, Sum
from frappe.utils import add_days, add_months, cint, cstr, flt, getdate from frappe.utils import add_days, add_months, cint, cstr, flt, getdate, parse_json
from erpnext import get_company_currency from erpnext import get_company_currency
from erpnext.accounts.doctype.pricing_rule.pricing_rule import ( from erpnext.accounts.doctype.pricing_rule.pricing_rule import (
@@ -902,7 +902,7 @@ def insert_item_price(args):
) )
def get_item_price(args, item_code, ignore_party=False) -> list[dict]: def get_item_price(args, item_code, ignore_party=False, force_batch_no=False) -> list[dict]:
""" """
Get name, price_list_rate from Item Price based on conditions Get name, price_list_rate from Item Price based on conditions
Check if the desired qty is within the increment of the packing list. Check if the desired qty is within the increment of the packing list.
@@ -919,7 +919,6 @@ def get_item_price(args, item_code, ignore_party=False) -> list[dict]:
(ip.item_code == item_code) (ip.item_code == item_code)
& (ip.price_list == args.get("price_list")) & (ip.price_list == args.get("price_list"))
& (IfNull(ip.uom, "").isin(["", args.get("uom")])) & (IfNull(ip.uom, "").isin(["", args.get("uom")]))
& (IfNull(ip.batch_no, "").isin(["", args.get("batch_no")]))
) )
.orderby(ip.valid_from, order=frappe.qb.desc) .orderby(ip.valid_from, order=frappe.qb.desc)
.orderby(IfNull(ip.batch_no, ""), order=frappe.qb.desc) .orderby(IfNull(ip.batch_no, ""), order=frappe.qb.desc)
@@ -927,6 +926,11 @@ def get_item_price(args, item_code, ignore_party=False) -> list[dict]:
.limit(1) .limit(1)
) )
if force_batch_no:
query = query.where(ip.batch_no == args.get("batch_no"))
else:
query = query.where(IfNull(ip.batch_no, "").isin(["", args.get("batch_no")]))
if not ignore_party: if not ignore_party:
if args.get("customer"): if args.get("customer"):
query = query.where(ip.customer == args.get("customer")) query = query.where(ip.customer == args.get("customer"))
@@ -944,6 +948,21 @@ def get_item_price(args, item_code, ignore_party=False) -> list[dict]:
return query.run(as_dict=True) return query.run(as_dict=True)
@frappe.whitelist()
def get_batch_based_item_price(params, item_code) -> float:
if isinstance(params, str):
params = parse_json(params)
item_price = get_item_price(params, item_code, force_batch_no=True)
if not item_price:
item_price = get_item_price(params, item_code, ignore_party=True, force_batch_no=True)
if item_price and item_price[0].uom == params.get("uom"):
return item_price[0].price_list_rate
return 0.0
def get_price_list_rate_for(args, item_code): def get_price_list_rate_for(args, item_code):
""" """
:param customer: link to Customer DocType :param customer: link to Customer DocType