fix: Billing % Logic and Map Pending Qty only in PR and DN
- Billing % should consider unreturned amount as total - While mapping to return doc, map unreturned amount - Added field Received Qty in Stock UOM, to tally against Returned Qty in PR - PR billing percentage updation custom function - In patch set received qty in stock uom first, then update returned qty and billing
This commit is contained in:
parent
7496ac0fe2
commit
d6596a169c
@ -1032,7 +1032,9 @@ class PurchaseInvoice(BuyingController):
|
||||
updated_pr += update_billed_amount_based_on_po(d.po_detail, update_modified)
|
||||
|
||||
for pr in set(updated_pr):
|
||||
frappe.get_doc("Purchase Receipt", pr).update_billing_percentage(update_modified=update_modified)
|
||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage
|
||||
pr_doc = frappe.get_doc("Purchase Receipt", pr)
|
||||
update_billing_percentage(pr_doc, update_modified=update_modified)
|
||||
|
||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||
self.due_date = None
|
||||
|
@ -497,6 +497,10 @@ class BuyingController(StockController):
|
||||
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
|
||||
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
|
||||
|
||||
if self.doctype=="Purchase Receipt" and d.meta.get_field("received_stock_qty"):
|
||||
# Set Received Qty in Stock UOM
|
||||
d.received_stock_qty = flt(d.received_qty) * flt(d.conversion_factor, d.precision("conversion_factor"))
|
||||
|
||||
def validate_purchase_return(self):
|
||||
for d in self.get("items"):
|
||||
if self.is_return and flt(d.rejected_qty) != 0:
|
||||
|
@ -203,6 +203,41 @@ def get_already_returned_items(doc):
|
||||
|
||||
return items
|
||||
|
||||
def get_returned_qty_map_for_row(row_name, doctype):
|
||||
child_doctype = doctype + " Item"
|
||||
reference_field = frappe.scrub(child_doctype) if doctype == "Purchase Receipt" else "dn_detail"
|
||||
reference_field = "child." + reference_field
|
||||
columns = ""
|
||||
|
||||
if doctype == "Purchase Receipt":
|
||||
columns += ", sum(abs(child.rejected_qty)) as rejected_qty, \
|
||||
sum(abs(child.received_qty)) as received_qty, \
|
||||
sum(abs(child.received_stock_qty)) as received_stock_qty"
|
||||
|
||||
data = frappe.db.sql("""
|
||||
select
|
||||
sum(abs(child.qty)) as qty,
|
||||
sum(abs(child.stock_qty)) as stock_qty,
|
||||
%(columns)s
|
||||
from
|
||||
`tab{0}` child, `tab{1}` parent
|
||||
where
|
||||
child.parent = parent.name
|
||||
and parent.docstatus = 1
|
||||
and parent.is_return = 1
|
||||
and {2} = %(row_name)s
|
||||
""".format(child_doctype, doctype, reference_field),
|
||||
{
|
||||
"row_name": row_name,
|
||||
"columns": columns,
|
||||
"child_doctype": child_doctype,
|
||||
"doctype": doctype,
|
||||
"reference_field": reference_field
|
||||
},
|
||||
as_dict=1)
|
||||
|
||||
return data[0]
|
||||
|
||||
def make_return_doc(doctype, source_name, target_doc=None):
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
company = frappe.db.get_value("Delivery Note", source_name, "company")
|
||||
@ -262,20 +297,25 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
doc.run_method("calculate_taxes_and_totals")
|
||||
|
||||
def update_item(source_doc, target_doc, source_parent):
|
||||
target_doc.qty = -1* source_doc.qty
|
||||
target_doc.qty = -1 * source_doc.qty
|
||||
|
||||
if doctype == "Purchase Receipt":
|
||||
target_doc.received_qty = -1* source_doc.received_qty
|
||||
target_doc.rejected_qty = -1* source_doc.rejected_qty
|
||||
target_doc.qty = -1* source_doc.qty
|
||||
target_doc.stock_qty = -1 * source_doc.stock_qty
|
||||
returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
|
||||
target_doc.received_qty = -1 * flt(source_doc.received_qty - (returned_qty_map.get('received_qty') or 0))
|
||||
target_doc.rejected_qty = -1 * flt(source_doc.rejected_qty - (returned_qty_map.get('rejected_qty') or 0))
|
||||
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get('qty') or 0))
|
||||
|
||||
target_doc.stock_qty = -1 * flt(source_doc.stock_qty - (returned_qty_map.get('stock_qty') or 0))
|
||||
target_doc.received_stock_qty = -1 * flt(source_doc.received_stock_qty - (returned_qty_map.get('received_stock_qty') or 0))
|
||||
|
||||
target_doc.purchase_order = source_doc.purchase_order
|
||||
target_doc.purchase_order_item = source_doc.purchase_order_item
|
||||
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
||||
target_doc.purchase_receipt_item = source_doc.name
|
||||
|
||||
elif doctype == "Purchase Invoice":
|
||||
target_doc.received_qty = -1* source_doc.received_qty
|
||||
target_doc.rejected_qty = -1* source_doc.rejected_qty
|
||||
target_doc.received_qty = -1 * source_doc.received_qty
|
||||
target_doc.rejected_qty = -1 * source_doc.rejected_qty
|
||||
target_doc.qty = -1* source_doc.qty
|
||||
target_doc.stock_qty = -1 * source_doc.stock_qty
|
||||
target_doc.purchase_order = source_doc.purchase_order
|
||||
@ -286,6 +326,10 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
target_doc.purchase_invoice_item = source_doc.name
|
||||
|
||||
elif doctype == "Delivery Note":
|
||||
returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
|
||||
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get('qty') or 0))
|
||||
target_doc.stock_qty = -1 * flt(source_doc.stock_qty - (returned_qty_map.get('stock_qty') or 0))
|
||||
|
||||
target_doc.against_sales_order = source_doc.against_sales_order
|
||||
target_doc.against_sales_invoice = source_doc.against_sales_invoice
|
||||
target_doc.so_detail = source_doc.so_detail
|
||||
|
@ -338,11 +338,15 @@ class StockController(AccountsController):
|
||||
validate_warehouse_company(w, self.company)
|
||||
|
||||
def update_billing_percentage(self, update_modified=True):
|
||||
target_ref_field = "amount"
|
||||
if self.doctype == "Delivery Note":
|
||||
target_ref_field = "amount - (returned_qty * rate)"
|
||||
|
||||
self._update_percent_field({
|
||||
"target_dt": self.doctype + " Item",
|
||||
"target_parent_dt": self.doctype,
|
||||
"target_parent_field": "per_billed",
|
||||
"target_ref_field": "amount",
|
||||
"target_ref_field": target_ref_field,
|
||||
"target_field": "billed_amt",
|
||||
"name": self.name,
|
||||
}, update_modified)
|
||||
|
@ -732,4 +732,4 @@ erpnext.patches.v13_0.set_youtube_video_id
|
||||
erpnext.patches.v13_0.print_uom_after_quantity_patch
|
||||
erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account
|
||||
erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail
|
||||
erpnext.patches.v13_0.update_returned_qty_in_pr_dn
|
||||
erpnext.patches.v13_0.update_returned_qty_in_pr_dn #12am
|
@ -15,6 +15,13 @@ def execute():
|
||||
# Update original receipt/delivery document from return
|
||||
return_doc = frappe.get_cached_doc(doctype, return_doc.name)
|
||||
return_doc.update_prevdoc_status()
|
||||
return_against = frappe.get_doc(doctype, return_doc.return_against)
|
||||
return_against.update_billing_status()
|
||||
|
||||
# Set received qty in stock uom in PR, as returned qty is checked against it
|
||||
frappe.db.sql(""" update `tabPurchase Receipt Item`
|
||||
set received_stock_qty = received_qty * conversion_factor
|
||||
where docstatus = 1 """)
|
||||
|
||||
for doctype in ('Purchase Receipt', 'Delivery Note'):
|
||||
update_from_return_docs(doctype)
|
@ -189,6 +189,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
frappe.model.round_floats_in(item, ["qty", "received_qty"]);
|
||||
item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item));
|
||||
item.received_stock_qty = flt(item.conversion_factor, precision("conversion_factor", item)) * flt(item.received_qty);
|
||||
}
|
||||
|
||||
this._super(doc, cdt, cdn);
|
||||
|
@ -77,8 +77,8 @@ class PurchaseReceipt(BuyingController):
|
||||
'target_field': 'returned_qty',
|
||||
'target_parent_dt': 'Purchase Receipt',
|
||||
'target_parent_field': 'per_returned',
|
||||
'target_ref_field': 'stock_qty',
|
||||
'source_field': '-1 * stock_qty',
|
||||
'target_ref_field': 'received_stock_qty',
|
||||
'source_field': '-1 * received_stock_qty',
|
||||
'percent_join_field_parent': 'return_against'
|
||||
}
|
||||
])
|
||||
@ -503,7 +503,7 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
for pr in set(updated_pr):
|
||||
pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
|
||||
pr_doc.update_billing_percentage(update_modified=update_modified)
|
||||
update_billing_percentage(pr_doc, update_modified=update_modified)
|
||||
|
||||
self.load_from_db()
|
||||
|
||||
@ -543,6 +543,39 @@ def update_billed_amount_based_on_po(po_detail, update_modified=True):
|
||||
|
||||
return updated_pr
|
||||
|
||||
def update_billing_percentage(pr_doc, update_modified=True):
|
||||
# Update Billing % based on pending accepted qty
|
||||
total_amount, total_billed_amount = 0, 0
|
||||
for item in pr_doc.items:
|
||||
returned_qty = frappe.db.sql("""
|
||||
select sum(abs(child.qty)) as qty
|
||||
from
|
||||
`tabPurchase Receipt Item` child,
|
||||
`tabPurchase Receipt` parent
|
||||
where
|
||||
child.parent = parent.name
|
||||
and parent.docstatus = 1
|
||||
and parent.is_return = 1
|
||||
and child.purchase_receipt_item = %(row_name)s
|
||||
""", {"row_name": item.name})
|
||||
returned_qty = returned_qty[0][0] if returned_qty else 0
|
||||
|
||||
returned_amount = flt(returned_qty) * flt(item.rate)
|
||||
pending_amount = flt(item.amount) - returned_amount
|
||||
total_billable_amount = pending_amount if item.billed_amt <= pending_amount else item.billed_amt
|
||||
|
||||
total_amount += total_billable_amount
|
||||
total_billed_amount += flt(item.billed_amt)
|
||||
|
||||
print(total_billed_amount, total_amount)
|
||||
percent_billed = round(100 * (total_billed_amount / total_amount), 6)
|
||||
pr_doc.db_set("per_billed", percent_billed)
|
||||
pr_doc.load_from_db()
|
||||
|
||||
if update_modified:
|
||||
pr_doc.set_status(update=True)
|
||||
pr_doc.notify_update()
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_purchase_invoice(source_name, target_doc=None):
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
@ -562,6 +595,7 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
|
||||
def update_item(source_doc, target_doc, source_parent):
|
||||
target_doc.qty, returned_qty = get_pending_qty(source_doc)
|
||||
target_doc.stock_qty = flt(target_doc.qty) * flt(target_doc.conversion_factor, target_doc.precision("conversion_factor"))
|
||||
returned_qty_map[source_doc.name] = returned_qty
|
||||
|
||||
def get_pending_qty(item_row):
|
||||
|
@ -31,6 +31,7 @@
|
||||
"retain_sample",
|
||||
"sample_quantity",
|
||||
"tracking_section",
|
||||
"received_stock_qty",
|
||||
"stock_qty",
|
||||
"col_break_tracking_section",
|
||||
"returned_qty",
|
||||
@ -854,12 +855,18 @@
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "received_stock_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Received Qty in Stock UOM",
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-09-09 13:39:46.452817",
|
||||
"modified": "2020-11-02 10:00:38.204294",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
Loading…
x
Reference in New Issue
Block a user