Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: billed amount in delivery note items #29290

Merged
6 changes: 3 additions & 3 deletions erpnext/accounts/doctype/sales_invoice/sales_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -1260,14 +1260,14 @@ def make_gle_for_rounding_adjustment(self, gl_entries):
def update_billing_status_in_dn(self, update_modified=True):
updated_delivery_notes = []
for d in self.get("items"):
if d.dn_detail:
if d.so_detail:
updated_delivery_notes += update_billed_amount_based_on_so(d.so_detail, update_modified)
elif d.dn_detail:
billed_amt = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item`
where dn_detail=%s and docstatus=1""", d.dn_detail)
billed_amt = billed_amt and billed_amt[0][0] or 0
frappe.db.set_value("Delivery Note Item", d.dn_detail, "billed_amt", billed_amt, update_modified=update_modified)
updated_delivery_notes.append(d.delivery_note)
elif d.so_detail:
updated_delivery_notes += update_billed_amount_based_on_so(d.so_detail, update_modified)

for dn in set(updated_delivery_notes):
frappe.get_doc("Delivery Note", dn).update_billing_percentage(update_modified=update_modified)
Expand Down
3 changes: 2 additions & 1 deletion erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
erpnext.patches.v13_0.update_tax_category_for_rcm
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
erpnext.patches.v13_0.agriculture_deprecation_warning
erpnext.patches.v13_0.set_billed_amount_in_returned_dn
erpnext.patches.v13_0.update_maintenance_schedule_field_in_visit
erpnext.patches.v13_0.hospitality_deprecation_warning
erpnext.patches.v13_0.delete_bank_reconciliation_detail
erpnext.patches.v13_0.update_sane_transfer_against
erpnext.patches.v13_0.update_sane_transfer_against
22 changes: 22 additions & 0 deletions erpnext/patches/v13_0/set_billed_amount_in_returned_dn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2022, Frappe and Contributors
# License: GNU General Public License v3. See license.txt

import frappe

from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so


def execute():
dn_item = frappe.qb.DocType('Delivery Note Item')

so_detail_list = (frappe.qb.from_(dn_item)
.select(dn_item.so_detail)
.where(
(dn_item.so_detail.notnull()) &
(dn_item.so_detail != '') &
(dn_item.docstatus == 1) &
(dn_item.returned_qty > 0)
)).run()

for so_detail in so_detail_list:
update_billed_amount_based_on_so(so_detail[0], False)
38 changes: 30 additions & 8 deletions erpnext/stock/doctype/delivery_note/delivery_note.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,35 @@ def make_return_invoice(self):
frappe.throw(_("Could not create Credit Note automatically, please uncheck 'Issue Credit Note' and submit again"))

def update_billed_amount_based_on_so(so_detail, update_modified=True):
from frappe.query_builder.functions import Sum

# Billed against Sales Order directly
billed_against_so = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item`
where so_detail=%s and (dn_detail is null or dn_detail = '') and docstatus=1""", so_detail)
si = frappe.qb.DocType("Sales Invoice").as_("si")
si_item = frappe.qb.DocType("Sales Invoice Item").as_("si_item")
sum_amount = Sum(si_item.amount).as_("amount")

billed_against_so = frappe.qb.from_(si).from_(si_item).select(sum_amount).where(
(si_item.parent == si.name) &
(si_item.so_detail == so_detail) &
((si_item.dn_detail.isnull()) | (si_item.dn_detail == '')) &
(si_item.docstatus == 1) &
(si.update_stock == 0)
).run()
billed_against_so = billed_against_so and billed_against_so[0][0] or 0

# Get all Delivery Note Item rows against the Sales Order Item row
dn_details = frappe.db.sql("""select dn_item.name, dn_item.amount, dn_item.si_detail, dn_item.parent
from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
where dn.name=dn_item.parent and dn_item.so_detail=%s
and dn.docstatus=1 and dn.is_return = 0
order by dn.posting_date asc, dn.posting_time asc, dn.name asc""", so_detail, as_dict=1)

dn = frappe.qb.DocType("Delivery Note").as_("dn")
dn_item = frappe.qb.DocType("Delivery Note Item").as_("dn_item")

dn_details = frappe.qb.from_(dn).from_(dn_item).select(dn_item.name, dn_item.amount, dn_item.si_detail, dn_item.parent, dn_item.stock_qty, dn_item.returned_qty).where(
(dn.name == dn_item.parent) &
(dn_item.so_detail == so_detail) &
(dn.docstatus == 1) &
(dn.is_return == 0)
).orderby(
dn.posting_date, dn.posting_time, dn.name
).run(as_dict=True)

updated_dn = []
for dnd in dn_details:
Expand All @@ -367,7 +385,11 @@ def update_billed_amount_based_on_so(so_detail, update_modified=True):

# Distribute billed amount directly against SO between DNs based on FIFO
if billed_against_so and billed_amt_agianst_dn < dnd.amount:
pending_to_bill = flt(dnd.amount) - billed_amt_agianst_dn
if dnd.returned_qty:
pending_to_bill = flt(dnd.amount) * (dnd.stock_qty - dnd.returned_qty) / dnd.stock_qty
else:
pending_to_bill = flt(dnd.amount)
pending_to_bill -= billed_amt_agianst_dn
if pending_to_bill <= billed_against_so:
billed_amt_agianst_dn += pending_to_bill
billed_against_so -= pending_to_bill
Expand Down