Merge branch 'edge'
diff --git a/accounts/doctype/c_form/c_form.py b/accounts/doctype/c_form/c_form.py
index a1cc9e8..4575653 100644
--- a/accounts/doctype/c_form/c_form.py
+++ b/accounts/doctype/c_form/c_form.py
@@ -18,11 +18,7 @@
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 @@
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)
+ }
\ No newline at end of file
diff --git a/manufacturing/doctype/production_plan_item/production_plan_item.txt b/manufacturing/doctype/production_plan_item/production_plan_item.txt
index 6ae2a04..2cb2a59 100644
--- a/manufacturing/doctype/production_plan_item/production_plan_item.txt
+++ b/manufacturing/doctype/production_plan_item/production_plan_item.txt
@@ -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,
diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py
index adc8091..a6c8458 100644
--- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py
+++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py
@@ -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 @@
"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 @@
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 @@
# 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 @@
if item_qty:
item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty])
- return item_list
\ No newline at end of file
+ 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")
\ No newline at end of file
diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.txt b/manufacturing/doctype/production_planning_tool/production_planning_tool.txt
index dd7acfd..d4a0d94 100644
--- a/manufacturing/doctype/production_planning_tool/production_planning_tool.txt
+++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.txt
@@ -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"
},
{
@@ -155,9 +157,18 @@
"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",
diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py
index 38ff797..cca814f 100644
--- a/stock/doctype/item/item.py
+++ b/stock/doctype/item/item.py
@@ -77,7 +77,7 @@
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)
diff --git a/stock/doctype/packing_slip/packing_slip.py b/stock/doctype/packing_slip/packing_slip.py
index 7ef7d36..b90b0e6 100644
--- a/stock/doctype/packing_slip/packing_slip.py
+++ b/stock/doctype/packing_slip/packing_slip.py
@@ -117,7 +117,7 @@
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 @@
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
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index bb55622..6613ec4 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -226,7 +226,8 @@
'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);
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index eaf7966..12e69e6 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -25,6 +25,8 @@
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 @@
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 @@
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 @@
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
diff --git a/stock/doctype/stock_reconciliation/stock_reconciliation.txt b/stock/doctype/stock_reconciliation/stock_reconciliation.txt
index 58384cc..145d6fa 100644
--- a/stock/doctype/stock_reconciliation/stock_reconciliation.txt
+++ b/stock/doctype/stock_reconciliation/stock_reconciliation.txt
@@ -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,
diff --git a/stock/stock_ledger.py b/stock/stock_ledger.py
index ffb6692..26f03c6 100644
--- a/stock/stock_ledger.py
+++ b/stock/stock_ledger.py
@@ -54,16 +54,13 @@
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)
diff --git a/stock/utils.py b/stock/utils.py
index a65406b..46dd9d0 100644
--- a/stock/utils.py
+++ b/stock/utils.py
@@ -78,12 +78,11 @@
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 @@
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"""
diff --git a/support/doctype/maintenance_visit/maintenance_visit_list.js b/support/doctype/maintenance_visit/maintenance_visit_list.js
index 654f455..6dc5dac 100644
--- a/support/doctype/maintenance_visit/maintenance_visit_list.js
+++ b/support/doctype/maintenance_visit/maintenance_visit_list.js
@@ -13,15 +13,12 @@
]);
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 + "]": "");
diff --git a/utilities/page/calendar/calendar.js b/utilities/page/calendar/calendar.js
index d62dc68..5e59f1f 100644
--- a/utilities/page/calendar/calendar.js
+++ b/utilities/page/calendar/calendar.js
@@ -94,13 +94,11 @@
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 @@
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 @@
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 @@
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);
diff --git a/website/utils.py b/website/utils.py
index 96fbdc8..6963b76 100644
--- a/website/utils.py
+++ b/website/utils.py
@@ -97,7 +97,14 @@
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"""