Multiple delivery dates in Sales Order and make DN based on selected delivery dates (#9933)
* Multiple delivery dates in Sales Order and make DN based on selected delivery dates * Test case and some other minor fixes * Updated docs for multi delivery date * removed the trailing whitespace * removed the trailing whitespace * removed trailing whitespace
This commit is contained in:
parent
ac9b1332d2
commit
8e0f23efc7
@ -289,7 +289,7 @@ def get_credit_days(party_type, party, company):
|
|||||||
credit_days_based_on, credit_days = \
|
credit_days_based_on, credit_days = \
|
||||||
frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"])
|
frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"])
|
||||||
|
|
||||||
if not (credit_days_based_on and credit_days):
|
if not credit_days_based_on:
|
||||||
credit_days_based_on, credit_days = \
|
credit_days_based_on, credit_days = \
|
||||||
frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
|
frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@ def test_recurring_document(obj, test_records):
|
|||||||
base_doc.set(date_field, today)
|
base_doc.set(date_field, today)
|
||||||
|
|
||||||
if base_doc.doctype == "Sales Order":
|
if base_doc.doctype == "Sales Order":
|
||||||
base_doc.set("delivery_date", add_days(today, 15))
|
for d in base_doc.get("items"):
|
||||||
|
d.set("delivery_date", add_days(today, 15))
|
||||||
|
|
||||||
# monthly
|
# monthly
|
||||||
doc1 = frappe.copy_doc(base_doc)
|
doc1 = frappe.copy_doc(base_doc)
|
||||||
|
@ -118,7 +118,8 @@ def make_sales_order():
|
|||||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||||
so = frappe.get_doc(make_sales_order(q))
|
so = frappe.get_doc(make_sales_order(q))
|
||||||
so.transaction_date = frappe.flags.current_date
|
so.transaction_date = frappe.flags.current_date
|
||||||
so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
|
for d in so.get("items"):
|
||||||
|
d.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
|
||||||
so.insert()
|
so.insert()
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
so.submit()
|
so.submit()
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 443 KiB |
@ -31,7 +31,7 @@ Most of the information in your Sales Order is the same as the Quotation.
|
|||||||
There are a few amongst other things that a Sales Order will ask you to
|
There are a few amongst other things that a Sales Order will ask you to
|
||||||
update.
|
update.
|
||||||
|
|
||||||
* Expected date of delivery.
|
* Enter delivery date agaist each item. If there are multiple items and if you enter delivery date in the first row, the date will be copied to other rows as well where it is blank.
|
||||||
* Customer Purchase Order number: If your customer has sent you a Purchase Order, you can update its number for future reference (in billing).
|
* Customer Purchase Order number: If your customer has sent you a Purchase Order, you can update its number for future reference (in billing).
|
||||||
|
|
||||||
### Packing List
|
### Packing List
|
||||||
@ -89,9 +89,9 @@ ERPNext will automatically create new Order and mail a notification to the Email
|
|||||||
Once you “Submit” your Sales Order, you can now trigger different aspects of
|
Once you “Submit” your Sales Order, you can now trigger different aspects of
|
||||||
your organization:
|
your organization:
|
||||||
|
|
||||||
* To begin purchase click on “Make Purchase Request”
|
* To begin purchase click on Make -> Purchase Request
|
||||||
* To make a shipment entry click on “Make Delivery Note”
|
* To make a shipment entry click on Make -> Delivery Note. You can also make Delivery Note for selected items based on delivery date.
|
||||||
* To bill, make “Make Sales Invoice”
|
* To bill, make Make -> Sales Invoice
|
||||||
* To stop further process on this Sales Order, click on “Stop”
|
* To stop further process on this Sales Order, click on “Stop”
|
||||||
|
|
||||||
### Submission
|
### Submission
|
||||||
|
@ -77,7 +77,6 @@ frappe.ui.form.on("Production Order", {
|
|||||||
if (!frm.doc.status)
|
if (!frm.doc.status)
|
||||||
frm.doc.status = 'Draft';
|
frm.doc.status = 'Draft';
|
||||||
|
|
||||||
frm.add_fetch("sales_order", "delivery_date", "expected_delivery_date");
|
|
||||||
frm.add_fetch("sales_order", "project", "project");
|
frm.add_fetch("sales_order", "project", "project");
|
||||||
|
|
||||||
if(frm.doc.__islocal) {
|
if(frm.doc.__islocal) {
|
||||||
|
@ -50,8 +50,12 @@ class ProductionOrder(Document):
|
|||||||
|
|
||||||
def validate_sales_order(self):
|
def validate_sales_order(self):
|
||||||
if self.sales_order:
|
if self.sales_order:
|
||||||
so = frappe.db.sql("""select name, delivery_date, project from `tabSales Order`
|
so = frappe.db.sql("""
|
||||||
where name=%s and docstatus = 1""", self.sales_order, as_dict=1)
|
select so.name, so_item.delivery_date, so.project
|
||||||
|
from `tabSales Order` so, `tabSales Order Item` so_item
|
||||||
|
where so.name=%s and so.name=so_item.parent
|
||||||
|
and so.docstatus = 1 and so_item.item_code=%s
|
||||||
|
""", (self.sales_order, self.production_item), as_dict=1)
|
||||||
|
|
||||||
if len(so):
|
if len(so):
|
||||||
if not self.expected_delivery_date:
|
if not self.expected_delivery_date:
|
||||||
|
@ -422,3 +422,4 @@ erpnext.patches.v8_1.add_indexes_in_transaction_doctypes
|
|||||||
erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
|
erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
|
||||||
erpnext.patches.v8_1.update_expense_claim_status
|
erpnext.patches.v8_1.update_expense_claim_status
|
||||||
erpnext.patches.v8_3.update_company_total_sales
|
erpnext.patches.v8_3.update_company_total_sales
|
||||||
|
erpnext.patches.v8_1.set_delivery_date_in_so_item
|
13
erpnext/patches/v8_1/set_delivery_date_in_so_item.py
Normal file
13
erpnext/patches/v8_1/set_delivery_date_in_so_item.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doctype("Sales Order")
|
||||||
|
frappe.reload_doctype("Sales Order Item")
|
||||||
|
|
||||||
|
frappe.db.sql("""update `tabSales Order` set final_delivery_date = delivery_date where docstatus=1""")
|
||||||
|
|
||||||
|
frappe.db.sql("""
|
||||||
|
update `tabSales Order` so, `tabSales Order Item` so_item
|
||||||
|
set so_item.delivery_date = so.delivery_date
|
||||||
|
where so.name = so_item.parent
|
||||||
|
""")
|
@ -27,7 +27,8 @@ class TestQuotation(unittest.TestCase):
|
|||||||
self.assertEquals(sales_order.get("items")[0].prevdoc_docname, quotation.name)
|
self.assertEquals(sales_order.get("items")[0].prevdoc_docname, quotation.name)
|
||||||
self.assertEquals(sales_order.customer, "_Test Customer")
|
self.assertEquals(sales_order.customer, "_Test Customer")
|
||||||
|
|
||||||
sales_order.delivery_date = "2014-01-01"
|
for d in sales_order.get("items"):
|
||||||
|
d.delivery_date = "2014-01-01"
|
||||||
sales_order.naming_series = "_T-Quotation-"
|
sales_order.naming_series = "_T-Quotation-"
|
||||||
sales_order.transaction_date = "2013-05-12"
|
sales_order.transaction_date = "2013-05-12"
|
||||||
sales_order.insert()
|
sales_order.insert()
|
||||||
@ -51,9 +52,11 @@ class TestQuotation(unittest.TestCase):
|
|||||||
quotation.submit()
|
quotation.submit()
|
||||||
|
|
||||||
sales_order = make_sales_order(quotation.name)
|
sales_order = make_sales_order(quotation.name)
|
||||||
sales_order.delivery_date = "2016-01-02"
|
|
||||||
sales_order.naming_series = "_T-Quotation-"
|
sales_order.naming_series = "_T-Quotation-"
|
||||||
sales_order.transaction_date = "2016-01-01"
|
sales_order.transaction_date = "2016-01-01"
|
||||||
|
for d in sales_order.get("items"):
|
||||||
|
d.delivery_date = "2016-01-02"
|
||||||
|
|
||||||
sales_order.insert()
|
sales_order.insert()
|
||||||
|
|
||||||
self.assertEquals(quotation.get("items")[0].rate, rate_with_margin)
|
self.assertEquals(quotation.get("items")[0].rate, rate_with_margin)
|
||||||
|
@ -33,6 +33,12 @@ frappe.ui.form.on("Sales Order", {
|
|||||||
function(doc) { return (doc.stock_qty<=doc.delivered_qty) ? "green" : "orange" })
|
function(doc) { return (doc.stock_qty<=doc.delivered_qty) ? "green" : "orange" })
|
||||||
|
|
||||||
erpnext.queries.setup_warehouse_query(frm);
|
erpnext.queries.setup_warehouse_query(frm);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Sales Order Item", {
|
||||||
|
delivery_date: function(frm, cdt, cdn) {
|
||||||
|
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -77,7 +83,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
// delivery note
|
// delivery note
|
||||||
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
||||||
this.frm.add_custom_button(__('Delivery'),
|
this.frm.add_custom_button(__('Delivery'),
|
||||||
function() { me.make_delivery_note() }, __("Make"));
|
function() { me.make_delivery_note_based_on_delivery_note(); }, __("Make"));
|
||||||
this.frm.add_custom_button(__('Production Order'),
|
this.frm.add_custom_button(__('Production Order'),
|
||||||
function() { me.make_production_order() }, __("Make"));
|
function() { me.make_production_order() }, __("Make"));
|
||||||
|
|
||||||
@ -235,7 +241,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
},
|
},
|
||||||
|
|
||||||
order_type: function() {
|
order_type: function() {
|
||||||
this.frm.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
|
this.frm.fields_dict.items.grid.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
|
||||||
},
|
},
|
||||||
|
|
||||||
tc_name: function() {
|
tc_name: function() {
|
||||||
@ -249,10 +255,72 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
make_delivery_note_based_on_delivery_note: function() {
|
||||||
|
var me = this;
|
||||||
|
|
||||||
|
var delivery_dates = [];
|
||||||
|
$.each(this.frm.doc.items || [], function(i, d) {
|
||||||
|
if(!delivery_dates.includes(d.delivery_date)) {
|
||||||
|
delivery_dates.push(d.delivery_date);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var item_grid = this.frm.fields_dict["items"].grid;
|
||||||
|
if(!item_grid.get_selected().length && delivery_dates.length > 1) {
|
||||||
|
var dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("Select Items based on Delivery Date"),
|
||||||
|
fields: [{fieldtype: "HTML", fieldname: "dates_html"}]
|
||||||
|
});
|
||||||
|
|
||||||
|
var html = $(`
|
||||||
|
<div style="border: 1px solid #d1d8dd">
|
||||||
|
<div class="list-item list-item--head">
|
||||||
|
<div class="list-item__content list-item__content--flex-2">
|
||||||
|
${__('Delivery Date')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
${delivery_dates.map(date => `
|
||||||
|
<div class="list-item">
|
||||||
|
<div class="list-item__content list-item__content--flex-2">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" data-date="${date}" checked="checked"/>
|
||||||
|
${frappe.datetime.str_to_user(date)}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join("")}
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
var wrapper = dialog.fields_dict.dates_html.$wrapper;
|
||||||
|
wrapper.html(html);
|
||||||
|
|
||||||
|
dialog.set_primary_action(__("Select"), function() {
|
||||||
|
var dates = wrapper.find('input[type=checkbox]:checked')
|
||||||
|
.map((i, el) => $(el).attr('data-date')).toArray();
|
||||||
|
|
||||||
|
if(!dates) return;
|
||||||
|
|
||||||
|
$.each(dates, function(i, d) {
|
||||||
|
$.each(item_grid.grid_rows || [], function(j, row) {
|
||||||
|
if(row.doc.delivery_date == d) {
|
||||||
|
row.doc.__checked = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
me.make_delivery_note();
|
||||||
|
dialog.hide();
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
} else {
|
||||||
|
this.make_delivery_note();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
make_delivery_note: function() {
|
make_delivery_note: function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
|
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
|
||||||
frm: this.frm
|
frm: me.frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -344,6 +412,11 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
if(cint(frappe.boot.notification_settings.sales_order)) {
|
if(cint(frappe.boot.notification_settings.sales_order)) {
|
||||||
this.frm.email_doc(frappe.boot.notification_settings.sales_order_message);
|
this.frm.email_doc(frappe.boot.notification_settings.sales_order_message);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
items_add: function(doc, cdt, cdn) {
|
||||||
|
var row = frappe.get_doc(cdt, cdn);
|
||||||
|
this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -367,32 +367,29 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "eval:doc.order_type == 'Sales'",
|
"fieldname": "final_delivery_date",
|
||||||
"fieldname": "delivery_date",
|
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Delivery Date",
|
"label": "Final Delivery Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "delivery_date",
|
|
||||||
"oldfieldtype": "Date",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0,
|
"unique": 0
|
||||||
"width": "160px"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
@ -3632,7 +3629,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-06-19 13:06:31.736384",
|
"modified": "2017-07-17 18:23:36.023797",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
@ -30,7 +30,6 @@ class SalesOrder(SellingController):
|
|||||||
|
|
||||||
self.validate_order_type()
|
self.validate_order_type()
|
||||||
self.validate_delivery_date()
|
self.validate_delivery_date()
|
||||||
self.validate_mandatory()
|
|
||||||
self.validate_proj_cust()
|
self.validate_proj_cust()
|
||||||
self.validate_po()
|
self.validate_po()
|
||||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||||
@ -48,25 +47,20 @@ class SalesOrder(SellingController):
|
|||||||
if not self.billing_status: self.billing_status = 'Not Billed'
|
if not self.billing_status: self.billing_status = 'Not Billed'
|
||||||
if not self.delivery_status: self.delivery_status = 'Not Delivered'
|
if not self.delivery_status: self.delivery_status = 'Not Delivered'
|
||||||
|
|
||||||
def validate_mandatory(self):
|
|
||||||
# validate transaction date v/s delivery date
|
|
||||||
if self.delivery_date:
|
|
||||||
if getdate(self.transaction_date) > getdate(self.delivery_date):
|
|
||||||
frappe.msgprint(_("Expected Delivery Date is be before Sales Order Date"),
|
|
||||||
indicator='orange',
|
|
||||||
title=_('Warning'))
|
|
||||||
|
|
||||||
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 and self.delivery_date and getdate(self.po_date) > getdate(self.delivery_date):
|
if self.po_date:
|
||||||
frappe.throw(_("Expected Delivery Date cannot be before Purchase Order Date"))
|
for d in self.get("items"):
|
||||||
|
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")
|
||||||
|
.format(d.idx))
|
||||||
|
|
||||||
if self.po_no and self.customer:
|
if self.po_no and self.customer:
|
||||||
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))
|
||||||
if so and so[0][0] and not \
|
if so and so[0][0] and not cint(frappe.db.get_single_value("Selling Settings",
|
||||||
cint(frappe.db.get_single_value("Selling Settings", "allow_against_multiple_purchase_orders")):
|
"allow_against_multiple_purchase_orders")):
|
||||||
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
|
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
|
||||||
|
|
||||||
def validate_for_items(self):
|
def validate_for_items(self):
|
||||||
@ -78,7 +72,7 @@ class SalesOrder(SellingController):
|
|||||||
d.transaction_date = self.transaction_date
|
d.transaction_date = self.transaction_date
|
||||||
|
|
||||||
tot_avail_qty = frappe.db.sql("select projected_qty from `tabBin` \
|
tot_avail_qty = frappe.db.sql("select projected_qty from `tabBin` \
|
||||||
where item_code = %s and warehouse = %s", (d.item_code,d.warehouse))
|
where item_code = %s and warehouse = %s", (d.item_code, d.warehouse))
|
||||||
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
|
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
|
||||||
|
|
||||||
# check for same entry multiple times
|
# check for same entry multiple times
|
||||||
@ -97,16 +91,30 @@ class SalesOrder(SellingController):
|
|||||||
def validate_sales_mntc_quotation(self):
|
def validate_sales_mntc_quotation(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.prevdoc_docname:
|
if d.prevdoc_docname:
|
||||||
res = frappe.db.sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.order_type))
|
res = frappe.db.sql("select name from `tabQuotation` where name=%s and order_type = %s",
|
||||||
|
(d.prevdoc_docname, self.order_type))
|
||||||
if not res:
|
if not res:
|
||||||
frappe.msgprint(_("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type))
|
frappe.msgprint(_("Quotation {0} not of type {1}")
|
||||||
|
.format(d.prevdoc_docname, self.order_type))
|
||||||
|
|
||||||
def validate_order_type(self):
|
def validate_order_type(self):
|
||||||
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' and not self.delivery_date:
|
self.final_delivery_date = None
|
||||||
frappe.throw(_("Please enter 'Expected Delivery Date'"))
|
if self.order_type == 'Sales':
|
||||||
|
for d in self.get("items"):
|
||||||
|
if not d.delivery_date:
|
||||||
|
frappe.throw(_("Row #{0}: Please enter Delivery Date against item {1}")
|
||||||
|
.format(d.idx, d.item_code))
|
||||||
|
|
||||||
|
if getdate(self.transaction_date) > getdate(d.delivery_date):
|
||||||
|
frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"),
|
||||||
|
indicator='orange', title=_('Warning'))
|
||||||
|
|
||||||
|
if not self.final_delivery_date or \
|
||||||
|
(d.delivery_date and getdate(d.delivery_date) > getdate(self.final_delivery_date)):
|
||||||
|
self.final_delivery_date = d.delivery_date
|
||||||
|
|
||||||
self.validate_sales_mntc_quotation()
|
self.validate_sales_mntc_quotation()
|
||||||
|
|
||||||
@ -122,7 +130,7 @@ class SalesOrder(SellingController):
|
|||||||
super(SalesOrder, self).validate_warehouse()
|
super(SalesOrder, self).validate_warehouse()
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if (frappe.db.get_value("Item", d.item_code, "is_stock_item")==1 or
|
if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 or
|
||||||
(self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code))) \
|
(self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code))) \
|
||||||
and not d.warehouse and not cint(d.delivered_by_supplier):
|
and not d.warehouse and not cint(d.delivered_by_supplier):
|
||||||
frappe.throw(_("Delivery warehouse required for stock item {0}").format(d.item_code),
|
frappe.throw(_("Delivery warehouse required for stock item {0}").format(d.item_code),
|
||||||
@ -336,11 +344,14 @@ class SalesOrder(SellingController):
|
|||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def on_recurring(self, reference_doc):
|
def on_recurring(self, reference_doc):
|
||||||
mcount = month_map[reference_doc.recurring_type]
|
mcount = month_map[reference_doc.recurring_type]
|
||||||
self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount,
|
for d in self.get("items"):
|
||||||
cint(reference_doc.repeat_on_day_of_month)))
|
reference_delivery_date = frappe.db.get_value("Sales Order Item",
|
||||||
|
{"parent": reference_doc.name, "item_code": d.item_code, "idx": d.idx}, "delivery_date")
|
||||||
|
|
||||||
|
d.set("delivery_date",
|
||||||
|
get_next_date(reference_delivery_date, mcount, cint(reference_doc.repeat_on_day_of_month)))
|
||||||
|
|
||||||
def get_list_context(context=None):
|
def get_list_context(context=None):
|
||||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||||
@ -423,7 +434,6 @@ def make_project(source_name, target_doc=None):
|
|||||||
},
|
},
|
||||||
"field_map":{
|
"field_map":{
|
||||||
"name" : "sales_order",
|
"name" : "sales_order",
|
||||||
"delivery_date" : "expected_end_date",
|
|
||||||
"base_grand_total" : "estimated_costing",
|
"base_grand_total" : "estimated_costing",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -614,12 +624,17 @@ def get_events(start, end, filters=None):
|
|||||||
from frappe.desk.calendar import get_event_conditions
|
from frappe.desk.calendar import get_event_conditions
|
||||||
conditions = get_event_conditions("Sales Order", filters)
|
conditions = get_event_conditions("Sales Order", filters)
|
||||||
|
|
||||||
data = frappe.db.sql("""select name, customer_name, status, delivery_status, billing_status, delivery_date
|
data = frappe.db.sql("""
|
||||||
from `tabSales Order`
|
select
|
||||||
where (ifnull(delivery_date, '0000-00-00')!= '0000-00-00') \
|
so.name, so.customer_name, so.status,
|
||||||
and (delivery_date between %(start)s and %(end)s)
|
so.delivery_status, so.billing_status, so_item.delivery_date
|
||||||
and docstatus < 2
|
from
|
||||||
{conditions}
|
`tabSales Order` so, `tabSales Order Item` so_item
|
||||||
|
where so.name = so_item.parent
|
||||||
|
and (ifnull(so_item.delivery_date, '0000-00-00')!= '0000-00-00') \
|
||||||
|
and (so_item.delivery_date between %(start)s and %(end)s)
|
||||||
|
and so.docstatus < 2
|
||||||
|
{conditions}
|
||||||
""".format(conditions=conditions), {
|
""".format(conditions=conditions), {
|
||||||
"start": start,
|
"start": start,
|
||||||
"end": end
|
"end": end
|
||||||
@ -659,7 +674,7 @@ def make_purchase_order_for_drop_shipment(source_name, for_supplier, target_doc=
|
|||||||
target.run_method("calculate_taxes_and_totals")
|
target.run_method("calculate_taxes_and_totals")
|
||||||
|
|
||||||
def update_item(source, target, source_parent):
|
def update_item(source, target, source_parent):
|
||||||
target.schedule_date = source_parent.delivery_date
|
target.schedule_date = source.delivery_date
|
||||||
target.qty = flt(source.qty) - flt(source.ordered_qty)
|
target.qty = flt(source.qty) - flt(source.ordered_qty)
|
||||||
target.stock_qty = (flt(source.qty) - flt(source.ordered_qty)) * flt(source.conversion_factor)
|
target.stock_qty = (flt(source.qty) - flt(source.ordered_qty)) * flt(source.conversion_factor)
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
frappe.listview_settings['Sales Order'] = {
|
frappe.listview_settings['Sales Order'] = {
|
||||||
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date", "per_delivered", "per_billed",
|
add_fields: ["base_grand_total", "customer_name", "currency", "final_delivery_date",
|
||||||
"status", "order_type"],
|
"per_delivered", "per_billed", "status", "order_type", "name"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status==="Closed"){
|
if(doc.status==="Closed"){
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
|
|
||||||
} else if (doc.order_type !== "Maintenance"
|
} else if (doc.order_type !== "Maintenance"
|
||||||
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.final_delivery_date) < 0) {
|
||||||
// to bill & overdue
|
// to bill & overdue
|
||||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
|
return [__("Overdue"), "red", "per_delivered,<,100|final_delivery_date,<,Today|status,!=,Closed"];
|
||||||
|
|
||||||
} else if (doc.order_type !== "Maintenance"
|
} else if (doc.order_type !== "Maintenance"
|
||||||
&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") {
|
&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_group": "_Test Customer Group",
|
"customer_group": "_Test Customer Group",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
"delivery_date": "2013-02-23",
|
|
||||||
"doctype": "Sales Order",
|
"doctype": "Sales Order",
|
||||||
"base_grand_total": 1000.0,
|
"base_grand_total": 1000.0,
|
||||||
"grand_total": 1000.0,
|
"grand_total": 1000.0,
|
||||||
@ -23,6 +22,7 @@
|
|||||||
"doctype": "Sales Order Item",
|
"doctype": "Sales Order Item",
|
||||||
"item_code": "_Test Item Home Desktop 100",
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
"item_name": "CPU",
|
"item_name": "CPU",
|
||||||
|
"delivery_date": "2013-02-23",
|
||||||
"parentfield": "items",
|
"parentfield": "items",
|
||||||
"qty": 10.0,
|
"qty": 10.0,
|
||||||
"rate": 100.0,
|
"rate": 100.0,
|
||||||
|
@ -512,7 +512,6 @@ def make_sales_order(**args):
|
|||||||
|
|
||||||
so.company = args.company or "_Test Company"
|
so.company = args.company or "_Test Company"
|
||||||
so.customer = args.customer or "_Test Customer"
|
so.customer = args.customer or "_Test Customer"
|
||||||
so.delivery_date = add_days(so.transaction_date, 10)
|
|
||||||
so.currency = args.currency or "INR"
|
so.currency = args.currency or "INR"
|
||||||
if args.selling_price_list:
|
if args.selling_price_list:
|
||||||
so.selling_price_list = args.selling_price_list
|
so.selling_price_list = args.selling_price_list
|
||||||
@ -533,6 +532,9 @@ def make_sales_order(**args):
|
|||||||
"rate": args.rate or 100
|
"rate": args.rate or 100
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for d in so.get("items"):
|
||||||
|
d.delivery_date = add_days(so.transaction_date, 10)
|
||||||
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
so.insert()
|
so.insert()
|
||||||
if not args.do_not_submit:
|
if not args.do_not_submit:
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 4,
|
"columns": 3,
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -200,6 +200,36 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "300px"
|
"width": "300px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 2,
|
||||||
|
"fieldname": "delivery_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Delivery Date",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -324,7 +354,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 2,
|
"columns": 1,
|
||||||
"fieldname": "qty",
|
"fieldname": "qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1933,7 +1963,7 @@
|
|||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-05-10 17:14:48.277982",
|
"modified": "2017-07-18 18:26:36.870342",
|
||||||
"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