Merge branch 'master' of github.com:webnotes/erpnext

This commit is contained in:
Anand Doshi 2013-08-12 17:33:23 +05:30
commit 3eb8c38efb
18 changed files with 290 additions and 137 deletions

View File

@ -47,18 +47,20 @@ def get_columns(filters):
msgprint(_("Please specify") + ": " + label, msgprint(_("Please specify") + ": " + label,
raise_exception=True) 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 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 from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]: for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]:
if group_months: 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: else:
columns.append(label % from_date.strftime("%b")) label = label % from_date.strftime("%b")
return columns + ["Total Target::80", "Total Actual::80", "Total Variance::80"] columns.append(label+":Float:120")
return columns + ["Total Target::120", "Total Actual::120", "Total Variance::120"]
#Get cost center & target details #Get cost center & target details
def get_costcenter_target_details(filters): def get_costcenter_target_details(filters):
@ -66,19 +68,17 @@ def get_costcenter_target_details(filters):
cc.parent_cost_center, bd.account, bd.budget_allocated cc.parent_cost_center, bd.account, bd.budget_allocated
from `tabCost Center` cc, `tabBudget Detail` bd from `tabCost Center` cc, `tabBudget Detail` bd
where bd.parent=cc.name and bd.fiscal_year=%s and where bd.parent=cc.name and bd.fiscal_year=%s and
cc.company=%s and ifnull(cc.distribution_id, '')!='' cc.company=%s order by cc.name""" % ('%s', '%s'),
order by cc.name""" % ('%s', '%s'),
(filters.get("fiscal_year"), filters.get("company")), as_dict=1) (filters.get("fiscal_year"), filters.get("company")), as_dict=1)
#Get target distribution details of accounts of cost center #Get target distribution details of accounts of cost center
def get_target_distribution_details(filters): def get_target_distribution_details(filters):
target_details = {} target_details = {}
for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation \
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
`tabCost Center` cc where bdd.parent=bd.name and cc.distribution_id=bd.name and \ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
target_details.setdefault(d.month, d)
return target_details return target_details
@ -99,15 +99,19 @@ def get_costcenter_account_month_map(filters):
cam_map = {} cam_map = {}
for ccd in costcenter_target_details: 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, {})\ cam_map.setdefault(ccd.name, {}).setdefault(ccd.account, {})\
.setdefault(month, webnotes._dict({ .setdefault(month, webnotes._dict({
"target": 0.0, "actual": 0.0 "target": 0.0, "actual": 0.0
})) }))
tav_dict = cam_map[ccd.name][ccd.account][month] tav_dict = cam_map[ccd.name][ccd.account][month]
tav_dict.target = flt(ccd.budget_allocated) * \ month_percentage = ccd.distribution_id and \
(tdd[month]["percentage_allocation"]/100) 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: for ad in actual_details:
if ad.month_name == month and ad.account == ccd.account \ if ad.month_name == month and ad.account == ccd.account \

View File

