Fixed merge conflict
This commit is contained in:
@@ -12,7 +12,7 @@ from erpnext.stock.doctype.item.item import get_last_purchase_details
|
|||||||
from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty
|
from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty
|
||||||
from frappe.desk.notifications import clear_doctype_notifications
|
from frappe.desk.notifications import clear_doctype_notifications
|
||||||
from erpnext.buying.utils import validate_for_items, check_for_closed_status
|
from erpnext.buying.utils import validate_for_items, check_for_closed_status
|
||||||
|
from erpnext.stock.utils import get_bin
|
||||||
|
|
||||||
form_grid_templates = {
|
form_grid_templates = {
|
||||||
"items": "templates/form_grid/item_grid.html"
|
"items": "templates/form_grid/item_grid.html"
|
||||||
@@ -196,6 +196,8 @@ class PurchaseOrder(BuyingController):
|
|||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
self.update_ordered_qty()
|
self.update_ordered_qty()
|
||||||
|
if self.is_subcontracted == "Yes":
|
||||||
|
self.update_reserved_qty_for_subcontract()
|
||||||
|
|
||||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||||
self.company, self.base_grand_total)
|
self.company, self.base_grand_total)
|
||||||
@@ -209,6 +211,9 @@ class PurchaseOrder(BuyingController):
|
|||||||
if self.has_drop_ship_item():
|
if self.has_drop_ship_item():
|
||||||
self.update_delivered_qty_in_sales_order()
|
self.update_delivered_qty_in_sales_order()
|
||||||
|
|
||||||
|
if self.is_subcontracted == "Yes":
|
||||||
|
self.update_reserved_qty_for_subcontract()
|
||||||
|
|
||||||
self.check_for_closed_status()
|
self.check_for_closed_status()
|
||||||
|
|
||||||
frappe.db.set(self,'status','Cancelled')
|
frappe.db.set(self,'status','Cancelled')
|
||||||
@@ -256,6 +261,12 @@ class PurchaseOrder(BuyingController):
|
|||||||
if item.delivered_by_supplier == 1:
|
if item.delivered_by_supplier == 1:
|
||||||
item.received_qty = item.qty
|
item.received_qty = item.qty
|
||||||
|
|
||||||
|
def update_reserved_qty_for_subcontract(self):
|
||||||
|
for d in self.supplied_items:
|
||||||
|
if d.rm_item_code:
|
||||||
|
stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse)
|
||||||
|
stock_bin.update_reserved_qty_for_sub_contracting()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def close_or_unclose_purchase_orders(names, status):
|
def close_or_unclose_purchase_orders(names, status):
|
||||||
if not frappe.has_permission("Purchase Order", "write"):
|
if not frappe.has_permission("Purchase Order", "write"):
|
||||||
|
|||||||
@@ -182,7 +182,21 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
pi.insert()
|
pi.insert()
|
||||||
self.assertTrue(pi.get('payment_schedule'))
|
self.assertTrue(pi.get('payment_schedule'))
|
||||||
|
|
||||||
|
def test_reserved_qty_subcontract_po(self):
|
||||||
|
bin = frappe.get_all("Bin", filters={"warehouse": "_Test Warehouse - _TC"},
|
||||||
|
fields=["item_code","reserved_qty_for_sub_contract"])
|
||||||
|
|
||||||
|
item_supplied = frappe.get_all("Purchase Order Item Supplied", filters={"main_item_code": "_Test FG Item", "reserve_warehouse": "_Test Warehouse - _TC"},
|
||||||
|
fields=["rm_item_code","required_qty"])
|
||||||
|
|
||||||
|
for item_bin in bin:
|
||||||
|
total_sup_qty = 0
|
||||||
|
for item_sup in item_supplied:
|
||||||
|
if item_bin["item_code"] == item_sup["rm_item_code"]:
|
||||||
|
total_sup_qty = total_sup_qty + item_sup["required_qty"]
|
||||||
|
|
||||||
|
self.assertEquals(item_bin["reserved_qty_for_sub_contract"],total_sup_qty)
|
||||||
|
|
||||||
def get_same_items():
|
def get_same_items():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -224,6 +238,10 @@ def create_purchase_order(**args):
|
|||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
po.insert()
|
po.insert()
|
||||||
if not args.do_not_submit:
|
if not args.do_not_submit:
|
||||||
|
if po.is_subcontracted == "Yes":
|
||||||
|
supp_items = po.get("supplied_items")
|
||||||
|
for d in supp_items:
|
||||||
|
d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
|
||||||
po.submit()
|
po.submit()
|
||||||
|
|
||||||
return po
|
return po
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
@@ -10,16 +11,20 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "main_item_code",
|
"fieldname": "main_item_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -29,6 +34,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -36,16 +42,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "rm_item_code",
|
"fieldname": "rm_item_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Raw Material Item Code",
|
"label": "Raw Material Item Code",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -55,6 +65,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -62,16 +73,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "required_qty",
|
"fieldname": "required_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Supplied Qty",
|
"label": "Supplied Qty",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -81,6 +96,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -88,16 +104,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Rate",
|
"label": "Rate",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -108,6 +128,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -115,16 +136,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Amount",
|
"label": "Amount",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -135,6 +160,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -142,16 +168,49 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_6",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "bom_detail_no",
|
"fieldname": "bom_detail_no",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "BOM Detail No",
|
"label": "BOM Detail No",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -161,6 +220,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -168,16 +228,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "reference_name",
|
"fieldname": "reference_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Reference Name",
|
"label": "Reference Name",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -187,6 +251,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -194,16 +259,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "conversion_factor",
|
"fieldname": "conversion_factor",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 1,
|
"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_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Conversion Factor",
|
"label": "Conversion Factor",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -213,6 +282,7 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -220,16 +290,20 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"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_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Stock Uom",
|
"label": "Stock Uom",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@@ -240,6 +314,38 @@
|
|||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "reserve_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Reserve Warehouse",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Warehouse",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
@@ -247,17 +353,17 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"image_view": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:28:05.533063",
|
"modified": "2017-11-29 21:10:40.431423",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item Supplied",
|
"name": "Purchase Order Item Supplied",
|
||||||
@@ -266,5 +372,7 @@
|
|||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
@@ -160,6 +160,10 @@ class BuyingController(StockController):
|
|||||||
if item in self.sub_contracted_items and not item.bom:
|
if item in self.sub_contracted_items and not item.bom:
|
||||||
frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code))
|
frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code))
|
||||||
|
|
||||||
|
for supplied_item in self.get("supplied_items"):
|
||||||
|
if not supplied_item.reserve_warehouse:
|
||||||
|
frappe.throw(_("Reserved Warehouse is mandatory for Item {0} in Raw Materials supplied").format(frappe.bold(supplied_item.rm_item_code)))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if item.bom:
|
if item.bom:
|
||||||
@@ -189,6 +193,9 @@ class BuyingController(StockController):
|
|||||||
def update_raw_materials_supplied(self, item, raw_material_table):
|
def update_raw_materials_supplied(self, item, raw_material_table):
|
||||||
bom_items = self.get_items_from_bom(item.item_code, item.bom)
|
bom_items = self.get_items_from_bom(item.item_code, item.bom)
|
||||||
raw_materials_cost = 0
|
raw_materials_cost = 0
|
||||||
|
items = list(set([d.item_code for d in bom_items]))
|
||||||
|
item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse
|
||||||
|
from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
|
||||||
|
|
||||||
for bom_item in bom_items:
|
for bom_item in bom_items:
|
||||||
# check if exists
|
# check if exists
|
||||||
@@ -210,6 +217,7 @@ class BuyingController(StockController):
|
|||||||
rm.rm_item_code = bom_item.item_code
|
rm.rm_item_code = bom_item.item_code
|
||||||
rm.stock_uom = bom_item.stock_uom
|
rm.stock_uom = bom_item.stock_uom
|
||||||
rm.required_qty = required_qty
|
rm.required_qty = required_qty
|
||||||
|
rm.reserve_warehouse = bom_item.source_warehouse or item_wh.get(bom_item.item_code)
|
||||||
|
|
||||||
rm.conversion_factor = item.conversion_factor
|
rm.conversion_factor = item.conversion_factor
|
||||||
|
|
||||||
@@ -261,7 +269,7 @@ class BuyingController(StockController):
|
|||||||
def get_items_from_bom(self, item_code, bom):
|
def get_items_from_bom(self, item_code, bom):
|
||||||
bom_items = frappe.db.sql("""select t2.item_code,
|
bom_items = frappe.db.sql("""select t2.item_code,
|
||||||
t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
|
t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
|
||||||
t2.rate, t2.stock_uom, t2.name, t2.description
|
t2.rate, t2.stock_uom, t2.name, t2.description, t2.source_warehouse
|
||||||
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
||||||
where t2.parent = t1.name and t1.item = %s
|
where t2.parent = t1.name and t1.item = %s
|
||||||
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from erpnext.stock.utils import get_bin
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
def_warehouse = frappe.db.sql("""select min(name) from `tabWarehouse` where is_group = 0""")[0][0]
|
||||||
|
|
||||||
|
po_item = list(frappe.db.sql(("""select distinct po.name as poname, poitem.rm_item_code as rm_item_code
|
||||||
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem
|
||||||
|
where po.name = poitem.parent
|
||||||
|
and po.is_subcontracted = "Yes"
|
||||||
|
and po.docstatus = 1"""),as_dict=1))
|
||||||
|
|
||||||
|
items = list(set([d.rm_item_code for d in po_item]))
|
||||||
|
item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse
|
||||||
|
from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
|
||||||
|
#Update reserved warehouse
|
||||||
|
for item in po_item:
|
||||||
|
reserve_warehouse = item_wh.get(item.rm_item_code) or def_warehouse
|
||||||
|
update_res_warehouse = frappe.db.sql("""update `tabPurchase Order Item Supplied`
|
||||||
|
set reserve_warehouse = %s
|
||||||
|
where parent = %s and rm_item_code = %s""",(reserve_warehouse
|
||||||
|
,item["poname"],item["rm_item_code"]))
|
||||||
|
#Update bin
|
||||||
|
item_wh_bin = frappe.db.sql(("""select distinct poitemsup.rm_item_code as rm_item_code,
|
||||||
|
poitemsup.reserve_warehouse as reserve_warehouse
|
||||||
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
||||||
|
where po.name = poitemsup.parent
|
||||||
|
and po.is_subcontracted = "Yes"
|
||||||
|
and po.docstatus = 1"""),as_dict=1)
|
||||||
|
for d in item_wh_bin:
|
||||||
|
stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"])
|
||||||
|
stock_bin.update_reserved_qty_for_sub_contracting()
|
||||||
@@ -89,7 +89,7 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
data.forEach(function(d) {
|
data.forEach(function(d) {
|
||||||
d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production;
|
d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production;
|
||||||
d.pending_qty = 0;
|
d.pending_qty = 0;
|
||||||
d.total_reserved = d.reserved_qty + d.reserved_qty_for_production;
|
d.total_reserved = d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
|
||||||
if(d.actual_or_pending > d.actual_qty) {
|
if(d.actual_or_pending > d.actual_qty) {
|
||||||
d.pending_qty = d.actual_or_pending - d.actual_qty;
|
d.pending_qty = d.actual_or_pending - d.actual_qty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,14 @@ def get_data(item_code=None, warehouse=None, item_group=None,
|
|||||||
return frappe.db.sql('''
|
return frappe.db.sql('''
|
||||||
select
|
select
|
||||||
b.item_code, b.warehouse, b.projected_qty, b.reserved_qty,
|
b.item_code, b.warehouse, b.projected_qty, b.reserved_qty,
|
||||||
b.reserved_qty_for_production, b.actual_qty, b.valuation_rate, i.item_name
|
b.reserved_qty_for_production, b.reserved_qty_for_sub_contract, b.actual_qty, b.valuation_rate, i.item_name
|
||||||
from
|
from
|
||||||
tabBin b, tabItem i
|
tabBin b, tabItem i
|
||||||
where
|
where
|
||||||
b.item_code = i.name
|
b.item_code = i.name
|
||||||
and
|
and
|
||||||
(b.projected_qty != 0 or b.reserved_qty != 0 or b.reserved_qty_for_production != 0 or b.actual_qty != 0)
|
(b.projected_qty != 0 or b.reserved_qty != 0 or b.reserved_qty_for_production != 0
|
||||||
|
or b.reserved_qty_for_sub_contract != 0 or b.actual_qty != 0)
|
||||||
{conditions}
|
{conditions}
|
||||||
order by
|
order by
|
||||||
{sort_by} {sort_order}
|
{sort_by} {sort_order}
|
||||||
|
|||||||
@@ -296,6 +296,36 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "reserved_qty_for_sub_contract",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Reserved Qty for sub contract",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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,
|
||||||
@@ -463,7 +493,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-06-13 13:06:32.601505",
|
"modified": "2017-11-22 08:14:30.615638",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Bin",
|
"name": "Bin",
|
||||||
|
|||||||
@@ -93,6 +93,31 @@ class Bin(Document):
|
|||||||
self.db_set('reserved_qty_for_production', flt(self.reserved_qty_for_production))
|
self.db_set('reserved_qty_for_production', flt(self.reserved_qty_for_production))
|
||||||
self.db_set('projected_qty', self.projected_qty)
|
self.db_set('projected_qty', self.projected_qty)
|
||||||
|
|
||||||
|
def update_reserved_qty_for_sub_contracting(self):
|
||||||
|
#reserved qty
|
||||||
|
reserved_qty_for_sub_contract = frappe.db.sql('''select ifnull(sum(itemsup.required_qty),0)
|
||||||
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` itemsup
|
||||||
|
where
|
||||||
|
itemsup.rm_item_code = %s
|
||||||
|
and itemsup.parent = po.name
|
||||||
|
and po.docstatus = 1
|
||||||
|
and po.is_subcontracted = 'Yes'
|
||||||
|
and itemsup.reserve_warehouse = %s''', (self.item_code, self.warehouse))[0][0]
|
||||||
|
#Get Transferred Entries
|
||||||
|
materials_transferred = frappe.db.sql("""
|
||||||
|
select
|
||||||
|
ifnull(sum(qty),0)
|
||||||
|
from
|
||||||
|
`tabStock Entry` se, `tabStock Entry Detail` sed, `tabPurchase Order` po
|
||||||
|
where
|
||||||
|
sed.item_code = %s
|
||||||
|
and se.name = sed.parent and se.docstatus=1 and se.purpose='Subcontract'
|
||||||
|
and se.purchase_order = po.name
|
||||||
|
and ifnull(se.purchase_order, '') !=''""", (self.item_code))[0][0]
|
||||||
|
|
||||||
|
self.set_projected_qty()
|
||||||
|
self.db_set('reserved_qty_for_sub_contract', (reserved_qty_for_sub_contract - materials_transferred))
|
||||||
|
self.db_set('projected_qty', self.projected_qty)
|
||||||
|
|
||||||
def update_item_projected_qty(item_code):
|
def update_item_projected_qty(item_code):
|
||||||
'''Set total_projected_qty in Item as sum of projected qty in all warehouses'''
|
'''Set total_projected_qty in Item as sum of projected qty in all warehouses'''
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError, get
|
|||||||
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
|
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
|
||||||
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
|
from erpnext.stock.doctype.batch.batch import get_batch_no, set_batch_nos, get_batch_qty
|
||||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
||||||
|
from erpnext.stock.utils import get_bin
|
||||||
import json
|
import json
|
||||||
|
|
||||||
class IncorrectValuationRateError(frappe.ValidationError): pass
|
class IncorrectValuationRateError(frappe.ValidationError): pass
|
||||||
@@ -69,11 +70,15 @@ class StockEntry(StockController):
|
|||||||
update_serial_nos_after_submit(self, "items")
|
update_serial_nos_after_submit(self, "items")
|
||||||
self.update_production_order()
|
self.update_production_order()
|
||||||
self.validate_purchase_order()
|
self.validate_purchase_order()
|
||||||
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
|
self.update_purchase_order_supplied_items()
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
self.update_production_order()
|
self.update_production_order()
|
||||||
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
|
self.update_purchase_order_supplied_items()
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
|
|
||||||
def validate_purpose(self):
|
def validate_purpose(self):
|
||||||
@@ -581,10 +586,18 @@ class StockEntry(StockController):
|
|||||||
frappe.throw(_("Manufacturing Quantity is mandatory"))
|
frappe.throw(_("Manufacturing Quantity is mandatory"))
|
||||||
|
|
||||||
item_dict = self.get_bom_raw_materials(self.fg_completed_qty)
|
item_dict = self.get_bom_raw_materials(self.fg_completed_qty)
|
||||||
|
#Get PO Supplied Items Details
|
||||||
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
|
#Get PO Supplied Items Details
|
||||||
|
item_wh = frappe._dict(frappe.db.sql("""select rm_item_code, reserve_warehouse
|
||||||
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
||||||
|
where po.name = poitemsup.parent
|
||||||
|
and po.name = %s""",self.purchase_order))
|
||||||
for item in item_dict.values():
|
for item in item_dict.values():
|
||||||
if self.pro_doc and not self.pro_doc.skip_transfer:
|
if self.pro_doc and not self.pro_doc.skip_transfer:
|
||||||
item["from_warehouse"] = self.pro_doc.wip_warehouse
|
item["from_warehouse"] = self.pro_doc.wip_warehouse
|
||||||
|
#Get Reserve Warehouse from PO
|
||||||
|
item["from_warehouse"] = item_wh.get(item.item_code)
|
||||||
item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else ""
|
item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else ""
|
||||||
|
|
||||||
self.add_to_stock_entry_detail(item_dict)
|
self.add_to_stock_entry_detail(item_dict)
|
||||||
@@ -830,8 +843,8 @@ class StockEntry(StockController):
|
|||||||
expiry_date = frappe.db.get_value("Batch", item.batch_no, "expiry_date")
|
expiry_date = frappe.db.get_value("Batch", item.batch_no, "expiry_date")
|
||||||
if expiry_date:
|
if expiry_date:
|
||||||
if getdate(self.posting_date) > getdate(expiry_date):
|
if getdate(self.posting_date) > getdate(expiry_date):
|
||||||
frappe.throw(_("Batch {0} of Item {1} has expired.").format(item.batch_no, item.item_code))
|
frappe.throw(_("Batch {0} of Item {1} has expired.")
|
||||||
|
.format(item.batch_no, item.item_code))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def move_sample_to_retention_warehouse(company, items):
|
def move_sample_to_retention_warehouse(company, items):
|
||||||
@@ -843,7 +856,8 @@ def move_sample_to_retention_warehouse(company, items):
|
|||||||
stock_entry.purpose = "Material Transfer"
|
stock_entry.purpose = "Material Transfer"
|
||||||
for item in items:
|
for item in items:
|
||||||
if item.get('sample_quantity') and item.get('batch_no'):
|
if item.get('sample_quantity') and item.get('batch_no'):
|
||||||
sample_quantity = validate_sample_quantity(item.get('item_code'), item.get('sample_quantity'), item.get('transfer_qty') or item.get('qty'), item.get('batch_no'))
|
sample_quantity = validate_sample_quantity(item.get('item_code'), item.get('sample_quantity'),
|
||||||
|
item.get('transfer_qty') or item.get('qty'), item.get('batch_no'))
|
||||||
if sample_quantity:
|
if sample_quantity:
|
||||||
sample_serial_nos = ''
|
sample_serial_nos = ''
|
||||||
if item.get('serial_no'):
|
if item.get('serial_no'):
|
||||||
@@ -851,6 +865,7 @@ def move_sample_to_retention_warehouse(company, items):
|
|||||||
if serial_nos and len(serial_nos) > item.get('sample_quantity'):
|
if serial_nos and len(serial_nos) > item.get('sample_quantity'):
|
||||||
serial_no_list = serial_nos[:-(len(serial_nos)-item.get('sample_quantity'))]
|
serial_no_list = serial_nos[:-(len(serial_nos)-item.get('sample_quantity'))]
|
||||||
sample_serial_nos = '\n'.join(serial_no_list)
|
sample_serial_nos = '\n'.join(serial_no_list)
|
||||||
|
|
||||||
stock_entry.append("items", {
|
stock_entry.append("items", {
|
||||||
"item_code": item.get('item_code'),
|
"item_code": item.get('item_code'),
|
||||||
"s_warehouse": item.get('t_warehouse'),
|
"s_warehouse": item.get('t_warehouse'),
|
||||||
@@ -866,6 +881,18 @@ def move_sample_to_retention_warehouse(company, items):
|
|||||||
if stock_entry.get('items'):
|
if stock_entry.get('items'):
|
||||||
return stock_entry.as_dict()
|
return stock_entry.as_dict()
|
||||||
|
|
||||||
|
def update_purchase_order_supplied_items(self):
|
||||||
|
#Get PO Supplied Items Details
|
||||||
|
item_wh = frappe._dict(frappe.db.sql("""select rm_item_code, reserve_warehouse
|
||||||
|
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
|
||||||
|
where po.name = poitemsup.parent
|
||||||
|
and po.name = %s""",self.purchase_order))
|
||||||
|
#Update reserved sub contracted quantity in bin based on Supplied Item Details
|
||||||
|
for d in self.get("items"):
|
||||||
|
reserve_warehouse = item_wh.get(item.item_code)
|
||||||
|
stock_bin = get_bin(d.item_code, reserve_warehouse)
|
||||||
|
stock_bin.update_reserved_qty_for_sub_contracting()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_production_order_details(production_order):
|
def get_production_order_details(production_order):
|
||||||
production_order = frappe.get_doc("Production Order", production_order)
|
production_order = frappe.get_doc("Production Order", production_order)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ frappe.pages['stock-balance'].on_page_load = function(wrapper) {
|
|||||||
{fieldname: 'projected_qty', label: __('Projected qty')},
|
{fieldname: 'projected_qty', label: __('Projected qty')},
|
||||||
{fieldname: 'reserved_qty', label: __('Reserved for sale')},
|
{fieldname: 'reserved_qty', label: __('Reserved for sale')},
|
||||||
{fieldname: 'reserved_qty_for_production', label: __('Reserved for manufacturing')},
|
{fieldname: 'reserved_qty_for_production', label: __('Reserved for manufacturing')},
|
||||||
|
{fieldname: 'reserved_qty_for_sub_contract', label: __('Reserved for sub contracting')},
|
||||||
{fieldname: 'actual_qty', label: __('Actual qty in stock')},
|
{fieldname: 'actual_qty', label: __('Actual qty in stock')},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ def update_bin_qty(item_code, warehouse, qty_dict=None):
|
|||||||
if mismatch:
|
if mismatch:
|
||||||
bin.projected_qty = (flt(bin.actual_qty) + flt(bin.ordered_qty) +
|
bin.projected_qty = (flt(bin.actual_qty) + flt(bin.ordered_qty) +
|
||||||
flt(bin.indented_qty) + flt(bin.planned_qty) - flt(bin.reserved_qty)
|
flt(bin.indented_qty) + flt(bin.planned_qty) - flt(bin.reserved_qty)
|
||||||
- flt(bin.reserved_qty_for_production))
|
- flt(bin.reserved_qty_for_production)) - flt(bin.reserved_qty_for_sub_contract)
|
||||||
|
|
||||||
bin.save()
|
bin.save()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user