mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-14 02:31:21 +00:00
refactor(treewide): formatting and ruff fixes, + manually enabled F401
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
@@ -95,7 +95,7 @@ force_item_fields = (
|
||||
|
||||
class AccountsController(TransactionBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AccountsController, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def get_print_settings(self):
|
||||
print_setting_fields = []
|
||||
@@ -200,14 +200,13 @@ class AccountsController(TransactionBase):
|
||||
self.validate_return_against_account()
|
||||
|
||||
if self.doctype in ["Purchase Invoice", "Sales Invoice"]:
|
||||
if invalid_advances := [
|
||||
x for x in self.advances if not x.reference_type or not x.reference_name
|
||||
]:
|
||||
if invalid_advances := [x for x in self.advances if not x.reference_type or not x.reference_name]:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Rows: {0} in {1} section are Invalid. Reference Name should point to a valid Payment Entry or Journal Entry."
|
||||
).format(
|
||||
frappe.bold(comma_and([x.idx for x in invalid_advances])), frappe.bold(_("Advance Payments"))
|
||||
frappe.bold(comma_and([x.idx for x in invalid_advances])),
|
||||
frappe.bold(_("Advance Payments")),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -352,9 +351,7 @@ class AccountsController(TransactionBase):
|
||||
)
|
||||
|
||||
def validate_return_against_account(self):
|
||||
if (
|
||||
self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against
|
||||
):
|
||||
if self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against:
|
||||
cr_dr_account_field = "debit_to" if self.doctype == "Sales Invoice" else "credit_to"
|
||||
cr_dr_account_label = "Debit To" if self.doctype == "Sales Invoice" else "Credit To"
|
||||
cr_dr_account = self.get(cr_dr_account_field)
|
||||
@@ -387,11 +384,7 @@ class AccountsController(TransactionBase):
|
||||
item.set(field_map.get(self.doctype), default_deferred_account)
|
||||
|
||||
def validate_auto_repeat_subscription_dates(self):
|
||||
if (
|
||||
self.get("from_date")
|
||||
and self.get("to_date")
|
||||
and getdate(self.from_date) > getdate(self.to_date)
|
||||
):
|
||||
if self.get("from_date") and self.get("to_date") and getdate(self.from_date) > getdate(self.to_date):
|
||||
frappe.throw(_("To Date cannot be before From Date"), title=_("Invalid Auto Repeat Date"))
|
||||
|
||||
def validate_deferred_start_and_end_date(self):
|
||||
@@ -399,11 +392,15 @@ class AccountsController(TransactionBase):
|
||||
if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"):
|
||||
if not (d.service_start_date and d.service_end_date):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Service Start and End Date is required for deferred accounting").format(d.idx)
|
||||
_("Row #{0}: Service Start and End Date is required for deferred accounting").format(
|
||||
d.idx
|
||||
)
|
||||
)
|
||||
elif getdate(d.service_start_date) > getdate(d.service_end_date):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Service Start Date cannot be greater than Service End Date").format(d.idx)
|
||||
_("Row #{0}: Service Start Date cannot be greater than Service End Date").format(
|
||||
d.idx
|
||||
)
|
||||
)
|
||||
elif getdate(self.posting_date) > getdate(d.service_end_date):
|
||||
frappe.throw(
|
||||
@@ -462,7 +459,9 @@ class AccountsController(TransactionBase):
|
||||
if not self.cash_bank_account:
|
||||
# show message that the amount is not paid
|
||||
frappe.throw(
|
||||
_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified")
|
||||
_(
|
||||
"Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"
|
||||
)
|
||||
)
|
||||
|
||||
if cint(self.is_return) and self.grand_total > self.paid_amount:
|
||||
@@ -506,7 +505,11 @@ class AccountsController(TransactionBase):
|
||||
|
||||
if date_field and self.get(date_field):
|
||||
validate_fiscal_year(
|
||||
self.get(date_field), self.fiscal_year, self.company, self.meta.get_label(date_field), self
|
||||
self.get(date_field),
|
||||
self.fiscal_year,
|
||||
self.company,
|
||||
self.meta.get_label(date_field),
|
||||
self,
|
||||
)
|
||||
|
||||
def validate_party_accounts(self):
|
||||
@@ -576,7 +579,9 @@ class AccountsController(TransactionBase):
|
||||
|
||||
if tax_updated:
|
||||
frappe.msgprint(
|
||||
_("Disabled tax included prices since this {} is an internal transfer").format(self.doctype),
|
||||
_("Disabled tax included prices since this {} is an internal transfer").format(
|
||||
self.doctype
|
||||
),
|
||||
alert=1,
|
||||
)
|
||||
|
||||
@@ -667,7 +672,7 @@ class AccountsController(TransactionBase):
|
||||
parent_dict[fieldname] = self.get(fieldname)
|
||||
|
||||
if self.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
|
||||
document_type = "{} Item".format(self.doctype)
|
||||
document_type = f"{self.doctype} Item"
|
||||
parent_dict.update({"document_type": document_type})
|
||||
|
||||
# party_name field used for customer in quotation
|
||||
@@ -708,7 +713,9 @@ class AccountsController(TransactionBase):
|
||||
if item.get(fieldname) is None or fieldname in force_item_fields:
|
||||
item.set(fieldname, value)
|
||||
|
||||
elif fieldname in ["cost_center", "conversion_factor"] and not item.get(fieldname):
|
||||
elif fieldname in ["cost_center", "conversion_factor"] and not item.get(
|
||||
fieldname
|
||||
):
|
||||
item.set(fieldname, value)
|
||||
|
||||
elif fieldname == "serial_no":
|
||||
@@ -744,7 +751,8 @@ class AccountsController(TransactionBase):
|
||||
# Items add via promotional scheme may not have cost center set
|
||||
if hasattr(item, "cost_center") and not item.get("cost_center"):
|
||||
item.set(
|
||||
"cost_center", self.get("cost_center") or erpnext.get_default_cost_center(self.company)
|
||||
"cost_center",
|
||||
self.get("cost_center") or erpnext.get_default_cost_center(self.company),
|
||||
)
|
||||
|
||||
if ret.get("pricing_rules"):
|
||||
@@ -871,9 +879,7 @@ class AccountsController(TransactionBase):
|
||||
if self.taxes_and_charges and frappe.get_cached_value(
|
||||
taxes_and_charges_doctype, self.taxes_and_charges, "disabled"
|
||||
):
|
||||
frappe.throw(
|
||||
_("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges)
|
||||
)
|
||||
frappe.throw(_("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges))
|
||||
|
||||
def validate_tax_account_company(self):
|
||||
for d in self.get("taxes"):
|
||||
@@ -998,9 +1004,8 @@ class AccountsController(TransactionBase):
|
||||
self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]}))
|
||||
|
||||
frappe.db.sql(
|
||||
"""delete from `tab%s` where parentfield=%s and parent = %s
|
||||
and allocated_amount = 0"""
|
||||
% (childtype, "%s", "%s"),
|
||||
"""delete from `tab{}` where parentfield={} and parent = {}
|
||||
and allocated_amount = 0""".format(childtype, "%s", "%s"),
|
||||
(parentfield, self.name),
|
||||
)
|
||||
|
||||
@@ -1088,9 +1093,7 @@ class AccountsController(TransactionBase):
|
||||
return res
|
||||
|
||||
def is_inclusive_tax(self):
|
||||
is_inclusive = cint(
|
||||
frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print")
|
||||
)
|
||||
is_inclusive = cint(frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print"))
|
||||
|
||||
if is_inclusive:
|
||||
is_inclusive = 0
|
||||
@@ -1133,7 +1136,6 @@ class AccountsController(TransactionBase):
|
||||
for d in self.get("advances"):
|
||||
advance_exchange_rate = d.ref_exchange_rate
|
||||
if d.allocated_amount and self.conversion_rate != advance_exchange_rate:
|
||||
|
||||
base_allocated_amount_in_ref_rate = advance_exchange_rate * d.allocated_amount
|
||||
base_allocated_amount_in_inv_rate = self.conversion_rate * d.allocated_amount
|
||||
difference = base_allocated_amount_in_ref_rate - base_allocated_amount_in_inv_rate
|
||||
@@ -1179,7 +1181,7 @@ class AccountsController(TransactionBase):
|
||||
return False
|
||||
|
||||
def make_exchange_gain_loss_journal(
|
||||
self, args: dict = None, dimensions_dict: dict = None
|
||||
self, args: dict | None = None, dimensions_dict: dict | None = None
|
||||
) -> None:
|
||||
"""
|
||||
Make Exchange Gain/Loss journal for Invoices and Payments
|
||||
@@ -1199,7 +1201,6 @@ class AccountsController(TransactionBase):
|
||||
flt(arg.get("difference_amount", 0), precision) != 0
|
||||
or flt(arg.get("exchange_gain_loss", 0), precision) != 0
|
||||
) and arg.get("difference_account"):
|
||||
|
||||
party_account = arg.get("account")
|
||||
gain_loss_account = arg.get("difference_account")
|
||||
difference_amount = arg.get("difference_amount") or arg.get("exchange_gain_loss")
|
||||
@@ -1250,8 +1251,8 @@ class AccountsController(TransactionBase):
|
||||
gain_loss_to_book = [x for x in self.references if x.exchange_gain_loss != 0]
|
||||
booked = []
|
||||
if gain_loss_to_book:
|
||||
vtypes = [x.reference_doctype for x in gain_loss_to_book]
|
||||
vnames = [x.reference_name for x in gain_loss_to_book]
|
||||
[x.reference_doctype for x in gain_loss_to_book]
|
||||
[x.reference_name for x in gain_loss_to_book]
|
||||
je = qb.DocType("Journal Entry")
|
||||
jea = qb.DocType("Journal Entry Account")
|
||||
parents = (
|
||||
@@ -1391,7 +1392,9 @@ class AccountsController(TransactionBase):
|
||||
"allocated_amount": flt(d.allocated_amount),
|
||||
"precision": d.precision("advance_amount"),
|
||||
"exchange_rate": (
|
||||
self.conversion_rate if self.party_account_currency != self.company_currency else 1
|
||||
self.conversion_rate
|
||||
if self.party_account_currency != self.company_currency
|
||||
else 1
|
||||
),
|
||||
"grand_total": (
|
||||
self.base_grand_total
|
||||
@@ -1574,9 +1577,12 @@ class AccountsController(TransactionBase):
|
||||
"account": item.discount_account,
|
||||
"against": supplier_or_customer,
|
||||
dr_or_cr: flt(
|
||||
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
||||
discount_amount * self.get("conversion_rate"),
|
||||
item.precision("discount_amount"),
|
||||
),
|
||||
dr_or_cr + "_in_account_currency": flt(
|
||||
discount_amount, item.precision("discount_amount")
|
||||
),
|
||||
dr_or_cr + "_in_account_currency": flt(discount_amount, item.precision("discount_amount")),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project,
|
||||
},
|
||||
@@ -1592,10 +1598,12 @@ class AccountsController(TransactionBase):
|
||||
"account": income_or_expense_account,
|
||||
"against": supplier_or_customer,
|
||||
rev_dr_cr: flt(
|
||||
discount_amount * self.get("conversion_rate"), item.precision("discount_amount")
|
||||
discount_amount * self.get("conversion_rate"),
|
||||
item.precision("discount_amount"),
|
||||
),
|
||||
rev_dr_cr + "_in_account_currency": flt(
|
||||
discount_amount, item.precision("discount_amount")
|
||||
),
|
||||
rev_dr_cr
|
||||
+ "_in_account_currency": flt(discount_amount, item.precision("discount_amount")),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
},
|
||||
@@ -1635,9 +1643,7 @@ class AccountsController(TransactionBase):
|
||||
total_overbilled_amt = 0.0
|
||||
|
||||
reference_names = [d.get(item_ref_dn) for d in self.get("items") if d.get(item_ref_dn)]
|
||||
reference_details = self.get_billing_reference_details(
|
||||
reference_names, ref_dt + " Item", based_on
|
||||
)
|
||||
reference_details = self.get_billing_reference_details(reference_names, ref_dt + " Item", based_on)
|
||||
|
||||
for item in self.get("items"):
|
||||
if not item.get(item_ref_dn):
|
||||
@@ -1823,17 +1829,13 @@ class AccountsController(TransactionBase):
|
||||
|
||||
def raise_missing_debit_credit_account_error(self, party_type, party):
|
||||
"""Raise an error if debit to/credit to account does not exist."""
|
||||
db_or_cr = (
|
||||
frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To")
|
||||
)
|
||||
db_or_cr = frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To")
|
||||
rec_or_pay = "Receivable" if self.doctype == "Sales Invoice" else "Payable"
|
||||
|
||||
link_to_party = frappe.utils.get_link_to_form(party_type, party)
|
||||
link_to_company = frappe.utils.get_link_to_form("Company", self.company)
|
||||
|
||||
message = _("{0} Account not found against Customer {1}.").format(
|
||||
db_or_cr, frappe.bold(party) or ""
|
||||
)
|
||||
message = _("{0} Account not found against Customer {1}.").format(db_or_cr, frappe.bold(party) or "")
|
||||
message += "<br>" + _("Please set one of the following:") + "<br>"
|
||||
message += (
|
||||
"<br><ul><li>"
|
||||
@@ -1886,7 +1888,6 @@ class AccountsController(TransactionBase):
|
||||
and party_account_currency != self.company_currency
|
||||
and self.currency != party_account_currency
|
||||
):
|
||||
|
||||
frappe.throw(
|
||||
_("Accounting Entry for {0}: {1} can only be made in currency: {2}").format(
|
||||
party_type, party, party_account_currency
|
||||
@@ -1907,9 +1908,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
party_type, party = self.get_party()
|
||||
party_gle_currency = get_party_gle_currency(party_type, party, self.company)
|
||||
party_account = (
|
||||
self.get("debit_to") if self.doctype == "Sales Invoice" else self.get("credit_to")
|
||||
)
|
||||
party_account = self.get("debit_to") if self.doctype == "Sales Invoice" else self.get("credit_to")
|
||||
party_account_currency = get_account_currency(party_account)
|
||||
allow_multi_currency_invoices_against_single_party_account = frappe.db.get_singles_value(
|
||||
"Accounts Settings", "allow_multi_currency_invoices_against_single_party_account"
|
||||
@@ -1932,10 +1931,8 @@ class AccountsController(TransactionBase):
|
||||
consider_for_total_advance = True
|
||||
if adv.reference_name == linked_doc_name:
|
||||
frappe.db.sql(
|
||||
"""delete from `tab{0} Advance`
|
||||
where name = %s""".format(
|
||||
self.doctype
|
||||
),
|
||||
f"""delete from `tab{self.doctype} Advance`
|
||||
where name = %s""",
|
||||
adv.name,
|
||||
)
|
||||
consider_for_total_advance = False
|
||||
@@ -2152,7 +2149,9 @@ class AccountsController(TransactionBase):
|
||||
for d in self.get("payment_schedule"):
|
||||
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
||||
frappe.throw(
|
||||
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(d.idx)
|
||||
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(
|
||||
d.idx
|
||||
)
|
||||
)
|
||||
elif d.due_date in dates:
|
||||
li.append(_("{0} in row {1}").format(d.due_date, d.idx))
|
||||
@@ -2160,9 +2159,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
if li:
|
||||
duplicates = "<br>" + "<br>".join(li)
|
||||
frappe.throw(
|
||||
_("Rows with duplicate due dates in other rows were found: {0}").format(duplicates)
|
||||
)
|
||||
frappe.throw(_("Rows with duplicate due dates in other rows were found: {0}").format(duplicates))
|
||||
|
||||
def validate_payment_schedule_amount(self):
|
||||
if self.doctype == "Sales Invoice" and self.is_pos:
|
||||
@@ -2285,7 +2282,7 @@ class AccountsController(TransactionBase):
|
||||
jv.voucher_type = "Journal Entry"
|
||||
jv.posting_date = self.posting_date
|
||||
jv.company = self.company
|
||||
jv.remark = "Adjustment for {} {}".format(self.doctype, self.name)
|
||||
jv.remark = f"Adjustment for {self.doctype} {self.name}"
|
||||
|
||||
reconcilation_entry = frappe._dict()
|
||||
advance_entry = frappe._dict()
|
||||
@@ -2295,9 +2292,7 @@ class AccountsController(TransactionBase):
|
||||
reconcilation_entry.party = secondary_party
|
||||
reconcilation_entry.reference_type = self.doctype
|
||||
reconcilation_entry.reference_name = self.name
|
||||
reconcilation_entry.cost_center = self.cost_center or erpnext.get_default_cost_center(
|
||||
self.company
|
||||
)
|
||||
reconcilation_entry.cost_center = self.cost_center or erpnext.get_default_cost_center(self.company)
|
||||
|
||||
advance_entry.account = primary_account
|
||||
advance_entry.party_type = primary_party_type
|
||||
@@ -2343,7 +2338,7 @@ class AccountsController(TransactionBase):
|
||||
def check_if_fields_updated(self, fields_to_check, child_tables):
|
||||
# Check if any field affecting accounting entry is altered
|
||||
doc_before_update = self.get_doc_before_save()
|
||||
accounting_dimensions = get_accounting_dimensions() + ["cost_center", "project"]
|
||||
accounting_dimensions = [*get_accounting_dimensions(), "cost_center", "project"]
|
||||
|
||||
# Check if opening entry check updated
|
||||
needs_repost = doc_before_update.get("is_opening") != self.is_opening
|
||||
@@ -2383,9 +2378,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_tax_rate(account_head):
|
||||
return frappe.get_cached_value(
|
||||
"Account", account_head, ["tax_rate", "account_name"], as_dict=True
|
||||
)
|
||||
return frappe.get_cached_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -2415,7 +2408,7 @@ def get_taxes_and_charges(master_doctype, master_name):
|
||||
tax_master = frappe.get_doc(master_doctype, master_name)
|
||||
|
||||
taxes_and_charges = []
|
||||
for i, tax in enumerate(tax_master.get("taxes")):
|
||||
for _i, tax in enumerate(tax_master.get("taxes")):
|
||||
tax = tax.as_dict()
|
||||
|
||||
for fieldname in default_fields + child_table_fields:
|
||||
@@ -2534,9 +2527,7 @@ def set_balance_in_account_currency(
|
||||
):
|
||||
if (not conversion_rate) and (account_currency != company_currency):
|
||||
frappe.throw(
|
||||
_("Account: {0} with currency: {1} can not be selected").format(
|
||||
gl_dict.account, account_currency
|
||||
)
|
||||
_("Account: {0} with currency: {1} can not be selected").format(gl_dict.account, account_currency)
|
||||
)
|
||||
|
||||
gl_dict["account_currency"] = (
|
||||
@@ -2546,9 +2537,7 @@ def set_balance_in_account_currency(
|
||||
# set debit/credit in account currency if not provided
|
||||
if flt(gl_dict.debit) and not flt(gl_dict.debit_in_account_currency):
|
||||
gl_dict.debit_in_account_currency = (
|
||||
gl_dict.debit
|
||||
if account_currency == company_currency
|
||||
else flt(gl_dict.debit / conversion_rate, 2)
|
||||
gl_dict.debit if account_currency == company_currency else flt(gl_dict.debit / conversion_rate, 2)
|
||||
)
|
||||
|
||||
if flt(gl_dict.credit) and not flt(gl_dict.credit_in_account_currency):
|
||||
@@ -2568,9 +2557,7 @@ def get_advance_journal_entries(
|
||||
order_list,
|
||||
include_unallocated=True,
|
||||
):
|
||||
dr_or_cr = (
|
||||
"credit_in_account_currency" if party_type == "Customer" else "debit_in_account_currency"
|
||||
)
|
||||
dr_or_cr = "credit_in_account_currency" if party_type == "Customer" else "debit_in_account_currency"
|
||||
|
||||
conditions = []
|
||||
if include_unallocated:
|
||||
@@ -2579,7 +2566,7 @@ def get_advance_journal_entries(
|
||||
if order_list:
|
||||
order_condition = ", ".join(["%s"] * len(order_list))
|
||||
conditions.append(
|
||||
" (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))".format(
|
||||
" (t2.reference_type = '{}' and ifnull(t2.reference_name, '') in ({}))".format(
|
||||
order_doctype, order_condition
|
||||
)
|
||||
)
|
||||
@@ -2588,10 +2575,10 @@ def get_advance_journal_entries(
|
||||
|
||||
# nosemgrep
|
||||
journal_entries = frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
select
|
||||
'Journal Entry' as reference_type, t1.name as reference_name,
|
||||
t1.remark as remarks, t2.{0} as amount, t2.name as reference_row,
|
||||
t1.remark as remarks, t2.{amount_field} as amount, t2.name as reference_row,
|
||||
t2.reference_name as against_order, t2.exchange_rate
|
||||
from
|
||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
@@ -2599,11 +2586,9 @@ def get_advance_journal_entries(
|
||||
t1.name = t2.parent and t2.account = %s
|
||||
and t2.party_type = %s and t2.party = %s
|
||||
and t2.is_advance = 'Yes' and t1.docstatus = 1
|
||||
and {1} > 0 {2}
|
||||
order by t1.posting_date""".format(
|
||||
amount_field, dr_or_cr, reference_condition
|
||||
),
|
||||
[party_account, party_type, party] + order_list,
|
||||
and {dr_or_cr} > 0 {reference_condition}
|
||||
order by t1.posting_date""",
|
||||
[party_account, party_type, party, *order_list],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
@@ -2631,13 +2616,9 @@ def get_advance_payment_entries(
|
||||
per = qb.DocType("Payment Entry Reference")
|
||||
|
||||
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
|
||||
currency_field = (
|
||||
"paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
||||
)
|
||||
currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
||||
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
||||
exchange_rate_field = (
|
||||
"source_exchange_rate" if payment_type == "Receive" else "target_exchange_rate"
|
||||
)
|
||||
exchange_rate_field = "source_exchange_rate" if payment_type == "Receive" else "target_exchange_rate"
|
||||
|
||||
payment_entries_against_order, unallocated_payment_entries = [], []
|
||||
|
||||
@@ -2783,9 +2764,7 @@ def get_payment_terms(
|
||||
|
||||
schedule = []
|
||||
for d in terms_doc.get("terms"):
|
||||
term_details = get_payment_term_details(
|
||||
d, posting_date, grand_total, base_grand_total, bill_date
|
||||
)
|
||||
term_details = get_payment_term_details(d, posting_date, grand_total, base_grand_total, bill_date)
|
||||
schedule.append(term_details)
|
||||
|
||||
return schedule
|
||||
@@ -2903,9 +2882,7 @@ def add_taxes_from_tax_template(child_item, parent_doc, db_insert=True):
|
||||
tax_row.db_insert()
|
||||
|
||||
|
||||
def set_order_defaults(
|
||||
parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item
|
||||
):
|
||||
def set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item):
|
||||
"""
|
||||
Returns a Sales/Purchase Order Item child item containing the default values
|
||||
"""
|
||||
@@ -2921,9 +2898,7 @@ def set_order_defaults(
|
||||
child_item.stock_uom = item.stock_uom
|
||||
child_item.uom = trans_item.get("uom") or item.stock_uom
|
||||
child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True)
|
||||
conversion_factor = flt(
|
||||
get_conversion_factor(item.item_code, child_item.uom).get("conversion_factor")
|
||||
)
|
||||
conversion_factor = flt(get_conversion_factor(item.item_code, child_item.uom).get("conversion_factor"))
|
||||
child_item.conversion_factor = flt(trans_item.get("conversion_factor")) or conversion_factor
|
||||
|
||||
if child_doctype == "Purchase Order Item":
|
||||
@@ -3070,9 +3045,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
|
||||
def get_new_child_item(item_row):
|
||||
child_doctype = "Sales Order Item" if parent_doctype == "Sales Order" else "Purchase Order Item"
|
||||
return set_order_defaults(
|
||||
parent_doctype, parent_doctype_name, child_doctype, child_docname, item_row
|
||||
)
|
||||
return set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, item_row)
|
||||
|
||||
def validate_quantity(child_item, new_data):
|
||||
if not flt(new_data.get("qty")):
|
||||
@@ -3086,9 +3059,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
if parent_doctype == "Sales Order" and flt(new_data.get("qty")) < flt(child_item.delivered_qty):
|
||||
frappe.throw(_("Cannot set quantity less than delivered quantity"))
|
||||
|
||||
if parent_doctype == "Purchase Order" and flt(new_data.get("qty")) < flt(
|
||||
child_item.received_qty
|
||||
):
|
||||
if parent_doctype == "Purchase Order" and flt(new_data.get("qty")) < flt(child_item.received_qty):
|
||||
frappe.throw(_("Cannot set quantity less than received quantity"))
|
||||
|
||||
def should_update_supplied_items(doc) -> bool:
|
||||
@@ -3103,9 +3074,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
item.supplied_qty or item.consumed_qty or item.returned_qty for item in doc.supplied_items
|
||||
)
|
||||
|
||||
update_supplied_items = (
|
||||
any_qty_changed or items_added_or_removed or any_conversion_factor_changed
|
||||
)
|
||||
update_supplied_items = any_qty_changed or items_added_or_removed or any_conversion_factor_changed
|
||||
if update_supplied_items and supplied_items_processed:
|
||||
frappe.throw(_("Item qty can not be updated as raw materials are already processed."))
|
||||
|
||||
@@ -3142,8 +3111,9 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
|
||||
prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate"))
|
||||
prev_qty, new_qty = flt(child_item.get("qty")), flt(d.get("qty"))
|
||||
prev_con_fac, new_con_fac = flt(child_item.get("conversion_factor")), flt(
|
||||
d.get("conversion_factor")
|
||||
prev_con_fac, new_con_fac = (
|
||||
flt(child_item.get("conversion_factor")),
|
||||
flt(d.get("conversion_factor")),
|
||||
)
|
||||
prev_uom, new_uom = child_item.get("uom"), d.get("uom")
|
||||
|
||||
@@ -3222,7 +3192,8 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(
|
||||
child_item.rate - child_item.price_list_rate, child_item.precision("margin_rate_or_amount")
|
||||
child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"),
|
||||
)
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
else:
|
||||
@@ -3302,10 +3273,8 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
parent.set_status()
|
||||
|
||||
|
||||
def check_if_child_table_updated(
|
||||
child_table_before_update, child_table_after_update, fields_to_check
|
||||
):
|
||||
accounting_dimensions = get_accounting_dimensions() + ["cost_center", "project"]
|
||||
def check_if_child_table_updated(child_table_before_update, child_table_after_update, fields_to_check):
|
||||
accounting_dimensions = [*get_accounting_dimensions(), "cost_center", "project"]
|
||||
# Check if any field affecting accounting entry is altered
|
||||
for index, item in enumerate(child_table_after_update):
|
||||
for field in fields_to_check:
|
||||
|
||||
@@ -33,7 +33,7 @@ class BuyingController(SubcontractingController):
|
||||
def validate(self):
|
||||
self.set_rate_for_standalone_debit_note()
|
||||
|
||||
super(BuyingController, self).validate()
|
||||
super().validate()
|
||||
if getattr(self, "supplier", None) and not self.supplier_name:
|
||||
self.supplier_name = frappe.db.get_value("Supplier", self.supplier, "supplier_name")
|
||||
|
||||
@@ -49,9 +49,7 @@ class BuyingController(SubcontractingController):
|
||||
if self.doctype == "Purchase Invoice":
|
||||
self.validate_purchase_receipt_if_update_stock()
|
||||
|
||||
if self.doctype == "Purchase Receipt" or (
|
||||
self.doctype == "Purchase Invoice" and self.update_stock
|
||||
):
|
||||
if self.doctype == "Purchase Receipt" or (self.doctype == "Purchase Invoice" and self.update_stock):
|
||||
# self.validate_purchase_return()
|
||||
self.validate_rejected_warehouse()
|
||||
self.validate_accepted_rejected_qty()
|
||||
@@ -67,12 +65,10 @@ class BuyingController(SubcontractingController):
|
||||
self.update_valuation_rate()
|
||||
|
||||
def onload(self):
|
||||
super(BuyingController, self).onload()
|
||||
super().onload()
|
||||
self.set_onload(
|
||||
"backflush_based_on",
|
||||
frappe.db.get_single_value(
|
||||
"Buying Settings", "backflush_raw_materials_of_subcontract_based_on"
|
||||
),
|
||||
frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on"),
|
||||
)
|
||||
|
||||
def set_rate_for_standalone_debit_note(self):
|
||||
@@ -101,7 +97,7 @@ class BuyingController(SubcontractingController):
|
||||
row.margin_rate_or_amount = 0.0
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
super(BuyingController, self).set_missing_values(for_validate)
|
||||
super().set_missing_values(for_validate)
|
||||
|
||||
self.set_supplier_from_item_default()
|
||||
self.set_price_list_currency("Buying")
|
||||
@@ -161,9 +157,7 @@ class BuyingController(SubcontractingController):
|
||||
if self.doctype not in ["Purchase Receipt", "Purchase Invoice"] or not self.is_return:
|
||||
return
|
||||
|
||||
purchase_doc_field = (
|
||||
"purchase_receipt" if self.doctype == "Purchase Receipt" else "purchase_invoice"
|
||||
)
|
||||
purchase_doc_field = "purchase_receipt" if self.doctype == "Purchase Receipt" else "purchase_invoice"
|
||||
not_cancelled_asset = []
|
||||
if self.return_against:
|
||||
not_cancelled_asset = [
|
||||
@@ -494,7 +488,6 @@ class BuyingController(SubcontractingController):
|
||||
pr_qty = flt(flt(d.qty) * flt(d.conversion_factor), d.precision("stock_qty"))
|
||||
|
||||
if pr_qty:
|
||||
|
||||
if d.from_warehouse and (
|
||||
(not cint(self.is_return) and self.docstatus == 1)
|
||||
or (cint(self.is_return) and self.docstatus == 2)
|
||||
@@ -559,7 +552,8 @@ class BuyingController(SubcontractingController):
|
||||
or (cint(self.is_return) and self.docstatus == 1)
|
||||
):
|
||||
from_warehouse_sle = self.get_sl_entries(
|
||||
d, {"actual_qty": -1 * pr_qty, "warehouse": d.from_warehouse, "recalculate_rate": 1}
|
||||
d,
|
||||
{"actual_qty": -1 * pr_qty, "warehouse": d.from_warehouse, "recalculate_rate": 1},
|
||||
)
|
||||
|
||||
if flt(rejected_qty) != 0:
|
||||
@@ -631,7 +625,7 @@ class BuyingController(SubcontractingController):
|
||||
update_last_purchase_rate(self, is_submit=1)
|
||||
|
||||
def on_cancel(self):
|
||||
super(BuyingController, self).on_cancel()
|
||||
super().on_cancel()
|
||||
|
||||
if self.get("is_return"):
|
||||
return
|
||||
@@ -656,7 +650,9 @@ class BuyingController(SubcontractingController):
|
||||
"doctype": self.doctype,
|
||||
"company": self.company,
|
||||
"posting_date": (
|
||||
self.schedule_date if self.doctype == "Material Request" else self.transaction_date
|
||||
self.schedule_date
|
||||
if self.doctype == "Material Request"
|
||||
else self.transaction_date
|
||||
),
|
||||
}
|
||||
)
|
||||
@@ -688,17 +684,21 @@ class BuyingController(SubcontractingController):
|
||||
asset = self.make_asset(d, is_grouped_asset=True)
|
||||
created_assets.append(asset)
|
||||
else:
|
||||
for qty in range(cint(d.qty)):
|
||||
for _qty in range(cint(d.qty)):
|
||||
asset = self.make_asset(d)
|
||||
created_assets.append(asset)
|
||||
|
||||
if len(created_assets) > 5:
|
||||
# dont show asset form links if more than 5 assets are created
|
||||
messages.append(
|
||||
_("{} Assets created for {}").format(len(created_assets), frappe.bold(d.item_code))
|
||||
_("{} Assets created for {}").format(
|
||||
len(created_assets), frappe.bold(d.item_code)
|
||||
)
|
||||
)
|
||||
else:
|
||||
assets_link = list(map(lambda d: frappe.utils.get_link_to_form("Asset", d), created_assets))
|
||||
assets_link = list(
|
||||
map(lambda d: frappe.utils.get_link_to_form("Asset", d), created_assets)
|
||||
)
|
||||
assets_link = frappe.bold(",".join(assets_link))
|
||||
|
||||
is_plural = "s" if len(created_assets) != 1 else ""
|
||||
@@ -709,9 +709,9 @@ class BuyingController(SubcontractingController):
|
||||
)
|
||||
else:
|
||||
frappe.throw(
|
||||
_("Row {}: Asset Naming Series is mandatory for the auto creation for item {}").format(
|
||||
d.idx, frappe.bold(d.item_code)
|
||||
)
|
||||
_(
|
||||
"Row {}: Asset Naming Series is mandatory for the auto creation for item {}"
|
||||
).format(d.idx, frappe.bold(d.item_code))
|
||||
)
|
||||
else:
|
||||
messages.append(
|
||||
@@ -874,11 +874,9 @@ def validate_item_type(doc, fieldname, message):
|
||||
invalid_items = [
|
||||
d[0]
|
||||
for d in frappe.db.sql(
|
||||
"""
|
||||
select item_code from tabItem where name in ({0}) and {1}=0
|
||||
""".format(
|
||||
item_list, fieldname
|
||||
),
|
||||
f"""
|
||||
select item_code from tabItem where name in ({item_list}) and {fieldname}=0
|
||||
""",
|
||||
as_list=True,
|
||||
)
|
||||
]
|
||||
|
||||
@@ -56,9 +56,7 @@ def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part
|
||||
variant.flags.ignore_mandatory = True
|
||||
variant.save()
|
||||
|
||||
if not frappe.db.exists(
|
||||
"Item Manufacturer", {"item_code": variant.name, "manufacturer": manufacturer}
|
||||
):
|
||||
if not frappe.db.exists("Item Manufacturer", {"item_code": variant.name, "manufacturer": manufacturer}):
|
||||
manufacturer_doc = frappe.new_doc("Item Manufacturer")
|
||||
manufacturer_doc.update(
|
||||
{
|
||||
@@ -122,9 +120,7 @@ def validate_is_incremental(numeric_attribute, attribute, value, item):
|
||||
)
|
||||
|
||||
|
||||
def validate_item_attribute_value(
|
||||
attributes_list, attribute, attribute_value, item, from_variant=True
|
||||
):
|
||||
def validate_item_attribute_value(attributes_list, attribute, attribute_value, item, from_variant=True):
|
||||
allow_rename_attribute_value = frappe.db.get_single_value(
|
||||
"Item Variant Settings", "allow_rename_attribute_value"
|
||||
)
|
||||
@@ -172,7 +168,7 @@ def get_attribute_values(item):
|
||||
|
||||
def find_variant(template, args, variant_item_code=None):
|
||||
conditions = [
|
||||
"""(iv_attribute.attribute={0} and iv_attribute.attribute_value={1})""".format(
|
||||
"""(iv_attribute.attribute={} and iv_attribute.attribute_value={})""".format(
|
||||
frappe.db.escape(key), frappe.db.escape(cstr(value))
|
||||
)
|
||||
for key, value in args.items()
|
||||
@@ -182,9 +178,7 @@ def find_variant(template, args, variant_item_code=None):
|
||||
|
||||
from erpnext.e_commerce.variant_selector.utils import get_item_codes_by_attributes
|
||||
|
||||
possible_variants = [
|
||||
i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code
|
||||
]
|
||||
possible_variants = [i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code]
|
||||
|
||||
for variant in possible_variants:
|
||||
variant = frappe.get_doc("Item", variant)
|
||||
@@ -360,7 +354,9 @@ def copy_attributes_to_variant(item, variant):
|
||||
if variant.attributes:
|
||||
attributes_description = item.description + " "
|
||||
for d in variant.attributes:
|
||||
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||
attributes_description += (
|
||||
"<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||
)
|
||||
|
||||
if attributes_description not in variant.description:
|
||||
variant.description = attributes_description
|
||||
@@ -394,8 +390,8 @@ def make_variant_item_code(template_item_code, template_item_name, variant):
|
||||
abbreviations.append(abbr_or_value)
|
||||
|
||||
if abbreviations:
|
||||
variant.item_code = "{0}-{1}".format(template_item_code, "-".join(abbreviations))
|
||||
variant.item_name = "{0}-{1}".format(template_item_name, "-".join(abbreviations))
|
||||
variant.item_code = "{}-{}".format(template_item_code, "-".join(abbreviations))
|
||||
variant.item_name = "{}-{}".format(template_item_name, "-".join(abbreviations))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -39,7 +39,7 @@ def set_print_templates_for_taxes(doc, settings):
|
||||
|
||||
|
||||
def format_columns(display_columns, compact_fields):
|
||||
compact_fields = compact_fields + ["image", "item_code", "item_name"]
|
||||
compact_fields = [*compact_fields, "image", "item_code", "item_name"]
|
||||
final_columns = []
|
||||
for column in display_columns:
|
||||
if column not in compact_fields:
|
||||
|
||||
@@ -162,7 +162,7 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
account_type_condition = "AND account_type in %(account_types)s"
|
||||
|
||||
accounts = frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
SELECT name, parent_account
|
||||
FROM `tabAccount`
|
||||
WHERE `tabAccount`.docstatus!=2
|
||||
@@ -172,20 +172,16 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
AND disabled = %(disabled)s
|
||||
AND (account_currency = %(currency)s or ifnull(account_currency, '') = '')
|
||||
AND `{searchfield}` LIKE %(txt)s
|
||||
{mcond}
|
||||
{get_match_cond(doctype)}
|
||||
ORDER BY idx DESC, name
|
||||
LIMIT %(limit)s offset %(offset)s
|
||||
""".format(
|
||||
account_type_condition=account_type_condition,
|
||||
searchfield=searchfield,
|
||||
mcond=get_match_cond(doctype),
|
||||
),
|
||||
""",
|
||||
dict(
|
||||
account_types=filters.get("account_type"),
|
||||
company=filters.get("company"),
|
||||
disabled=filters.get("disabled", 0),
|
||||
currency=company_currency,
|
||||
txt="%{}%".format(txt),
|
||||
txt=f"%{txt}%",
|
||||
offset=start,
|
||||
limit=page_len,
|
||||
),
|
||||
@@ -215,7 +211,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
searchfields = meta.get_search_fields()
|
||||
|
||||
columns = ""
|
||||
extra_searchfields = [field for field in searchfields if not field in ["name", "description"]]
|
||||
extra_searchfields = [field for field in searchfields if field not in ["name", "description"]]
|
||||
|
||||
if extra_searchfields:
|
||||
columns += ", " + ", ".join(extra_searchfields)
|
||||
@@ -227,7 +223,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
searchfields = searchfields + [
|
||||
field
|
||||
for field in [searchfield or "name", "item_code", "item_group", "item_name"]
|
||||
if not field in searchfields
|
||||
if field not in searchfields
|
||||
]
|
||||
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||
|
||||
@@ -235,7 +231,9 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
if filters.get("customer") or filters.get("supplier"):
|
||||
party = filters.get("customer") or filters.get("supplier")
|
||||
item_rules_list = frappe.get_all(
|
||||
"Party Specific Item", filters={"party": party}, fields=["restrict_based_on", "based_on_value"]
|
||||
"Party Specific Item",
|
||||
filters={"party": party},
|
||||
fields=["restrict_based_on", "based_on_value"],
|
||||
)
|
||||
|
||||
filters_dict = {}
|
||||
@@ -384,11 +382,11 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
|
||||
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
select %(fields)s
|
||||
select {fields}
|
||||
from `tabDelivery Note`
|
||||
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
||||
where `tabDelivery Note`.`{key}` like {txt} and
|
||||
`tabDelivery Note`.docstatus = 1
|
||||
and status not in ('Stopped', 'Closed') %(fcond)s
|
||||
and status not in ('Stopped', 'Closed') {fcond}
|
||||
and (
|
||||
(`tabDelivery Note`.is_return = 0 and `tabDelivery Note`.per_billed < 100)
|
||||
or (`tabDelivery Note`.grand_total = 0 and `tabDelivery Note`.per_billed < 100)
|
||||
@@ -397,17 +395,16 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
|
||||
and return_against in (select name from `tabDelivery Note` where per_billed < 100)
|
||||
)
|
||||
)
|
||||
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc limit %(page_len)s offset %(start)s
|
||||
"""
|
||||
% {
|
||||
"fields": ", ".join(["`tabDelivery Note`.{0}".format(f) for f in fields]),
|
||||
"key": searchfield,
|
||||
"fcond": get_filters_cond(doctype, filters, []),
|
||||
"mcond": get_match_cond(doctype),
|
||||
"start": start,
|
||||
"page_len": page_len,
|
||||
"txt": "%(txt)s",
|
||||
},
|
||||
{mcond} order by `tabDelivery Note`.`{key}` asc limit {page_len} offset {start}
|
||||
""".format(
|
||||
fields=", ".join([f"`tabDelivery Note`.{f}" for f in fields]),
|
||||
key=searchfield,
|
||||
fcond=get_filters_cond(doctype, filters, []),
|
||||
mcond=get_match_cond(doctype),
|
||||
start=start,
|
||||
page_len=page_len,
|
||||
txt="%(txt)s",
|
||||
),
|
||||
{"txt": ("%%%s%%" % txt)},
|
||||
as_dict=as_dict,
|
||||
)
|
||||
@@ -426,7 +423,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
"item_code": filters.get("item_code"),
|
||||
"warehouse": filters.get("warehouse"),
|
||||
"posting_date": filters.get("posting_date"),
|
||||
"txt": "%{0}%".format(txt),
|
||||
"txt": f"%{txt}%",
|
||||
"start": start,
|
||||
"page_len": page_len,
|
||||
}
|
||||
@@ -452,7 +449,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||
|
||||
batch_nos = frappe.db.sql(
|
||||
"""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||
f"""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
{search_columns}
|
||||
from `tabStock Ledger Entry` sle
|
||||
@@ -468,23 +465,17 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
{search_cond})
|
||||
and batch.docstatus < 2
|
||||
{cond}
|
||||
{match_conditions}
|
||||
{get_match_cond(doctype)}
|
||||
group by batch_no {having_clause}
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(page_len)s offset %(start)s""".format(
|
||||
search_columns=search_columns,
|
||||
cond=cond,
|
||||
match_conditions=get_match_cond(doctype),
|
||||
having_clause=having_clause,
|
||||
search_cond=search_cond,
|
||||
),
|
||||
limit %(page_len)s offset %(start)s""",
|
||||
args,
|
||||
)
|
||||
|
||||
return batch_nos
|
||||
else:
|
||||
return frappe.db.sql(
|
||||
"""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date)
|
||||
f"""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date)
|
||||
{search_columns}
|
||||
from `tabBatch` batch
|
||||
where batch.disabled = 0
|
||||
@@ -494,16 +485,11 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
or manufacturing_date like %(txt)s
|
||||
{search_cond})
|
||||
and docstatus < 2
|
||||
{0}
|
||||
{match_conditions}
|
||||
{cond}
|
||||
{get_match_cond(doctype)}
|
||||
|
||||
order by expiry_date, name desc
|
||||
limit %(page_len)s offset %(start)s""".format(
|
||||
cond,
|
||||
search_columns=search_columns,
|
||||
search_cond=search_cond,
|
||||
match_conditions=get_match_cond(doctype),
|
||||
),
|
||||
limit %(page_len)s offset %(start)s""",
|
||||
args,
|
||||
)
|
||||
|
||||
@@ -516,7 +502,7 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
if isinstance(filters, dict):
|
||||
for key, val in filters.items():
|
||||
if isinstance(val, (list, tuple)):
|
||||
if isinstance(val, list | tuple):
|
||||
filter_list.append([doctype, key, val[0], val[1]])
|
||||
else:
|
||||
filter_list.append([doctype, key, "=", val])
|
||||
@@ -577,24 +563,20 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
condition += f"and tabAccount.disabled = {filters.get('disabled', 0)}"
|
||||
|
||||
return frappe.db.sql(
|
||||
"""select tabAccount.name from `tabAccount`
|
||||
f"""select tabAccount.name from `tabAccount`
|
||||
where (tabAccount.report_type = "Profit and Loss"
|
||||
or tabAccount.account_type in ("Income Account", "Temporary"))
|
||||
and tabAccount.is_group=0
|
||||
and tabAccount.`{key}` LIKE %(txt)s
|
||||
{condition} {match_condition}
|
||||
order by idx desc, name""".format(
|
||||
condition=condition, match_condition=get_match_cond(doctype), key=searchfield
|
||||
),
|
||||
and tabAccount.`{searchfield}` LIKE %(txt)s
|
||||
{condition} {get_match_cond(doctype)}
|
||||
order by idx desc, name""",
|
||||
{"txt": "%" + txt + "%", "company": filters.get("company", "")},
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_filtered_dimensions(
|
||||
doctype, txt, searchfield, start, page_len, filters, reference_doctype=None
|
||||
):
|
||||
def get_filtered_dimensions(doctype, txt, searchfield, start, page_len, filters, reference_doctype=None):
|
||||
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import (
|
||||
get_dimension_filter_map,
|
||||
)
|
||||
@@ -660,15 +642,13 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
condition += "and tabAccount.company = %(company)s"
|
||||
|
||||
return frappe.db.sql(
|
||||
"""select tabAccount.name from `tabAccount`
|
||||
f"""select tabAccount.name from `tabAccount`
|
||||
where (tabAccount.report_type = "Profit and Loss"
|
||||
or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed", "Capital Work in Progress"))
|
||||
and tabAccount.is_group=0
|
||||
and tabAccount.docstatus!=2
|
||||
and tabAccount.{key} LIKE %(txt)s
|
||||
{condition} {match_condition}""".format(
|
||||
condition=condition, key=searchfield, match_condition=get_match_cond(doctype)
|
||||
),
|
||||
and tabAccount.{searchfield} LIKE %(txt)s
|
||||
{condition} {get_match_cond(doctype)}""",
|
||||
{"company": filters.get("company", ""), "txt": "%" + txt + "%"},
|
||||
)
|
||||
|
||||
@@ -707,7 +687,7 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
mcond=get_match_cond(doctype),
|
||||
start=start,
|
||||
page_len=page_len,
|
||||
txt=frappe.db.escape("%{0}%".format(txt)),
|
||||
txt=frappe.db.escape(f"%{txt}%"),
|
||||
)
|
||||
|
||||
return frappe.db.sql(query)
|
||||
@@ -727,9 +707,7 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = """select batch_id from `tabBatch`
|
||||
where disabled = 0
|
||||
and (expiry_date >= CURRENT_DATE or expiry_date IS NULL)
|
||||
and name like {txt}""".format(
|
||||
txt=frappe.db.escape("%{0}%".format(txt))
|
||||
)
|
||||
and name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%"))
|
||||
|
||||
if filters and filters.get("item"):
|
||||
query += " and item = {item}".format(item=frappe.db.escape(filters.get("item")))
|
||||
@@ -763,9 +741,7 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
|
||||
select pr.name
|
||||
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pritem
|
||||
where pr.docstatus = 1 and pritem.parent = pr.name
|
||||
and pr.name like {txt}""".format(
|
||||
txt=frappe.db.escape("%{0}%".format(txt))
|
||||
)
|
||||
and pr.name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%"))
|
||||
|
||||
if filters and filters.get("item_code"):
|
||||
query += " and pritem.item_code = {item_code}".format(
|
||||
@@ -782,9 +758,7 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
|
||||
select pi.name
|
||||
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` piitem
|
||||
where pi.docstatus = 1 and piitem.parent = pi.name
|
||||
and pi.name like {txt}""".format(
|
||||
txt=frappe.db.escape("%{0}%".format(txt))
|
||||
)
|
||||
and pi.name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%"))
|
||||
|
||||
if filters and filters.get("item_code"):
|
||||
query += " and piitem.item_code = {item_code}".format(
|
||||
@@ -806,7 +780,6 @@ def get_doctypes_for_closing(doctype, txt, searchfield, start, page_len, filters
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
item_doc = frappe.get_cached_doc("Item", filters.get("item_code"))
|
||||
item_group = filters.get("item_group")
|
||||
company = filters.get("company")
|
||||
@@ -818,9 +791,7 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
||||
item_group = item_group_doc.parent_item_group
|
||||
|
||||
if not taxes:
|
||||
return frappe.get_all(
|
||||
"Item Tax Template", filters={"disabled": 0, "company": company}, as_list=True
|
||||
)
|
||||
return frappe.get_all("Item Tax Template", filters={"disabled": 0, "company": company}, as_list=True)
|
||||
else:
|
||||
valid_from = filters.get("valid_from")
|
||||
valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
|
||||
@@ -842,7 +813,7 @@ def get_fields(doctype, fields=None):
|
||||
meta = frappe.get_meta(doctype)
|
||||
fields.extend(meta.get_search_fields())
|
||||
|
||||
if meta.title_field and not meta.title_field.strip() in fields:
|
||||
if meta.title_field and meta.title_field.strip() not in fields:
|
||||
fields.insert(1, meta.title_field.strip())
|
||||
|
||||
return unique(fields)
|
||||
|
||||
@@ -26,9 +26,7 @@ def validate_return(doc):
|
||||
|
||||
def validate_return_against(doc):
|
||||
if not frappe.db.exists(doc.doctype, doc.return_against):
|
||||
frappe.throw(
|
||||
_("Invalid {0}: {1}").format(doc.meta.get_label("return_against"), doc.return_against)
|
||||
)
|
||||
frappe.throw(_("Invalid {0}: {1}").format(doc.meta.get_label("return_against"), doc.return_against))
|
||||
else:
|
||||
ref_doc = frappe.get_doc(doc.doctype, doc.return_against)
|
||||
|
||||
@@ -40,8 +38,8 @@ def validate_return_against(doc):
|
||||
and ref_doc.docstatus.is_submitted()
|
||||
):
|
||||
# validate posting date time
|
||||
return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00")
|
||||
ref_posting_datetime = "%s %s" % (
|
||||
return_posting_datetime = "{} {}".format(doc.posting_date, doc.get("posting_time") or "00:00:00")
|
||||
ref_posting_datetime = "{} {}".format(
|
||||
ref_doc.posting_date,
|
||||
ref_doc.get("posting_time") or "00:00:00",
|
||||
)
|
||||
@@ -81,7 +79,7 @@ def validate_returned_items(doc):
|
||||
select_fields += ",rejected_qty, received_qty"
|
||||
|
||||
for d in frappe.db.sql(
|
||||
"""select {0} from `tab{1} Item` where parent = %s""".format(select_fields, doc.doctype),
|
||||
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
|
||||
doc.return_against,
|
||||
as_dict=1,
|
||||
):
|
||||
@@ -249,17 +247,15 @@ def get_already_returned_items(doc):
|
||||
sum(abs(child.received_qty) * child.conversion_factor) as received_qty"""
|
||||
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
select {0}
|
||||
f"""
|
||||
select {column}
|
||||
from
|
||||
`tab{1} Item` child, `tab{2}` par
|
||||
`tab{doc.doctype} Item` child, `tab{doc.doctype}` par
|
||||
where
|
||||
child.parent = par.name and par.docstatus = 1
|
||||
and par.is_return = 1 and par.return_against = %s
|
||||
group by item_code
|
||||
""".format(
|
||||
column, doc.doctype, doc.doctype
|
||||
),
|
||||
""",
|
||||
doc.return_against,
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -292,22 +288,22 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype):
|
||||
party_type = "customer"
|
||||
|
||||
fields = [
|
||||
"sum(abs(`tab{0}`.qty)) as qty".format(child_doctype),
|
||||
f"sum(abs(`tab{child_doctype}`.qty)) as qty",
|
||||
]
|
||||
|
||||
if doctype != "Subcontracting Receipt":
|
||||
fields += [
|
||||
"sum(abs(`tab{0}`.stock_qty)) as stock_qty".format(child_doctype),
|
||||
f"sum(abs(`tab{child_doctype}`.stock_qty)) as stock_qty",
|
||||
]
|
||||
|
||||
if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
|
||||
fields += [
|
||||
"sum(abs(`tab{0}`.rejected_qty)) as rejected_qty".format(child_doctype),
|
||||
"sum(abs(`tab{0}`.received_qty)) as received_qty".format(child_doctype),
|
||||
f"sum(abs(`tab{child_doctype}`.rejected_qty)) as rejected_qty",
|
||||
f"sum(abs(`tab{child_doctype}`.received_qty)) as received_qty",
|
||||
]
|
||||
|
||||
if doctype == "Purchase Receipt":
|
||||
fields += ["sum(abs(`tab{0}`.received_stock_qty)) as received_stock_qty".format(child_doctype)]
|
||||
fields += [f"sum(abs(`tab{child_doctype}`.received_stock_qty)) as received_stock_qty"]
|
||||
|
||||
# Used retrun against and supplier and is_retrun because there is an index added for it
|
||||
data = frappe.get_all(
|
||||
@@ -523,8 +519,7 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
|
||||
"docstatus": ["=", 1],
|
||||
},
|
||||
},
|
||||
doctype
|
||||
+ " Item": {
|
||||
doctype + " Item": {
|
||||
"doctype": doctype + " Item",
|
||||
"field_map": {"serial_no": "serial_no", "batch_no": "batch_no", "bom": "bom"},
|
||||
"postprocess": update_item,
|
||||
@@ -623,11 +618,7 @@ def get_filters(
|
||||
if reference_voucher_detail_no:
|
||||
filters["voucher_detail_no"] = reference_voucher_detail_no
|
||||
|
||||
if (
|
||||
voucher_type in ["Purchase Receipt", "Purchase Invoice"]
|
||||
and item_row
|
||||
and item_row.get("warehouse")
|
||||
):
|
||||
if voucher_type in ["Purchase Receipt", "Purchase Invoice"] and item_row and item_row.get("warehouse"):
|
||||
filters["warehouse"] = item_row.get("warehouse")
|
||||
|
||||
return filters
|
||||
|
||||
@@ -23,13 +23,13 @@ class SellingController(StockController):
|
||||
return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total)
|
||||
|
||||
def onload(self):
|
||||
super(SellingController, self).onload()
|
||||
super().onload()
|
||||
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
||||
for item in self.get("items") + (self.get("packed_items") or []):
|
||||
item.update(get_bin_details(item.item_code, item.warehouse, include_child_warehouses=True))
|
||||
|
||||
def validate(self):
|
||||
super(SellingController, self).validate()
|
||||
super().validate()
|
||||
self.validate_items()
|
||||
if not self.get("is_debit_note"):
|
||||
self.validate_max_discount()
|
||||
@@ -44,7 +44,7 @@ class SellingController(StockController):
|
||||
self.validate_auto_repeat_subscription_dates()
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
super(SellingController, self).set_missing_values(for_validate)
|
||||
super().set_missing_values(for_validate)
|
||||
|
||||
# set contact and address details for customer, if they are not mentioned
|
||||
self.set_missing_lead_customer_details(for_validate=for_validate)
|
||||
@@ -284,7 +284,10 @@ class SellingController(StockController):
|
||||
|
||||
if flt(item.base_net_rate) < flt(last_valuation_rate_in_sales_uom):
|
||||
throw_message(
|
||||
item.idx, item.item_name, last_valuation_rate_in_sales_uom, "valuation rate (Moving Average)"
|
||||
item.idx,
|
||||
item.item_name,
|
||||
last_valuation_rate_in_sales_uom,
|
||||
"valuation rate (Moving Average)",
|
||||
)
|
||||
|
||||
def get_item_list(self):
|
||||
@@ -412,7 +415,8 @@ class SellingController(StockController):
|
||||
"Cancelled"
|
||||
]:
|
||||
frappe.throw(
|
||||
_("{0} {1} is cancelled or closed").format(_("Sales Order"), so), frappe.InvalidStatusError
|
||||
_("{0} {1} is cancelled or closed").format(_("Sales Order"), so),
|
||||
frappe.InvalidStatusError,
|
||||
)
|
||||
|
||||
sales_order.update_reserved_qty(so_item_rows)
|
||||
@@ -587,7 +591,8 @@ class SellingController(StockController):
|
||||
if self.doctype in ["Sales Order", "Quotation"]:
|
||||
for item in self.items:
|
||||
item.gross_profit = flt(
|
||||
((item.base_rate - flt(item.valuation_rate)) * item.stock_qty), self.precision("amount", item)
|
||||
((item.base_rate - flt(item.valuation_rate)) * item.stock_qty),
|
||||
self.precision("amount", item),
|
||||
)
|
||||
|
||||
def set_customer_address(self):
|
||||
@@ -664,9 +669,9 @@ class SellingController(StockController):
|
||||
if d.get("target_warehouse") and d.get("warehouse") == d.get("target_warehouse"):
|
||||
warehouse = frappe.bold(d.get("target_warehouse"))
|
||||
frappe.throw(
|
||||
_("Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same").format(
|
||||
d.idx, warehouse, warehouse
|
||||
)
|
||||
_(
|
||||
"Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same"
|
||||
).format(d.idx, warehouse, warehouse)
|
||||
)
|
||||
|
||||
if not self.get("is_internal_customer") and any(d.get("target_warehouse") for d in items):
|
||||
|
||||
@@ -253,9 +253,7 @@ class StatusUpdater(Document):
|
||||
"""select item_code, `{target_ref_field}`,
|
||||
`{target_field}`, parenttype, parent from `tab{target_dt}`
|
||||
where `{target_ref_field}` < `{target_field}`
|
||||
and name=%s and docstatus=1""".format(
|
||||
**args
|
||||
),
|
||||
and name=%s and docstatus=1""".format(**args),
|
||||
args["name"],
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -300,9 +298,7 @@ class StatusUpdater(Document):
|
||||
role_allowed_to_over_bill = frappe.db.get_single_value(
|
||||
"Accounts Settings", "role_allowed_to_over_bill"
|
||||
)
|
||||
role = (
|
||||
role_allowed_to_over_deliver_receive if qty_or_amount == "qty" else role_allowed_to_over_bill
|
||||
)
|
||||
role = role_allowed_to_over_deliver_receive if qty_or_amount == "qty" else role_allowed_to_over_bill
|
||||
|
||||
overflow_percent = (
|
||||
(item[args["target_field"]] - item[args["target_ref_field"]]) / item[args["target_ref_field"]]
|
||||
@@ -413,12 +409,11 @@ class StatusUpdater(Document):
|
||||
args["second_source_extra_cond"] = ""
|
||||
|
||||
args["second_source_condition"] = frappe.db.sql(
|
||||
""" select ifnull((select sum(%(second_source_field)s)
|
||||
from `tab%(second_source_dt)s`
|
||||
where `%(second_join_field)s`='%(detail_id)s'
|
||||
and (`tab%(second_source_dt)s`.docstatus=1)
|
||||
%(second_source_extra_cond)s), 0) """
|
||||
% args
|
||||
""" select ifnull((select sum({second_source_field})
|
||||
from `tab{second_source_dt}`
|
||||
where `{second_join_field}`='{detail_id}'
|
||||
and (`tab{second_source_dt}`.docstatus=1)
|
||||
{second_source_extra_cond}), 0) """.format(**args)
|
||||
)[0][0]
|
||||
|
||||
if args["detail_id"]:
|
||||
@@ -428,11 +423,10 @@ class StatusUpdater(Document):
|
||||
args["source_dt_value"] = (
|
||||
frappe.db.sql(
|
||||
"""
|
||||
(select ifnull(sum(%(source_field)s), 0)
|
||||
from `tab%(source_dt)s` where `%(join_field)s`='%(detail_id)s'
|
||||
and (docstatus=1 %(cond)s) %(extra_cond)s)
|
||||
"""
|
||||
% args
|
||||
(select ifnull(sum({source_field}), 0)
|
||||
from `tab{source_dt}` where `{join_field}`='{detail_id}'
|
||||
and (docstatus=1 {cond}) {extra_cond})
|
||||
""".format(**args)
|
||||
)[0][0]
|
||||
or 0.0
|
||||
)
|
||||
@@ -441,10 +435,9 @@ class StatusUpdater(Document):
|
||||
args["source_dt_value"] += flt(args["second_source_condition"])
|
||||
|
||||
frappe.db.sql(
|
||||
"""update `tab%(target_dt)s`
|
||||
set %(target_field)s = %(source_dt_value)s %(update_modified)s
|
||||
where name='%(detail_id)s'"""
|
||||
% args
|
||||
"""update `tab{target_dt}`
|
||||
set {target_field} = {source_dt_value} {update_modified}
|
||||
where name='{detail_id}'""".format(**args)
|
||||
)
|
||||
|
||||
def _update_percent_field_in_targets(self, args, update_modified=True):
|
||||
@@ -471,26 +464,24 @@ class StatusUpdater(Document):
|
||||
|
||||
if args.get("target_parent_field"):
|
||||
frappe.db.sql(
|
||||
"""update `tab%(target_parent_dt)s`
|
||||
set %(target_parent_field)s = round(
|
||||
"""update `tab{target_parent_dt}`
|
||||
set {target_parent_field} = round(
|
||||
ifnull((select
|
||||
ifnull(sum(case when abs(%(target_ref_field)s) > abs(%(target_field)s) then abs(%(target_field)s) else abs(%(target_ref_field)s) end), 0)
|
||||
/ sum(abs(%(target_ref_field)s)) * 100
|
||||
from `tab%(target_dt)s` where parent='%(name)s' and parenttype='%(target_parent_dt)s' having sum(abs(%(target_ref_field)s)) > 0), 0), 6)
|
||||
%(update_modified)s
|
||||
where name='%(name)s'"""
|
||||
% args
|
||||
ifnull(sum(case when abs({target_ref_field}) > abs({target_field}) then abs({target_field}) else abs({target_ref_field}) end), 0)
|
||||
/ sum(abs({target_ref_field})) * 100
|
||||
from `tab{target_dt}` where parent='{name}' and parenttype='{target_parent_dt}' having sum(abs({target_ref_field})) > 0), 0), 6)
|
||||
{update_modified}
|
||||
where name='{name}'""".format(**args)
|
||||
)
|
||||
|
||||
# update field
|
||||
if args.get("status_field"):
|
||||
frappe.db.sql(
|
||||
"""update `tab%(target_parent_dt)s`
|
||||
set %(status_field)s = (case when %(target_parent_field)s<0.001 then 'Not %(keyword)s'
|
||||
else case when %(target_parent_field)s>=99.999999 then 'Fully %(keyword)s'
|
||||
else 'Partly %(keyword)s' end end)
|
||||
where name='%(name)s'"""
|
||||
% args
|
||||
"""update `tab{target_parent_dt}`
|
||||
set {status_field} = (case when {target_parent_field}<0.001 then 'Not {keyword}'
|
||||
else case when {target_parent_field}>=99.999999 then 'Fully {keyword}'
|
||||
else 'Partly {keyword}' end end)
|
||||
where name='{name}'""".format(**args)
|
||||
)
|
||||
|
||||
if update_modified:
|
||||
@@ -503,21 +494,19 @@ class StatusUpdater(Document):
|
||||
args["update_modified"] = ""
|
||||
return
|
||||
|
||||
args["update_modified"] = ", modified = {0}, modified_by = {1}".format(
|
||||
args["update_modified"] = ", modified = {}, modified_by = {}".format(
|
||||
frappe.db.escape(now()), frappe.db.escape(frappe.session.user)
|
||||
)
|
||||
|
||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||
ref_fieldname = frappe.scrub(ref_dt)
|
||||
|
||||
ref_docs = [
|
||||
item.get(ref_fieldname) for item in (self.get("items") or []) if item.get(ref_fieldname)
|
||||
]
|
||||
ref_docs = [item.get(ref_fieldname) for item in (self.get("items") or []) if item.get(ref_fieldname)]
|
||||
if not ref_docs:
|
||||
return
|
||||
|
||||
zero_amount_refdocs = frappe.db.sql_list(
|
||||
"""
|
||||
f"""
|
||||
SELECT
|
||||
name
|
||||
from
|
||||
@@ -526,9 +515,7 @@ class StatusUpdater(Document):
|
||||
docstatus = 1
|
||||
and base_net_total = 0
|
||||
and name in %(ref_docs)s
|
||||
""".format(
|
||||
ref_dt=ref_dt
|
||||
),
|
||||
""",
|
||||
{"ref_docs": ref_docs},
|
||||
)
|
||||
|
||||
@@ -539,9 +526,8 @@ class StatusUpdater(Document):
|
||||
for ref_dn in zero_amount_refdoc:
|
||||
ref_doc_qty = flt(
|
||||
frappe.db.sql(
|
||||
"""select ifnull(sum(qty), 0) from `tab%s Item`
|
||||
where parent=%s"""
|
||||
% (ref_dt, "%s"),
|
||||
"""select ifnull(sum(qty), 0) from `tab{} Item`
|
||||
where parent={}""".format(ref_dt, "%s"),
|
||||
(ref_dn),
|
||||
)[0][0]
|
||||
)
|
||||
@@ -549,8 +535,7 @@ class StatusUpdater(Document):
|
||||
billed_qty = flt(
|
||||
frappe.db.sql(
|
||||
"""select ifnull(sum(qty), 0)
|
||||
from `tab%s Item` where %s=%s and docstatus=1"""
|
||||
% (self.doctype, ref_fieldname, "%s"),
|
||||
from `tab{} Item` where {}={} and docstatus=1""".format(self.doctype, ref_fieldname, "%s"),
|
||||
(ref_dn),
|
||||
)[0][0]
|
||||
)
|
||||
@@ -608,13 +593,13 @@ def get_allowance_for(
|
||||
)
|
||||
|
||||
if qty_or_amount == "qty" and not qty_allowance:
|
||||
if global_qty_allowance == None:
|
||||
if global_qty_allowance is None:
|
||||
global_qty_allowance = flt(
|
||||
frappe.get_cached_value("Stock Settings", None, "over_delivery_receipt_allowance")
|
||||
)
|
||||
qty_allowance = global_qty_allowance
|
||||
elif qty_or_amount == "amount" and not over_billing_allowance:
|
||||
if global_amount_allowance == None:
|
||||
if global_amount_allowance is None:
|
||||
global_amount_allowance = flt(
|
||||
frappe.get_cached_value("Accounts Settings", None, "over_billing_allowance")
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from typing import List, Tuple
|
||||
|
||||
import frappe
|
||||
from frappe import _, bold
|
||||
@@ -42,7 +41,7 @@ class BatchExpiredError(frappe.ValidationError):
|
||||
|
||||
class StockController(AccountsController):
|
||||
def validate(self):
|
||||
super(StockController, self).validate()
|
||||
super().validate()
|
||||
if not self.get("is_return"):
|
||||
self.validate_inspection()
|
||||
self.validate_serialized_batch()
|
||||
@@ -126,10 +125,7 @@ class StockController(AccountsController):
|
||||
# remove extra whitespace and store one serial no on each line
|
||||
row.serial_no = clean_serial_no_string(row.serial_no)
|
||||
|
||||
def get_gl_entries(
|
||||
self, warehouse_account=None, default_expense_account=None, default_cost_center=None
|
||||
):
|
||||
|
||||
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None):
|
||||
if not warehouse_account:
|
||||
warehouse_account = get_warehouse_account_map(self.company)
|
||||
|
||||
@@ -167,7 +163,9 @@ class StockController(AccountsController):
|
||||
"project": item_row.project or self.get("project"),
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(sle.stock_value_difference, precision),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
"is_opening": item_row.get("is_opening")
|
||||
or self.get("is_opening")
|
||||
or "No",
|
||||
},
|
||||
warehouse_account[sle.warehouse]["account_currency"],
|
||||
item=item_row,
|
||||
@@ -183,7 +181,9 @@ class StockController(AccountsController):
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": -1 * flt(sle.stock_value_difference, precision),
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
"is_opening": item_row.get("is_opening")
|
||||
or self.get("is_opening")
|
||||
or "No",
|
||||
},
|
||||
item=item_row,
|
||||
)
|
||||
@@ -250,9 +250,7 @@ class StockController(AccountsController):
|
||||
|
||||
def get_debit_field_precision(self):
|
||||
if not frappe.flags.debit_field_precision:
|
||||
frappe.flags.debit_field_precision = frappe.get_precision(
|
||||
"GL Entry", "debit_in_account_currency"
|
||||
)
|
||||
frappe.flags.debit_field_precision = frappe.get_precision("GL Entry", "debit_in_account_currency")
|
||||
|
||||
return frappe.flags.debit_field_precision
|
||||
|
||||
@@ -285,7 +283,7 @@ class StockController(AccountsController):
|
||||
|
||||
return details
|
||||
|
||||
def get_items_and_warehouses(self) -> Tuple[List[str], List[str]]:
|
||||
def get_items_and_warehouses(self) -> tuple[list[str], list[str]]:
|
||||
"""Get list of items and warehouses affected by a transaction"""
|
||||
|
||||
if not (hasattr(self, "items") or hasattr(self, "packed_items")):
|
||||
@@ -395,9 +393,7 @@ class StockController(AccountsController):
|
||||
if not d.batch_no:
|
||||
continue
|
||||
|
||||
frappe.db.set_value(
|
||||
"Serial No", {"batch_no": d.batch_no, "status": "Inactive"}, "batch_no", None
|
||||
)
|
||||
frappe.db.set_value("Serial No", {"batch_no": d.batch_no, "status": "Inactive"}, "batch_no", None)
|
||||
|
||||
d.batch_no = None
|
||||
d.db_set("batch_no", None)
|
||||
@@ -520,9 +516,7 @@ class StockController(AccountsController):
|
||||
if item_codes:
|
||||
serialized_items = frappe.db.sql_list(
|
||||
"""select name from `tabItem`
|
||||
where has_serial_no=1 and name in ({})""".format(
|
||||
", ".join(["%s"] * len(item_codes))
|
||||
),
|
||||
where has_serial_no=1 and name in ({})""".format(", ".join(["%s"] * len(item_codes))),
|
||||
tuple(item_codes),
|
||||
)
|
||||
|
||||
@@ -610,16 +604,12 @@ class StockController(AccountsController):
|
||||
|
||||
def validate_qi_submission(self, row):
|
||||
"""Check if QI is submitted on row level, during submission"""
|
||||
action = frappe.db.get_single_value(
|
||||
"Stock Settings", "action_if_quality_inspection_is_not_submitted"
|
||||
)
|
||||
action = frappe.db.get_single_value("Stock Settings", "action_if_quality_inspection_is_not_submitted")
|
||||
qa_docstatus = frappe.db.get_value("Quality Inspection", row.quality_inspection, "docstatus")
|
||||
|
||||
if not qa_docstatus == 1:
|
||||
link = frappe.utils.get_link_to_form("Quality Inspection", row.quality_inspection)
|
||||
msg = (
|
||||
f"Row #{row.idx}: Quality Inspection {link} is not submitted for the item: {row.item_code}"
|
||||
)
|
||||
msg = f"Row #{row.idx}: Quality Inspection {link} is not submitted for the item: {row.item_code}"
|
||||
if action == "Stop":
|
||||
frappe.throw(_(msg), title=_("Inspection Submission"), exc=QualityInspectionNotSubmittedError)
|
||||
else:
|
||||
@@ -683,9 +673,7 @@ class StockController(AccountsController):
|
||||
row.from_warehouse = None
|
||||
|
||||
def validate_in_transit_warehouses(self):
|
||||
if (
|
||||
self.doctype == "Sales Invoice" and self.get("update_stock")
|
||||
) or self.doctype == "Delivery Note":
|
||||
if (self.doctype == "Sales Invoice" and self.get("update_stock")) or self.doctype == "Delivery Note":
|
||||
for item in self.get("items"):
|
||||
if not item.target_warehouse:
|
||||
frappe.throw(
|
||||
@@ -854,7 +842,9 @@ class StockController(AccountsController):
|
||||
if self.doctype == "Stock Reconciliation":
|
||||
stock_qty = flt(item.qty)
|
||||
else:
|
||||
stock_qty = flt(item.transfer_qty) if self.doctype == "Stock Entry" else flt(item.stock_qty)
|
||||
stock_qty = (
|
||||
flt(item.transfer_qty) if self.doctype == "Stock Entry" else flt(item.stock_qty)
|
||||
)
|
||||
|
||||
rule_name = rule.get("name")
|
||||
if not rule_map[rule_name]:
|
||||
@@ -870,9 +860,7 @@ class StockController(AccountsController):
|
||||
frappe.throw(msg=message, title=_("Over Receipt"))
|
||||
|
||||
def prepare_over_receipt_message(self, rule, values):
|
||||
message = _(
|
||||
"{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}."
|
||||
).format(
|
||||
message = _("{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}.").format(
|
||||
frappe.bold(values["qty_put"]),
|
||||
frappe.bold(values["item"]),
|
||||
frappe.bold(values["warehouse"]),
|
||||
@@ -923,7 +911,6 @@ class StockController(AccountsController):
|
||||
item=None,
|
||||
posting_date=None,
|
||||
):
|
||||
|
||||
gl_entry = {
|
||||
"account": account,
|
||||
"cost_center": cost_center,
|
||||
@@ -1050,9 +1037,7 @@ def future_sle_exists(args, sl_entries=None):
|
||||
and is_cancelled = 0
|
||||
GROUP BY
|
||||
item_code, warehouse
|
||||
""".format(
|
||||
" or ".join(or_conditions)
|
||||
),
|
||||
""".format(" or ".join(or_conditions)),
|
||||
args,
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ from erpnext.stock.utils import get_incoming_rate
|
||||
|
||||
class SubcontractingController(StockController):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SubcontractingController, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.get("is_old_subcontracting_flow"):
|
||||
self.subcontract_data = frappe._dict(
|
||||
{
|
||||
@@ -49,7 +49,7 @@ class SubcontractingController(StockController):
|
||||
self.validate_items()
|
||||
self.create_raw_materials_supplied()
|
||||
else:
|
||||
super(SubcontractingController, self).validate()
|
||||
super().validate()
|
||||
|
||||
def remove_empty_rows(self):
|
||||
for key in ["service_items", "items", "supplied_items"]:
|
||||
@@ -85,11 +85,15 @@ class SubcontractingController(StockController):
|
||||
bom = frappe.get_doc("BOM", item.bom)
|
||||
if not bom.is_active:
|
||||
frappe.throw(
|
||||
_("Row {0}: Please select an active BOM for Item {1}.").format(item.idx, item.item_name)
|
||||
_("Row {0}: Please select an active BOM for Item {1}.").format(
|
||||
item.idx, item.item_name
|
||||
)
|
||||
)
|
||||
if bom.item != item.item_code:
|
||||
frappe.throw(
|
||||
_("Row {0}: Please select an valid BOM for Item {1}.").format(item.idx, item.item_name)
|
||||
_("Row {0}: Please select an valid BOM for Item {1}.").format(
|
||||
item.idx, item.item_name
|
||||
)
|
||||
)
|
||||
else:
|
||||
frappe.throw(_("Row {0}: Please select a BOM for Item {1}.").format(item.idx, item.item_name))
|
||||
@@ -165,7 +169,6 @@ class SubcontractingController(StockController):
|
||||
fields=["item_code", "(qty - received_qty) as qty", "parent", "name"],
|
||||
filters={"docstatus": 1, "parent": ("in", self.subcontract_orders)},
|
||||
):
|
||||
|
||||
self.qty_to_be_received[(row.item_code, row.parent)] += row.qty
|
||||
|
||||
def __get_transferred_items(self):
|
||||
@@ -253,9 +256,7 @@ class SubcontractingController(StockController):
|
||||
if not receipt_items:
|
||||
return ([], {}) if return_consumed_items else None
|
||||
|
||||
receipt_items = {
|
||||
item.name: item.get(self.subcontract_data.order_field) for item in receipt_items
|
||||
}
|
||||
receipt_items = {item.name: item.get(self.subcontract_data.order_field) for item in receipt_items}
|
||||
consumed_materials = self.__get_consumed_items(doctype, receipt_items.keys())
|
||||
|
||||
if return_consumed_items:
|
||||
@@ -370,9 +371,7 @@ class SubcontractingController(StockController):
|
||||
[doctype, "sourced_by_supplier", "=", 0],
|
||||
]
|
||||
|
||||
return (
|
||||
frappe.get_all("BOM", fields=fields, filters=filters, order_by=f"`tab{doctype}`.`idx`") or []
|
||||
)
|
||||
return frappe.get_all("BOM", fields=fields, filters=filters, order_by=f"`tab{doctype}`.`idx`") or []
|
||||
|
||||
def __update_reserve_warehouse(self, row, item):
|
||||
if self.doctype == self.subcontract_data.order_doctype:
|
||||
@@ -809,7 +808,8 @@ class SubcontractingController(StockController):
|
||||
|
||||
if mr_obj.status in ["Stopped", "Cancelled"]:
|
||||
frappe.throw(
|
||||
_("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError
|
||||
_("Material Request {0} is cancelled or stopped").format(mr),
|
||||
frappe.InvalidStatusError,
|
||||
)
|
||||
|
||||
mr_obj.update_requested_qty(mr_item_rows)
|
||||
@@ -892,8 +892,10 @@ def make_rm_stock_entry(
|
||||
|
||||
for fg_item_code in fg_item_code_list:
|
||||
for rm_item in rm_items:
|
||||
|
||||
if rm_item.get("main_item_code") == fg_item_code or rm_item.get("item_code") == fg_item_code:
|
||||
if (
|
||||
rm_item.get("main_item_code") == fg_item_code
|
||||
or rm_item.get("item_code") == fg_item_code
|
||||
):
|
||||
rm_item_code = rm_item.get("rm_item_code")
|
||||
|
||||
items_dict = {
|
||||
@@ -904,13 +906,16 @@ def make_rm_stock_entry(
|
||||
"description": item_wh.get(rm_item_code, {}).get("description", ""),
|
||||
"qty": rm_item.get("qty")
|
||||
or max(rm_item.get("required_qty") - rm_item.get("total_supplied_qty"), 0),
|
||||
"from_warehouse": rm_item.get("warehouse") or rm_item.get("reserve_warehouse"),
|
||||
"from_warehouse": rm_item.get("warehouse")
|
||||
or rm_item.get("reserve_warehouse"),
|
||||
"to_warehouse": subcontract_order.supplier_warehouse,
|
||||
"stock_uom": rm_item.get("stock_uom"),
|
||||
"serial_no": rm_item.get("serial_no"),
|
||||
"batch_no": rm_item.get("batch_no"),
|
||||
"main_item_code": fg_item_code,
|
||||
"allow_alternative_item": item_wh.get(rm_item_code, {}).get("allow_alternative_item"),
|
||||
"allow_alternative_item": item_wh.get(rm_item_code, {}).get(
|
||||
"allow_alternative_item"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,9 +929,7 @@ def make_rm_stock_entry(
|
||||
frappe.throw(_("No Items selected for transfer."))
|
||||
|
||||
|
||||
def add_items_in_ste(
|
||||
ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_detail", batch_no=None
|
||||
):
|
||||
def add_items_in_ste(ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_detail", batch_no=None):
|
||||
item = ste_doc.append("items", row.item_details)
|
||||
|
||||
rm_detail = list(set(row.get(f"{rm_detail_field}s")).intersection(rm_details))
|
||||
@@ -971,7 +974,7 @@ def make_return_stock_entry_for_subcontract(
|
||||
ste_doc.company = order_doc.company
|
||||
ste_doc.is_return = 1
|
||||
|
||||
for key, value in available_materials.items():
|
||||
for _key, value in available_materials.items():
|
||||
if not value.qty:
|
||||
continue
|
||||
|
||||
@@ -989,9 +992,7 @@ def make_return_stock_entry_for_subcontract(
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_materials_from_supplier(
|
||||
subcontract_order, rm_details, order_doctype="Subcontracting Order"
|
||||
):
|
||||
def get_materials_from_supplier(subcontract_order, rm_details, order_doctype="Subcontracting Order"):
|
||||
if isinstance(rm_details, str):
|
||||
rm_details = json.loads(rm_details)
|
||||
|
||||
@@ -1005,6 +1006,4 @@ def get_materials_from_supplier(
|
||||
_("Materials are already received against the {0} {1}").format(order_doctype, subcontract_order)
|
||||
)
|
||||
|
||||
return make_return_stock_entry_for_subcontract(
|
||||
doc.available_materials, doc, rm_details, order_doctype
|
||||
)
|
||||
return make_return_stock_entry_for_subcontract(doc.available_materials, doc, rm_details, order_doctype)
|
||||
|
||||
@@ -21,7 +21,7 @@ from erpnext.stock.get_item_details import _get_item_tax_template
|
||||
from erpnext.utilities.regional import temporary_flag
|
||||
|
||||
|
||||
class calculate_taxes_and_totals(object):
|
||||
class calculate_taxes_and_totals:
|
||||
def __init__(self, doc: Document):
|
||||
self.doc = doc
|
||||
frappe.flags.round_off_applicable_accounts = []
|
||||
@@ -155,7 +155,8 @@ class calculate_taxes_and_totals(object):
|
||||
elif item.price_list_rate:
|
||||
if not item.rate or (item.pricing_rules and item.discount_percentage > 0):
|
||||
item.rate = flt(
|
||||
item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
|
||||
item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)),
|
||||
item.precision("rate"),
|
||||
)
|
||||
|
||||
item.discount_amount = item.price_list_rate * (item.discount_percentage / 100.0)
|
||||
@@ -176,7 +177,8 @@ class calculate_taxes_and_totals(object):
|
||||
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
|
||||
if flt(item.rate_with_margin) > 0:
|
||||
item.rate = flt(
|
||||
item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
|
||||
item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)),
|
||||
item.precision("rate"),
|
||||
)
|
||||
|
||||
if item.discount_amount and not item.discount_percentage:
|
||||
@@ -192,7 +194,9 @@ class calculate_taxes_and_totals(object):
|
||||
item.net_rate = item.rate
|
||||
|
||||
if (
|
||||
not item.qty and self.doc.get("is_return") and self.doc.get("doctype") != "Purchase Receipt"
|
||||
not item.qty
|
||||
and self.doc.get("is_return")
|
||||
and self.doc.get("doctype") != "Purchase Receipt"
|
||||
):
|
||||
item.amount = flt(-1 * item.rate, item.precision("amount"))
|
||||
elif not item.qty and self.doc.get("is_debit_note"):
|
||||
@@ -278,7 +282,9 @@ class calculate_taxes_and_totals(object):
|
||||
|
||||
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
|
||||
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
|
||||
item.discount_percentage = flt(item.discount_percentage, item.precision("discount_percentage"))
|
||||
item.discount_percentage = flt(
|
||||
item.discount_percentage, item.precision("discount_percentage")
|
||||
)
|
||||
|
||||
self._set_in_company_currency(item, ["net_rate", "net_amount"])
|
||||
|
||||
@@ -339,7 +345,6 @@ class calculate_taxes_and_totals(object):
|
||||
self.doc.round_floats_in(self.doc, ["total", "base_total", "net_total", "base_net_total"])
|
||||
|
||||
def calculate_shipping_charges(self):
|
||||
|
||||
# Do not apply shipping rule for POS
|
||||
if self.doc.get("is_pos"):
|
||||
return
|
||||
@@ -351,9 +356,7 @@ class calculate_taxes_and_totals(object):
|
||||
self._calculate()
|
||||
|
||||
def calculate_taxes(self):
|
||||
rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get(
|
||||
"rounding_adjustment"
|
||||
)
|
||||
rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get("rounding_adjustment")
|
||||
if not rounding_adjustment_computed:
|
||||
self.doc.rounding_adjustment = 0
|
||||
|
||||
@@ -391,7 +394,9 @@ class calculate_taxes_and_totals(object):
|
||||
# set tax after discount
|
||||
tax.tax_amount_after_discount_amount += current_tax_amount
|
||||
|
||||
current_tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(current_tax_amount, tax)
|
||||
current_tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(
|
||||
current_tax_amount, tax
|
||||
)
|
||||
|
||||
# note: grand_total_for_current_item contains the contribution of
|
||||
# item's amount, previously applied tax and the current tax on that item
|
||||
@@ -455,9 +460,7 @@ class calculate_taxes_and_totals(object):
|
||||
if tax.charge_type == "Actual":
|
||||
# distribute the tax amount proportionally to each item row
|
||||
actual = flt(tax.tax_amount, tax.precision("tax_amount"))
|
||||
current_tax_amount = (
|
||||
item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
|
||||
)
|
||||
current_tax_amount = item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
|
||||
|
||||
elif tax.charge_type == "On Net Total":
|
||||
current_tax_amount = (tax_rate / 100.0) * item.net_amount
|
||||
@@ -571,9 +574,7 @@ class calculate_taxes_and_totals(object):
|
||||
else self.doc.base_net_total
|
||||
)
|
||||
|
||||
self._set_in_company_currency(
|
||||
self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]
|
||||
)
|
||||
self._set_in_company_currency(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])
|
||||
|
||||
self.doc.round_floats_in(self.doc, ["grand_total", "base_grand_total"])
|
||||
|
||||
@@ -627,12 +628,11 @@ class calculate_taxes_and_totals(object):
|
||||
frappe.throw(_("Please select Apply Discount On"))
|
||||
|
||||
self.doc.base_discount_amount = flt(
|
||||
self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount")
|
||||
self.doc.discount_amount * self.doc.conversion_rate,
|
||||
self.doc.precision("base_discount_amount"),
|
||||
)
|
||||
|
||||
if self.doc.apply_discount_on == "Grand Total" and self.doc.get(
|
||||
"is_cash_or_non_trade_discount"
|
||||
):
|
||||
if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"):
|
||||
self.discount_amount_applied = True
|
||||
return
|
||||
|
||||
@@ -657,12 +657,17 @@ class calculate_taxes_and_totals(object):
|
||||
or total_for_discount_amount == self.doc.net_total
|
||||
) and i == len(self._items) - 1:
|
||||
discount_amount_loss = flt(
|
||||
self.doc.net_total - net_total - self.doc.discount_amount, self.doc.precision("net_total")
|
||||
self.doc.net_total - net_total - self.doc.discount_amount,
|
||||
self.doc.precision("net_total"),
|
||||
)
|
||||
|
||||
item.net_amount = flt(item.net_amount + discount_amount_loss, item.precision("net_amount"))
|
||||
item.net_amount = flt(
|
||||
item.net_amount + discount_amount_loss, item.precision("net_amount")
|
||||
)
|
||||
|
||||
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0
|
||||
item.net_rate = (
|
||||
flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0
|
||||
)
|
||||
|
||||
self._set_in_company_currency(item, ["net_rate", "net_amount"])
|
||||
|
||||
@@ -818,7 +823,6 @@ class calculate_taxes_and_totals(object):
|
||||
self.calculate_paid_amount()
|
||||
|
||||
def calculate_paid_amount(self):
|
||||
|
||||
paid_amount = base_paid_amount = 0.0
|
||||
|
||||
if self.doc.is_pos:
|
||||
@@ -918,7 +922,9 @@ class calculate_taxes_and_totals(object):
|
||||
total_paid_amount = 0
|
||||
for payment in self.doc.get("payments"):
|
||||
total_paid_amount += (
|
||||
payment.amount if self.doc.party_account_currency == self.doc.currency else payment.base_amount
|
||||
payment.amount
|
||||
if self.doc.party_account_currency == self.doc.currency
|
||||
else payment.base_amount
|
||||
)
|
||||
|
||||
pending_amount = total_amount_to_pay - total_paid_amount
|
||||
@@ -992,7 +998,7 @@ def update_itemised_tax_data(doc):
|
||||
|
||||
@erpnext.allow_regional
|
||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||
return [_("Item"), _("Taxable Amount")] + tax_accounts
|
||||
return [_("Item"), _("Taxable Amount"), *tax_accounts]
|
||||
|
||||
|
||||
@erpnext.allow_regional
|
||||
@@ -1060,7 +1066,7 @@ def get_rounded_tax_amount(itemised_tax, precision):
|
||||
row["tax_amount"] = flt(row["tax_amount"], precision)
|
||||
|
||||
|
||||
class init_landed_taxes_and_totals(object):
|
||||
class init_landed_taxes_and_totals:
|
||||
def __init__(self, doc):
|
||||
self.doc = doc
|
||||
self.tax_field = "taxes" if self.doc.doctype == "Landed Cost Voucher" else "additional_costs"
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe import qb
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.tests.utils import FrappeTestCase, change_settings
|
||||
from frappe.utils import add_days, flt, getdate, nowdate
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
from frappe.utils import add_days, getdate, nowdate
|
||||
|
||||
from erpnext import get_default_cost_center
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry
|
||||
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.party import get_party_account
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
@@ -174,9 +171,7 @@ class TestAccountsController(FrappeTestCase):
|
||||
)
|
||||
return sinv
|
||||
|
||||
def create_payment_entry(
|
||||
self, amount=1, source_exc_rate=75, posting_date=nowdate(), customer=None
|
||||
):
|
||||
def create_payment_entry(self, amount=1, source_exc_rate=75, posting_date=nowdate(), customer=None):
|
||||
"""
|
||||
Helper function to populate default values in payment entry
|
||||
"""
|
||||
@@ -294,9 +289,7 @@ class TestAccountsController(FrappeTestCase):
|
||||
.run(as_dict=True)[0]
|
||||
)
|
||||
self.assertEqual(outstanding, current_outstanding.outstanding)
|
||||
self.assertEqual(
|
||||
outstanding_in_account_currency, current_outstanding.outstanding_in_account_currency
|
||||
)
|
||||
self.assertEqual(outstanding_in_account_currency, current_outstanding.outstanding_in_account_currency)
|
||||
|
||||
def test_10_payment_against_sales_invoice(self):
|
||||
# Sales Invoice in Foreign Currency
|
||||
@@ -402,7 +395,6 @@ class TestAccountsController(FrappeTestCase):
|
||||
adv.reload()
|
||||
|
||||
# sales invoice with advance(partial amount)
|
||||
rate = 80
|
||||
rate_in_account_currency = 1
|
||||
si = self.create_sales_invoice(
|
||||
qty=2, conversion_rate=80, rate=rate_in_account_currency, do_not_submit=True
|
||||
@@ -789,7 +781,9 @@ class TestAccountsController(FrappeTestCase):
|
||||
self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0)
|
||||
|
||||
# Exchange Gain/Loss Journal should've been created.
|
||||
exc_je_for_si = [x for x in self.get_journals_for(si.doctype, si.name) if x.parent != adv.name]
|
||||
exc_je_for_si = [
|
||||
x for x in self.get_journals_for(si.doctype, si.name) if x.parent != adv.name
|
||||
]
|
||||
exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name)
|
||||
self.assertNotEqual(exc_je_for_si, [])
|
||||
self.assertEqual(len(exc_je_for_si), 1)
|
||||
@@ -1254,7 +1248,9 @@ class TestAccountsController(FrappeTestCase):
|
||||
with self.subTest(x=x):
|
||||
self.assertEqual(
|
||||
[self.cost_center, self.cost_center],
|
||||
frappe.db.get_all("Journal Entry Account", filters={"parent": x.parent}, pluck="cost_center"),
|
||||
frappe.db.get_all(
|
||||
"Journal Entry Account", filters={"parent": x.parent}, pluck="cost_center"
|
||||
),
|
||||
)
|
||||
|
||||
frappe.db.set_value("Company", self.company, "cost_center", cc)
|
||||
@@ -1419,14 +1415,15 @@ class TestAccountsController(FrappeTestCase):
|
||||
with self.subTest(x=x):
|
||||
self.assertEqual(
|
||||
[cr_note.department, cr_note.department],
|
||||
frappe.db.get_all("Journal Entry Account", filters={"parent": x.parent}, pluck="department"),
|
||||
frappe.db.get_all(
|
||||
"Journal Entry Account", filters={"parent": x.parent}, pluck="department"
|
||||
),
|
||||
)
|
||||
self.disable_dimensions()
|
||||
|
||||
def test_92_dimension_inhertiance_exc_gain_loss(self):
|
||||
# Sales Invoice in Foreign Currency
|
||||
self.setup_dimensions()
|
||||
rate = 80
|
||||
rate_in_account_currency = 1
|
||||
dpt = "Research & Development"
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ class TestMapper(unittest.TestCase):
|
||||
self.assertEqual(set(d for d in src_items), set(d.item_code for d in updated_so.items))
|
||||
|
||||
def make_quotation(self, item_list, customer):
|
||||
|
||||
qtn = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Quotation",
|
||||
|
||||
@@ -25,7 +25,7 @@ class TestTaxes(unittest.TestCase):
|
||||
"account_name": uuid4(),
|
||||
"account_type": "Tax",
|
||||
"company": self.company.name,
|
||||
"parent_account": "Duties and Taxes - {self.company.abbr}".format(self=self),
|
||||
"parent_account": f"Duties and Taxes - {self.company.abbr}",
|
||||
}
|
||||
).insert()
|
||||
self.item_group = frappe.get_doc(
|
||||
|
||||
@@ -7,13 +7,10 @@ from erpnext.controllers import queries
|
||||
|
||||
|
||||
def add_default_params(func, doctype):
|
||||
return partial(
|
||||
func, doctype=doctype, txt="", searchfield="name", start=0, page_len=20, filters=None
|
||||
)
|
||||
return partial(func, doctype=doctype, txt="", searchfield="name", start=0, page_len=20, filters=None)
|
||||
|
||||
|
||||
class TestQueries(unittest.TestCase):
|
||||
|
||||
# All tests are based on doctype/test_records.json
|
||||
|
||||
def assert_nested_in(self, item, container):
|
||||
|
||||
@@ -423,7 +423,7 @@ class TestSubcontractingController(FrappeTestCase):
|
||||
scr1.set_missing_values()
|
||||
scr1.submit()
|
||||
|
||||
for key, value in get_supplied_items(scr1).items():
|
||||
for _key, value in get_supplied_items(scr1).items():
|
||||
self.assertEqual(value.qty, 4)
|
||||
|
||||
scr2 = make_subcontracting_receipt(sco.name)
|
||||
@@ -434,7 +434,7 @@ class TestSubcontractingController(FrappeTestCase):
|
||||
scr2.set_missing_values()
|
||||
scr2.submit()
|
||||
|
||||
for key, value in get_supplied_items(scr2).items():
|
||||
for _key, value in get_supplied_items(scr2).items():
|
||||
self.assertEqual(value.qty, 4)
|
||||
|
||||
scr3 = make_subcontracting_receipt(sco.name)
|
||||
@@ -444,7 +444,7 @@ class TestSubcontractingController(FrappeTestCase):
|
||||
scr3.set_missing_values()
|
||||
scr3.submit()
|
||||
|
||||
for key, value in get_supplied_items(scr3).items():
|
||||
for _key, value in get_supplied_items(scr3).items():
|
||||
self.assertEqual(value.qty, 2)
|
||||
|
||||
def test_item_with_batch_based_on_material_transfer(self):
|
||||
@@ -729,7 +729,7 @@ class TestSubcontractingController(FrappeTestCase):
|
||||
|
||||
scr1.load_from_db()
|
||||
scr1.supplied_items[0].consumed_qty = 5
|
||||
scr1.supplied_items[0].batch_no = list(transferred_batch_no.keys())[0]
|
||||
scr1.supplied_items[0].batch_no = next(iter(transferred_batch_no.keys()))
|
||||
scr1.save()
|
||||
scr1.submit()
|
||||
|
||||
@@ -872,9 +872,7 @@ def make_stock_in_entry(**args):
|
||||
|
||||
def update_item_details(child_row, details):
|
||||
details.qty += (
|
||||
child_row.get("qty")
|
||||
if child_row.doctype == "Stock Entry Detail"
|
||||
else child_row.get("consumed_qty")
|
||||
child_row.get("qty") if child_row.doctype == "Stock Entry Detail" else child_row.get("consumed_qty")
|
||||
)
|
||||
|
||||
if child_row.serial_no:
|
||||
@@ -967,7 +965,9 @@ def make_raw_materials():
|
||||
make_item(item, properties)
|
||||
|
||||
|
||||
def make_service_item(item, properties={}):
|
||||
def make_service_item(item, properties=None):
|
||||
if properties is None:
|
||||
properties = {}
|
||||
if not frappe.db.exists("Item", item):
|
||||
properties.update({"is_stock_item": 0})
|
||||
make_item(item, properties)
|
||||
@@ -1015,9 +1015,7 @@ def make_bom_for_subcontracted_items():
|
||||
|
||||
|
||||
def set_backflush_based_on(based_on):
|
||||
frappe.db.set_value(
|
||||
"Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", based_on
|
||||
)
|
||||
frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", based_on)
|
||||
|
||||
|
||||
def get_subcontracting_order(**args):
|
||||
|
||||
@@ -44,7 +44,10 @@ class TestUtils(unittest.TestCase):
|
||||
item_code="_Test Item", qty=1, basic_rate=200, s_warehouse="_Test Warehouse - _TC"
|
||||
),
|
||||
frappe._dict(
|
||||
item_code="_Test FG Item", qty=4, t_warehouse="_Test Warehouse 1 - _TC", is_finished_item=1
|
||||
item_code="_Test FG Item",
|
||||
qty=4,
|
||||
t_warehouse="_Test Warehouse 1 - _TC",
|
||||
is_finished_item=1,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -100,12 +100,11 @@ def get_data(filters, conditions):
|
||||
else:
|
||||
inc = 1
|
||||
data1 = frappe.db.sql(
|
||||
""" select %s from `tab%s` t1, `tab%s Item` t2 %s
|
||||
where t2.parent = t1.name and t1.company = %s and %s between %s and %s and
|
||||
t1.docstatus = 1 %s %s
|
||||
group by %s
|
||||
"""
|
||||
% (
|
||||
""" select {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {} and
|
||||
t1.docstatus = 1 {} {}
|
||||
group by {}
|
||||
""".format(
|
||||
query_details,
|
||||
conditions["trans"],
|
||||
conditions["trans"],
|
||||
@@ -130,11 +129,10 @@ def get_data(filters, conditions):
|
||||
|
||||
# to get distinct value of col specified by group_by in filter
|
||||
row = frappe.db.sql(
|
||||
"""select DISTINCT(%s) from `tab%s` t1, `tab%s Item` t2 %s
|
||||
where t2.parent = t1.name and t1.company = %s and %s between %s and %s
|
||||
and t1.docstatus = 1 and %s = %s %s %s
|
||||
"""
|
||||
% (
|
||||
"""select DISTINCT({}) from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {}
|
||||
and t1.docstatus = 1 and {} = {} {} {}
|
||||
""".format(
|
||||
sel_col,
|
||||
conditions["trans"],
|
||||
conditions["trans"],
|
||||
@@ -157,11 +155,10 @@ def get_data(filters, conditions):
|
||||
|
||||
# get data for group_by filter
|
||||
row1 = frappe.db.sql(
|
||||
""" select %s , %s from `tab%s` t1, `tab%s Item` t2 %s
|
||||
where t2.parent = t1.name and t1.company = %s and %s between %s and %s
|
||||
and t1.docstatus = 1 and %s = %s and %s = %s %s %s
|
||||
"""
|
||||
% (
|
||||
""" select {} , {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {}
|
||||
and t1.docstatus = 1 and {} = {} and {} = {} {} {}
|
||||
""".format(
|
||||
sel_col,
|
||||
conditions["period_wise_select"],
|
||||
conditions["trans"],
|
||||
@@ -190,12 +187,11 @@ def get_data(filters, conditions):
|
||||
data.append(des)
|
||||
else:
|
||||
data = frappe.db.sql(
|
||||
""" select %s from `tab%s` t1, `tab%s Item` t2 %s
|
||||
where t2.parent = t1.name and t1.company = %s and %s between %s and %s and
|
||||
t1.docstatus = 1 %s %s
|
||||
group by %s
|
||||
"""
|
||||
% (
|
||||
""" select {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {} and
|
||||
t1.docstatus = 1 {} {}
|
||||
group by {}
|
||||
""".format(
|
||||
query_details,
|
||||
conditions["trans"],
|
||||
conditions["trans"],
|
||||
@@ -260,13 +256,13 @@ def get_period_wise_columns(bet_dates, period, pwc):
|
||||
|
||||
|
||||
def get_period_wise_query(bet_dates, trans_date, query_details):
|
||||
query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.stock_qty, NULL)),
|
||||
SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.base_net_amount, NULL)),
|
||||
""" % {
|
||||
"trans_date": trans_date,
|
||||
"sd": bet_dates[0],
|
||||
"ed": bet_dates[1],
|
||||
}
|
||||
query_details += """SUM(IF(t1.{trans_date} BETWEEN '{sd}' AND '{ed}', t2.stock_qty, NULL)),
|
||||
SUM(IF(t1.{trans_date} BETWEEN '{sd}' AND '{ed}', t2.base_net_amount, NULL)),
|
||||
""".format(
|
||||
trans_date=trans_date,
|
||||
sd=bet_dates[0],
|
||||
ed=bet_dates[1],
|
||||
)
|
||||
return query_details
|
||||
|
||||
|
||||
@@ -282,7 +278,7 @@ def get_period_date_ranges(period, fiscal_year=None, year_start_date=None):
|
||||
increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(period)
|
||||
|
||||
period_date_ranges = []
|
||||
for i in range(1, 13, increment):
|
||||
for _i in range(1, 13, increment):
|
||||
period_end_date = getdate(year_start_date) + relativedelta(months=increment, days=-1)
|
||||
if period_end_date > getdate(year_end_date):
|
||||
period_end_date = year_end_date
|
||||
@@ -331,9 +327,7 @@ def based_wise_columns_query(based_on, trans):
|
||||
"Territory:Link/Territory:120",
|
||||
]
|
||||
based_on_details["based_on_select"] = "t1.customer_name, t1.territory, "
|
||||
based_on_details["based_on_group_by"] = (
|
||||
"t1.party_name" if trans == "Quotation" else "t1.customer"
|
||||
)
|
||||
based_on_details["based_on_group_by"] = "t1.party_name" if trans == "Quotation" else "t1.customer"
|
||||
based_on_details["addl_tables"] = ""
|
||||
|
||||
elif based_on == "Customer Group":
|
||||
|
||||
@@ -81,9 +81,7 @@ def get_transaction_list(
|
||||
filters["docstatus"] = ["<", "2"] if doctype in ["Supplier Quotation", "Purchase Invoice"] else 1
|
||||
|
||||
if (user != "Guest" and is_website_user()) or doctype == "Request for Quotation":
|
||||
parties_doctype = (
|
||||
"Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype
|
||||
)
|
||||
parties_doctype = "Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype
|
||||
# find party for this contact
|
||||
customers, suppliers = get_customers_suppliers(parties_doctype, user)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user