@ -115,7 +115,8 @@ class DocType(DocListController):
self.doc.leave_balance = get_leave_balance(self.doc.employee, self.doc.leave_balance = get_leave_balance(self.doc.employee,
self.doc.leave_type, self.doc.fiscal_year)["leave_balance"] 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. #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" % \ msgprint("There is not enough leave balance for Leave Type: %s" % \
(self.doc.leave_type,), (self.doc.leave_type,),

View File

@ -61,30 +61,25 @@ cur_frm.cscript['Unstop Production Order'] = function() {
} }
cur_frm.cscript['Transfer Raw Materials'] = function() { cur_frm.cscript['Transfer Raw Materials'] = function() {
var doc = cur_frm.doc; cur_frm.cscript.make_se('Material Transfer');
cur_frm.cscript.make_se(doc, 'Material Transfer');
} }
cur_frm.cscript['Update Finished Goods'] = function() { cur_frm.cscript['Update Finished Goods'] = function() {
var doc = cur_frm.doc; cur_frm.cscript.make_se('Manufacture/Repack');
cur_frm.cscript.make_se(doc, 'Manufacture/Repack');
} }
cur_frm.cscript.make_se = function(doc, purpose) { cur_frm.cscript.make_se = function(purpose) {
var se = wn.model.get_new_doc("Stock Entry"); wn.call({
se.purpose = purpose; method:"manufacturing.doctype.production_order.production_order.make_stock_entry",
se.production_order = doc.name; args: {
if(purpose==="Material Transfer") { "production_order_id": cur_frm.doc.name,
se.to_warehouse = doc.wip_warehouse; "purpose": purpose
} else { },
se.from_warehouse = doc.wip_warehouse; callback: function(r) {
se.to_warehouse = doc.fg_warehouse; var doclist = wn.model.sync(r.message);
wn.set_route("Form", doclist[0].doctype, doclist[0].name);
} }
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.fields_dict['production_item'].get_query = function(doc) { cur_frm.fields_dict['production_item'].get_query = function(doc) {

View File

@ -138,3 +138,22 @@ def get_item_details(item):
res.bom_no = bom[0][0] res.bom_no = bom[0][0]
return res 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]

View File

@ -64,11 +64,26 @@ wn.module_page["Manufacturing"] = [
right: true, right: true,
icon: "icon-list", icon: "icon-list",
items: [ 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"), "label":wn._("Issued Items Against Production Order"),
route: "query-report/Issued Items Against Production Order", route: "query-report/Issued Items Against Production Order",
doctype:"Production Order" doctype:"Production Order"
}, },
{
"label":wn._("Completed Production Orders"),
route: "query-report/Completed Production Orders",
doctype:"Production Order"
},
] ]
} }
] ]

View File

@ -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"
}
]

View File

@ -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"
}
]

View File

@ -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"
}
]

View File

