[cleanup]
This commit is contained in:
parent
e37625b0c2
commit
cca33b2ff0
@ -0,0 +1,12 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'docstatus': 1,
|
||||
'fieldname': 'purchase_order',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related Documents'),
|
||||
'items': ['Purchase Receipt', 'Purchase Invoice', 'Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -1775,6 +1776,7 @@
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-shopping-cart",
|
||||
"idx": 29,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 1,
|
||||
@ -1782,7 +1784,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-05-23 15:20:34.288790",
|
||||
"modified": "2016-07-08 06:48:04.162164",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
@ -1845,7 +1847,7 @@
|
||||
"role": "Purchase User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
|
@ -1,145 +1,178 @@
|
||||
[
|
||||
{
|
||||
"item": "Bearing Assembly",
|
||||
"item": "Bearing Assembly",
|
||||
"items": [
|
||||
{
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 15.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Block",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Block",
|
||||
"qty": 1.0,
|
||||
"rate": 10.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Collar",
|
||||
"qty": 2.0,
|
||||
"item_code": "Bearing Collar",
|
||||
"qty": 2.0,
|
||||
"rate": 20.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Pipe",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Pipe",
|
||||
"qty": 1.0,
|
||||
"rate": 15.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Upper Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Upper Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 50.0
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"item": "Wind Mill A Series",
|
||||
"item": "Wind Mill A Series",
|
||||
"items": [
|
||||
{
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 15.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Base Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 20.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Block",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Block",
|
||||
"qty": 1.0,
|
||||
"rate": 10.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Pipe",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Pipe",
|
||||
"qty": 1.0,
|
||||
"rate": 15.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "External Disc",
|
||||
"qty": 1.0,
|
||||
"item_code": "External Disc",
|
||||
"qty": 1.0,
|
||||
"rate": 45.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Shaft",
|
||||
"qty": 1.0,
|
||||
"item_code": "Shaft",
|
||||
"qty": 1.0,
|
||||
"rate": 30.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 4.0,
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 4.0,
|
||||
"rate": 22.0
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"item": "Wind MIll C Series",
|
||||
"item": "Wind MIll C Series",
|
||||
"items": [
|
||||
{
|
||||
"item_code": "Base Plate",
|
||||
"qty": 2.0,
|
||||
"item_code": "Base Plate",
|
||||
"qty": 2.0,
|
||||
"rate": 20.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Internal Disc",
|
||||
"qty": 1.0,
|
||||
"item_code": "Internal Disc",
|
||||
"qty": 1.0,
|
||||
"rate": 33.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "External Disc",
|
||||
"qty": 1.0,
|
||||
"item_code": "External Disc",
|
||||
"qty": 1.0,
|
||||
"rate": 45.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Assembly",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Assembly",
|
||||
"qty": 1.0,
|
||||
"rate": 130.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 3.0,
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 3.0,
|
||||
"rate": 22.0
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"item": "Wind Turbine",
|
||||
"item": "Wind Turbine",
|
||||
"with_operations": 1,
|
||||
"operations": [
|
||||
{
|
||||
"operation": "Prepare Frame",
|
||||
"time_in_mins": 30.0,
|
||||
"workstation": "Drilling Machine 1"
|
||||
},
|
||||
{
|
||||
"operation": "Setup Fixtures",
|
||||
"time_in_mins": 15.0,
|
||||
"workstation": "Assembly Station 1"
|
||||
},
|
||||
{
|
||||
"operation": "Assembly Operation",
|
||||
"time_in_mins": 30.0,
|
||||
"workstation": "Assembly Station 1"
|
||||
},
|
||||
{
|
||||
"operation": "Wiring",
|
||||
"time_in_mins": 20.0,
|
||||
"workstation": "Assembly Station 1"
|
||||
},
|
||||
{
|
||||
"operation": "Testing",
|
||||
"time_in_mins": 10.0,
|
||||
"workstation": "Packing and Testing Station"
|
||||
},
|
||||
{
|
||||
"operation": "Packing",
|
||||
"time_in_mins": 25.0,
|
||||
"workstation": "Packing and Testing Station"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Bearing Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 15.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Base Plate",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Plate",
|
||||
"qty": 1.0,
|
||||
"rate": 20.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Bearing Collar",
|
||||
"qty": 1.0,
|
||||
"item_code": "Bearing Collar",
|
||||
"qty": 1.0,
|
||||
"rate": 20.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Blade Rib",
|
||||
"qty": 1.0,
|
||||
"item_code": "Blade Rib",
|
||||
"qty": 1.0,
|
||||
"rate": 10.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Shaft",
|
||||
"qty": 1.0,
|
||||
"item_code": "Shaft",
|
||||
"qty": 1.0,
|
||||
"rate": 30.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 2.0,
|
||||
"item_code": "Wing Sheet",
|
||||
"qty": 2.0,
|
||||
"rate": 22.0
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"item": "Base Plate",
|
||||
"item": "Base Plate",
|
||||
"items": [
|
||||
{
|
||||
"item_code": "Base Plate Un Painted",
|
||||
"qty": 1.0,
|
||||
"item_code": "Base Plate Un Painted",
|
||||
"qty": 1.0,
|
||||
"rate": 16.0
|
||||
}
|
||||
]
|
||||
|
@ -4,7 +4,7 @@ import frappe, sys
|
||||
import erpnext
|
||||
import frappe.utils
|
||||
from erpnext.demo.setup_data import setup_data
|
||||
from erpnext.demo.user import hr, sales, purchase
|
||||
from erpnext.demo.user import hr, sales, purchase, manufacturing, stock
|
||||
|
||||
def make(domain='Manufacturing'):
|
||||
frappe.flags.domain = domain
|
||||
@ -43,7 +43,8 @@ def simulate():
|
||||
hr.work()
|
||||
sales.work()
|
||||
purchase.work()
|
||||
# run_manufacturing()
|
||||
manufacturing.work()
|
||||
stock.work()
|
||||
# run_stock()
|
||||
# run_accounts()
|
||||
# run_projects()
|
||||
|
@ -14,6 +14,7 @@ def setup_data():
|
||||
setup_customer()
|
||||
setup_supplier()
|
||||
setup_item()
|
||||
setup_warehouse()
|
||||
import_json('Address')
|
||||
import_json('Contact')
|
||||
setup_workstation()
|
||||
@ -147,6 +148,11 @@ def setup_item():
|
||||
item.default_warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1)[0].name
|
||||
item.insert()
|
||||
|
||||
def setup_warehouse():
|
||||
w = frappe.new_doc('Warehouse')
|
||||
w.warehouse_name = 'Supplier'
|
||||
w.insert()
|
||||
|
||||
def setup_currency_exchange():
|
||||
frappe.get_doc({
|
||||
'doctype': 'Currency Exchange',
|
||||
@ -182,7 +188,7 @@ def setup_user():
|
||||
user.password = 'demo'
|
||||
user.insert()
|
||||
|
||||
def import_json(doctype, submit=False):
|
||||
def import_json(doctype, submit=False, values=None):
|
||||
frappe.flags.in_import = True
|
||||
data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
|
||||
frappe.scrub(doctype) + '.json')).read())
|
||||
@ -266,13 +272,14 @@ def setup_salary_structure():
|
||||
and e.date_of_joining > f.year_start_date) else f.year_start_date
|
||||
ss.to_date = f.year_end_date
|
||||
ss.append('earnings', {
|
||||
'earning_type': 'Basic',
|
||||
'modified_value': random.random() * 10000
|
||||
'salary_component': 'Basic',
|
||||
'amount': random.random() * 10000
|
||||
})
|
||||
ss.append('deductions', {
|
||||
'deduction_type': 'Income Tax',
|
||||
'd_modified_amt': random.random() * 1000
|
||||
'salary_component': 'Income Tax',
|
||||
'amount': random.random() * 1000
|
||||
})
|
||||
|
||||
ss.insert()
|
||||
|
||||
def setup_account():
|
||||
@ -303,5 +310,16 @@ def setup_user_roles():
|
||||
|
||||
if not frappe.db.get_global('demo_purchase_user'):
|
||||
user = frappe.get_doc('User', 'MichalSobczak@example.com')
|
||||
user.add_roles('Purchase User', 'Purchase Manager', 'Accounts User')
|
||||
user.add_roles('Purchase User', 'Purchase Manager', 'Accounts User', 'Stock User')
|
||||
frappe.db.set_global('demo_purchase_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_manufacturing_user'):
|
||||
user = frappe.get_doc('User', 'NuranVerkleij@example.com')
|
||||
user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
|
||||
frappe.db.set_global('demo_manufacturing_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_stock_user'):
|
||||
user = frappe.get_doc('User', 'HatsueKashiwagi@example.com')
|
||||
user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
|
||||
frappe.db.set_global('demo_stock_user', user.name)
|
||||
|
||||
|
77
erpnext/demo/user/manufacturing.py
Normal file
77
erpnext/demo/user/manufacturing.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe, random, erpnext
|
||||
from frappe.utils.make_random import how_many
|
||||
from frappe.desk import query_report
|
||||
|
||||
def work():
|
||||
frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
|
||||
|
||||
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||
|
||||
ppt = frappe.get_doc("Production Planning Tool", "Production Planning Tool")
|
||||
ppt.company = erpnext.get_default_company()
|
||||
ppt.use_multi_level_bom = 1
|
||||
ppt.get_items_from = "Sales Order"
|
||||
ppt.purchase_request_for_warehouse = "Stores - WPL"
|
||||
ppt.run_method("get_open_sales_orders")
|
||||
ppt.run_method("get_items")
|
||||
ppt.run_method("raise_production_orders")
|
||||
ppt.run_method("raise_material_requests")
|
||||
frappe.db.commit()
|
||||
|
||||
# submit production orders
|
||||
for pro in frappe.db.get_values("Production Order", {"docstatus": 0}, "name"):
|
||||
b = frappe.get_doc("Production Order", pro[0])
|
||||
b.wip_warehouse = "Work in Progress - WPL"
|
||||
b.submit()
|
||||
frappe.db.commit()
|
||||
|
||||
# submit material requests
|
||||
for pro in frappe.db.get_values("Material Request", {"docstatus": 0}, "name"):
|
||||
b = frappe.get_doc("Material Request", pro[0])
|
||||
b.submit()
|
||||
frappe.db.commit()
|
||||
|
||||
# stores -> wip
|
||||
if random.random() < 0.3:
|
||||
for pro in query_report.run("Open Production Orders")["result"][:how_many("Stock Entry for WIP")]:
|
||||
make_stock_entry_from_pro(pro[0], "Material Transfer for Manufacture")
|
||||
|
||||
# wip -> fg
|
||||
if random.random() < 0.3:
|
||||
for pro in query_report.run("Production Orders in Progress")["result"][:how_many("Stock Entry for FG")]:
|
||||
make_stock_entry_from_pro(pro[0], "Manufacture")
|
||||
|
||||
# submit time logs
|
||||
for timesheet in frappe.get_all("Timesheet", ["name"], {"docstatus": 0,
|
||||
"production_order": ("!=", ""), "to_time": ("<", frappe.flags.current_date)}):
|
||||
timesheet = frappe.get_doc("Timesheet", timesheet.name)
|
||||
try:
|
||||
timesheet.submit()
|
||||
frappe.db.commit()
|
||||
except OverlapError:
|
||||
pass
|
||||
|
||||
def make_stock_entry_from_pro(pro_id, purpose):
|
||||
from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry
|
||||
from erpnext.stock.stock_ledger import NegativeStockError
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \
|
||||
DuplicateEntryForProductionOrderError, OperationsNotCompleteError
|
||||
|
||||
try:
|
||||
st = frappe.get_doc(make_stock_entry(pro_id, purpose))
|
||||
st.posting_date = frappe.flags.current_date
|
||||
st.fiscal_year = str(frappe.flags.current_date.year)
|
||||
for d in st.get("items"):
|
||||
d.cost_center = "Main - " + frappe.db.get_value('Company', st.company, 'abbr')
|
||||
st.insert()
|
||||
frappe.db.commit()
|
||||
st.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForProductionOrderError,
|
||||
OperationsNotCompleteError):
|
||||
frappe.db.rollback()
|
@ -27,6 +27,7 @@ def work():
|
||||
for mr in frappe.get_all('Material Request',
|
||||
filters={'material_request_type': 'Purchase', 'status': 'Open'},
|
||||
limit=random.randint(1,6)):
|
||||
print mr.name
|
||||
if not frappe.get_all('Request for Quotation',
|
||||
filters={'material_request': mr.name}, limit=1):
|
||||
rfq = make_request_for_quotation(mr.name)
|
||||
@ -59,11 +60,11 @@ def work():
|
||||
exchange_rate = get_exchange_rate(party_account_currency, company_currency)
|
||||
|
||||
# make supplier quotations
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.2:
|
||||
from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation
|
||||
|
||||
report = "Material Requests for which Supplier Quotations are not created"
|
||||
for row in query_report.run(report)["result"][:how_many("Supplier Quotation")]:
|
||||
for row in query_report.run(report)["result"][:random.randint(1, 3)]:
|
||||
if row[0] != "'Total'":
|
||||
sq = frappe.get_doc(make_supplier_quotation(row[0]))
|
||||
sq.transaction_date = frappe.flags.current_date
|
||||
@ -89,13 +90,15 @@ def work():
|
||||
po.submit()
|
||||
frappe.db.commit()
|
||||
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.2:
|
||||
make_subcontract()
|
||||
|
||||
def make_material_request(item_code, qty):
|
||||
mr = frappe.new_doc("Material Request")
|
||||
|
||||
if frappe.db.get_value('BOM', {'item': item_code, 'is_default': 1, 'is_active': 1}):
|
||||
variant_of = frappe.db.get_value('Item', item_code, 'variant_of') or item_code
|
||||
|
||||
if frappe.db.get_value('BOM', {'item': variant_of, 'is_default': 1, 'is_active': 1}):
|
||||
mr.material_request_type = 'Manufacture'
|
||||
else:
|
||||
mr.material_request_type = "Purchase"
|
||||
@ -143,6 +146,6 @@ def make_subcontract():
|
||||
|
||||
# transfer material for sub-contract
|
||||
stock_entry = frappe.get_doc(make_stock_entry(po.name, po.items[0].item_code))
|
||||
stock_entry.from_warehouse = "Stores - WP"
|
||||
stock_entry.to_warehouse = "Supplier - WP"
|
||||
stock_entry.from_warehouse = "Stores - WPL"
|
||||
stock_entry.to_warehouse = "Supplier - WPL"
|
||||
stock_entry.insert()
|
||||
|
97
erpnext/demo/user/stock.py
Normal file
97
erpnext/demo/user/stock.py
Normal file
@ -0,0 +1,97 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe, random
|
||||
from frappe.desk import query_report
|
||||
from erpnext.stock.stock_ledger import NegativeStockError
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoRequiredError, SerialNoQtyError
|
||||
|
||||
def work():
|
||||
frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
|
||||
|
||||
make_purchase_receipt()
|
||||
make_delivery_note()
|
||||
make_stock_reconciliation()
|
||||
submit_draft_stock_entries()
|
||||
|
||||
def make_purchase_receipt():
|
||||
if random.random() < 0.6:
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
||||
report = "Purchase Order Items To Be Received"
|
||||
po_list =list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="'Total'"]))[:random.randint(1, 10)]
|
||||
for po in po_list:
|
||||
pr = frappe.get_doc(make_purchase_receipt(po))
|
||||
|
||||
if pr.is_subcontracted=="Yes":
|
||||
pr.supplier_warehouse = "Supplier - WPL"
|
||||
|
||||
pr.posting_date = frappe.flags.current_date
|
||||
pr.insert()
|
||||
try:
|
||||
pr.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError):
|
||||
frappe.db.rollback()
|
||||
|
||||
def make_delivery_note():
|
||||
# make purchase requests
|
||||
|
||||
# make delivery notes (if possible)
|
||||
if random.random() < 0.3:
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
|
||||
report = "Ordered Items To Be Delivered"
|
||||
for so in list(set([r[0] for r in query_report.run(report)["result"]
|
||||
if r[0]!="'Total'"]))[:random.randint(1, 3)]:
|
||||
dn = frappe.get_doc(make_delivery_note(so))
|
||||
dn.posting_date = frappe.flags.current_date
|
||||
for d in dn.get("items"):
|
||||
if not d.expense_account:
|
||||
d.expense_account = ("Cost of Goods Sold - {0}".format(
|
||||
frappe.db.get_value('Company', dn.company, 'abbr')))
|
||||
dn.insert()
|
||||
try:
|
||||
dn.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError, SerialNoRequiredError, SerialNoQtyError):
|
||||
frappe.db.rollback()
|
||||
|
||||
def make_stock_reconciliation():
|
||||
# random set some items as damaged
|
||||
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \
|
||||
import OpeningEntryAccountError, EmptyStockReconciliationItemsError
|
||||
|
||||
if random.random() < 0.1:
|
||||
stock_reco = frappe.new_doc("Stock Reconciliation")
|
||||
stock_reco.posting_date = frappe.flags.current_date
|
||||
stock_reco.get_items_for("Stores - WP")
|
||||
if stock_reco.items:
|
||||
for item in stock_reco.items:
|
||||
if item.qty:
|
||||
item.qty = item.qty - round(random.randint(1, item.qty))
|
||||
try:
|
||||
stock_reco.insert()
|
||||
stock_reco.submit()
|
||||
frappe.db.commit()
|
||||
except OpeningEntryAccountError:
|
||||
frappe.db.rollback()
|
||||
except EmptyStockReconciliationItemsError:
|
||||
frappe.db.rollback()
|
||||
|
||||
def submit_draft_stock_entries():
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \
|
||||
DuplicateEntryForProductionOrderError, OperationsNotCompleteError
|
||||
|
||||
# try posting older drafts (if exists)
|
||||
for st in frappe.db.get_values("Stock Entry", {"docstatus":0}, "name"):
|
||||
try:
|
||||
ste = frappe.get_doc("Stock Entry", st[0])
|
||||
ste.posting_date = frappe.flags.current_date
|
||||
ste.save()
|
||||
ste.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForProductionOrderError,
|
||||
OperationsNotCompleteError):
|
||||
frappe.db.rollback()
|
||||
|
@ -41,8 +41,8 @@ class BOM(Document):
|
||||
|
||||
self.validate_materials()
|
||||
self.set_bom_material_details()
|
||||
self.calculate_cost()
|
||||
self.validate_operations()
|
||||
self.calculate_cost()
|
||||
|
||||
def on_update(self):
|
||||
self.check_recursion()
|
||||
@ -64,7 +64,7 @@ class BOM(Document):
|
||||
self.manage_default_bom()
|
||||
|
||||
def get_item_det(self, item_code):
|
||||
item = frappe.db.sql("""select name, item_name, docstatus, description, image,
|
||||
item = frappe.db.sql("""select name, item_name, docstatus, description, image,
|
||||
is_sub_contracted_item, stock_uom, default_bom, last_purchase_rate
|
||||
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
||||
|
||||
@ -370,7 +370,12 @@ class BOM(Document):
|
||||
|
||||
def validate_operations(self):
|
||||
if self.with_operations and not self.get('operations'):
|
||||
frappe.throw(_("Operations cannot be left blank."))
|
||||
frappe.throw(_("Operations cannot be left blank"))
|
||||
|
||||
if self.with_operations:
|
||||
for d in self.operations:
|
||||
if not d.description:
|
||||
d.description = frappe.db.get_value('Operation', d.operation, 'description')
|
||||
|
||||
def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1):
|
||||
item_dict = {}
|
||||
|
@ -2,10 +2,13 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -15,6 +18,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operation",
|
||||
@ -25,6 +29,7 @@
|
||||
"options": "Operation",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
@ -40,6 +45,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
@ -50,6 +56,7 @@
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -65,18 +72,20 @@
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -89,12 +98,14 @@
|
||||
"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,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -110,6 +121,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
@ -119,6 +131,7 @@
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -135,6 +148,7 @@
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time ",
|
||||
@ -145,6 +159,7 @@
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
@ -160,6 +175,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Operating Cost",
|
||||
@ -169,6 +185,7 @@
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -180,18 +197,21 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:42.924201",
|
||||
"modified": "2016-07-08 08:42:17.903362",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
8
erpnext/manufacturing/doctype/operation/operation.js
Normal file
8
erpnext/manufacturing/doctype/operation/operation.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('Operation', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -3,11 +3,13 @@
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "Prompt",
|
||||
"beta": 0,
|
||||
"creation": "2014-11-07 16:20:30.683186",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -17,6 +19,7 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Default Workstation",
|
||||
@ -26,6 +29,7 @@
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -41,6 +45,7 @@
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
@ -48,6 +53,7 @@
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -63,14 +69,16 @@
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Description",
|
||||
"label": "Description",
|
||||
"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,
|
||||
@ -82,13 +90,15 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-wrench",
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:50.879598",
|
||||
"modified": "2016-07-08 08:42:35.126397",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Operation",
|
||||
@ -136,8 +146,10 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -197,6 +198,32 @@
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sales Order",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Order",
|
||||
"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,
|
||||
@ -948,32 +975,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "Manufacture against Sales Order",
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Sales Order",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Order",
|
||||
"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,
|
||||
@ -1091,7 +1092,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-06 16:09:38.879785",
|
||||
"modified": "2016-07-08 07:09:06.847763",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"login_required": 1,
|
||||
"modified": "2016-06-24 16:11:10.935835",
|
||||
"modified": "2016-07-07 06:04:30.979390",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "tasks",
|
||||
|
@ -183,7 +183,10 @@ def install(country=None):
|
||||
{"doctype": "Offer Term", "offer_term": _("Incentives")},
|
||||
|
||||
{'doctype': "Print Heading", 'print_heading': _("Credit Note")},
|
||||
{'doctype': "Print Heading", 'print_heading': _("Debit Note")}
|
||||
{'doctype': "Print Heading", 'print_heading': _("Debit Note")},
|
||||
|
||||
{"doctype": "Salary Component", "salary_component": _("Basic")},
|
||||
{"doctype": "Salary Component", "salary_component": _("Income Tax")},
|
||||
]
|
||||
|
||||
from erpnext.setup.setup_wizard.industry_type import get_industry_types
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe.defaults
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate
|
||||
from frappe.utils import cstr, cint, flt, comma_or, getdate, nowdate, formatdate, format_time
|
||||
from erpnext.stock.utils import get_incoming_rate
|
||||
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
|
||||
from erpnext.stock.get_item_details import get_bin_details, get_default_cost_center, get_conversion_factor
|
||||
@ -225,9 +225,12 @@ class StockEntry(StockController):
|
||||
|
||||
# validate qty during submit
|
||||
if d.docstatus==1 and d.s_warehouse and not allow_negative_stock and d.actual_qty < d.transfer_qty:
|
||||
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
|
||||
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
|
||||
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty), NegativeStockError)
|
||||
frappe.throw(_("Row {0}: Qty not available for {4} in warehouse {1} at posting time of the entry ({2} {3})".format(d.idx,
|
||||
frappe.bold(d.s_warehouse), formatdate(self.posting_date),
|
||||
format_time(self.posting_time), frappe.bold(d.item_code)))
|
||||
+ '<br><br>' + _("Available qty is {0}, you need {1}").format(frappe.bold(d.actual_qty),
|
||||
frappe.bold(d.transfer_qty)),
|
||||
NegativeStockError, title=_('Insufficient Stock'))
|
||||
|
||||
def get_stock_and_rate(self):
|
||||
self.set_transfer_qty()
|
||||
|
@ -9,6 +9,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -428,7 +429,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "pin",
|
||||
"fieldtype": "Int",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -588,7 +589,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-29 19:47:24.336215",
|
||||
"modified": "2016-07-08 06:00:36.113988",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Warehouse",
|
||||
|
@ -14,7 +14,7 @@ frappe.treeview_settings['Warehouse'] = {
|
||||
{fieldtype:'Data', fieldname: 'name_field',
|
||||
label:__('New Warehouse Name'), reqd:true},
|
||||
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
|
||||
description: __("Further nodes can be only created under 'Group' type nodes")}
|
||||
description: __("Child nodes can be only created under 'Group' type nodes")}
|
||||
],
|
||||
onrender: function(node) {
|
||||
if (node.data && node.data.balance!==undefined) {
|
||||
|
@ -1,17 +1,19 @@
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-08-09 12:20:58",
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-03-30 05:46:11.917037",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Material Requests for which Supplier Quotations are not created",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n mr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tmr_item.qty as \"Qty:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\",\n\tmr.company as \"Company:Link/Company:\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\n\tand not exists(select name from `tabSupplier Quotation Item` where prevdoc_docname=mr.name)\norder by mr.transaction_date asc",
|
||||
"ref_doctype": "Material Request",
|
||||
"report_name": "Material Requests for which Supplier Quotations are not created",
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-08-09 12:20:58",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2016-07-08 05:43:10.236943",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Material Requests for which Supplier Quotations are not created",
|
||||
"owner": "Administrator",
|
||||
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n mr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tmr_item.qty as \"Qty:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\",\n\tmr.company as \"Company:Link/Company:\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\n\tand not exists(select name from `tabSupplier Quotation Item` where material_request=mr.name)\norder by mr.transaction_date asc",
|
||||
"ref_doctype": "Material Request",
|
||||
"report_name": "Material Requests for which Supplier Quotations are not created",
|
||||
"report_type": "Query Report"
|
||||
}
|
@ -229,7 +229,7 @@ class update_entries_after(object):
|
||||
# calculate new valuation rate only if stock value is positive
|
||||
# else it remains the same as that of previous entry
|
||||
self.valuation_rate = new_stock_value / new_stock_qty
|
||||
|
||||
|
||||
def get_moving_average_values(self, sle):
|
||||
actual_qty = flt(sle.actual_qty)
|
||||
new_stock_qty = flt(self.qty_after_transaction) + actual_qty
|
||||
@ -303,7 +303,7 @@ class update_entries_after(object):
|
||||
break
|
||||
else:
|
||||
index = 0
|
||||
|
||||
|
||||
# select first batch or the batch with same rate
|
||||
batch = self.stock_queue[index]
|
||||
if qty_to_pop >= batch[0]:
|
||||
@ -327,7 +327,7 @@ class update_entries_after(object):
|
||||
|
||||
if stock_qty:
|
||||
self.valuation_rate = stock_value / flt(stock_qty)
|
||||
|
||||
|
||||
if not self.stock_queue:
|
||||
self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate])
|
||||
|
||||
@ -346,8 +346,9 @@ class update_entries_after(object):
|
||||
|
||||
|
||||
|
||||
if frappe.local.flags.currently_saving.doctype==self.exceptions[0]["voucher_type"] \
|
||||
and frappe.local.flags.currently_saving.name==self.exceptions[0]["voucher_no"]:
|
||||
if (frappe.local.flags.currently_saving
|
||||
and frappe.local.flags.currently_saving.doctype==self.exceptions[0]["voucher_type"]
|
||||
and frappe.local.flags.currently_saving.name==self.exceptions[0]["voucher_no"]):
|
||||
msg = _("{0} units of {1} needed in {2} to complete this transaction.").format(
|
||||
abs(deficiency), frappe.get_desk_link('Item', self.item_code),
|
||||
frappe.get_desk_link('Warehouse', self.warehouse))
|
||||
|
Loading…
x
Reference in New Issue
Block a user