Merge branch 'master' of github.com:webnotes/erpnext
This commit is contained in:
commit
80721518e3
@ -18,11 +18,7 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import flt, getdate
|
||||
from webnotes.model.doc import make_autoname
|
||||
from webnotes.model.wrapper import getlist, copy_doclist
|
||||
from webnotes import msgprint
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
from webnotes.model.wrapper import getlist
|
||||
|
||||
class DocType:
|
||||
def __init__(self,d,dl):
|
||||
@ -31,53 +27,57 @@ class DocType:
|
||||
def autoname(self):
|
||||
self.doc.name = make_autoname(self.doc.naming_series + '.#####')
|
||||
|
||||
def validate(self):
|
||||
"""Validate invoice that c-form is applicable
|
||||
and no other c-form is received for that"""
|
||||
|
||||
for d in getlist(self.doclist, 'invoice_details'):
|
||||
inv = webnotes.conn.sql("""select c_form_applicable, c_form_no from
|
||||
`tabSales Invoice` where name = %s""", d.invoice_no)
|
||||
|
||||
if not inv:
|
||||
webnotes.msgprint("Invoice: %s is not exists in the system, please check." %
|
||||
d.invoice_no, raise_exception=1)
|
||||
|
||||
elif inv[0][0] != 'Yes':
|
||||
webnotes.msgprint("C-form is not applicable for Invoice: %s" %
|
||||
d.invoice_no, raise_exception=1)
|
||||
|
||||
elif inv[0][1] and inv[0][1] != self.doc.name:
|
||||
webnotes.msgprint("""Invoice %s is tagged in another C-form: %s.
|
||||
If you want to change C-form no for this invoice,
|
||||
please remove invoice no from the previous c-form and then try again""" %
|
||||
(d.invoice_no, inv[0][1]), raise_exception=1)
|
||||
|
||||
def on_update(self):
|
||||
""" Update C-Form No on invoices"""
|
||||
|
||||
if len(getlist(self.doclist, 'invoice_details')):
|
||||
inv = "'" + "', '".join([d.invoice_no for d in getlist(self.doclist, 'invoice_details')]) + "'"
|
||||
sql("""update `tabSales Invoice` set c_form_no = '%s', modified ='%s'
|
||||
where name in (%s)"""%(self.doc.name, self.doc.modified, inv))
|
||||
sql("""update `tabSales Invoice` set c_form_no = '', modified = %s where name not
|
||||
in (%s) and ifnull(c_form_no, '') = %s""", (self.doc.modified, self.doc.name, inv))
|
||||
inv = [d.invoice_no for d in getlist(self.doclist, 'invoice_details')]
|
||||
if inv:
|
||||
webnotes.conn.sql("""update `tabSales Invoice` set c_form_no=%s, modified=%s
|
||||
where name in (%s)""" % ('%s', '%s', ', '.join(['%s'] * len(inv))),
|
||||
tuple([self.doc.name, self.doc.modified] + inv))
|
||||
|
||||
webnotes.conn.sql("""update `tabSales Invoice` set c_form_no = '', modified = %s
|
||||
where name not in (%s) and ifnull(c_form_no, '') = %s""" %
|
||||
('%s', ', '.join(['%s']*len(inv)), '%s'),
|
||||
tuple([self.doc.modified] + inv + [self.doc.name]))
|
||||
else:
|
||||
msgprint("Please enter atleast 1 invoice in the table below", raise_exception=1)
|
||||
webnotes.msgprint("Please enter atleast 1 invoice in the table", raise_exception=1)
|
||||
|
||||
self.calculate_total_invoiced_amount()
|
||||
self.set_total_invoiced_amount()
|
||||
|
||||
def calculate_total_invoiced_amount(self):
|
||||
total = 0
|
||||
for d in getlist(self.doclist, 'invoice_details'):
|
||||
total += flt(d.grand_total)
|
||||
def set_total_invoiced_amount(self):
|
||||
total = sum([flt(d.total) for d in getlist(self.doclist, 'invoice_details')])
|
||||
webnotes.conn.set(self.doc, 'total_invoiced_amount', total)
|
||||
|
||||
|
||||
def get_invoice_details(self, invoice_no):
|
||||
""" Pull details from invoices for referrence """
|
||||
|
||||
inv = sql("""select posting_date, territory, net_total, grand_total from
|
||||
`tabSales Invoice` where name = %s""", invoice_no)
|
||||
ret = {
|
||||
inv = webnotes.conn.sql("""select posting_date, territory, net_total, grand_total
|
||||
from `tabSales Invoice` where name = %s""", invoice_no)
|
||||
return {
|
||||
'invoice_date' : inv and getdate(inv[0][0]).strftime('%Y-%m-%d') or '',
|
||||
'territory' : inv and inv[0][1] or '',
|
||||
'net_total' : inv and flt(inv[0][2]) or '',
|
||||
'grand_total' : inv and flt(inv[0][3]) or ''
|
||||
}
|
||||
return ret
|
||||
|
||||
|
||||
def validate_invoice(self):
|
||||
"""Validate invoice that c-form is applicable and no other c-form is
|
||||
received for that"""
|
||||
|
||||
for d in getlist(self.doclist, 'invoice_details'):
|
||||
inv = sql("""select c_form_applicable, c_form_no from
|
||||
`tabSales Invoice` where name = %s""", invoice_no)
|
||||
if not inv:
|
||||
msgprint("Invoice: %s is not exists in the system, please check." % d.invoice_no, raise_exception=1)
|
||||
elif inv[0][0] != 'Yes':
|
||||
msgprint("C-form is not applicable for Invoice: %s" % d.invoice_no, raise_exception=1)
|
||||
elif inv[0][1] and inv[0][1] != self.doc.name:
|
||||
msgprint("""Invoice %s is tagged in another C-form: %s. \nIf you want to change C-form no for this invoice,
|
||||
please remove invoice no from the previous c-form and then try again""" % (d.invoice_no, inv[0][1]), raise_exception=1)
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
{
|
||||
"owner": "Administrator",
|
||||
"docstatus": 0,
|
||||
"creation": "2012-12-20 18:14:55",
|
||||
"creation": "2013-01-16 14:48:56",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2012-12-24 19:37:34"
|
||||
"modified": "2013-01-17 11:21:46"
|
||||
},
|
||||
{
|
||||
"istable": 1,
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import cstr, flt, nowdate, get_defaults
|
||||
from webnotes.utils import cstr, flt, cint, nowdate, add_days
|
||||
from webnotes.model.doc import addchild, Document
|
||||
from webnotes.model.wrapper import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
@ -210,7 +210,7 @@ class DocType:
|
||||
"wip_warehouse" : "",
|
||||
"fg_warehouse" : "",
|
||||
"status" : "Draft",
|
||||
"fiscal_year" : get_defaults()["fiscal_year"]
|
||||
"fiscal_year" : webnotes.conn.get_default("fiscal_year")
|
||||
}
|
||||
return bom_dict, item_dict
|
||||
|
||||
@ -239,18 +239,22 @@ class DocType:
|
||||
return self.get_csv()
|
||||
|
||||
def get_raw_materials(self, bom_dict):
|
||||
""" Get raw materials considering sub-assembly items """
|
||||
""" Get raw materials considering sub-assembly items
|
||||
{
|
||||
"item_code": [qty_required, description, stock_uom]
|
||||
}
|
||||
"""
|
||||
for bom in bom_dict:
|
||||
if self.doc.use_multi_level_bom:
|
||||
# get all raw materials with sub assembly childs
|
||||
fl_bom_items = sql("""
|
||||
select
|
||||
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,
|
||||
description, stock_uom
|
||||
description, stock_uom, min_order_qty
|
||||
from
|
||||
(
|
||||
select distinct fb.name, fb.description, fb.item_code,
|
||||
fb.qty_consumed_per_unit, fb.stock_uom
|
||||
fb.qty_consumed_per_unit, fb.stock_uom, it.min_order_qty
|
||||
from `tabBOM Explosion Item` fb,`tabItem` it
|
||||
where it.name = fb.item_code
|
||||
and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||
@ -263,18 +267,20 @@ class DocType:
|
||||
# Get all raw materials considering SA items as raw materials,
|
||||
# so no childs of SA items
|
||||
fl_bom_items = sql("""
|
||||
select item_code, ifnull(sum(qty_consumed_per_unit), 0) * '%s',
|
||||
description, stock_uom
|
||||
from `tabBOM Item`
|
||||
where parent = '%s' and docstatus < 2
|
||||
select bom_item.item_code,
|
||||
ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s,
|
||||
bom_item.description, bom_item.stock_uom, item.min_order_qty
|
||||
from `tabBOM Item` bom_item, tabItem item
|
||||
where bom_item.parent = %s and bom_item.docstatus < 2
|
||||
and bom_item.item_code = item.name
|
||||
group by item_code
|
||||
""" % (flt(bom_dict[bom]), bom))
|
||||
|
||||
""", (flt(bom_dict[bom]), bom))
|
||||
self.make_items_dict(fl_bom_items)
|
||||
|
||||
def make_items_dict(self, item_list):
|
||||
for i in item_list:
|
||||
self.item_dict[i[0]] = [(flt(self.item_dict.get(i[0], [0])[0]) + flt(i[1])), i[2], i[3]]
|
||||
self.item_dict[i[0]] = [(flt(self.item_dict.get(i[0], [0])[0]) + flt(i[1])),
|
||||
i[2], i[3], i[4]]
|
||||
|
||||
|
||||
def get_csv(self):
|
||||
@ -291,4 +297,85 @@ class DocType:
|
||||
if item_qty:
|
||||
item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty])
|
||||
|
||||
return item_list
|
||||
return item_list
|
||||
|
||||
def raise_purchase_request(self):
|
||||
"""
|
||||
Raise Purchase Request if projected qty is less than qty required
|
||||
Requested qty should be shortage qty considering minimum order qty
|
||||
"""
|
||||
if not self.doc.purchase_request_for_warehouse:
|
||||
webnotes.msgprint("Please enter Warehouse for which Purchase Request will be raised",
|
||||
raise_exception=1)
|
||||
|
||||
bom_dict = self.get_distinct_items_and_boms()[0]
|
||||
self.get_raw_materials(bom_dict)
|
||||
item_projected_qty = self.get_projected_qty()
|
||||
|
||||
from accounts.utils import get_fiscal_year
|
||||
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||
|
||||
items_to_be_requested = webnotes._dict()
|
||||
for item in self.item_dict:
|
||||
if flt(self.item_dict[item][0]) > item_projected_qty[item]:
|
||||
# shortage
|
||||
requested_qty = flt(self.item_dict[item][0]) - item_projected_qty[item]
|
||||
# comsider minimum order qty
|
||||
requested_qty = requested_qty > flt(self.item_dict[item][3]) and \
|
||||
requested_qty or flt(self.item_dict[item][3])
|
||||
items_to_be_requested[item] = requested_qty
|
||||
|
||||
self.insert_purchase_request(items_to_be_requested, fiscal_year)
|
||||
|
||||
def get_projected_qty(self):
|
||||
items = self.item_dict.keys()
|
||||
item_projected_qty = webnotes.conn.sql("""select item_code, sum(projected_qty)
|
||||
from `tabBin` where item_code in (%s) group by item_code""" %
|
||||
(", ".join(["%s"]*len(items)),), tuple(items))
|
||||
|
||||
return dict(item_projected_qty)
|
||||
|
||||
def insert_purchase_request(self, items_to_be_requested, fiscal_year):
|
||||
purchase_request_list = []
|
||||
if items_to_be_requested:
|
||||
for item in items_to_be_requested:
|
||||
item_wrapper = webnotes.model_wrapper("Item", item)
|
||||
pr_doclist = [
|
||||
{
|
||||
"doctype": "Purchase Request",
|
||||
"__islocal": 1,
|
||||
"naming_series": "IDT",
|
||||
"transaction_date": nowdate(),
|
||||
"status": "Draft",
|
||||
"company": self.doc.company,
|
||||
"fiscal_year": fiscal_year,
|
||||
"requested_by": webnotes.session.user,
|
||||
"remark": "Automatically raised from Production Planning Tool"
|
||||
},
|
||||
{
|
||||
"doctype": "Purchase Request Item",
|
||||
"__islocal": 1,
|
||||
"parentfield": "indent_details",
|
||||
"item_code": item,
|
||||
"item_name": item_wrapper.doc.item_name,
|
||||
"description": item_wrapper.doc.description,
|
||||
"uom": item_wrapper.doc.stock_uom,
|
||||
"item_group": item_wrapper.doc.item_group,
|
||||
"brand": item_wrapper.doc.brand,
|
||||
"qty": items_to_be_requested[item],
|
||||
"schedule_date": add_days(nowdate(), cint(item_wrapper.doc.lead_time_days)),
|
||||
"warehouse": self.doc.purchase_request_for_warehouse
|
||||
}
|
||||
]
|
||||
pr_wrapper = webnotes.model_wrapper(pr_doclist)
|
||||
pr_wrapper.ignore_permissions = 1
|
||||
pr_wrapper.submit()
|
||||
purchase_request_list.append(pr_wrapper.doc.name)
|
||||
|
||||
if purchase_request_list:
|
||||
pur_req = ["""<a href="#Form/Purchase Request/%s" target="_blank">%s</a>""" % \
|
||||
(p, p) for p in purchase_request_list]
|
||||
webnotes.msgprint("Following Purchase Request created successfully: \n%s" %
|
||||
"\n".join(pur_req))
|
||||
else:
|
||||
webnotes.msgprint("Nothing to request")
|
@ -2,9 +2,9 @@
|
||||
{
|
||||
"owner": "jai@webnotestech.com",
|
||||
"docstatus": 0,
|
||||
"creation": "2012-12-14 10:15:16",
|
||||
"creation": "2013-01-16 14:48:56",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2012-12-14 11:37:40"
|
||||
"modified": "2013-01-17 11:39:55"
|
||||
},
|
||||
{
|
||||
"read_only": 1,
|
||||
@ -28,8 +28,10 @@
|
||||
"parent": "Production Planning Tool",
|
||||
"read": 1,
|
||||
"create": 1,
|
||||
"submit": 0,
|
||||
"doctype": "DocPerm",
|
||||
"write": 1,
|
||||
"report": 0,
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"parentfield": "permissions"
|
||||
@ -68,9 +70,9 @@
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"label": "Company",
|
||||
"reqd": 1,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"reqd": 1,
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
@ -154,10 +156,19 @@
|
||||
"fieldtype": "Section Break",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
|
||||
"default": "1",
|
||||
"doctype": "DocField",
|
||||
"label": "Use Multi-Level BOM",
|
||||
"reqd": 0,
|
||||
"fieldname": "use_multi_level_bom",
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"width": "50%",
|
||||
"fieldname": "column_break5",
|
||||
"fieldname": "cb5",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
@ -170,18 +181,9 @@
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"width": "50%",
|
||||
"fieldname": "column_break6",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
|
||||
"default": "1",
|
||||
"doctype": "DocField",
|
||||
"label": "Use Multi-Level BOM",
|
||||
"fieldname": "use_multi_level_bom",
|
||||
"fieldtype": "Check",
|
||||
"reqd": 0
|
||||
"fieldname": "sb5",
|
||||
"fieldtype": "Section Break",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"description": "Download a report containing all raw materials with their latest inventory status",
|
||||
@ -191,8 +193,25 @@
|
||||
"fieldtype": "Button"
|
||||
},
|
||||
{
|
||||
"role": "System Manager",
|
||||
"doctype": "DocPerm"
|
||||
"doctype": "DocField",
|
||||
"width": "50%",
|
||||
"fieldname": "column_break6",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"label": "Purchase Request For Warehouse",
|
||||
"fieldname": "purchase_request_for_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"description": "Items to be requested which are \"Out of Stock\" considering all warehouses based on projected qty and minimum order qty",
|
||||
"doctype": "DocField",
|
||||
"label": "Raise Purchase Request",
|
||||
"fieldname": "raise_purchase_request",
|
||||
"fieldtype": "Button",
|
||||
"options": "raise_purchase_request"
|
||||
},
|
||||
{
|
||||
"role": "Manufacturing User",
|
||||
|
@ -77,7 +77,7 @@ class DocType:
|
||||
|
||||
def update_website(self):
|
||||
from website.utils import update_page_name
|
||||
update_page_name(self.doc, self.doc.item_name)
|
||||
update_page_name(self.doc, self.doc.name + " " + self.doc.item_name)
|
||||
|
||||
from website.helpers.product import invalidate_cache_for
|
||||
invalidate_cache_for(self.doc.item_group)
|
||||
|
@ -117,7 +117,7 @@ class DocType:
|
||||
from `tabDelivery Note Item` dni
|
||||
where parent=%s and item_code in (%s)
|
||||
group by item_code""" % ("%s", ", ".join(["%s"]*len(items))),
|
||||
tuple([self.doc.delivery_note] + items), as_dict=1, debug=1)
|
||||
tuple([self.doc.delivery_note] + items), as_dict=1)
|
||||
|
||||
ps_item_qty = dict([[d.item_code, d.qty] for d in self.doclist])
|
||||
|
||||
@ -170,9 +170,6 @@ class DocType:
|
||||
webnotes.msgprint("Invalid new packed quantity for item %s. \
|
||||
Please try again or contact support@erpnext.com" % item['item_code'], raise_exception=1)
|
||||
|
||||
delivery_note_item = webnotes.conn.get_value("Delivery Note Item", {
|
||||
"parent": self.doc.delivery_note, "item_code": item["item_code"]})
|
||||
|
||||
webnotes.conn.sql("""\
|
||||
UPDATE `tabDelivery Note Item`
|
||||
SET packed_qty = %s
|
||||
|
@ -226,7 +226,8 @@ cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
|
||||
'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse),
|
||||
'transfer_qty' : d.transfer_qty,
|
||||
'serial_no' : d.serial_no,
|
||||
'bom_no' : d.bom_no
|
||||
'bom_no' : d.bom_no,
|
||||
'qty' : d.s_warehouse ? -1* d.qty : d.qty
|
||||
}
|
||||
get_server_fields('get_warehouse_details', JSON.stringify(args),
|
||||
'mtn_details', doc, cdt, cdn, 1);
|
||||
|
@ -25,6 +25,8 @@ from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint, _
|
||||
from stock.utils import get_incoming_rate
|
||||
from stock.stock_ledger import get_previous_sle
|
||||
import json
|
||||
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
@ -157,23 +159,46 @@ class DocType(TransactionBase):
|
||||
def get_stock_and_rate(self):
|
||||
"""get stock and incoming rate on posting date"""
|
||||
for d in getlist(self.doclist, 'mtn_details'):
|
||||
args = {
|
||||
args = webnotes._dict({
|
||||
"item_code": d.item_code,
|
||||
"warehouse": d.s_warehouse or d.t_warehouse,
|
||||
"posting_date": self.doc.posting_date,
|
||||
"posting_time": self.doc.posting_time,
|
||||
"qty": d.transfer_qty,
|
||||
"qty": d.s_warehouse and -1*d.transfer_qty or d.transfer_qty,
|
||||
"serial_no": d.serial_no,
|
||||
"bom_no": d.bom_no
|
||||
}
|
||||
"bom_no": d.bom_no,
|
||||
})
|
||||
# get actual stock at source warehouse
|
||||
d.actual_qty = get_previous_sle(args).get("qty_after_transaction") or 0
|
||||
|
||||
# get incoming rate
|
||||
if not flt(d.incoming_rate):
|
||||
d.incoming_rate = get_incoming_rate(args)
|
||||
if not flt(d.incoming_rate) or self.doc.purpose == "Sales Return":
|
||||
d.incoming_rate = self.get_incoming_rate(args)
|
||||
|
||||
d.amount = flt(d.qty) * flt(d.incoming_rate)
|
||||
|
||||
def get_incoming_rate(self, args):
|
||||
if self.doc.purpose == "Sales Return" and \
|
||||
(self.doc.delivery_note_no or self.doc.sales_invoice_no):
|
||||
sle = webnotes.conn.sql("""select name, posting_date, posting_time,
|
||||
actual_qty, stock_value from `tabStock Ledger Entry`
|
||||
where voucher_type = %s and voucher_no = %s and
|
||||
item_code = %s and ifnull(is_cancelled, 'No') = 'No' limit 1""",
|
||||
((self.doc.delivery_note_no and "Delivery Note" or "Sales Invoice"),
|
||||
self.doc.delivery_note_no or self.doc.sales_invoice_no, args.item_code), as_dict=1)
|
||||
if sle:
|
||||
args.update({
|
||||
"posting_date": sle[0].posting_date,
|
||||
"posting_time": sle[0].posting_time,
|
||||
"sle": sle[0].name
|
||||
})
|
||||
previous_sle = get_previous_sle(args)
|
||||
incoming_rate = (flt(sle[0].stock_value) - flt(previous_sle.get("stock_value"))) / \
|
||||
flt(sle[0].actual_qty)
|
||||
else:
|
||||
incoming_rate = get_incoming_rate(args)
|
||||
|
||||
return incoming_rate
|
||||
|
||||
def validate_incoming_rate(self):
|
||||
for d in getlist(self.doclist, 'mtn_details'):
|
||||
@ -264,8 +289,7 @@ class DocType(TransactionBase):
|
||||
pro_obj.doc.save()
|
||||
|
||||
def get_item_details(self, arg):
|
||||
import json
|
||||
arg, actual_qty, in_rate = json.loads(arg), 0, 0
|
||||
arg = json.loads(arg)
|
||||
|
||||
item = sql("""select stock_uom, description, item_name from `tabItem`
|
||||
where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00'
|
||||
@ -305,16 +329,16 @@ class DocType(TransactionBase):
|
||||
return ret
|
||||
|
||||
def get_warehouse_details(self, args):
|
||||
import json
|
||||
args, actual_qty, in_rate = json.loads(args), 0, 0
|
||||
args = json.loads(args)
|
||||
args.update({
|
||||
"posting_date": self.doc.posting_date,
|
||||
"posting_time": self.doc.posting_time
|
||||
"posting_time": self.doc.posting_time,
|
||||
})
|
||||
args = webnotes._dict(args)
|
||||
|
||||
ret = {
|
||||
"actual_qty" : get_previous_sle(args).get("qty_after_transaction") or 0,
|
||||
"incoming_rate" : get_incoming_rate(args)
|
||||
"incoming_rate" : self.get_incoming_rate(args)
|
||||
}
|
||||
return ret
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
{
|
||||
"owner": "Administrator",
|
||||
"docstatus": 0,
|
||||
"creation": "2013-01-14 15:14:40",
|
||||
"creation": "2013-01-15 12:28:57",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2013-01-15 12:25:13"
|
||||
"modified": "2013-01-16 13:59:28"
|
||||
},
|
||||
{
|
||||
"allow_attach": 0,
|
||||
@ -13,6 +13,7 @@
|
||||
"search_fields": "posting_date",
|
||||
"module": "Stock",
|
||||
"doctype": "DocType",
|
||||
"read_only_onload": 0,
|
||||
"autoname": "SR/.######",
|
||||
"description": "This tool helps you to update or fix the quantity and valuation of stock in the system. It is typically used to synchronise the system values and what actually exists in your warehouses.",
|
||||
"allow_email": 1,
|
||||
@ -33,7 +34,7 @@
|
||||
"read": 1,
|
||||
"cancel": 1,
|
||||
"name": "__common__",
|
||||
"amend": 0,
|
||||
"amend": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"submit": 1,
|
||||
|
@ -54,16 +54,13 @@ def update_entries_after(args, verbose=1):
|
||||
if not validate_negative_stock(qty_after_transaction, sle):
|
||||
qty_after_transaction += flt(sle.actual_qty)
|
||||
continue
|
||||
|
||||
|
||||
if sle.serial_no:
|
||||
valuation_rate = get_serialized_values(qty_after_transaction, sle,
|
||||
valuation_rate)
|
||||
valuation_rate = get_serialized_values(qty_after_transaction, sle, valuation_rate)
|
||||
elif valuation_method == "Moving Average":
|
||||
valuation_rate = get_moving_average_values(qty_after_transaction, sle,
|
||||
valuation_rate)
|
||||
valuation_rate = get_moving_average_values(qty_after_transaction, sle, valuation_rate)
|
||||
else:
|
||||
valuation_rate = get_fifo_values(qty_after_transaction, sle,
|
||||
stock_queue)
|
||||
valuation_rate = get_fifo_values(qty_after_transaction, sle, stock_queue)
|
||||
|
||||
qty_after_transaction += flt(sle.actual_qty)
|
||||
|
||||
|
@ -78,12 +78,11 @@ def get_incoming_rate(args):
|
||||
valuation_method = get_valuation_method(args.get("item_code"))
|
||||
previous_sle = get_previous_sle(args)
|
||||
if valuation_method == 'FIFO':
|
||||
# get rate based on the last item value?
|
||||
if args.get("qty"):
|
||||
if not previous_sle:
|
||||
return 0.0
|
||||
stock_queue = json.loads(previous_sle.get('stock_queue', '[]'))
|
||||
in_rate = stock_queue and get_fifo_rate(stock_queue) or 0
|
||||
if not previous_sle:
|
||||
return 0.0
|
||||
previous_stock_queue = json.loads(previous_sle.get('stock_queue', '[]'))
|
||||
in_rate = previous_stock_queue and \
|
||||
get_fifo_rate(previous_stock_queue, args.get("qty") or 0) or 0
|
||||
elif valuation_method == 'Moving Average':
|
||||
in_rate = previous_sle.get('valuation_rate') or 0
|
||||
return in_rate
|
||||
@ -104,13 +103,29 @@ def get_valuation_method(item_code):
|
||||
val_method = get_defaults().get('valuation_method', 'FIFO')
|
||||
return val_method
|
||||
|
||||
def get_fifo_rate(stock_queue):
|
||||
"""get FIFO (average) Rate from Stack"""
|
||||
if not stock_queue:
|
||||
return 0.0
|
||||
|
||||
total = sum(f[0] for f in stock_queue)
|
||||
return total and sum(f[0] * f[1] for f in stock_queue) / flt(total) or 0.0
|
||||
def get_fifo_rate(previous_stock_queue, qty):
|
||||
"""get FIFO (average) Rate from Queue"""
|
||||
if qty >= 0:
|
||||
total = sum(f[0] for f in previous_stock_queue)
|
||||
return total and sum(f[0] * f[1] for f in previous_stock_queue) / flt(total) or 0.0
|
||||
else:
|
||||
outgoing_cost = 0
|
||||
qty_to_pop = abs(qty)
|
||||
while qty_to_pop and previous_stock_queue:
|
||||
batch = previous_stock_queue[0]
|
||||
if 0 < batch[0] <= qty_to_pop:
|
||||
# if batch qty > 0
|
||||
# not enough or exactly same qty in current batch, clear batch
|
||||
outgoing_cost += flt(batch[0]) * flt(batch[1])
|
||||
qty_to_pop -= batch[0]
|
||||
previous_stock_queue.pop(0)
|
||||
else:
|
||||
# all from current batch
|
||||
outgoing_cost += flt(qty_to_pop) * flt(batch[1])
|
||||
batch[0] -= qty_to_pop
|
||||
qty_to_pop = 0
|
||||
# if queue gets blank and qty_to_pop remaining, get average rate of full queue
|
||||
return outgoing_cost / abs(qty) - qty_to_pop
|
||||
|
||||
def get_valid_serial_nos(sr_nos, qty=0, item_code=''):
|
||||
"""split serial nos, validate and return list of valid serial nos"""
|
||||
|
@ -13,15 +13,12 @@ wn.doclistviews['Maintenance Visit'] = wn.views.ListView.extend({
|
||||
|
||||
]);
|
||||
this.stats = this.stats.concat(['completion_status', 'company']);
|
||||
//this.show_hide_check_column();
|
||||
},
|
||||
|
||||
prepare_data: function(data) {
|
||||
this._super(data);
|
||||
data.mntc_date = wn.datetime.str_to_user(data.mntc_date);
|
||||
data.mntc_time = wn.datetime.time_to_ampm(data.mntc_time);
|
||||
data.date_time = "on " + data.mntc_date + " at " +
|
||||
data.mntc_time[0] + ":" + data.mntc_time[1] + " " + data.mntc_time[2];
|
||||
data.date_time = "on " + data.mntc_date + " at " + data.mntc_time;
|
||||
data.customer_name = data.customer_name + " " + data.date_time;
|
||||
data.completion_status = data.completion_status +
|
||||
(data.maintenance_type ? " [" + data.maintenance_type + "]": "");
|
||||
|
@ -94,13 +94,11 @@ Calendar.prototype.show_event = function(ev, cal_ev) {
|
||||
d.onshow = function() {
|
||||
// heading
|
||||
var c = me.selected_date;
|
||||
var tmp = time_to_ampm(this.ev.event_hour);
|
||||
tmp = tmp[0]+':'+tmp[1]+' '+tmp[2];
|
||||
|
||||
this.widgets['Heading'].innerHTML =
|
||||
'<div style="text-align: center; padding:4px; font-size: 14px">'
|
||||
+ erpnext.calendar.weekdays[c.getDay()] + ', ' + c.getDate() + ' ' + month_list_full[c.getMonth()] + ' ' + c.getFullYear()
|
||||
+ ' - <b>'+tmp+'</b></div>';
|
||||
+ ' - <b>'+this.ev.event_hour+'</b></div>';
|
||||
|
||||
// set
|
||||
this.widgets['Description'].value = cstr(this.ev.description);
|
||||
@ -175,7 +173,7 @@ Calendar.prototype.add_event = function() {
|
||||
ev = locals['Event'][ev];
|
||||
|
||||
ev.event_date = dateutil.obj_to_str(this.selected_date);
|
||||
ev.event_hour = this.selected_hour+':00';
|
||||
ev.event_hour = this.selected_hour+':00:00';
|
||||
ev.event_type = 'Private';
|
||||
|
||||
this.show_event(ev);
|
||||
@ -447,8 +445,7 @@ Calendar.DayView.prototype.create_table = function() {
|
||||
for(var j=0;j<2;j++) {
|
||||
var cell = r.insertCell(j);
|
||||
if(j==0) {
|
||||
var tmp = time_to_ampm((i)+':00');
|
||||
cell.innerHTML = tmp[0]+':'+tmp[1]+' '+tmp[2];
|
||||
cell.innerHTML = i+':00:00';
|
||||
$w(cell, '10%');
|
||||
} else {
|
||||
cell.viewunit = new Calendar.DayViewUnit(cell);
|
||||
@ -510,9 +507,7 @@ Calendar.WeekView.prototype.create_table = function() {
|
||||
for(var j=0;j<8;j++) {
|
||||
var cell = r.insertCell(j);
|
||||
if(j==0) {
|
||||
var tmp = time_to_ampm(i+':00');
|
||||
cell.innerHTML = tmp[0]+':'+tmp[1]+' '+tmp[2];
|
||||
|
||||
cell.innerHTML = i+':00:00';
|
||||
$w(cell, '10%');
|
||||
} else {
|
||||
cell.viewunit = new Calendar.WeekViewUnit(cell);
|
||||
|
@ -97,7 +97,14 @@ def page_name(title):
|
||||
import re
|
||||
name = title.lower()
|
||||
name = re.sub('[~!@#$%^&*()<>,."\']', '', name)
|
||||
return '-'.join(name.split()[:8])
|
||||
name = re.sub('[:/]', '-', name)
|
||||
|
||||
name = '-'.join(name.split())
|
||||
|
||||
# replace repeating hyphens
|
||||
name = re.sub(r"(-)\1+", r"\1", name)
|
||||
|
||||
return name
|
||||
|
||||
def update_page_name(doc, title):
|
||||
"""set page_name and check if it is unique"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user