@ -8,6 +8,7 @@ from webnotes.utils import flt
import time import time
from accounts.utils import get_fiscal_year from accounts.utils import get_fiscal_year
from controllers.trends import get_period_date_ranges, get_period_month_ranges from controllers.trends import get_period_date_ranges, get_period_month_ranges
from webnotes.model.meta import get_field_precision
def execute(filters=None): def execute(filters=None):
if not filters: filters = {} if not filters: filters = {}
@ -16,10 +17,7 @@ def execute(filters=None):
period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"])
sim_map = get_salesperson_item_month_map(filters) sim_map = get_salesperson_item_month_map(filters)
precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2
data = [] data = []
for salesperson, salesperson_items in sim_map.items(): for salesperson, salesperson_items in sim_map.items():
for item_group, monthwise_data in salesperson_items.items(): for item_group, monthwise_data in salesperson_items.items():
row = [salesperson, item_group] row = [salesperson, item_group]
@ -29,7 +27,7 @@ def execute(filters=None):
for month in relevant_months: for month in relevant_months:
month_data = monthwise_data.get(month, {}) month_data = monthwise_data.get(month, {})
for i, fieldname in enumerate(["target", "achieved", "variance"]): 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 period_data[i] += value
totals[i] += value totals[i] += value
period_data[2] = period_data[0] - period_data[1] period_data[2] = period_data[0] - period_data[1]
@ -47,37 +45,37 @@ def get_columns(filters):
msgprint(_("Please specify") + ": " + label, msgprint(_("Please specify") + ": " + label,
raise_exception=True) 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 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 from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]: for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]:
if group_months: 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: else:
columns.append(label % from_date.strftime("%b")) label = label % from_date.strftime("%b")
return columns + ["Total Target::80", "Total Achieved::80", "Total Variance::80"] columns.append(label+":Float:120")
return columns + ["Total Target::120", "Total Achieved::120", "Total Variance::120"]
#Get sales person & item group details #Get sales person & item group details
def get_salesperson_details(filters): def get_salesperson_details(filters):
return webnotes.conn.sql("""select sp.name, td.item_group, td.target_qty, return webnotes.conn.sql("""select sp.name, td.item_group, td.target_qty,
td.target_amount, sp.distribution_id td.target_amount, sp.distribution_id
from `tabSales Person` sp, `tabTarget Detail` td from `tabSales Person` sp, `tabTarget Detail` td
where td.parent=sp.name and td.fiscal_year=%s and where td.parent=sp.name and td.fiscal_year=%s order by sp.name""",
ifnull(sp.distribution_id, '')!='' order by sp.name""",
(filters["fiscal_year"]), as_dict=1) (filters["fiscal_year"]), as_dict=1)
#Get target distribution details of item group #Get target distribution details of item group
def get_target_distribution_details(filters): def get_target_distribution_details(filters):
target_details = {} target_details = {}
for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
`tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
target_details.setdefault(d.month, d)
return target_details return target_details
@ -94,32 +92,33 @@ def get_achieved_details(filters):
(start_date, end_date), as_dict=1) (start_date, end_date), as_dict=1)
def get_salesperson_item_month_map(filters): def get_salesperson_item_month_map(filters):
import datetime
salesperson_details = get_salesperson_details(filters) salesperson_details = get_salesperson_details(filters)
tdd = get_target_distribution_details(filters) tdd = get_target_distribution_details(filters)
achieved_details = get_achieved_details(filters) achieved_details = get_achieved_details(filters)
sim_map = {} sim_map = {}
for sd in salesperson_details: 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, {})\ sim_map.setdefault(sd.name, {}).setdefault(sd.item_group, {})\
.setdefault(month, webnotes._dict({ .setdefault(month, webnotes._dict({
"target": 0.0, "achieved": 0.0 "target": 0.0, "achieved": 0.0
})) }))
tav_dict = sim_map[sd.name][sd.item_group][month] 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: for ad in achieved_details:
if (filters["target_on"] == "Quantity"): if (filters["target_on"] == "Quantity"):
tav_dict.target = flt(sd.target_qty) * \ tav_dict.target = flt(flt(sd.target_qty) * month_percentage/100, 2)
(tdd[month]["percentage_allocation"]/100)
if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \
and ad.sales_person == sd.name: and ad.sales_person == sd.name:
tav_dict.achieved += ad.qty tav_dict.achieved += ad.qty
if (filters["target_on"] == "Amount"): if (filters["target_on"] == "Amount"):
tav_dict.target = flt(sd.target_amount) * \ tav_dict.target = flt(flt(sd.target_amount) * month_percentage/100, 2)
(tdd[month]["percentage_allocation"]/100)
if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \
and ad.sales_person == sd.name: and ad.sales_person == sd.name:
tav_dict.achieved += ad.amount tav_dict.achieved += ad.amount

View File

@ -46,37 +46,36 @@ def get_columns(filters):
label = (" ".join(fieldname.split("_"))).title() label = (" ".join(fieldname.split("_"))).title()
msgprint(_("Please specify") + ": " + label, raise_exception=True) 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 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 from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]: for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]:
if group_months: 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: 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 #Get territory & item group details
def get_territory_details(filters): def get_territory_details(filters):
return webnotes.conn.sql("""select t.name, td.item_group, td.target_qty, return webnotes.conn.sql("""select t.name, td.item_group, td.target_qty,
td.target_amount, t.distribution_id td.target_amount, t.distribution_id
from `tabTerritory` t, `tabTarget Detail` td from `tabTerritory` t, `tabTarget Detail` td
where td.parent=t.name and td.fiscal_year=%s and where td.parent=t.name and td.fiscal_year=%s order by t.name""",
ifnull(t.distribution_id, '')!='' order by t.name""",
(filters["fiscal_year"]), as_dict=1) (filters["fiscal_year"]), as_dict=1)
#Get target distribution details of item group #Get target distribution details of item group
def get_target_distribution_details(filters): def get_target_distribution_details(filters):
target_details = {} target_details = {}
for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
`tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \ where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
target_details.setdefault(d.month, d)
return target_details return target_details
@ -99,25 +98,27 @@ def get_territory_item_month_map(filters):
tim_map = {} tim_map = {}
for td in territory_details: 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, {})\ tim_map.setdefault(td.name, {}).setdefault(td.item_group, {})\
.setdefault(month, webnotes._dict({ .setdefault(month, webnotes._dict({
"target": 0.0, "achieved": 0.0 "target": 0.0, "achieved": 0.0
})) }))
tav_dict = tim_map[td.name][td.item_group][month] 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: for ad in achieved_details:
if (filters["target_on"] == "Quantity"): if (filters["target_on"] == "Quantity"):
tav_dict.target = flt(td.target_qty) * \ tav_dict.target = flt(flt(td.target_qty) * month_percentage /100)
(tdd[month]["percentage_allocation"]/100)
if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \
and ad.territory == td.name: and ad.territory == td.name:
tav_dict.achieved += ad.qty tav_dict.achieved += ad.qty
if (filters["target_on"] == "Amount"): if (filters["target_on"] == "Amount"):
tav_dict.target = flt(td.target_amount) * \ tav_dict.target = flt(flt(td.target_amount) * month_percentage / 100)
(tdd[month]["percentage_allocation"]/100)
if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \
and ad.territory == td.name: and ad.territory == td.name:
tav_dict.achieved += ad.amount tav_dict.achieved += ad.amount

