Update billing status in Delivery Note if directly invoiced against SO

This commit is contained in:
Nabin Hait 2015-12-28 13:03:55 +05:30 committed by Anand Doshi
parent a3e87c7af1
commit 5b13b99441
7 changed files with 1322 additions and 1207 deletions

View File

@ -12,6 +12,8 @@ from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from erpnext.accounts.utils import get_account_currency
from erpnext.stock.doctype.delivery_note.delivery_note \
import update_billing_amount_based_on_so, update_billing_percentage
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@ -98,6 +100,7 @@ class SalesInvoice(SellingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.update_billing_status_in_dn()
# this sequence because outstanding may get -ve
self.make_gl_entries()
@ -111,6 +114,7 @@ class SalesInvoice(SellingController):
self.update_time_log_batch(self.name)
def before_cancel(self):
self.update_time_log_batch(None)
@ -129,6 +133,7 @@ class SalesInvoice(SellingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.update_billing_status_in_dn()
if not self.is_return:
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
@ -630,6 +635,18 @@ class SalesInvoice(SellingController):
}, write_off_account_currency)
)
def update_billing_status_in_dn(self):
updated_delivery_notes = []
for d in self.get("items"):
if d.dn_detail and not d.so_detail:
frappe.db.set_value("Delivery Note Item", d.dn_detail, "billed_amt", d.amount)
updated_delivery_notes.append(d.delivery_note)
elif d.so_detail:
updated_delivery_notes += update_billing_amount_based_on_so(d.so_detail)
for dn in set(updated_delivery_notes):
update_billing_percentage(dn)
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)

View File

@ -52,7 +52,8 @@ status_map = {
],
"Delivery Note": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["To Bill", "eval:self.per_billed < 100 and self.docstatus == 1"],
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
["Cancelled", "eval:self.docstatus==2"],
["Closed", "eval:self.status=='Closed'"],
],
@ -153,7 +154,6 @@ class StatusUpdater(Document):
# check if overflow is within tolerance
tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'],
self.tolerance, self.global_tolerance)
overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
item[args['target_ref_field']]) * 100

View File

@ -52,15 +52,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
}
}
if(doc.__onload && !doc.__onload.billing_complete && doc.docstatus==1
&& !doc.is_return && doc.status!="Closed") {
// show Make Invoice button only if Delivery Note is not created from Sales Invoice
var from_sales_invoice = false;
from_sales_invoice = cur_frm.doc.items.some(function(item) {
return item.against_sales_invoice ? true : false;
});
if(!from_sales_invoice)
if(doc.docstatus==1 && !doc.is_return && doc.status!="Closed" && flt(doc.per_billed, 2) < 100) {
cur_frm.add_custom_button(__('Invoice'), this.make_sales_invoice).addClass("btn-primary");
}
@ -285,6 +277,3 @@ if (sys_defaults.auto_accounting_for_stock) {
}
}
}

View File

@ -2154,6 +2154,30 @@
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "per_billed",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "% Amount Billed",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@ -2317,7 +2341,7 @@
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nCancelled\nClosed",
"options": "\nDraft\nTo Bill\nCompleted\nCancelled\nClosed",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
@ -2672,7 +2696,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2015-12-17 16:19:27.004718",
"modified": "2015-12-25 16:20:39.014291",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",

View File

