[enhancement] added reserved_qty_for_production in bin and updated item dashboard
This commit is contained in:
parent
c46c1f0288
commit
0525387328
@ -3,10 +3,13 @@
|
||||
|
||||
frappe.require("assets/erpnext/js/financial_statements.js");
|
||||
|
||||
frappe.query_reports["Profit and Loss Statement"] = erpnext.financial_statements;
|
||||
frappe.query_reports["Profit and Loss Statement"] = $.extend({}, erpnext.financial_statements);
|
||||
|
||||
frappe.query_reports["Profit and Loss Statement"]["filters"].push({
|
||||
"fieldname": "accumulated_values",
|
||||
"label": __("Accumulated Values"),
|
||||
"fieldtype": "Check"
|
||||
})
|
||||
});
|
||||
|
||||
console.log(frappe.query_reports["Profit and Loss Statement"]);
|
||||
|
||||
|
@ -72,15 +72,15 @@ class PurchaseCommon(BuyingController):
|
||||
|
||||
if items and len(items) != len(set(items)) and \
|
||||
not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
|
||||
frappe.msgprint(_("Warning: Same item has been entered multiple times."))
|
||||
frappe.msgprint(_("Warning: Same item has been entered multiple times."), small=True)
|
||||
|
||||
|
||||
def check_for_closed_status(self, doctype, docname):
|
||||
status = frappe.db.get_value(doctype, docname, "status")
|
||||
|
||||
|
||||
if status == "Closed":
|
||||
frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError)
|
||||
|
||||
|
||||
def check_docstatus(self, check, doctype, docname, detail_doctype = ''):
|
||||
if check == 'Next':
|
||||
submitted = frappe.db.sql("""select t1.name from `tab%s` t1,`tab%s` t2
|
||||
|
@ -7,7 +7,7 @@ frappe.ui.form.on("Supplier", {
|
||||
frappe.setup_language_field(frm);
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.dashboard.show_links();
|
||||
frm.dashboard.show_dashboard();
|
||||
|
||||
if(frappe.defaults.get_default("supp_master_name")!="Naming Series") {
|
||||
frm.toggle_display("naming_series", false);
|
||||
|
@ -25,7 +25,7 @@ erpnext.hr.EmployeeController = frappe.ui.form.Controller.extend({
|
||||
refresh: function() {
|
||||
var me = this;
|
||||
erpnext.toggle_naming_series();
|
||||
this.frm.dashboard.show_links();
|
||||
this.frm.dashboard.show_dashboard();
|
||||
},
|
||||
|
||||
date_of_birth: function() {
|
||||
|
8
erpnext/manufacturing/doctype/production_order/.py
Normal file
8
erpnext/manufacturing/doctype/production_order/.py
Normal file
@ -0,0 +1,8 @@
|
||||
import frappe
|
||||
|
||||
def set_required_items(production_order):
|
||||
pass
|
||||
|
||||
def reserve_for_production(production_order):
|
||||
'''Reserve pending raw materials for production'''
|
||||
pass
|
@ -78,7 +78,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled",
|
||||
"options": "\nDraft\nSubmitted\nNot Started\nStopped\nIn Process\nCompleted\nCancelled",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -305,6 +305,33 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Warehouse for reserving items",
|
||||
"fieldname": "source_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Source Warehouse",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -1024,6 +1051,32 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "required_items",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Required Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Production Order Item",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@ -1036,7 +1089,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-06 05:44:08.681263",
|
||||
"modified": "2016-04-18 08:42:47.582203",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
@ -1083,6 +1136,7 @@
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
|
@ -15,6 +15,8 @@ from erpnext.projects.doctype.time_log.time_log import OverlapError
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
|
||||
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
||||
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
class OverProductionError(frappe.ValidationError): pass
|
||||
class StockOverProductionError(frappe.ValidationError): pass
|
||||
@ -27,13 +29,6 @@ form_grid_templates = {
|
||||
|
||||
class ProductionOrder(Document):
|
||||
def validate(self):
|
||||
if self.docstatus == 0:
|
||||
self.status = "Draft"
|
||||
|
||||
from erpnext.controllers.status_updater import validate_status
|
||||
validate_status(self.status, ["Draft", "Submitted", "Stopped",
|
||||
"In Process", "Completed", "Cancelled"])
|
||||
|
||||
self.validate_production_item()
|
||||
if self.bom_no:
|
||||
validate_bom_no(self.production_item, self.bom_no)
|
||||
@ -43,6 +38,7 @@ class ProductionOrder(Document):
|
||||
self.calculate_operating_cost()
|
||||
self.validate_qty()
|
||||
self.validate_operation_time()
|
||||
self.status = self.get_status()
|
||||
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
|
||||
@ -65,7 +61,7 @@ class ProductionOrder(Document):
|
||||
def validate_warehouse(self):
|
||||
from erpnext.stock.utils import validate_warehouse_company
|
||||
|
||||
for w in [self.fg_warehouse, self.wip_warehouse]:
|
||||
for w in [self.source_warehouse, self.fg_warehouse, self.wip_warehouse]:
|
||||
validate_warehouse_company(w, self.company)
|
||||
|
||||
def calculate_operating_cost(self):
|
||||
@ -113,23 +109,36 @@ class ProductionOrder(Document):
|
||||
|
||||
|
||||
def update_status(self, status=None):
|
||||
'''Update status of production order'''
|
||||
status = self.get_status()
|
||||
if status != self.status:
|
||||
self.db_set("status", status)
|
||||
|
||||
self.update_required_items()
|
||||
|
||||
def get_status(self, status=None):
|
||||
'''Return the status based on stock entries against this production order'''
|
||||
if not status:
|
||||
status = self.status
|
||||
|
||||
if status != 'Stopped':
|
||||
stock_entries = frappe._dict(frappe.db.sql("""select purpose, sum(fg_completed_qty)
|
||||
from `tabStock Entry` where production_order=%s and docstatus=1
|
||||
group by purpose""", self.name))
|
||||
if self.docstatus==0:
|
||||
status = 'Draft'
|
||||
elif self.docstatus==1:
|
||||
if status != 'Stopped':
|
||||
stock_entries = frappe._dict(frappe.db.sql("""select purpose, sum(fg_completed_qty)
|
||||
from `tabStock Entry` where production_order=%s and docstatus=1
|
||||
group by purpose""", self.name))
|
||||
|
||||
status = "Submitted"
|
||||
if stock_entries:
|
||||
status = "In Process"
|
||||
produced_qty = stock_entries.get("Manufacture")
|
||||
if flt(produced_qty) == flt(self.qty):
|
||||
status = "Completed"
|
||||
status = "Not Started"
|
||||
if stock_entries:
|
||||
status = "In Process"
|
||||
produced_qty = stock_entries.get("Manufacture")
|
||||
if flt(produced_qty) == flt(self.qty):
|
||||
status = "Completed"
|
||||
else:
|
||||
status = 'Cancelled'
|
||||
|
||||
if status != self.status:
|
||||
self.db_set("status", status)
|
||||
return status
|
||||
|
||||
def update_production_order_qty(self):
|
||||
"""Update **Manufactured Qty** and **Material Transferred for Qty** in Production Order
|
||||
@ -147,13 +156,16 @@ class ProductionOrder(Document):
|
||||
|
||||
self.db_set(fieldname, qty)
|
||||
|
||||
def before_submit(self):
|
||||
self.set_required_items()
|
||||
|
||||
def on_submit(self):
|
||||
if not self.wip_warehouse:
|
||||
frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
|
||||
if not self.fg_warehouse:
|
||||
frappe.throw(_("For Warehouse is required before Submit"))
|
||||
|
||||
frappe.db.set(self,'status', 'Submitted')
|
||||
self.update_reserved_qty_for_production()
|
||||
self.make_time_logs()
|
||||
self.update_completed_qty_in_material_request()
|
||||
self.update_planned_qty()
|
||||
@ -162,6 +174,7 @@ class ProductionOrder(Document):
|
||||
self.validate_cancel()
|
||||
|
||||
frappe.db.set(self,'status', 'Cancelled')
|
||||
self.clear_required_items()
|
||||
self.delete_time_logs()
|
||||
self.update_completed_qty_in_material_request()
|
||||
self.update_planned_qty()
|
||||
@ -342,6 +355,74 @@ class ProductionOrder(Document):
|
||||
if not d.time_in_mins > 0:
|
||||
frappe.throw(_("Operation Time must be greater than 0 for Operation {0}".format(d.operation)))
|
||||
|
||||
def update_required_items(self):
|
||||
'''
|
||||
update bin reserved_qty_for_production
|
||||
called from Stock Entry for production, after submit, cancel
|
||||
'''
|
||||
if self.docstatus==1 and self.source_warehouse:
|
||||
if self.material_transferred_for_manufacturing == self.produced_qty:
|
||||
# clear required items table and save document
|
||||
self.clear_required_items()
|
||||
else:
|
||||
# calculate transferred qty based on submitted
|
||||
# stock entries
|
||||
self.update_transaferred_qty_for_required_items()
|
||||
|
||||
# update in bin
|
||||
self.update_reserved_qty_for_production()
|
||||
|
||||
def clear_required_items(self):
|
||||
'''Remove the required_items table and update the bins'''
|
||||
items = [d.item_code for d in self.required_items]
|
||||
self.required_items = []
|
||||
|
||||
self.update_child_table('required_items')
|
||||
|
||||
# completed, update reserved qty in bin
|
||||
self.update_reserved_qty_for_production(items)
|
||||
|
||||
def update_reserved_qty_for_production(self, items=None):
|
||||
'''update reserved_qty_for_production in bins'''
|
||||
if not self.source_warehouse:
|
||||
return
|
||||
|
||||
if not items:
|
||||
items = [d.item_code for d in self.required_items]
|
||||
|
||||
for item in items:
|
||||
stock_bin = get_bin(item, self.source_warehouse)
|
||||
stock_bin.update_reserved_qty_for_production()
|
||||
|
||||
def set_required_items(self):
|
||||
'''set required_items for production to keep track of reserved qty'''
|
||||
if self.source_warehouse:
|
||||
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty,
|
||||
fetch_exploded = self.use_multi_level_bom)
|
||||
|
||||
for item in item_dict.values():
|
||||
self.append('required_items', {'item_code': item.item_code,
|
||||
'required_qty': item.qty})
|
||||
|
||||
#print frappe.as_json(self.required_items)
|
||||
|
||||
def update_transaferred_qty_for_required_items(self):
|
||||
'''update transferred qty from submitted stock entries for that item against
|
||||
the production order'''
|
||||
|
||||
for d in self.required_items:
|
||||
transferred_qty = frappe.db.sql('''select count(qty)
|
||||
from `tabStock Entry` entry, `tabStock Entry Detail` detail
|
||||
where
|
||||
entry.production_order = %s
|
||||
entry.purpose = "Material Transfer for Manufacture"
|
||||
and entry.docstatus = 1
|
||||
and detail.parent = entry.name
|
||||
and detail.item_code = %s''', (self.name, d.item_code))[0][0]
|
||||
|
||||
d.db_set('transferred_qty', transferred_qty, update_modified = False)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item):
|
||||
res = frappe.db.sql("""select stock_uom, description
|
||||
@ -372,6 +453,8 @@ def make_stock_entry(production_order_id, purpose, qty=None):
|
||||
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
|
||||
|
||||
if purpose=="Material Transfer for Manufacture":
|
||||
if production_order.source_warehouse:
|
||||
stock_entry.from_warehouse = production_order.source_warehouse
|
||||
stock_entry.to_warehouse = production_order.wip_warehouse
|
||||
else:
|
||||
stock_entry.from_warehouse = production_order.wip_warehouse
|
||||
|
@ -5,14 +5,19 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
from frappe.utils import flt, time_diff_in_hours, now, add_days
|
||||
from frappe.utils import flt, time_diff_in_hours, now, add_days, cint
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
from erpnext.manufacturing.doctype.production_order.production_order \
|
||||
import make_stock_entry, ItemHasVariantError
|
||||
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
||||
from erpnext.projects.doctype.time_log.time_log import OverProductionLoggedError
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
class TestProductionOrder(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.warehouse = '_Test Warehouse 2 - _TC'
|
||||
self.item = '_Test Item'
|
||||
|
||||
def check_planned_qty(self):
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
@ -140,6 +145,73 @@ class TestProductionOrder(unittest.TestCase):
|
||||
prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True)
|
||||
self.assertRaises(ItemHasVariantError, prod_order.save)
|
||||
|
||||
def test_reserved_qty_for_production_submit(self):
|
||||
self.bin1_at_start = get_bin(self.item, self.warehouse)
|
||||
|
||||
# reset to correct value
|
||||
self.bin1_at_start.update_reserved_qty_for_production()
|
||||
|
||||
self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2,
|
||||
source_warehouse=self.warehouse)
|
||||
|
||||
self.bin1_on_submit = get_bin(self.item, self.warehouse)
|
||||
|
||||
# reserved qty for production is updated
|
||||
self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production) + 2,
|
||||
cint(self.bin1_on_submit.reserved_qty_for_production))
|
||||
self.assertEqual(cint(self.bin1_at_start.projected_qty),
|
||||
cint(self.bin1_on_submit.projected_qty) + 2)
|
||||
|
||||
def test_reserved_qty_for_production_cancel(self):
|
||||
self.test_reserved_qty_for_production_submit()
|
||||
|
||||
self.pro_order.cancel()
|
||||
|
||||
bin1_on_cancel = get_bin(self.item, self.warehouse)
|
||||
|
||||
# reserved_qty_for_producion updated
|
||||
self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production),
|
||||
cint(bin1_on_cancel.reserved_qty_for_production))
|
||||
self.assertEqual(self.bin1_at_start.projected_qty,
|
||||
cint(bin1_on_cancel.projected_qty))
|
||||
|
||||
def test_reserved_qty_for_production_on_stock_entry(self):
|
||||
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||
target= self.warehouse, qty=100, basic_rate=100)
|
||||
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
|
||||
target= self.warehouse, qty=100, basic_rate=100)
|
||||
|
||||
self.test_reserved_qty_for_production_submit()
|
||||
|
||||
s = frappe.get_doc(make_stock_entry(self.pro_order.name,
|
||||
"Material Transfer for Manufacture", 2))
|
||||
|
||||
s.submit()
|
||||
|
||||
bin1_on_start_production = get_bin(self.item, self.warehouse)
|
||||
|
||||
# reserved_qty_for_producion updated
|
||||
self.assertEqual(cint(self.bin1_at_start.reserved_qty_for_production),
|
||||
cint(bin1_on_start_production.reserved_qty_for_production))
|
||||
|
||||
# projected qty will now be 2 less (becuase of item movement)
|
||||
self.assertEqual(cint(self.bin1_at_start.projected_qty),
|
||||
cint(bin1_on_start_production.projected_qty) + 2)
|
||||
|
||||
s = frappe.get_doc(make_stock_entry(self.pro_order.name, "Manufacture", 2))
|
||||
|
||||
bin1_on_end_production = get_bin(self.item, self.warehouse)
|
||||
|
||||
# no change in reserved / projected
|
||||
self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production),
|
||||
cint(bin1_on_start_production.reserved_qty_for_production))
|
||||
self.assertEqual(cint(bin1_on_end_production.projected_qty),
|
||||
cint(bin1_on_end_production.projected_qty))
|
||||
|
||||
# required_items removed
|
||||
self.pro_order.reload()
|
||||
self.assertEqual(len(self.pro_order.required_items), 0)
|
||||
|
||||
def make_prod_order_test_record(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
@ -152,6 +224,10 @@ def make_prod_order_test_record(**args):
|
||||
pro_order.fg_warehouse = args.fg_warehouse or "_Test Warehouse 1 - _TC"
|
||||
pro_order.company = args.company or "_Test Company"
|
||||
pro_order.stock_uom = "_Test UOM"
|
||||
|
||||
if args.source_warehouse:
|
||||
pro_order.source_warehouse = args.source_warehouse
|
||||
|
||||
if args.planned_start_date:
|
||||
pro_order.planned_start_date = args.planned_start_date
|
||||
|
||||
|
@ -0,0 +1,110 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2016-04-18 07:38:26.314642",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Required Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "transferred_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Transferred Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-18 07:38:26.314642",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order Item",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ProductionOrderItem(Document):
|
||||
pass
|
@ -1,9 +1,21 @@
|
||||
import frappe
|
||||
from erpnext.accounts.party_status import update_status
|
||||
from erpnext.accounts.party_status import status_depends_on, default_status
|
||||
from frappe.desk.notifications import get_filters_for
|
||||
|
||||
def execute():
|
||||
for doctype in ('Customer', 'Supplier'):
|
||||
frappe.reload_doctype(doctype)
|
||||
for doc in frappe.get_all(doctype):
|
||||
doc = frappe.get_doc(doctype, doc.name)
|
||||
update_status(doc)
|
||||
for party_type in ('Customer', 'Supplier'):
|
||||
frappe.reload_doctype(party_type)
|
||||
|
||||
# set all as default status
|
||||
frappe.db.sql('update `tab{0}` set status=%s'.format(party_type), default_status[party_type])
|
||||
|
||||
for doctype in status_depends_on[party_type]:
|
||||
filters = get_filters_for(doctype)
|
||||
parties = frappe.get_all(doctype, fields="{0} as party".format(party_type.lower()),
|
||||
filters=filters, limit_page_length=1)
|
||||
|
||||
parties = filter(None, [p.party for p in parties])
|
||||
|
||||
if parties:
|
||||
frappe.db.sql('update `tab{0}` set status="Open" where name in ({1})'.format(party_type,
|
||||
', '.join(len(parties) * ['%s'])), parties)
|
@ -10,6 +10,32 @@
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"depends_on": "__islocal",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
@ -896,31 +922,6 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Title",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@ -933,7 +934,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-29 15:55:12.780956",
|
||||
"modified": "2016-04-15 07:51:03.097280",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Time Log",
|
||||
@ -953,8 +954,6 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"restrict": 0,
|
||||
"restricted": 1,
|
||||
"role": "Projects User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
@ -975,8 +974,6 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"restrict": 0,
|
||||
"restricted": 0,
|
||||
"role": "Projects Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
@ -984,6 +981,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
|
@ -68,5 +68,20 @@ erpnext.financial_statements = {
|
||||
"tree": true,
|
||||
"name_field": "account",
|
||||
"parent_field": "parent_account",
|
||||
"initial_depth": 3
|
||||
"initial_depth": 3,
|
||||
onload: function(report) {
|
||||
// dropdown for links to other financial statements
|
||||
report.page.add_inner_button(__("Balance Sheet"), function() {
|
||||
var filters = report.get_values();
|
||||
frappe.set_route('query-report', 'Balance Sheet', {company: filters.company});
|
||||
}, 'Financial Statements');
|
||||
report.page.add_inner_button(__("Profit and Loss"), function() {
|
||||
var filters = report.get_values();
|
||||
frappe.set_route('query-report', 'Profit and Loss Statement', {company: filters.company});
|
||||
}, 'Financial Statements');
|
||||
report.page.add_inner_button(__("Cash Flow Statement"), function() {
|
||||
var filters = report.get_values();
|
||||
frappe.set_route('query-report', 'Cash Flow', {company: filters.company});
|
||||
}, 'Financial Statements');
|
||||
},
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ frappe.ui.form.on("Customer", {
|
||||
frappe.setup_language_field(frm);
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.dashboard.show_links();
|
||||
frm.dashboard.show_dashboard();
|
||||
|
||||
if(frappe.defaults.get_default("cust_master_name")!="Naming Series") {
|
||||
frm.toggle_display("naming_series", false);
|
||||
|
8
erpnext/stock/doctype/bin/bin.js
Normal file
8
erpnext/stock/doctype/bin/bin.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bin', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -16,6 +16,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
@ -42,6 +43,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item Code",
|
||||
@ -69,6 +71,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Reserved Quantity",
|
||||
@ -95,6 +98,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Actual Quantity",
|
||||
@ -121,6 +125,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Ordered Quantity",
|
||||
@ -147,6 +152,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Requested Quantity",
|
||||
@ -172,6 +178,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Planned Qty",
|
||||
@ -197,6 +204,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Projected Qty",
|
||||
@ -214,6 +222,31 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "reserved_qty_for_production",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reserved Qty for Production",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -222,6 +255,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Moving Average Rate",
|
||||
@ -247,6 +281,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "UOM",
|
||||
@ -273,6 +308,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "FCFS Rate",
|
||||
@ -298,6 +334,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Valuation Rate",
|
||||
@ -323,6 +360,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Stock Value",
|
||||
@ -350,7 +388,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-02-10 02:39:45.738623",
|
||||
"modified": "2016-04-18 08:12:57.341517",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Bin",
|
||||
@ -417,8 +455,10 @@
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "item_code,warehouse",
|
||||
"sort_order": "ASC"
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
@ -65,12 +65,15 @@ class Bin(Document):
|
||||
self.indented_qty = flt(self.indented_qty) + flt(args.get("indented_qty"))
|
||||
self.planned_qty = flt(self.planned_qty) + flt(args.get("planned_qty"))
|
||||
|
||||
self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
|
||||
flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
|
||||
|
||||
self.set_projected_qty()
|
||||
self.save()
|
||||
update_item_projected_qty(self.item_code)
|
||||
|
||||
def set_projected_qty(self):
|
||||
self.projected_qty = (flt(self.actual_qty) + flt(self.ordered_qty)
|
||||
+ flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
|
||||
- flt(self.reserved_qty_for_production))
|
||||
|
||||
def get_first_sle(self):
|
||||
sle = frappe.db.sql("""
|
||||
select * from `tabStock Ledger Entry`
|
||||
@ -81,8 +84,25 @@ class Bin(Document):
|
||||
""", (self.item_code, self.warehouse), as_dict=1)
|
||||
return sle and sle[0] or None
|
||||
|
||||
def update_reserved_qty_for_production(self):
|
||||
'''Update qty reserved for production from Production Item tables
|
||||
in open production orders'''
|
||||
self.reserved_qty_for_production = frappe.db.sql('''select sum(required_qty - transferred_qty)
|
||||
from `tabProduction Order` pro, `tabProduction Order Item` item
|
||||
where
|
||||
item.item_code = %s
|
||||
and item.parent = pro.name
|
||||
and pro.docstatus = 1
|
||||
and pro.source_warehouse = %s''', (self.item_code, self.warehouse))[0][0]
|
||||
|
||||
self.set_projected_qty()
|
||||
|
||||
self.db_set('reserved_qty_for_production', self.reserved_qty_for_production)
|
||||
self.db_set('projected_qty', self.projected_qty)
|
||||
|
||||
|
||||
def update_item_projected_qty(item_code):
|
||||
'''Set Item project qty'''
|
||||
'''Set total_projected_qty in Item as sum of projected qty in all warehouses'''
|
||||
frappe.db.sql('''update tabItem set
|
||||
total_projected_qty = ifnull((select sum(projected_qty) from tabBin where item_code=%s), 0)
|
||||
where name=%s''', (item_code, item_code))
|
||||
|
@ -16,12 +16,6 @@ frappe.ui.form.on("Item", {
|
||||
|
||||
},
|
||||
|
||||
dashboard_update: function(frm) {
|
||||
if(frm.dashboard_data.stock_data && frm.dashboard_data.stock_data.length) {
|
||||
frm.dashboard.add_stats(frappe.render_template('item_dashboard', {data: frm.dashboard_data.stock_data}))
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
||||
if(frm.doc.is_stock_item) {
|
||||
@ -82,7 +76,25 @@ frappe.ui.form.on("Item", {
|
||||
|
||||
erpnext.item.toggle_attributes(frm);
|
||||
|
||||
frm.dashboard.show_links();
|
||||
frm.dashboard.show_dashboard();
|
||||
},
|
||||
|
||||
dashboard_update: function(frm) {
|
||||
if(frm.dashboard_data.stock_data && frm.dashboard_data.stock_data.length) {
|
||||
var max_count = 0;
|
||||
frm.dashboard_data.stock_data.forEach(function(d) {
|
||||
d.actual_or_pending = d.projected_qty - d.reserved_qty;
|
||||
d.pending_qty = 0;
|
||||
if(d.actual_or_pending > d.actual_qty) {
|
||||
d.pending_qty = d.actual_or_pending - d.actual_qty;
|
||||
}
|
||||
|
||||
max_count = Math.max(d.actual_or_pending, d.actual_qty,
|
||||
d.reserved_qty, max_count);
|
||||
})
|
||||
frm.dashboard.add_stats(frappe.render_template('item_dashboard',
|
||||
{data: frm.dashboard_data.stock_data, max_count: max_count}));
|
||||
}
|
||||
},
|
||||
|
||||
validate: function(frm){
|
||||
|
@ -633,8 +633,8 @@ def get_timeline_data(name):
|
||||
group by posting_date''', name))
|
||||
|
||||
def get_stock_data(name):
|
||||
return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty'],
|
||||
filters={'item_code': name})
|
||||
return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty', 'reserved_qty'],
|
||||
filters={'item_code': name}, order_by = 'warehouse asc')
|
||||
|
||||
def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1):
|
||||
if (not end_of_life) or (disabled is None):
|
||||
|
@ -1,12 +1,39 @@
|
||||
<div style="padding-left: 15px;">
|
||||
<div style="padding-left: 15px; padding-right: 15px;">
|
||||
<h5>Stock Levels</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-xs-12">
|
||||
<ul class="list-unstyled">
|
||||
{% data.every(function(d) { %}
|
||||
<li class="small">{{ d.warehouse }}: {{ d.actual_qty }} ({{ d.projected_qty }})</li>
|
||||
{% }) %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{% for(var i=0; i < data.length; i++) { var d = data[i]; %}
|
||||
<li class="list-group-item" style="background-color: inherit;">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 small" style="margin-top: 8px;">{{ d.warehouse }}</div>
|
||||
<div class="col-sm-4 small">
|
||||
<span class="inline-graph">
|
||||
<span class="inline-graph-half" title="{{ __("Reserved Qty") }}">
|
||||
<span class="inline-graph-count">{{ d.reserved_qty }}</span>
|
||||
<span class="inline-graph-bar">
|
||||
<span class="inline-graph-bar-inner"
|
||||
style="width: {{ cint(Math.abs(d.reserved_qty)/max_count * 100) || 5 }}%">
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="inline-graph-half" title="{{ __("Acutal Qty {0} / Waiting Qty {1}", [d.actual_qty, d.pending_qty]) }}">
|
||||
<span class="inline-graph-count">
|
||||
{{ d.actual_qty }} {{ (d.pending_qty > 0) ? ("(" + d.pending_qty+ ")") : "" }}
|
||||
</span>
|
||||
<span class="inline-graph-bar">
|
||||
<span class="inline-graph-bar-inner dark"
|
||||
style="width: {{ cint(d.actual_qty/max_count * 100) }}%">
|
||||
</span>
|
||||
{% if(d.pending_qty > 0) { %}
|
||||
<span class="inline-graph-bar-inner" title="{{ __("Projected Qty") }}"
|
||||
style="width: {{ cint(d.pending_qty/max_count * 100) }}%">
|
||||
</span>
|
||||
{% } %}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% } %}
|
||||
</ul>
|
||||
</div>
|
@ -11,6 +11,12 @@
|
||||
"doctype": "Warehouse",
|
||||
"warehouse_name": "_Test Warehouse 1"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"create_account_under": "Fixed Assets - _TC",
|
||||
"doctype": "Warehouse",
|
||||
"warehouse_name": "_Test Warehouse 2"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"create_account_under": "Stock Assets - _TC",
|
||||
|
@ -87,6 +87,54 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Disabled",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@ -117,32 +165,8 @@
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Disabled",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "For Reference Only.",
|
||||
"collapsible": 1,
|
||||
"description": "",
|
||||
"fieldname": "warehouse_contact_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -408,7 +432,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-30 03:31:43.954827",
|
||||
"modified": "2016-04-18 05:44:24.837579",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Warehouse",
|
||||
@ -535,6 +559,7 @@
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "DESC",
|
||||
|
@ -14,7 +14,8 @@ def get_columns():
|
||||
return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200",
|
||||
_("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100", _("Warehouse") + ":Link/Warehouse:120",
|
||||
_("UOM") + ":Link/UOM:100", _("Actual Qty") + ":Float:100", _("Planned Qty") + ":Float:100",
|
||||
_("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100", _("Reserved Qty") + ":Float:100",
|
||||
_("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100",
|
||||
_("Reserved Qty") + ":Float:100", _("Reserved Qty for Production") + ":Float:100",
|
||||
_("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100",
|
||||
_("Shortage Qty") + ":Float:100"]
|
||||
|
||||
@ -51,7 +52,7 @@ def get_data(filters):
|
||||
|
||||
data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse,
|
||||
item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty,
|
||||
bin.reserved_qty, bin.projected_qty, re_order_level, re_order_qty, shortage_qty])
|
||||
bin.reserved_qty, bin.reserved_qty_for_production, bin.projected_qty, re_order_level, re_order_qty, shortage_qty])
|
||||
|
||||
return data
|
||||
|
||||
@ -63,7 +64,8 @@ def get_bin_list(filters):
|
||||
bin_filters.warehouse = filters.warehouse
|
||||
|
||||
bin_list = frappe.get_all("Bin", fields=["item_code", "warehouse",
|
||||
"actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty", "projected_qty"],
|
||||
"actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty",
|
||||
"reserved_qty_for_production", "projected_qty"],
|
||||
filters=bin_filters, order_by="item_code, warehouse")
|
||||
|
||||
return bin_list
|
||||
|
@ -148,8 +148,9 @@ def update_bin_qty(item_code, warehouse, qty_dict=None):
|
||||
mismatch = True
|
||||
|
||||
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.reserved_qty_for_production))
|
||||
|
||||
bin.save()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user