View File

@ -5,33 +5,6 @@ wn.require("public/app/js/controllers/stock_controller.js");
wn.provide("erpnext.stock"); wn.provide("erpnext.stock");
erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ 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);
}
});
}
},
setup: function() { setup: function() {
var me = this; var me = this;
@ -80,11 +53,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}, },
onload_post_render: function() { onload_post_render: function() {
if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no) this.set_default_account();
&& !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) {
// if production order / bom is mentioned, get items
this.get_items();
}
}, },
refresh: function() { refresh: function() {
@ -116,6 +85,33 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
this.clean_up(); 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() { clean_up: function() {
// Clear Production Order record from locals, because it is updated via Stock Entry // Clear Production Order record from locals, because it is updated via Stock Entry
if(this.frm.doc.production_order && if(this.frm.doc.production_order &&
@ -126,6 +122,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}, },
get_items: function() { get_items: 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
return this.frm.call({ return this.frm.call({
doc: this.frm.doc, doc: this.frm.doc,
method: "get_items", method: "get_items",
@ -133,6 +132,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
if(!r.exc) refresh_field("mtn_details"); if(!r.exc) refresh_field("mtn_details");
} }
}); });
}
}, },
qty: function(doc, cdt, cdn) { qty: function(doc, cdt, cdn) {
@ -212,7 +212,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}); });
loaddoc("Journal Voucher", jv_name); loaddoc("Journal Voucher", jv_name);
} }
} }
}); });
} }

View File

@ -19,6 +19,7 @@ sql = webnotes.conn.sql
class NotUpdateStockError(webnotes.ValidationError): pass class NotUpdateStockError(webnotes.ValidationError): pass
class StockOverReturnError(webnotes.ValidationError): pass class StockOverReturnError(webnotes.ValidationError): pass
class IncorrectValuationRateError(webnotes.ValidationError): pass
from controllers.stock_controller import StockController from controllers.stock_controller import StockController
@ -245,7 +246,7 @@ class DocType(StockController):
def validate_incoming_rate(self): def validate_incoming_rate(self):
for d in getlist(self.doclist, 'mtn_details'): for d in getlist(self.doclist, 'mtn_details'):
if d.t_warehouse: 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): def validate_bom(self):
for d in getlist(self.doclist, 'mtn_details'): for d in getlist(self.doclist, 'mtn_details'):

View File

