refactor(treewide): formatting and ruff fixes, + manually enabled F401

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
Akhil Narang
2024-03-27 11:37:26 +05:30
parent c28d19cf7f
commit 4d34b1ead7
618 changed files with 4188 additions and 6384 deletions

View File

@@ -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:

View File

@@ -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,
)
]

View File

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

View File

@@ -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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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",

View File

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

View File

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

View File

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

View File

@@ -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,
),
],
)

View File

@@ -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":

View File

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