mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 00:44:45 +00:00
Merge pull request #16827 from Mangesh-Khairnar/so-on-hold
Feature: Sales order on hold
This commit is contained in:
@@ -171,7 +171,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
},
|
},
|
||||||
get_query_filters: {
|
get_query_filters: {
|
||||||
docstatus: 1,
|
docstatus: 1,
|
||||||
status: ["!=", "Closed"],
|
status: ["not in", ["Closed", "On Hold"]],
|
||||||
per_billed: ["<", 99.99],
|
per_billed: ["<", 99.99],
|
||||||
company: me.frm.doc.company
|
company: me.frm.doc.company
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.validate_with_previous_doc()
|
self.validate_with_previous_doc()
|
||||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||||
self.validate_uom_is_integer("uom", "qty")
|
self.validate_uom_is_integer("uom", "qty")
|
||||||
self.check_close_sales_order("sales_order")
|
self.check_sales_order_on_hold_or_close("sales_order")
|
||||||
self.validate_debit_to_acc()
|
self.validate_debit_to_acc()
|
||||||
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
||||||
self.add_remarks()
|
self.add_remarks()
|
||||||
@@ -209,7 +209,7 @@ class SalesInvoice(SellingController):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
super(SalesInvoice, self).on_cancel()
|
super(SalesInvoice, self).on_cancel()
|
||||||
|
|
||||||
self.check_close_sales_order("sales_order")
|
self.check_sales_order_on_hold_or_close("sales_order")
|
||||||
|
|
||||||
if self.is_return and not self.update_billed_amount_in_sales_order:
|
if self.is_return and not self.update_billed_amount_in_sales_order:
|
||||||
# NOTE status updating bypassed for is_return
|
# NOTE status updating bypassed for is_return
|
||||||
@@ -1397,4 +1397,4 @@ def get_loyalty_programs(customer):
|
|||||||
frappe.db.set(customer, 'loyalty_program', lp_details[0])
|
frappe.db.set(customer, 'loyalty_program', lp_details[0])
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
return lp_details
|
return lp_details
|
||||||
@@ -442,6 +442,13 @@ class BuyingController(StockController):
|
|||||||
frappe.throw(_("Row #{0}: {1} can not be negative for item {2}".format(item_row['idx'],
|
frappe.throw(_("Row #{0}: {1} can not be negative for item {2}".format(item_row['idx'],
|
||||||
frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
|
frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
|
||||||
|
|
||||||
|
def check_for_on_hold_or_closed_status(self, ref_doctype, ref_fieldname):
|
||||||
|
for d in self.get("items"):
|
||||||
|
if d.get(ref_fieldname):
|
||||||
|
status = frappe.db.get_value(ref_doctype, d.get(ref_fieldname), "status")
|
||||||
|
if status in ("Closed", "On Hold"):
|
||||||
|
frappe.throw(_("{0} {1} is {2}").format(ref_doctype,d.get(ref_fieldname), status))
|
||||||
|
|
||||||
def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
|
def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||||
self.update_ordered_and_reserved_qty()
|
self.update_ordered_and_reserved_qty()
|
||||||
|
|
||||||
|
|||||||
@@ -257,11 +257,11 @@ class SellingController(StockController):
|
|||||||
so_warehouse = so_item and so_item[0]["warehouse"] or ""
|
so_warehouse = so_item and so_item[0]["warehouse"] or ""
|
||||||
return so_qty, so_warehouse
|
return so_qty, so_warehouse
|
||||||
|
|
||||||
def check_close_sales_order(self, ref_fieldname):
|
def check_sales_order_on_hold_or_close(self, ref_fieldname):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.get(ref_fieldname):
|
if d.get(ref_fieldname):
|
||||||
status = frappe.db.get_value("Sales Order", d.get(ref_fieldname), "status")
|
status = frappe.db.get_value("Sales Order", d.get(ref_fieldname), "status")
|
||||||
if status == "Closed":
|
if status in ("Closed", "On Hold"):
|
||||||
frappe.throw(_("Sales Order {0} is {1}").format(d.get(ref_fieldname), status))
|
frappe.throw(_("Sales Order {0} is {1}").format(d.get(ref_fieldname), status))
|
||||||
|
|
||||||
def update_reserved_qty(self):
|
def update_reserved_qty(self):
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ status_map = {
|
|||||||
["Completed", "eval:self.order_type == 'Maintenance' and self.per_billed == 100 and self.docstatus == 1"],
|
["Completed", "eval:self.order_type == 'Maintenance' 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'"],
|
||||||
],
|
],
|
||||||
"Sales Invoice": [
|
"Sales Invoice": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("sales_order", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
"status": ["not in", ["Closed", "On Hold"]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("fg_warehouse", function() {
|
frm.set_query("fg_warehouse", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
def validate_sales_order(self):
|
def validate_sales_order(self):
|
||||||
if self.sales_order:
|
if self.sales_order:
|
||||||
|
self.check_sales_order_on_hold_or_close()
|
||||||
so = frappe.db.sql("""
|
so = frappe.db.sql("""
|
||||||
select so.name, so_item.delivery_date, so.project
|
select so.name, so_item.delivery_date, so.project
|
||||||
from `tabSales Order` so
|
from `tabSales Order` so
|
||||||
@@ -91,6 +92,11 @@ class WorkOrder(Document):
|
|||||||
else:
|
else:
|
||||||
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
||||||
|
|
||||||
|
def check_sales_order_on_hold_or_close(self):
|
||||||
|
status = frappe.db.get_value("Sales Order", self.sales_order, "status")
|
||||||
|
if status in ("Closed", "On Hold"):
|
||||||
|
frappe.throw(_("Sales Order {0} is {1}").format(self.sales_order, status))
|
||||||
|
|
||||||
def set_default_warehouse(self):
|
def set_default_warehouse(self):
|
||||||
if not self.wip_warehouse:
|
if not self.wip_warehouse:
|
||||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ frappe.ui.form.on("Sales Order", {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if(frm.doc.docstatus == 1 && frm.doc.status == 'To Deliver and Bill') {
|
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
|
||||||
|
&& flt(frm.doc.per_delivered) < 100 && flt(frm.doc.per_billed) < 100) {
|
||||||
frm.add_custom_button(__('Update Items'), () => {
|
frm.add_custom_button(__('Update Items'), () => {
|
||||||
erpnext.utils.update_child_items({
|
erpnext.utils.update_child_items({
|
||||||
frm: frm,
|
frm: frm,
|
||||||
@@ -114,103 +115,102 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
var allow_delivery = false;
|
var allow_delivery = false;
|
||||||
|
|
||||||
if(doc.docstatus==1) {
|
if(doc.docstatus==1) {
|
||||||
if(doc.status != 'Closed') {
|
if(this.frm.has_perm("submit")) {
|
||||||
|
if(doc.status === 'On Hold') {
|
||||||
|
// un-hold
|
||||||
|
this.frm.add_custom_button(__('Resume'), function() {
|
||||||
|
me.frm.cscript.update_status('Resume', 'Draft')
|
||||||
|
}, __("Status"));
|
||||||
|
|
||||||
for (var i in this.frm.doc.items) {
|
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
||||||
var item = this.frm.doc.items[i];
|
// close
|
||||||
if(item.delivered_by_supplier === 1 || item.supplier){
|
this.frm.add_custom_button(__('Close'), () => this.close_sales_order(), __("Status"))
|
||||||
if(item.qty > flt(item.ordered_qty)
|
}
|
||||||
&& item.qty > flt(item.delivered_qty)) {
|
}
|
||||||
allow_purchase = true;
|
else if(doc.status === 'Closed') {
|
||||||
|
// un-close
|
||||||
|
this.frm.add_custom_button(__('Re-open'), function() {
|
||||||
|
me.frm.cscript.update_status('Re-open', 'Draft')
|
||||||
|
}, __("Status"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(doc.status !== 'Closed') {
|
||||||
|
if(doc.status !== 'On Hold') {
|
||||||
|
for (var i in this.frm.doc.items) {
|
||||||
|
var item = this.frm.doc.items[i];
|
||||||
|
if(item.delivered_by_supplier === 1 || item.supplier){
|
||||||
|
if(item.qty > flt(item.ordered_qty)
|
||||||
|
&& item.qty > flt(item.delivered_qty)) {
|
||||||
|
allow_purchase = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.delivered_by_supplier===0) {
|
||||||
|
if(item.qty > flt(item.delivered_qty)) {
|
||||||
|
allow_delivery = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_delivery && allow_purchase) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.delivered_by_supplier===0) {
|
if (this.frm.has_perm("submit")) {
|
||||||
if(item.qty > flt(item.delivered_qty)) {
|
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
||||||
allow_delivery = true;
|
// hold
|
||||||
|
this.frm.add_custom_button(__('Hold'), () => this.hold_sales_order(), __("Status"))
|
||||||
|
// close
|
||||||
|
this.frm.add_custom_button(__('Close'), () => this.close_sales_order(), __("Status"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allow_delivery && allow_purchase) {
|
// delivery note
|
||||||
break;
|
if(flt(doc.per_delivered, 6) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
||||||
|
this.frm.add_custom_button(__('Delivery'), () => this.make_delivery_note_based_on_delivery_date(), __('Create'));
|
||||||
|
this.frm.add_custom_button(__('Work Order'), () => this.make_work_order(), __('Create'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// sales invoice
|
||||||
|
if(flt(doc.per_billed, 6) < 100) {
|
||||||
|
this.frm.add_custom_button(__('Invoice'), () => me.make_sales_invoice(), __('Create'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// material request
|
||||||
|
if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1
|
||||||
|
&& flt(doc.per_delivered, 6) < 100) {
|
||||||
|
this.frm.add_custom_button(__('Material Request'), () => this.make_material_request(), __('Create'));
|
||||||
|
this.frm.add_custom_button(__('Request for Raw Materials'), () => this.make_raw_material_request(), __('Create'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// make purchase order
|
||||||
|
if(flt(doc.per_delivered, 6) < 100 && allow_purchase) {
|
||||||
|
this.frm.add_custom_button(__('Purchase Order'), () => this.make_purchase_order(), __('Create'));
|
||||||
|
}
|
||||||
|
// maintenance
|
||||||
|
if(flt(doc.per_delivered, 2) < 100 &&
|
||||||
|
["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
|
||||||
|
this.frm.add_custom_button(__('Maintenance Visit'), () => this.make_maintenance_visit(), __('Create'));
|
||||||
|
this.frm.add_custom_button(__('Maintenance Schedule'), () => this.make_maintenance_schedule(), __('Create'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// project
|
||||||
|
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
||||||
|
this.frm.add_custom_button(__('Project'), () => this.make_project(), __('Create'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!doc.auto_repeat) {
|
||||||
|
this.frm.add_custom_button(__('Subscription'), function() {
|
||||||
|
erpnext.utils.make_subscription(doc.doctype, doc.name)
|
||||||
|
}, __('Create'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.frm.has_perm("submit")) {
|
|
||||||
// close
|
|
||||||
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
|
||||||
this.frm.add_custom_button(__('Close'),
|
|
||||||
function() { me.close_sales_order() }, __("Status"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// delivery note
|
|
||||||
if(flt(doc.per_delivered, 6) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
|
||||||
this.frm.add_custom_button(__('Delivery'),
|
|
||||||
function() { me.make_delivery_note_based_on_delivery_date(); }, __('Create'));
|
|
||||||
this.frm.add_custom_button(__('Work Order'),
|
|
||||||
function() { me.make_work_order() }, __('Create'));
|
|
||||||
|
|
||||||
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sales invoice
|
|
||||||
if(flt(doc.per_billed, 6) < 100) {
|
|
||||||
this.frm.add_custom_button(__('Invoice'),
|
|
||||||
function() { me.make_sales_invoice() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// material request
|
|
||||||
if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1
|
|
||||||
&& flt(doc.per_delivered, 6) < 100) {
|
|
||||||
this.frm.add_custom_button(__('Material Request'),
|
|
||||||
function() { me.make_material_request() }, __('Create'));
|
|
||||||
this.frm.add_custom_button(__('Request for Raw Materials'),
|
|
||||||
function() { me.make_raw_material_request() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// make purchase order
|
|
||||||
if(flt(doc.per_delivered, 6) < 100 && allow_purchase) {
|
|
||||||
this.frm.add_custom_button(__('Purchase Order'),
|
|
||||||
function() { me.make_purchase_order() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// payment request
|
// payment request
|
||||||
if(flt(doc.per_billed)==0) {
|
if(flt(doc.per_billed)==0) {
|
||||||
this.frm.add_custom_button(__('Payment Request'),
|
this.frm.add_custom_button(__('Payment Request'), () => this.make_payment_request(), __('Create'));
|
||||||
function() { me.make_payment_request() }, __('Create'));
|
this.frm.add_custom_button(__('Payment'), () => this.make_payment_entry(), __('Create'));
|
||||||
this.frm.add_custom_button(__('Payment'),
|
|
||||||
function() { me.make_payment_entry() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// maintenance
|
|
||||||
if(flt(doc.per_delivered, 2) < 100 &&
|
|
||||||
["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
|
|
||||||
this.frm.add_custom_button(__('Maintenance Visit'),
|
|
||||||
function() { me.make_maintenance_visit() }, __('Create'));
|
|
||||||
this.frm.add_custom_button(__('Maintenance Schedule'),
|
|
||||||
function() { me.make_maintenance_schedule() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// project
|
|
||||||
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
|
||||||
this.frm.add_custom_button(__('Project'),
|
|
||||||
function() { me.make_project() }, __('Create'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!doc.auto_repeat) {
|
|
||||||
this.frm.add_custom_button(__('Subscription'), function() {
|
|
||||||
erpnext.utils.make_subscription(doc.doctype, doc.name)
|
|
||||||
}, __('Create'))
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (this.frm.has_perm("submit")) {
|
|
||||||
// un-close
|
|
||||||
this.frm.add_custom_button(__('Re-open'), function() {
|
|
||||||
me.frm.cscript.update_status('Re-open', 'Draft')
|
|
||||||
}, __("Status"));
|
|
||||||
}
|
}
|
||||||
|
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +555,38 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
});
|
});
|
||||||
dialog.show();
|
dialog.show();
|
||||||
},
|
},
|
||||||
|
hold_sales_order: function(){
|
||||||
|
var me = this;
|
||||||
|
var d = new frappe.ui.Dialog({
|
||||||
|
title: __('Reason for Hold'),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
"fieldname": "reason_for_hold",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"reqd": 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
primary_action: function() {
|
||||||
|
var data = d.get_values();
|
||||||
|
frappe.call({
|
||||||
|
method: "frappe.desk.form.utils.add_comment",
|
||||||
|
args: {
|
||||||
|
reference_doctype: me.frm.doctype,
|
||||||
|
reference_name: me.frm.docname,
|
||||||
|
content: __('Reason for hold: ')+data.reason_for_hold,
|
||||||
|
comment_email: frappe.session.user
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc) {
|
||||||
|
me.update_status('Hold', 'On Hold')
|
||||||
|
d.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.show();
|
||||||
|
},
|
||||||
close_sales_order: function(){
|
close_sales_order: function(){
|
||||||
this.frm.cscript.update_status("Close", "Closed")
|
this.frm.cscript.update_status("Close", "Closed")
|
||||||
},
|
},
|
||||||
@@ -574,4 +606,4 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
|
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -965,4 +965,4 @@ def make_raw_material_request(items, company, sales_order, project=None):
|
|||||||
material_request.flags.ignore_permissions = 1
|
material_request.flags.ignore_permissions = 1
|
||||||
material_request.run_method("set_missing_values")
|
material_request.run_method("set_missing_values")
|
||||||
material_request.submit()
|
material_request.submit()
|
||||||
return material_request
|
return material_request
|
||||||
@@ -5,6 +5,9 @@ frappe.listview_settings['Sales Order'] = {
|
|||||||
if (doc.status === "Closed") {
|
if (doc.status === "Closed") {
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
|
|
||||||
|
} else if (doc.status === "On Hold") {
|
||||||
|
// on hold
|
||||||
|
return [__("On Hold"), "orange", "status,=,On Hold"];
|
||||||
} else if (doc.order_type !== "Maintenance"
|
} else if (doc.order_type !== "Maintenance"
|
||||||
&& flt(doc.per_delivered, 6) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
&& flt(doc.per_delivered, 6) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||||
// not delivered & overdue
|
// not delivered & overdue
|
||||||
|
|||||||
@@ -242,6 +242,13 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
|
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
|
||||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
|
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
|
||||||
|
|
||||||
|
def test_sales_order_on_hold(self):
|
||||||
|
so = make_sales_order(item_code="_Test Product Bundle Item")
|
||||||
|
so.db_set('Status', "On Hold")
|
||||||
|
si = make_sales_invoice(so.name)
|
||||||
|
self.assertRaises(frappe.ValidationError, create_dn_against_so, so.name)
|
||||||
|
self.assertRaises(frappe.ValidationError, si.submit)
|
||||||
|
|
||||||
def test_reserved_qty_for_over_delivery_with_packing_list(self):
|
def test_reserved_qty_for_over_delivery_with_packing_list(self):
|
||||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||||
make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
|
make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
|
|||||||
},
|
},
|
||||||
get_query_filters: {
|
get_query_filters: {
|
||||||
docstatus: 1,
|
docstatus: 1,
|
||||||
status: ["!=", "Closed"],
|
status: ["not in", ["Closed", "On Hold"]],
|
||||||
per_delivered: ["<", 99.99],
|
per_delivered: ["<", 99.99],
|
||||||
company: me.frm.doc.company,
|
company: me.frm.doc.company,
|
||||||
project: me.frm.doc.project || undefined,
|
project: me.frm.doc.project || undefined,
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class DeliveryNote(SellingController):
|
|||||||
self.set_status()
|
self.set_status()
|
||||||
self.so_required()
|
self.so_required()
|
||||||
self.validate_proj_cust()
|
self.validate_proj_cust()
|
||||||
self.check_close_sales_order("against_sales_order")
|
self.check_sales_order_on_hold_or_close("against_sales_order")
|
||||||
self.validate_for_items()
|
self.validate_for_items()
|
||||||
self.validate_warehouse()
|
self.validate_warehouse()
|
||||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||||
@@ -225,7 +225,7 @@ class DeliveryNote(SellingController):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
super(DeliveryNote, self).on_cancel()
|
super(DeliveryNote, self).on_cancel()
|
||||||
|
|
||||||
self.check_close_sales_order("against_sales_order")
|
self.check_sales_order_on_hold_or_close("against_sales_order")
|
||||||
self.check_next_docstatus()
|
self.check_next_docstatus()
|
||||||
|
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ frappe.ui.form.on('Material Request', {
|
|||||||
},
|
},
|
||||||
get_query_filters: {
|
get_query_filters: {
|
||||||
docstatus: 1,
|
docstatus: 1,
|
||||||
status: ["!=", "Closed"],
|
status: ["not in", ["Closed", "On Hold"]],
|
||||||
per_delivered: ["<", 99.99],
|
per_delivered: ["<", 99.99],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class MaterialRequest(BuyingController):
|
|||||||
super(MaterialRequest, self).validate()
|
super(MaterialRequest, self).validate()
|
||||||
|
|
||||||
self.validate_schedule_date()
|
self.validate_schedule_date()
|
||||||
|
self.check_for_on_hold_or_closed_status('Sales Order', 'sales_order')
|
||||||
self.validate_uom_is_integer("uom", "qty")
|
self.validate_uom_is_integer("uom", "qty")
|
||||||
|
|
||||||
if not self.status:
|
if not self.status:
|
||||||
@@ -101,6 +102,7 @@ class MaterialRequest(BuyingController):
|
|||||||
def before_cancel(self):
|
def before_cancel(self):
|
||||||
# if MRQ is already closed, no point saving the document
|
# if MRQ is already closed, no point saving the document
|
||||||
check_on_hold_or_closed_status(self.doctype, self.name)
|
check_on_hold_or_closed_status(self.doctype, self.name)
|
||||||
|
|
||||||
self.set_status(update=True, status='Cancelled')
|
self.set_status(update=True, status='Cancelled')
|
||||||
|
|
||||||
def check_modified_date(self):
|
def check_modified_date(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user