Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py
index 158ff3a..015e2c0 100644
--- a/accounts/report/budget_variance_report/budget_variance_report.py
+++ b/accounts/report/budget_variance_report/budget_variance_report.py
@@ -47,18 +47,20 @@
msgprint(_("Please specify") + ": " + label,
raise_exception=True)
- columns = ["Cost Center:Link/Cost Center:100", "Account:Link/Account:100"]
+ columns = ["Cost Center:Link/Cost Center:120", "Account:Link/Account:120"]
group_months = False if filters["period"] == "Monthly" else True
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]:
if group_months:
- columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")))
+ label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))
else:
- columns.append(label % from_date.strftime("%b"))
+ label = label % from_date.strftime("%b")
+
+ columns.append(label+":Float:120")
- return columns + ["Total Target::80", "Total Actual::80", "Total Variance::80"]
+ return columns + ["Total Target::120", "Total Actual::120", "Total Variance::120"]
#Get cost center & target details
def get_costcenter_target_details(filters):
@@ -66,19 +68,17 @@
cc.parent_cost_center, bd.account, bd.budget_allocated
from `tabCost Center` cc, `tabBudget Detail` bd
where bd.parent=cc.name and bd.fiscal_year=%s and
- cc.company=%s and ifnull(cc.distribution_id, '')!=''
- order by cc.name""" % ('%s', '%s'),
+ cc.company=%s order by cc.name""" % ('%s', '%s'),
(filters.get("fiscal_year"), filters.get("company")), as_dict=1)
#Get target distribution details of accounts of cost center
def get_target_distribution_details(filters):
target_details = {}
- for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \
- from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \
- `tabCost Center` cc where bdd.parent=bd.name and cc.distribution_id=bd.name and \
- bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
- target_details.setdefault(d.month, d)
+ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation \
+ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
+ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
+ target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
return target_details
@@ -99,15 +99,19 @@
cam_map = {}
for ccd in costcenter_target_details:
- for month in tdd:
+ for month_id in range(1, 13):
+ month = datetime.date(2013, month_id, 1).strftime('%B')
+
cam_map.setdefault(ccd.name, {}).setdefault(ccd.account, {})\
- .setdefault(month, webnotes._dict({
- "target": 0.0, "actual": 0.0
- }))
+ .setdefault(month, webnotes._dict({
+ "target": 0.0, "actual": 0.0
+ }))
tav_dict = cam_map[ccd.name][ccd.account][month]
- tav_dict.target = flt(ccd.budget_allocated) * \
- (tdd[month]["percentage_allocation"]/100)
+ month_percentage = ccd.distribution_id and \
+ tdd.get(ccd.distribution_id, {}).get(month, 0) or 100.0/12
+
+ tav_dict.target = flt(flt(ccd.budget_allocated) * month_percentage /100)
for ad in actual_details:
if ad.month_name == month and ad.account == ccd.account \
diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py
index 14c8b1f..8a2df1e 100755
--- a/hr/doctype/leave_application/leave_application.py
+++ b/hr/doctype/leave_application/leave_application.py
@@ -115,7 +115,8 @@
self.doc.leave_balance = get_leave_balance(self.doc.employee,
self.doc.leave_type, self.doc.fiscal_year)["leave_balance"]
- if self.doc.leave_balance - self.doc.total_leave_days < 0:
+ if self.doc.status != "Rejected" \
+ and self.doc.leave_balance - self.doc.total_leave_days < 0:
#check if this leave type allow the remaining balance to be in negative. If yes then warn the user and continue to save else warn the user and don't save.
msgprint("There is not enough leave balance for Leave Type: %s" % \
(self.doc.leave_type,),
diff --git a/manufacturing/doctype/production_order/production_order.js b/manufacturing/doctype/production_order/production_order.js
index 012c279..f680776 100644
--- a/manufacturing/doctype/production_order/production_order.js
+++ b/manufacturing/doctype/production_order/production_order.js
@@ -61,30 +61,25 @@
}
cur_frm.cscript['Transfer Raw Materials'] = function() {
- var doc = cur_frm.doc;
- cur_frm.cscript.make_se(doc, 'Material Transfer');
+ cur_frm.cscript.make_se('Material Transfer');
}
cur_frm.cscript['Update Finished Goods'] = function() {
- var doc = cur_frm.doc;
- cur_frm.cscript.make_se(doc, 'Manufacture/Repack');
+ cur_frm.cscript.make_se('Manufacture/Repack');
}
-cur_frm.cscript.make_se = function(doc, purpose) {
- var se = wn.model.get_new_doc("Stock Entry");
- se.purpose = purpose;
- se.production_order = doc.name;
- if(purpose==="Material Transfer") {
- se.to_warehouse = doc.wip_warehouse;
- } else {
- se.from_warehouse = doc.wip_warehouse;
- se.to_warehouse = doc.fg_warehouse;
- }
- se.company = doc.company;
- se.fg_completed_qty = doc.qty - doc.produced_qty;
- se.bom_no = doc.bom_no;
- se.use_multi_level_bom = doc.use_multi_level_bom;
- loaddoc('Stock Entry', se.name);
+cur_frm.cscript.make_se = function(purpose) {
+ wn.call({
+ method:"manufacturing.doctype.production_order.production_order.make_stock_entry",
+ args: {
+ "production_order_id": cur_frm.doc.name,
+ "purpose": purpose
+ },
+ callback: function(r) {
+ var doclist = wn.model.sync(r.message);
+ wn.set_route("Form", doclist[0].doctype, doclist[0].name);
+ }
+ })
}
cur_frm.fields_dict['production_item'].get_query = function(doc) {
diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py
index 2f31180..90a74e9 100644
--- a/manufacturing/doctype/production_order/production_order.py
+++ b/manufacturing/doctype/production_order/production_order.py
@@ -137,4 +137,23 @@
if bom:
res.bom_no = bom[0][0]
- return res
\ No newline at end of file
+ return res
+
+@webnotes.whitelist()
+def make_stock_entry(production_order_id, purpose):
+ production_order = webnotes.bean("Production Order", production_order_id)
+
+ stock_entry = webnotes.new_bean("Stock Entry")
+ stock_entry.doc.purpose = purpose
+ stock_entry.doc.production_order = production_order_id
+ stock_entry.doc.company = production_order.doc.company
+ stock_entry.doc.bom_no = production_order.doc.bom_no
+ stock_entry.doc.fg_completed_qty = flt(production_order.doc.qty) - flt(production_order.doc.produced_qty)
+
+ if purpose=="Material Transfer":
+ stock_entry.doc.to_warehouse = production_order.doc.wip_warehouse
+ else:
+ stock_entry.doc.from_warehouse = production_order.doc.wip_warehouse
+ stock_entry.doc.to_warehouse = production_order.doc.fg_warehouse
+
+ return [d.fields for d in stock_entry.doclist]
diff --git a/manufacturing/page/manufacturing_home/manufacturing_home.js b/manufacturing/page/manufacturing_home/manufacturing_home.js
index b29bbbb..a2a4eaa 100644
--- a/manufacturing/page/manufacturing_home/manufacturing_home.js
+++ b/manufacturing/page/manufacturing_home/manufacturing_home.js
@@ -65,10 +65,25 @@
icon: "icon-list",
items: [
{
+ "label":wn._("Open Production Orders"),
+ route: "query-report/Open Production Orders",
+ doctype:"Production Order"
+ },
+ {
+ "label":wn._("Production Orders in Progress"),
+ route: "query-report/Production Orders in Progress",
+ doctype:"Production Order"
+ },
+ {
"label":wn._("Issued Items Against Production Order"),
route: "query-report/Issued Items Against Production Order",
doctype:"Production Order"
},
+ {
+ "label":wn._("Completed Production Orders"),
+ route: "query-report/Completed Production Orders",
+ doctype:"Production Order"
+ },
]
}
]
diff --git a/manufacturing/report/completed_production_orders/__init__.py b/manufacturing/report/completed_production_orders/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manufacturing/report/completed_production_orders/__init__.py
diff --git a/manufacturing/report/completed_production_orders/completed_production_orders.txt b/manufacturing/report/completed_production_orders/completed_production_orders.txt
new file mode 100644
index 0000000..facda7e
--- /dev/null
+++ b/manufacturing/report/completed_production_orders/completed_production_orders.txt
@@ -0,0 +1,22 @@
+[
+ {
+ "creation": "2013-08-12 12:44:27",
+ "docstatus": 0,
+ "modified": "2013-08-12 12:44:27",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "doctype": "Report",
+ "is_standard": "Yes",
+ "name": "__common__",
+ "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) = `tabProduction Order`.qty",
+ "ref_doctype": "Production Order",
+ "report_name": "Completed Production Orders",
+ "report_type": "Query Report"
+ },
+ {
+ "doctype": "Report",
+ "name": "Completed Production Orders"
+ }
+]
\ No newline at end of file
diff --git a/manufacturing/report/open_production_orders/__init__.py b/manufacturing/report/open_production_orders/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manufacturing/report/open_production_orders/__init__.py
diff --git a/manufacturing/report/open_production_orders/open_production_orders.txt b/manufacturing/report/open_production_orders/open_production_orders.txt
new file mode 100644
index 0000000..f92bdd3
--- /dev/null
+++ b/manufacturing/report/open_production_orders/open_production_orders.txt
@@ -0,0 +1,22 @@
+[
+ {
+ "creation": "2013-08-12 12:32:30",
+ "docstatus": 0,
+ "modified": "2013-08-12 12:42:29",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "doctype": "Report",
+ "is_standard": "Yes",
+ "name": "__common__",
+ "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND NOT EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ",
+ "ref_doctype": "Production Order",
+ "report_name": "Open Production Orders",
+ "report_type": "Query Report"
+ },
+ {
+ "doctype": "Report",
+ "name": "Open Production Orders"
+ }
+]
\ No newline at end of file
diff --git a/manufacturing/report/production_orders_in_progress/__init__.py b/manufacturing/report/production_orders_in_progress/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manufacturing/report/production_orders_in_progress/__init__.py
diff --git a/manufacturing/report/production_orders_in_progress/production_orders_in_progress.txt b/manufacturing/report/production_orders_in_progress/production_orders_in_progress.txt
new file mode 100644
index 0000000..3d3493f
--- /dev/null
+++ b/manufacturing/report/production_orders_in_progress/production_orders_in_progress.txt
@@ -0,0 +1,22 @@
+[
+ {
+ "creation": "2013-08-12 12:43:47",
+ "docstatus": 0,
+ "modified": "2013-08-12 12:43:47",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "doctype": "Report",
+ "is_standard": "Yes",
+ "name": "__common__",
+ "query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ",
+ "ref_doctype": "Production Order",
+ "report_name": "Production Orders in Progress",
+ "report_type": "Query Report"
+ },
+ {
+ "doctype": "Report",
+ "name": "Production Orders in Progress"
+ }
+]
\ No newline at end of file
diff --git a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py
index 96c147f..6fdafe0 100644
--- a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py
+++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py
@@ -8,6 +8,7 @@
import time
from accounts.utils import get_fiscal_year
from controllers.trends import get_period_date_ranges, get_period_month_ranges
+from webnotes.model.meta import get_field_precision
def execute(filters=None):
if not filters: filters = {}
@@ -16,10 +17,7 @@
period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"])
sim_map = get_salesperson_item_month_map(filters)
- precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2
-
data = []
-
for salesperson, salesperson_items in sim_map.items():
for item_group, monthwise_data in salesperson_items.items():
row = [salesperson, item_group]
@@ -29,7 +27,7 @@
for month in relevant_months:
month_data = monthwise_data.get(month, {})
for i, fieldname in enumerate(["target", "achieved", "variance"]):
- value = flt(month_data.get(fieldname), precision)
+ value = flt(month_data.get(fieldname))
period_data[i] += value
totals[i] += value
period_data[2] = period_data[0] - period_data[1]
@@ -47,37 +45,37 @@
msgprint(_("Please specify") + ": " + label,
raise_exception=True)
- columns = ["Sales Person:Link/Sales Person:80", "Item Group:Link/Item Group:80"]
+ columns = ["Sales Person:Link/Sales Person:120", "Item Group:Link/Item Group:120"]
group_months = False if filters["period"] == "Monthly" else True
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]:
if group_months:
- columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")))
+ label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))
else:
- columns.append(label % from_date.strftime("%b"))
+ label = label % from_date.strftime("%b")
+
+ columns.append(label+":Float:120")
- return columns + ["Total Target::80", "Total Achieved::80", "Total Variance::80"]
+ return columns + ["Total Target::120", "Total Achieved::120", "Total Variance::120"]
#Get sales person & item group details
def get_salesperson_details(filters):
return webnotes.conn.sql("""select sp.name, td.item_group, td.target_qty,
td.target_amount, sp.distribution_id
from `tabSales Person` sp, `tabTarget Detail` td
- where td.parent=sp.name and td.fiscal_year=%s and
- ifnull(sp.distribution_id, '')!='' order by sp.name""",
+ where td.parent=sp.name and td.fiscal_year=%s order by sp.name""",
(filters["fiscal_year"]), as_dict=1)
#Get target distribution details of item group
def get_target_distribution_details(filters):
target_details = {}
- for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \
- from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \
- `tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \
- bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
- target_details.setdefault(d.month, d)
+ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
+ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
+ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
+ target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
return target_details
@@ -94,32 +92,33 @@
(start_date, end_date), as_dict=1)
def get_salesperson_item_month_map(filters):
+ import datetime
salesperson_details = get_salesperson_details(filters)
tdd = get_target_distribution_details(filters)
achieved_details = get_achieved_details(filters)
sim_map = {}
-
for sd in salesperson_details:
- for month in tdd:
+ for month_id in range(1, 13):
+ month = datetime.date(2013, month_id, 1).strftime('%B')
sim_map.setdefault(sd.name, {}).setdefault(sd.item_group, {})\
- .setdefault(month, webnotes._dict({
- "target": 0.0, "achieved": 0.0
- }))
+ .setdefault(month, webnotes._dict({
+ "target": 0.0, "achieved": 0.0
+ }))
tav_dict = sim_map[sd.name][sd.item_group][month]
-
+ month_percentage = sd.distribution_id and \
+ tdd.get(sd.distribution_id, {}).get(month, 0) or 100.0/12
+
for ad in achieved_details:
if (filters["target_on"] == "Quantity"):
- tav_dict.target = flt(sd.target_qty) * \
- (tdd[month]["percentage_allocation"]/100)
+ tav_dict.target = flt(flt(sd.target_qty) * month_percentage/100, 2)
if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \
and ad.sales_person == sd.name:
tav_dict.achieved += ad.qty
if (filters["target_on"] == "Amount"):
- tav_dict.target = flt(sd.target_amount) * \
- (tdd[month]["percentage_allocation"]/100)
+ tav_dict.target = flt(flt(sd.target_amount) * month_percentage/100, 2)
if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \
and ad.sales_person == sd.name:
tav_dict.achieved += ad.amount
diff --git a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py
index 4a8cc7c..829f781 100644
--- a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py
+++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py
@@ -46,37 +46,36 @@
label = (" ".join(fieldname.split("_"))).title()
msgprint(_("Please specify") + ": " + label, raise_exception=True)
- columns = ["Territory:Link/Territory:80", "Item Group:Link/Item Group:80"]
+ columns = ["Territory:Link/Territory:120", "Item Group:Link/Item Group:120"]
group_months = False if filters["period"] == "Monthly" else True
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]:
if group_months:
- columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")))
+ label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))
else:
- columns.append(label % from_date.strftime("%b"))
+ label = label % from_date.strftime("%b")
+ columns.append(label+":Float:120")
- return columns + ["Total Target::80", "Total Achieved::80", "Total Variance::80"]
+ return columns + ["Total Target::120", "Total Achieved::120", "Total Variance::120"]
#Get territory & item group details
def get_territory_details(filters):
return webnotes.conn.sql("""select t.name, td.item_group, td.target_qty,
td.target_amount, t.distribution_id
from `tabTerritory` t, `tabTarget Detail` td
- where td.parent=t.name and td.fiscal_year=%s and
- ifnull(t.distribution_id, '')!='' order by t.name""",
+ where td.parent=t.name and td.fiscal_year=%s order by t.name""",
(filters["fiscal_year"]), as_dict=1)
#Get target distribution details of item group
def get_target_distribution_details(filters):
target_details = {}
- for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \
- from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \
- `tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \
- bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
- target_details.setdefault(d.month, d)
+ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
+ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
+ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
+ target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
return target_details
@@ -99,25 +98,27 @@
tim_map = {}
for td in territory_details:
- for month in tdd:
+ for month_id in range(1, 13):
+ month = datetime.date(2013, month_id, 1).strftime('%B')
+
tim_map.setdefault(td.name, {}).setdefault(td.item_group, {})\
- .setdefault(month, webnotes._dict({
- "target": 0.0, "achieved": 0.0
- }))
+ .setdefault(month, webnotes._dict({
+ "target": 0.0, "achieved": 0.0
+ }))
tav_dict = tim_map[td.name][td.item_group][month]
+ month_percentage = td.distribution_id and \
+ tdd.get(td.distribution_id, {}).get(month, 0) or 100.0/12
for ad in achieved_details:
if (filters["target_on"] == "Quantity"):
- tav_dict.target = flt(td.target_qty) * \
- (tdd[month]["percentage_allocation"]/100)
+ tav_dict.target = flt(flt(td.target_qty) * month_percentage /100)
if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \
and ad.territory == td.name:
tav_dict.achieved += ad.qty
if (filters["target_on"] == "Amount"):
- tav_dict.target = flt(td.target_amount) * \
- (tdd[month]["percentage_allocation"]/100)
+ tav_dict.target = flt(flt(td.target_amount) * month_percentage / 100)
if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \
and ad.territory == td.name:
tav_dict.achieved += ad.amount
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index 4fa6c6c..53998f8 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -4,34 +4,7 @@
wn.require("public/app/js/controllers/stock_controller.js");
wn.provide("erpnext.stock");
-erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
- onload: function() {
- this.set_default_account();
- },
-
- set_default_account: function() {
- var me = this;
-
- if (cint(wn.defaults.get_default("auto_inventory_accounting")) && !this.frm.doc.expense_adjustment_account) {
- if (this.frm.doc.purpose == "Sales Return")
- account_for = "stock_in_hand_account";
- else if (this.frm.doc.purpose == "Purchase Return")
- account_for = "stock_received_but_not_billed";
- else account_for = "stock_adjustment_account";
-
- return this.frm.call({
- method: "accounts.utils.get_company_default",
- args: {
- "fieldname": account_for,
- "company": this.frm.doc.company
- },
- callback: function(r) {
- if (!r.exc) me.frm.set_value("expense_adjustment_account", r.message);
- }
- });
- }
- },
-
+erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
setup: function() {
var me = this;
@@ -80,11 +53,7 @@
},
onload_post_render: function() {
- if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no)
- && !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) {
- // if production order / bom is mentioned, get items
- this.get_items();
- }
+ this.set_default_account();
},
refresh: function() {
@@ -115,6 +84,33 @@
after_cancel: function() {
this.clean_up();
},
+
+ set_default_account: function() {
+ var me = this;
+
+ if (cint(wn.defaults.get_default("auto_inventory_accounting")) && !this.frm.doc.expense_adjustment_account) {
+ var account_for = "stock_adjustment_account";
+ if (this.frm.doc.purpose == "Sales Return")
+ account_for = "stock_in_hand_account";
+ else if (this.frm.doc.purpose == "Purchase Return")
+ account_for = "stock_received_but_not_billed";
+
+ return this.frm.call({
+ method: "accounts.utils.get_company_default",
+ args: {
+ "fieldname": account_for,
+ "company": this.frm.doc.company
+ },
+ callback: function(r) {
+ if (!r.exc) me.frm.set_value("expense_adjustment_account", r.message);
+
+ me.get_items();
+ }
+ });
+ } else {
+ me.get_items();
+ }
+ },
clean_up: function() {
// Clear Production Order record from locals, because it is updated via Stock Entry
@@ -126,13 +122,17 @@
},
get_items: function() {
- return this.frm.call({
- doc: this.frm.doc,
- method: "get_items",
- callback: function(r) {
- if(!r.exc) refresh_field("mtn_details");
- }
- });
+ if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no)
+ && !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) {
+ // if production order / bom is mentioned, get items
+ return this.frm.call({
+ doc: this.frm.doc,
+ method: "get_items",
+ callback: function(r) {
+ if(!r.exc) refresh_field("mtn_details");
+ }
+ });
+ }
},
qty: function(doc, cdt, cdn) {
@@ -212,7 +212,6 @@
});
loaddoc("Journal Voucher", jv_name);
}
-
}
});
}
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 66d1dbf..b702316 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -19,6 +19,7 @@
class NotUpdateStockError(webnotes.ValidationError): pass
class StockOverReturnError(webnotes.ValidationError): pass
+class IncorrectValuationRateError(webnotes.ValidationError): pass
from controllers.stock_controller import StockController
@@ -245,7 +246,7 @@
def validate_incoming_rate(self):
for d in getlist(self.doclist, 'mtn_details'):
if d.t_warehouse:
- self.validate_value("incoming_rate", ">", 0, d)
+ self.validate_value("incoming_rate", ">", 0, d, raise_exception=IncorrectValuationRateError)
def validate_bom(self):
for d in getlist(self.doclist, 'mtn_details'):
diff --git a/stock/stock_ledger.py b/stock/stock_ledger.py
index 4dcca67..f0619c7 100644
--- a/stock/stock_ledger.py
+++ b/stock/stock_ledger.py
@@ -8,6 +8,7 @@
import json
# future reposting
+class NegativeStockError(webnotes.ValidationError): pass
_exceptions = []
def update_entries_after(args, verbose=1):
@@ -253,9 +254,9 @@
_exceptions[0]["voucher_type"], _exceptions[0]["voucher_no"],
abs(deficiency))
if verbose:
- msgprint(msg, raise_exception=1)
+ msgprint(msg, raise_exception=NegativeStockError)
else:
- raise webnotes.ValidationError, msg
+ raise NegativeStockError, msg
def get_previous_sle(args, for_update=False):
"""
diff --git a/stock/utils.py b/stock/utils.py
index 96eeef6..848783b 100644
--- a/stock/utils.py
+++ b/stock/utils.py
@@ -69,7 +69,7 @@
if valuation_method == 'FIFO':
if not previous_sle:
return 0.0
- previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]'))
+ previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]') or '[]')
in_rate = previous_stock_queue and \
get_fifo_rate(previous_stock_queue, args.get("qty") or 0) or 0
elif valuation_method == 'Moving Average':
@@ -184,8 +184,8 @@
def reorder_item():
""" Reorder item if stock reaches reorder level"""
if not hasattr(webnotes, "auto_indent"):
- webnotes.auto_indent = webnotes.conn.get_value('Stock Settings', None, 'auto_indent')
-
+ webnotes.auto_indent = cint(webnotes.conn.get_value('Stock Settings', None, 'auto_indent'))
+
if webnotes.auto_indent:
material_requests = {}
bin_list = webnotes.conn.sql("""select item_code, warehouse, projected_qty
@@ -280,8 +280,8 @@
if mr_list:
if not hasattr(webnotes, "reorder_email_notify"):
- webnotes.reorder_email_notify = webnotes.conn.get_value('Stock Settings', None,
- 'reorder_email_notify')
+ webnotes.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None,
+ 'reorder_email_notify'))
if(webnotes.reorder_email_notify):
send_email_notification(mr_list)
@@ -307,7 +307,6 @@
msg += "<tr><td>" + item.item_code + "</td><td>" + item.warehouse + "</td><td>" + \
cstr(item.qty) + "</td><td>" + cstr(item.uom) + "</td></tr>"
msg += "</table>"
-
sendmail(email_list, subject='Auto Material Request Generation Notification', msg = msg)
def notify_errors(exceptions_list):
diff --git a/utilities/make_demo.py b/utilities/make_demo.py
index 124259f..a522862 100644
--- a/utilities/make_demo.py
+++ b/utilities/make_demo.py
@@ -19,15 +19,18 @@
prob = {
"Quotation": { "make": 0.5, "qty": (1,5) },
"Sales Order": { "make": 0.5, "qty": (1,4) },
+ "Purchase Order": { "make": 0.7, "qty": (1,4) },
+ "Purchase Receipt": { "make": 0.7, "qty": (1,4) },
"Supplier Quotation": { "make": 0.5, "qty": (1, 3) }
}
-def make():
+def make(reset=False):
webnotes.connect()
webnotes.print_messages = True
webnotes.mute_emails = True
- #setup()
+ if reset:
+ setup()
simulate()
def setup():
@@ -68,13 +71,29 @@
make_sales_order(current_date)
def run_stock(current_date):
- pass
# make purchase requests
+ if can_make("Purchase Receipt"):
+ from buying.doctype.purchase_order.purchase_order import make_purchase_receipt
+ report = "Purchase Order Items To Be Received"
+ for po in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Purchase Receipt")]:
+ pr = webnotes.bean(make_purchase_receipt(po))
+ pr.doc.posting_date = current_date
+ pr.doc.fiscal_year = "2010"
+ pr.insert()
+ pr.submit()
# make delivery notes (if possible)
+ if can_make("Delivery Note"):
+ from 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"]))[:how_many("Delivery Note")]:
+ dn = webnotes.bean(make_delivery_note(so))
+ dn.doc.posting_date = current_date
+ dn.doc.fiscal_year = "2010"
+ dn.insert()
+ dn.submit()
- # make stock entry (from production order)
-
+
def run_purchase(current_date):
# make supplier quotations
if can_make("Supplier Quotation"):
@@ -121,6 +140,40 @@
b = webnotes.bean("Material Request", pro[0])
b.submit()
+ # stores -> wip
+ if can_make("Stock Entry for WIP"):
+ 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", current_date)
+
+ # wip -> fg
+ if can_make("Stock Entry for FG"):
+ 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/Repack", current_date)
+
+ # try posting older drafts (if exists)
+ for st in webnotes.conn.get_values("Stock Entry", {"docstatus":0}):
+ try:
+ webnotes.bean("Stock Entry", st[0]).submit()
+ except NegativeStockError: pass
+ except IncorrectValuationRateError: pass
+
+
+def make_stock_entry_from_pro(pro_id, purpose, current_date):
+ from manufacturing.doctype.production_order.production_order import make_stock_entry
+ from stock.stock_ledger import NegativeStockError
+ from stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError
+
+ st = webnotes.bean(make_stock_entry(pro_id, purpose))
+ st.run_method("get_items")
+ st.doc.posting_date = current_date
+ st.doc.fiscal_year = "2010"
+ st.doc.expense_adjustment_account = "Stock in Hand - WP"
+ try:
+ st.insert()
+ st.submit()
+ except NegativeStockError: pass
+ except IncorrectValuationRateError: pass
+
def make_quotation(current_date):
b = webnotes.bean([{
"creation": current_date,