Merge pull request #44740 from frappe/version-14-hotfix

chore: release v14
This commit is contained in:
ruthra kumar
2024-12-18 10:30:20 +05:30
committed by GitHub
11 changed files with 63 additions and 24 deletions

View File

@@ -16,7 +16,7 @@ concurrency:
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
timeout-minutes: 60 timeout-minutes: 60
name: Patch Test name: Patch Test

View File

@@ -1088,6 +1088,24 @@ frappe.ui.form.on('Payment Entry', {
if (r.message) { if (r.message) {
if (!frm.doc.mode_of_payment) { if (!frm.doc.mode_of_payment) {
frm.set_value(field, r.message.account); frm.set_value(field, r.message.account);
} else {
frappe.call({
method: "frappe.client.get_value",
args: {
doctype: "Mode of Payment Account",
filters: {
parent: frm.doc.mode_of_payment,
company: frm.doc.company,
},
fieldname: "default_account",
parent: "Mode of Payment",
},
callback: function (res) {
if (!res.message.default_account) {
frm.set_value(field, r.message.account);
}
},
});
} }
frm.set_value('bank', r.message.bank); frm.set_value('bank', r.message.bank);
frm.set_value('bank_account_no', r.message.bank_account_no); frm.set_value('bank_account_no', r.message.bank_account_no);

View File

@@ -328,6 +328,8 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False):
"parent": args.parent, "parent": args.parent,
"parenttype": args.parenttype, "parenttype": args.parenttype,
"child_docname": args.get("child_docname"), "child_docname": args.get("child_docname"),
"discount_percentage": 0.0,
"discount_amount": 0,
} }
) )

View File

@@ -529,9 +529,7 @@ class ReceivablePayableReport:
self.append_payment_term(row, d, term) self.append_payment_term(row, d, term)
def append_payment_term(self, row, d, term): def append_payment_term(self, row, d, term):
if ( if d.currency == d.party_account_currency:
self.filters.get("customer") or self.filters.get("supplier")
) and d.currency == d.party_account_currency:
invoiced = d.payment_amount invoiced = d.payment_amount
else: else:
invoiced = d.base_payment_amount invoiced = d.base_payment_amount

View File

@@ -526,9 +526,16 @@ def get_accounting_entries(
query = apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters) query = apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters)
query = query.where(gl_entry.account.isin(accounts)) query = query.where(gl_entry.account.isin(accounts))
entries = query.run(as_dict=True) from frappe.desk.reportview import build_match_conditions
return entries match_conditions = build_match_conditions(doctype)
if match_conditions:
query += "and" + match_conditions
query, params = query.walk()
return frappe.db.sql(query, params, as_dict=True)
def apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters): def apply_additional_conditions(doctype, query, from_date, ignore_closing_entries, filters):

View File

@@ -768,7 +768,10 @@ class GrossProfitGenerator:
""" """
if self.filters.group_by == "Sales Person": if self.filters.group_by == "Sales Person":
sales_person_cols = ", sales.sales_person, sales.allocated_amount, sales.incentives" sales_person_cols = """, sales.sales_person,
sales.allocated_percentage * `tabSales Invoice Item`.base_net_amount / 100 as allocated_amount,
sales.incentives
"""
sales_team_table = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name" sales_team_table = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name"
else: else:
sales_person_cols = "" sales_person_cols = ""

View File