@ -48,7 +48,8 @@ class DeliveryNote(SellingController):
'target_ref_field': 'qty',
'source_field': 'qty',
'percent_join_field': 'against_sales_invoice',
'overflow_type': 'delivery'
'overflow_type': 'delivery',
'no_tolerance': 1
},
{
'source_dt': 'Delivery Note Item',
@ -56,21 +57,11 @@ class DeliveryNote(SellingController):
'join_field': 'so_detail',
'target_field': 'returned_qty',
'target_parent_dt': 'Sales Order',
# 'target_parent_field': 'per_delivered',
# 'target_ref_field': 'qty',
'source_field': '-1 * qty',
# 'percent_join_field': 'against_sales_order',
# 'overflow_type': 'delivery',
'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)"""
}]
def onload(self):
billed_qty = frappe.db.sql("""select sum(qty) from `tabSales Invoice Item`
where docstatus=1 and delivery_note=%s""", self.name)
if billed_qty:
total_qty = sum((item.qty for item in self.get("items")))
self.set_onload("billing_complete", (billed_qty[0][0] == total_qty))
self.set_onload("has_return_entry", len(frappe.db.exists({"doctype": "Delivery Note",
"is_return": 1, "return_against": self.name, "docstatus": 1})))
@ -199,6 +190,7 @@ class DeliveryNote(SellingController):
# update delivered qty in sales order
self.update_prevdoc_status()
self.update_billing_status()
if not self.is_return:
self.check_credit_limit()
@ -206,18 +198,15 @@ class DeliveryNote(SellingController):
self.update_stock_ledger()
self.make_gl_entries()
frappe.db.set(self, 'status', 'Submitted')
def on_cancel(self):
self.check_stop_or_close_sales_order("against_sales_order")
self.check_next_docstatus()
self.update_prevdoc_status()
self.update_billing_status()
self.update_stock_ledger()
frappe.db.set(self, 'status', 'Cancelled')
self.cancel_packing_slips()
self.make_gl_entries_on_cancel()
@ -280,6 +269,73 @@ class DeliveryNote(SellingController):
self.notify_update()
clear_doctype_notifications(self)
def update_billing_status(self):
updated_delivery_notes = [self.name]
for d in self.get("items"):
if d.si_detail and not d.so_detail:
d.billed_amt = d.amount
frappe.db.set(d, 'billed_amt', d.amount)
elif d.so_detail:
updated_delivery_notes += update_billing_amount_based_on_so(d.so_detail)
d.billed_amt = frappe.db.get_value("Delivery Note Item", d.name, "billed_amt")
for dn in set(updated_delivery_notes):
update_billing_percentage(dn)
self.per_billed = frappe.db.get_value("Delivery Note", self.name, "per_billed")
def update_billing_percentage(delivery_note, set_modified=True):
frappe.db.sql("""update `tabDelivery Note`
set per_billed = round(ifnull(
(select ifnull(sum(if(amount > billed_amt, billed_amt, amount)), 0) * 100 / sum(amount)
from `tabDelivery Note Item` where parent=%s), 0), 2)
, modified = now(), modified_by = %s
where name=%s""", (delivery_note, frappe.session.user, delivery_note))
if set_modified:
dn = frappe.get_doc("Delivery Note", delivery_note)
dn.set_status(update=True)
dn.notify_update()
def update_billing_amount_based_on_so(so_detail):
# 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)
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)
updated_dn = []
for dnd in dn_details:
billed_amt_agianst_dn = 0
# If delivered against Sales Invoice
if dnd.si_detail:
billed_amt_agianst_dn = flt(dnd.amount)
billed_against_so -= billed_amt_agianst_dn
else:
# Get billed amount directly against Delivery Note
billed_amt_agianst_dn = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item`
where dn_detail=%s and docstatus=1""", dnd.name)
billed_amt_agianst_dn = billed_amt_agianst_dn and billed_amt_agianst_dn[0][0] or 0
# 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 pending_to_bill <= billed_against_so:
billed_amt_agianst_dn += pending_to_bill
else:
billed_amt_agianst_dn += billed_against_so
frappe.db.set_value("Delivery Note Item", dnd.name, "billed_amt", billed_amt_agianst_dn)
updated_dn.append(dnd.parent)
return updated_dn
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)

View File

@ -6,6 +6,10 @@ frappe.listview_settings['Delivery Note'] = {
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if(doc.status==="Closed") {
return [__("Closed"), "green", "status,=,Closed"];
} else if (flt(doc.per_billed, 2) < 100) {
return [__("To Bill"), "orange", "per_billed,<,100"];
} else if (flt(doc.per_billed, 2) == 100) {
return [__("Completed"), "green", "per_billed,=,100"];
}
}
};

View File

@ -1226,6 +1226,31 @@
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "billed_amt",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Billed Amt",
"length": 0,
"no_copy": 1,
"options": "currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
"bold": 0,
@ -1261,7 +1286,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-01-06 02:22:36.503314",
"modified": "2016-01-06 02:22:36.503315",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",