mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 15:09:20 +00:00
Merge remote-tracking branch 'origin/develop' into feat/so-po-advance-payment-status
This commit is contained in:
@@ -129,6 +129,17 @@ class AccountsController(TransactionBase):
|
||||
if self.doctype in relevant_docs:
|
||||
self.set_payment_schedule()
|
||||
|
||||
def remove_bundle_for_non_stock_invoices(self):
|
||||
has_sabb = False
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.update_stock:
|
||||
for item in self.get("items"):
|
||||
if item.serial_and_batch_bundle:
|
||||
item.serial_and_batch_bundle = None
|
||||
has_sabb = True
|
||||
|
||||
if has_sabb:
|
||||
self.remove_serial_and_batch_bundle()
|
||||
|
||||
def ensure_supplier_is_not_blocked(self):
|
||||
is_supplier_payment = self.doctype == "Payment Entry" and self.party_type == "Supplier"
|
||||
is_buying_invoice = self.doctype in ["Purchase Invoice", "Purchase Order"]
|
||||
@@ -156,6 +167,9 @@ class AccountsController(TransactionBase):
|
||||
if self.get("_action") and self._action != "update_after_submit":
|
||||
self.set_missing_values(for_validate=True)
|
||||
|
||||
if self.get("_action") == "submit":
|
||||
self.remove_bundle_for_non_stock_invoices()
|
||||
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
|
||||
self.validate_date_with_fiscal_year()
|
||||
@@ -225,6 +239,11 @@ class AccountsController(TransactionBase):
|
||||
apply_pricing_rule_on_transaction(self)
|
||||
|
||||
self.set_total_in_words()
|
||||
self.set_default_letter_head()
|
||||
|
||||
def set_default_letter_head(self):
|
||||
if hasattr(self, "letter_head") and not self.letter_head:
|
||||
self.letter_head = frappe.db.get_value("Company", self.company, "default_letter_head")
|
||||
|
||||
def init_internal_values(self):
|
||||
# init all the internal values as 0 on sa
|
||||
@@ -556,18 +575,12 @@ class AccountsController(TransactionBase):
|
||||
validate_due_date(
|
||||
self.posting_date,
|
||||
self.due_date,
|
||||
"Customer",
|
||||
self.customer,
|
||||
self.company,
|
||||
self.payment_terms_template,
|
||||
)
|
||||
elif self.doctype == "Purchase Invoice":
|
||||
validate_due_date(
|
||||
self.bill_date or self.posting_date,
|
||||
self.due_date,
|
||||
"Supplier",
|
||||
self.supplier,
|
||||
self.company,
|
||||
self.bill_date,
|
||||
self.payment_terms_template,
|
||||
)
|
||||
@@ -874,6 +887,7 @@ class AccountsController(TransactionBase):
|
||||
"project": self.get("project"),
|
||||
"post_net_value": args.get("post_net_value"),
|
||||
"voucher_detail_no": args.get("voucher_detail_no"),
|
||||
"voucher_subtype": self.get_voucher_subtype(),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -916,7 +930,7 @@ class AccountsController(TransactionBase):
|
||||
# Update details in transaction currency
|
||||
gl_dict.update(
|
||||
{
|
||||
"transaction_currency": self.get("currency") or self.company_currency,
|
||||
"transaction_currency": args.get("currency") or self.get("currency") or self.company_currency,
|
||||
"transaction_exchange_rate": self.get("conversion_rate", 1),
|
||||
"debit_in_transaction_currency": self.get_value_in_transaction_currency(
|
||||
account_currency, args, "debit"
|
||||
@@ -927,13 +941,38 @@ class AccountsController(TransactionBase):
|
||||
}
|
||||
)
|
||||
|
||||
if not args.get("against_voucher_type") and self.get("against_voucher_type"):
|
||||
gl_dict.update({"against_voucher_type": self.get("against_voucher_type")})
|
||||
|
||||
if not args.get("against_voucher") and self.get("against_voucher"):
|
||||
gl_dict.update({"against_voucher": self.get("against_voucher")})
|
||||
|
||||
return gl_dict
|
||||
|
||||
def get_voucher_subtype(self):
|
||||
voucher_subtypes = {
|
||||
"Journal Entry": "voucher_type",
|
||||
"Payment Entry": "payment_type",
|
||||
"Stock Entry": "stock_entry_type",
|
||||
"Asset Capitalization": "entry_type",
|
||||
}
|
||||
if self.doctype in voucher_subtypes:
|
||||
return self.get(voucher_subtypes[self.doctype])
|
||||
elif self.doctype == "Purchase Receipt" and self.is_return:
|
||||
return "Purchase Return"
|
||||
elif self.doctype == "Delivery Note" and self.is_return:
|
||||
return "Sales Return"
|
||||
elif (self.doctype == "Sales Invoice" and self.is_return) or self.doctype == "Purchase Invoice":
|
||||
return "Credit Note"
|
||||
elif (self.doctype == "Purchase Invoice" and self.is_return) or self.doctype == "Sales Invoice":
|
||||
return "Debit Note"
|
||||
return self.doctype
|
||||
|
||||
def get_value_in_transaction_currency(self, account_currency, args, field):
|
||||
if account_currency == self.get("currency"):
|
||||
if account_currency == args.get("currency") or self.get("currency"):
|
||||
return args.get(field + "_in_account_currency")
|
||||
else:
|
||||
return flt(args.get(field, 0) / self.get("conversion_rate", 1))
|
||||
return flt(args.get(field, 0) / (args.get("conversion_rate") or self.get("conversion_rate", 1)))
|
||||
|
||||
def validate_qty_is_not_zero(self):
|
||||
if self.doctype == "Purchase Receipt":
|
||||
@@ -2412,6 +2451,7 @@ def validate_taxes_and_charges(tax):
|
||||
|
||||
def validate_account_head(idx, account, company, context=""):
|
||||
account_company = frappe.get_cached_value("Account", account, "company")
|
||||
is_group = frappe.get_cached_value("Account", account, "is_group")
|
||||
|
||||
if account_company != company:
|
||||
frappe.throw(
|
||||
@@ -2421,6 +2461,12 @@ def validate_account_head(idx, account, company, context=""):
|
||||
title=_("Invalid Account"),
|
||||
)
|
||||
|
||||
if is_group:
|
||||
frappe.throw(
|
||||
_("Row {0}: Account {1} is a Group Account").format(idx, frappe.bold(account)),
|
||||
title=_("Invalid Account"),
|
||||
)
|
||||
|
||||
|
||||
def validate_cost_center(tax, doc):
|
||||
if not tax.cost_center:
|
||||
|
||||
@@ -896,3 +896,31 @@ def get_payment_terms_for_references(doctype, txt, searchfield, start, page_len,
|
||||
as_list=1,
|
||||
)
|
||||
return terms
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_filtered_child_rows(doctype, txt, searchfield, start, page_len, filters) -> list:
|
||||
table = frappe.qb.DocType(doctype)
|
||||
query = (
|
||||
frappe.qb.from_(table)
|
||||
.select(
|
||||
table.name,
|
||||
Concat("#", table.idx, ", ", table.item_code),
|
||||
)
|
||||
.orderby(table.idx)
|
||||
.offset(start)
|
||||
.limit(page_len)
|
||||
)
|
||||
|
||||
if filters:
|
||||
for field, value in filters.items():
|
||||
query = query.where(table[field] == value)
|
||||
|
||||
if txt:
|
||||
txt += "%"
|
||||
query = query.where(
|
||||
((table.idx.like(txt.replace("#", ""))) | (table.item_code.like(txt))) | (table.name.like(txt))
|
||||
)
|
||||
|
||||
return query.run(as_dict=False)
|
||||
|
||||
@@ -562,16 +562,17 @@ def make_return_doc(
|
||||
if default_warehouse_for_sales_return:
|
||||
target_doc.warehouse = default_warehouse_for_sales_return
|
||||
|
||||
item_details = frappe.get_cached_value(
|
||||
"Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1
|
||||
)
|
||||
if source_doc.item_code:
|
||||
item_details = frappe.get_cached_value(
|
||||
"Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1
|
||||
)
|
||||
|
||||
if not item_details.has_batch_no and not item_details.has_serial_no:
|
||||
return
|
||||
if not item_details.has_batch_no and not item_details.has_serial_no:
|
||||
return
|
||||
|
||||
for qty_field in ["stock_qty", "rejected_qty"]:
|
||||
if target_doc.get(qty_field):
|
||||
update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field)
|
||||
for qty_field in ["stock_qty", "rejected_qty"]:
|
||||
if target_doc.get(qty_field):
|
||||
update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field)
|
||||
|
||||
def update_terms(source_doc, target_doc, source_parent):
|
||||
target_doc.payment_amount = -source_doc.payment_amount
|
||||
|
||||
@@ -432,13 +432,18 @@ class SellingController(StockController):
|
||||
|
||||
items = self.get("items") + (self.get("packed_items") or [])
|
||||
for d in items:
|
||||
if not frappe.get_cached_value("Item", d.item_code, "is_stock_item"):
|
||||
continue
|
||||
|
||||
if not self.get("return_against") or (
|
||||
get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return")
|
||||
):
|
||||
# Get incoming rate based on original item cost based on valuation method
|
||||
qty = flt(d.get("stock_qty") or d.get("actual_qty"))
|
||||
|
||||
if not d.incoming_rate:
|
||||
if not d.incoming_rate or (
|
||||
get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return")
|
||||
):
|
||||
d.incoming_rate = get_incoming_rate(
|
||||
{
|
||||
"item_code": d.item_code,
|
||||
|
||||
Reference in New Issue
Block a user