@@ -72,8 +72,8 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
if net_total_map.get((voucher_type, name)): if net_total_map.get((voucher_type, name)):
if voucher_type == "Journal Entry" and tax_amount and rate: if voucher_type == "Journal Entry" and tax_amount and rate:
# back calcalute total amount from rate and tax_amount # back calcalute total amount from rate and tax_amount
if rate: base_total = min(tax_amount / (rate / 100), net_total_map.get((voucher_type, name))[0])
total_amount = grand_total = base_total = tax_amount / (rate / 100) total_amount = grand_total = base_total
elif voucher_type == "Purchase Invoice": elif voucher_type == "Purchase Invoice":
total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get( total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get(
(voucher_type, name) (voucher_type, name)
@@ -405,7 +405,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
"paid_amount_after_tax", "paid_amount_after_tax",
"base_paid_amount", "base_paid_amount",
], ],
"Journal Entry": ["total_amount"], "Journal Entry": ["total_debit"],
} }
entries = frappe.get_all( entries = frappe.get_all(
@@ -427,7 +427,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
elif doctype == "Payment Entry": elif doctype == "Payment Entry":
value = [entry.paid_amount, entry.paid_amount_after_tax, entry.base_paid_amount] value = [entry.paid_amount, entry.paid_amount_after_tax, entry.base_paid_amount]
else: else:
value = [entry.total_amount] * 3 value = [entry.total_debit] * 3
net_total_map[(doctype, entry.name)] = value net_total_map[(doctype, entry.name)] = value

View File

@@ -71,16 +71,13 @@ def validate_returned_items(doc):
valid_items = frappe._dict() valid_items = frappe._dict()
select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor" select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor, name"
if doc.doctype != "Purchase Invoice": if doc.doctype != "Purchase Invoice":
select_fields += ",serial_no, batch_no" select_fields += ",serial_no, batch_no"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]: if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
select_fields += ",rejected_qty, received_qty" select_fields += ",rejected_qty, received_qty"
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
select_fields += ",name"
for d in frappe.db.sql( for d in frappe.db.sql(
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""", f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
doc.return_against, doc.return_against,
@@ -108,11 +105,13 @@ def validate_returned_items(doc):
for d in doc.get("items"): for d in doc.get("items"):
key = d.item_code key = d.item_code
raise_exception = False raise_exception = False
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]: if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Sales Invoice"]:
field = frappe.scrub(doc.doctype) + "_item" field = frappe.scrub(doc.doctype) + "_item"
if d.get(field): if d.get(field):
key = (d.item_code, d.get(field)) key = (d.item_code, d.get(field))
raise_exception = True raise_exception = True
elif doc.doctype == "Delivery Note":
key = (d.item_code, d.get("dn_detail"))
if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0): if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0):
if key not in valid_items: if key not in valid_items:
@@ -124,7 +123,7 @@ def validate_returned_items(doc):
) )
else: else:
ref = valid_items.get(key, frappe._dict()) ref = valid_items.get(key, frappe._dict())
validate_quantity(doc, d, ref, valid_items, already_returned_items) validate_quantity(doc, key, d, ref, valid_items, already_returned_items)
if ( if (
ref.rate ref.rate
@@ -174,12 +173,12 @@ def validate_returned_items(doc):
frappe.throw(_("Atleast one item should be entered with negative quantity in return document")) frappe.throw(_("Atleast one item should be entered with negative quantity in return document"))
def validate_quantity(doc, args, ref, valid_items, already_returned_items): def validate_quantity(doc, key, args, ref, valid_items, already_returned_items):
fields = ["stock_qty"] fields = ["stock_qty"]
if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"]: if doc.doctype in ["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"]:
fields.extend(["received_qty", "rejected_qty"]) fields.extend(["received_qty", "rejected_qty"])
already_returned_data = already_returned_items.get(args.item_code) or {} already_returned_data = already_returned_items.get(key) or {}
company_currency = erpnext.get_company_currency(doc.company) company_currency = erpnext.get_company_currency(doc.company)
stock_qty_precision = get_field_precision( stock_qty_precision = get_field_precision(
@@ -262,15 +261,20 @@ def get_already_returned_items(doc):
column += """, sum(abs(child.rejected_qty) * child.conversion_factor) as rejected_qty, column += """, sum(abs(child.rejected_qty) * child.conversion_factor) as rejected_qty,
sum(abs(child.received_qty) * child.conversion_factor) as received_qty""" sum(abs(child.received_qty) * child.conversion_factor) as received_qty"""
field = (
frappe.scrub(doc.doctype) + "_item"
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Sales Invoice"]
else "dn_detail"
)
data = frappe.db.sql( data = frappe.db.sql(
f""" f"""
select {column} select {column}, {field}
from from
`tab{doc.doctype} Item` child, `tab{doc.doctype}` par `tab{doc.doctype} Item` child, `tab{doc.doctype}` par
where where
child.parent = par.name and par.docstatus = 1 child.parent = par.name and par.docstatus = 1
and par.is_return = 1 and par.return_against = %s and par.is_return = 1 and par.return_against = %s
group by item_code group by item_code, {field}
""", """,
doc.return_against, doc.return_against,
as_dict=1, as_dict=1,
@@ -280,7 +284,7 @@ def get_already_returned_items(doc):
for d in data: for d in data:
items.setdefault( items.setdefault(
d.item_code, (d.item_code, d.get(field)),
frappe._dict( frappe._dict(
{ {
"qty": d.get("qty"), "qty": d.get("qty"),

View File

@@ -94,7 +94,10 @@ status_map = {
["To Bill", "eval:self.per_billed == 0 and self.docstatus == 1"], ["To Bill", "eval:self.per_billed == 0 and self.docstatus == 1"],
["Partly Billed", "eval:self.per_billed > 0 and self.per_billed < 100 and self.docstatus == 1"], ["Partly Billed", "eval:self.per_billed > 0 and self.per_billed < 100 and self.docstatus == 1"],
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"], ["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"], [
"Completed",
"eval:(self.per_billed == 100 and self.docstatus == 1) or (self.docstatus == 1 and self.grand_total == 0 and self.per_returned != 100 and self.is_return == 0)",
],
["Cancelled", "eval:self.docstatus==2"], ["Cancelled", "eval:self.docstatus==2"],
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"], ["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
], ],

View File

@@ -107,9 +107,12 @@ $.extend(erpnext.queries, {
}, },
dispatch_address_query: function (doc) { dispatch_address_query: function (doc) {
var filters = { link_doctype: "Company", link_name: doc.company || "" };
var is_drop_ship = doc.items.some((item) => item.delivered_by_supplier);
if (is_drop_ship) filters = {};
return { return {
query: "frappe.contacts.doctype.address.address.address_query", query: "frappe.contacts.doctype.address.address.address_query",
filters: { link_doctype: "Company", link_name: doc.company || "" }, filters: filters,
}; };
}, },

View File

@@ -982,6 +982,7 @@ def create_stock_entry(pick_list):
stock_entry = frappe.new_doc("Stock Entry") stock_entry = frappe.new_doc("Stock Entry")
stock_entry.pick_list = pick_list.get("name") stock_entry.pick_list = pick_list.get("name")
stock_entry.purpose = pick_list.get("purpose") stock_entry.purpose = pick_list.get("purpose")
stock_entry.company = pick_list.get("company")
stock_entry.set_stock_entry_type() stock_entry.set_stock_entry_type()
if pick_list.get("work_order"): if pick_list.get("work_order"):