feat(Sales Order): Allow to skip delivery note creation (#19222)
* feat(sales-order): add option to skip delivery note creation for order type maintenance * fix(sales-order): hide delivery date on setting skip delivery note creation * fix: allow skipping delivery note for all order types * fix: bypass delivery note creation on setting skip delivery note creation * fix: show skip delivery note in list view * fix: check for duplicate project name after submitting prompt * fix: toggle delivery note reqd for skip delivery note * fix: update status based on skip delivery note
This commit is contained in:
parent
86870b0aa6
commit
4ed9b45fb8
@ -37,9 +37,9 @@ status_map = {
|
|||||||
"Sales Order": [
|
"Sales Order": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
["To Bill", "eval:self.per_delivered == 100 and self.per_billed < 100 and self.docstatus == 1"],
|
["To Bill", "eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1"],
|
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1 and not self.skip_delivery_note"],
|
||||||
["Completed", "eval:self.per_delivered == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
["Completed", "eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed == 100 and self.docstatus == 1"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
["Closed", "eval:self.status=='Closed'"],
|
["Closed", "eval:self.status=='Closed'"],
|
||||||
["On Hold", "eval:self.status=='On Hold'"],
|
["On Hold", "eval:self.status=='On Hold'"],
|
||||||
|
@ -64,7 +64,8 @@ class WorkOrder(Document):
|
|||||||
from `tabSales Order` so
|
from `tabSales Order` so
|
||||||
inner join `tabSales Order Item` so_item on so_item.parent = so.name
|
inner join `tabSales Order Item` so_item on so_item.parent = so.name
|
||||||
left join `tabProduct Bundle Item` pk_item on so_item.item_code = pk_item.parent
|
left join `tabProduct Bundle Item` pk_item on so_item.item_code = pk_item.parent
|
||||||
where so.name=%s and so.docstatus = 1 and (
|
where so.name=%s and so.docstatus = 1
|
||||||
|
and so.skip_delivery_note = 0 and (
|
||||||
so_item.item_code=%s or
|
so_item.item_code=%s or
|
||||||
pk_item.item_code=%s )
|
pk_item.item_code=%s )
|
||||||
""", (self.sales_order, self.production_item, self.production_item), as_dict=1)
|
""", (self.sales_order, self.production_item, self.production_item), as_dict=1)
|
||||||
@ -78,6 +79,7 @@ class WorkOrder(Document):
|
|||||||
where so.name=%s
|
where so.name=%s
|
||||||
and so.name=so_item.parent
|
and so.name=so_item.parent
|
||||||
and so.name=packed_item.parent
|
and so.name=packed_item.parent
|
||||||
|
and so.skip_delivery_note = 0
|
||||||
and so_item.item_code = packed_item.parent_item
|
and so_item.item_code = packed_item.parent_item
|
||||||
and so.docstatus = 1 and packed_item.item_code=%s
|
and so.docstatus = 1 and packed_item.item_code=%s
|
||||||
""", (self.sales_order, self.production_item), as_dict=1)
|
""", (self.sales_order, self.production_item), as_dict=1)
|
||||||
|
@ -137,6 +137,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
if(doc.status !== 'On Hold') {
|
if(doc.status !== 'On Hold') {
|
||||||
|
|
||||||
allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty))
|
allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty))
|
||||||
|
&& !this.frm.doc.skip_delivery_note
|
||||||
|
|
||||||
if (this.frm.has_perm("submit")) {
|
if (this.frm.has_perm("submit")) {
|
||||||
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
||||||
@ -341,7 +342,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
},
|
},
|
||||||
|
|
||||||
order_type: function() {
|
order_type: function() {
|
||||||
this.frm.fields_dict.items.grid.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
|
this.toggle_delivery_date();
|
||||||
},
|
},
|
||||||
|
|
||||||
tc_name: function() {
|
tc_name: function() {
|
||||||
@ -355,6 +356,15 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
skip_delivery_note: function() {
|
||||||
|
this.toggle_delivery_date();
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_delivery_date: function() {
|
||||||
|
this.frm.fields_dict.items.grid.toggle_reqd("delivery_date",
|
||||||
|
(this.frm.doc.order_type == "Sales" && !this.frm.doc.skip_delivery_note));
|
||||||
|
},
|
||||||
|
|
||||||
make_raw_material_request: function() {
|
make_raw_material_request: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.frm.call({
|
this.frm.call({
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"customer",
|
"customer",
|
||||||
"customer_name",
|
"customer_name",
|
||||||
"order_type",
|
"order_type",
|
||||||
|
"skip_delivery_note",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"amended_from",
|
"amended_from",
|
||||||
"company",
|
"company",
|
||||||
@ -252,6 +253,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
|
"depends_on": "eval:!doc.skip_delivery_note",
|
||||||
"fieldname": "delivery_date",
|
"fieldname": "delivery_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@ -1023,7 +1025,7 @@
|
|||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.__islocal",
|
"depends_on": "eval:!doc.__islocal && !doc.skip_delivery_note_creation",
|
||||||
"description": "% of materials delivered against this Sales Order",
|
"description": "% of materials delivered against this Sales Order",
|
||||||
"fieldname": "per_delivered",
|
"fieldname": "per_delivered",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
@ -1171,12 +1173,19 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Phone",
|
"label": "Phone",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "skip_delivery_note",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Skip Delivery Note",
|
||||||
|
"print_hide": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2019-09-27 14:23:52.233323",
|
"modified": "2019-10-10 08:46:07.540565",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
@ -57,13 +57,13 @@ class SalesOrder(SellingController):
|
|||||||
|
|
||||||
def validate_po(self):
|
def validate_po(self):
|
||||||
# validate p.o date v/s delivery date
|
# validate p.o date v/s delivery date
|
||||||
if self.po_date:
|
if self.po_date and not self.skip_delivery_note:
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date):
|
if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date):
|
||||||
frappe.throw(_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date")
|
frappe.throw(_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date")
|
||||||
.format(d.idx))
|
.format(d.idx))
|
||||||
|
|
||||||
if self.po_no and self.customer:
|
if self.po_no and self.customer and not self.skip_delivery_note:
|
||||||
so = frappe.db.sql("select name from `tabSales Order` \
|
so = frappe.db.sql("select name from `tabSales Order` \
|
||||||
where ifnull(po_no, '') = %s and name != %s and docstatus < 2\
|
where ifnull(po_no, '') = %s and name != %s and docstatus < 2\
|
||||||
and customer = %s", (self.po_no, self.name, self.customer))
|
and customer = %s", (self.po_no, self.name, self.customer))
|
||||||
@ -100,7 +100,7 @@ class SalesOrder(SellingController):
|
|||||||
super(SalesOrder, self).validate_order_type()
|
super(SalesOrder, self).validate_order_type()
|
||||||
|
|
||||||
def validate_delivery_date(self):
|
def validate_delivery_date(self):
|
||||||
if self.order_type == 'Sales':
|
if self.order_type == 'Sales' and not self.skip_delivery_note:
|
||||||
delivery_date_list = [d.delivery_date for d in self.get("items") if d.delivery_date]
|
delivery_date_list = [d.delivery_date for d in self.get("items") if d.delivery_date]
|
||||||
max_delivery_date = max(delivery_date_list) if delivery_date_list else None
|
max_delivery_date = max(delivery_date_list) if delivery_date_list else None
|
||||||
if not self.delivery_date:
|
if not self.delivery_date:
|
||||||
@ -760,6 +760,7 @@ def get_events(start, end, filters=None):
|
|||||||
from
|
from
|
||||||
`tabSales Order`, `tabSales Order Item`
|
`tabSales Order`, `tabSales Order Item`
|
||||||
where `tabSales Order`.name = `tabSales Order Item`.parent
|
where `tabSales Order`.name = `tabSales Order Item`.parent
|
||||||
|
and `tabSales Order`.skip_delivery_note = 0
|
||||||
and (ifnull(`tabSales Order Item`.delivery_date, '0000-00-00')!= '0000-00-00') \
|
and (ifnull(`tabSales Order Item`.delivery_date, '0000-00-00')!= '0000-00-00') \
|
||||||
and (`tabSales Order Item`.delivery_date between %(start)s and %(end)s)
|
and (`tabSales Order Item`.delivery_date between %(start)s and %(end)s)
|
||||||
and `tabSales Order`.docstatus < 2
|
and `tabSales Order`.docstatus < 2
|
||||||
|
@ -1,58 +1,41 @@
|
|||||||
frappe.listview_settings['Sales Order'] = {
|
frappe.listview_settings['Sales Order'] = {
|
||||||
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date",
|
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date",
|
||||||
"per_delivered", "per_billed", "status", "order_type", "name"],
|
"per_delivered", "per_billed", "status", "order_type", "name", "skip_delivery_note"],
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
if (doc.status === "Closed") {
|
if (doc.status === "Closed") {
|
||||||
|
// Closed
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
|
|
||||||
} else if (doc.status === "On Hold") {
|
} else if (doc.status === "On Hold") {
|
||||||
// on hold
|
// on hold
|
||||||
return [__("On Hold"), "orange", "status,=,On Hold"];
|
return [__("On Hold"), "orange", "status,=,On Hold"];
|
||||||
} else if (doc.order_type !== "Maintenance"
|
} else if (doc.status === "Completed") {
|
||||||
&& flt(doc.per_delivered, 6) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
return [__("Completed"), "green", "status,=,Completed"];
|
||||||
|
} else if (!doc.skip_delivery_note && flt(doc.per_delivered, 6) < 100) {
|
||||||
|
if (frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||||
// not delivered & overdue
|
// not delivered & overdue
|
||||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
|
return [__("Overdue"), "red",
|
||||||
|
"per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
|
||||||
} else if (doc.order_type !== "Maintenance"
|
} else if (flt(doc.grand_total) === 0) {
|
||||||
&& flt(doc.per_delivered, 6) < 100 && doc.status !== "Closed") {
|
|
||||||
// not delivered
|
|
||||||
|
|
||||||
if (flt(doc.grand_total) === 0) {
|
|
||||||
// not delivered (zero-amount order)
|
// not delivered (zero-amount order)
|
||||||
|
|
||||||
return [__("To Deliver"), "orange",
|
return [__("To Deliver"), "orange",
|
||||||
"per_delivered,<,100|grand_total,=,0|status,!=,Closed"];
|
"per_delivered,<,100|grand_total,=,0|status,!=,Closed"];
|
||||||
} else if (flt(doc.per_billed, 6) < 100) {
|
} else if (flt(doc.per_billed, 6) < 100) {
|
||||||
// not delivered & not billed
|
// not delivered & not billed
|
||||||
|
|
||||||
return [__("To Deliver and Bill"), "orange",
|
return [__("To Deliver and Bill"), "orange",
|
||||||
"per_delivered,<,100|per_billed,<,100|status,!=,Closed"];
|
"per_delivered,<,100|per_billed,<,100|status,!=,Closed"];
|
||||||
} else {
|
} else {
|
||||||
// not billed
|
// not billed
|
||||||
|
|
||||||
return [__("To Deliver"), "orange",
|
return [__("To Deliver"), "orange",
|
||||||
"per_delivered,<,100|per_billed,=,100|status,!=,Closed"];
|
"per_delivered,<,100|per_billed,=,100|status,!=,Closed"];
|
||||||
}
|
}
|
||||||
|
} else if ((flt(doc.per_delivered, 6) === 100) && flt(doc.grand_total) !== 0
|
||||||
} else if ((flt(doc.per_delivered, 6) === 100)
|
&& flt(doc.per_billed, 6) < 100) {
|
||||||
&& flt(doc.grand_total) !== 0 && flt(doc.per_billed, 6) < 100 && doc.status !== "Closed") {
|
|
||||||
// to bill
|
// to bill
|
||||||
|
return [__("To Bill"), "orange",
|
||||||
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"];
|
"per_delivered,=,100|per_billed,<,100|status,!=,Closed"];
|
||||||
|
} else if (doc.skip_delivery_note && flt(doc.per_billed, 6) < 100){
|
||||||
} else if ((flt(doc.per_delivered, 6) === 100)
|
return [__("To Bill"), "orange", "per_billed,<,100|status,!=,Closed"];
|
||||||
&& (flt(doc.grand_total) === 0 || flt(doc.per_billed, 6) == 100) && doc.status !== "Closed") {
|
|
||||||
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"];
|
|
||||||
|
|
||||||
}else if (doc.order_type === "Maintenance" && flt(doc.per_delivered, 6) < 100 && doc.status !== "Closed"){
|
|
||||||
|
|
||||||
if(flt(doc.per_billed, 6) < 100 ){
|
|
||||||
return [__("To Deliver and Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"];
|
|
||||||
}else if(flt(doc.per_billed, 6) === 100){
|
|
||||||
return [__("To Deliver"), "orange", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
onload: function(listview) {
|
onload: function(listview) {
|
||||||
var method = "erpnext.selling.doctype.sales_order.sales_order.close_or_unclose_sales_orders";
|
var method = "erpnext.selling.doctype.sales_order.sales_order.close_or_unclose_sales_orders";
|
||||||
|
@ -149,6 +149,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
|
"depends_on": "eval: !parent.skip_delivery_note",
|
||||||
"fieldname": "delivery_date",
|
"fieldname": "delivery_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@ -693,6 +694,7 @@
|
|||||||
"description": "For Production",
|
"description": "For Production",
|
||||||
"fieldname": "produced_qty",
|
"fieldname": "produced_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 1,
|
||||||
"label": "Produced Quantity",
|
"label": "Produced Quantity",
|
||||||
"oldfieldname": "produced_qty",
|
"oldfieldname": "produced_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
@ -743,7 +745,7 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-09-13 12:18:54.903107",
|
"modified": "2019-10-10 08:46:26.244823",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order Item",
|
"name": "Sales Order Item",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user