@ -8,6 +8,7 @@ from stock.utils import get_valuation_method
import json import json
# future reposting # future reposting
class NegativeStockError(webnotes.ValidationError): pass
_exceptions = [] _exceptions = []
def update_entries_after(args, verbose=1): def update_entries_after(args, verbose=1):
@ -253,9 +254,9 @@ def _raise_exceptions(args, verbose=1):
_exceptions[0]["voucher_type"], _exceptions[0]["voucher_no"], _exceptions[0]["voucher_type"], _exceptions[0]["voucher_no"],
abs(deficiency)) abs(deficiency))
if verbose: if verbose:
msgprint(msg, raise_exception=1) msgprint(msg, raise_exception=NegativeStockError)
else: else:
raise webnotes.ValidationError, msg raise NegativeStockError, msg
def get_previous_sle(args, for_update=False): def get_previous_sle(args, for_update=False):
""" """

View File

@ -69,7 +69,7 @@ def get_incoming_rate(args):
if valuation_method == 'FIFO': if valuation_method == 'FIFO':
if not previous_sle: if not previous_sle:
return 0.0 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 \ in_rate = previous_stock_queue and \
get_fifo_rate(previous_stock_queue, args.get("qty") or 0) or 0 get_fifo_rate(previous_stock_queue, args.get("qty") or 0) or 0
elif valuation_method == 'Moving Average': elif valuation_method == 'Moving Average':
@ -184,7 +184,7 @@ def _get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries)
def reorder_item(): def reorder_item():
""" Reorder item if stock reaches reorder level""" """ Reorder item if stock reaches reorder level"""
if not hasattr(webnotes, "auto_indent"): 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: if webnotes.auto_indent:
material_requests = {} material_requests = {}
@ -280,8 +280,8 @@ def create_material_request(material_requests):
if mr_list: if mr_list:
if not hasattr(webnotes, "reorder_email_notify"): if not hasattr(webnotes, "reorder_email_notify"):
webnotes.reorder_email_notify = webnotes.conn.get_value('Stock Settings', None, webnotes.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None,
'reorder_email_notify') 'reorder_email_notify'))
if(webnotes.reorder_email_notify): if(webnotes.reorder_email_notify):
send_email_notification(mr_list) send_email_notification(mr_list)
@ -307,7 +307,6 @@ def send_email_notification(mr_list):
msg += "<tr><td>" + item.item_code + "</td><td>" + item.warehouse + "</td><td>" + \ msg += "<tr><td>" + item.item_code + "</td><td>" + item.warehouse + "</td><td>" + \
cstr(item.qty) + "</td><td>" + cstr(item.uom) + "</td></tr>" cstr(item.qty) + "</td><td>" + cstr(item.uom) + "</td></tr>"
msg += "</table>" msg += "</table>"
sendmail(email_list, subject='Auto Material Request Generation Notification', msg = msg) sendmail(email_list, subject='Auto Material Request Generation Notification', msg = msg)
def notify_errors(exceptions_list): def notify_errors(exceptions_list):

View File

@ -19,15 +19,18 @@ runs_for = 20
prob = { prob = {
"Quotation": { "make": 0.5, "qty": (1,5) }, "Quotation": { "make": 0.5, "qty": (1,5) },
"Sales Order": { "make": 0.5, "qty": (1,4) }, "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) } "Supplier Quotation": { "make": 0.5, "qty": (1, 3) }
} }
def make(): def make(reset=False):
webnotes.connect() webnotes.connect()
webnotes.print_messages = True webnotes.print_messages = True
webnotes.mute_emails = True webnotes.mute_emails = True
#setup() if reset:
setup()
simulate() simulate()
def setup(): def setup():
@ -68,12 +71,28 @@ def run_sales(current_date):
make_sales_order(current_date) make_sales_order(current_date)
def run_stock(current_date): def run_stock(current_date):
pass
# make purchase requests # 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) # 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): def run_purchase(current_date):
# make supplier quotations # make supplier quotations
@ -121,6 +140,40 @@ def run_manufacturing(current_date):
b = webnotes.bean("Material Request", pro[0]) b = webnotes.bean("Material Request", pro[0])
b.submit() 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): def make_quotation(current_date):
b = webnotes.bean([{ b = webnotes.bean([{
"creation": current_date, "creation": current_date,