Merge branch 'master' of github.com:webnotes/erpnext
This commit is contained in:
commit
3eb8c38efb
@ -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 \
|
||||||
|
@ -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,),
|
||||||
|
@ -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) {
|
||||||
|
@ -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]
|
||||||
|
@ -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"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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'):
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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):
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user