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

Conflicts:
	accounts/doctype/sales_invoice/sales_invoice.txt
	controllers/selling_controller.py
	patches/patch_list.py
	selling/doctype/lead/lead.py
	selling/doctype/opportunity/opportunity.py
	selling/doctype/quotation/quotation.py
	selling/doctype/quotation/quotation.txt
	selling/doctype/sales_order/sales_order.txt
	stock/doctype/purchase_receipt/purchase_receipt.py
	stock/doctype/serial_no/serial_no.py
	stock/doctype/stock_entry/stock_entry.py
	stock/doctype/stock_ledger_entry/stock_ledger_entry.py
This commit is contained in:
Anand Doshi
2013-10-15 12:18:46 +05:30
44 changed files with 902 additions and 332 deletions

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:09",
"docstatus": 0,
"modified": "2013-08-09 14:46:32",
"modified": "2013-10-11 13:19:40",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -230,7 +230,7 @@
"depends_on": "eval:doc.po_no",
"doctype": "DocField",
"fieldname": "po_date",
"fieldtype": "Data",
"fieldtype": "Date",
"hidden": 1,
"label": "Customer's Purchase Order Date",
"no_copy": 0,
@@ -263,7 +263,6 @@
"reqd": 1
},
{
"default": "1.00",
"description": "Rate at which customer's currency is converted to company's base currency",
"doctype": "DocField",
"fieldname": "conversion_rate",

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-08-09 14:47:05",
"modified": "2013-10-11 13:20:13",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -215,7 +215,6 @@
"reqd": 1
},
{
"default": "1.00",
"description": "Rate at which supplier's currency is converted to company's base currency",
"doctype": "DocField",
"fieldname": "conversion_rate",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, getdate, nowdate, cstr, flt, add_days
from webnotes.utils import cint, getdate, cstr, flt, add_days
import datetime
from webnotes import msgprint, _, ValidationError
@@ -36,9 +36,8 @@ class DocType(StockController):
self.validate_amc_status()
self.validate_warehouse()
self.validate_item()
self.on_stock_ledger_entry()
def validate_amc_status(self):
"""
validate amc status
@@ -115,7 +114,7 @@ class DocType(StockController):
and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""",
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
self.doc.item_code), as_dict=1)
if purchase_sle:
self.doc.purchase_document_type = purchase_sle[0].voucher_type
self.doc.purchase_document_no = purchase_sle[0].voucher_no
@@ -178,7 +177,7 @@ class DocType(StockController):
webnotes.conn.sql("""update `tab%s` set serial_no = %s
where name=%s""" % (dt[0], '%s', '%s'),
('\n'.join(serial_nos), item[0]))
def on_stock_ledger_entry(self):
if self.via_stock_ledger and not self.doc.fields.get("__islocal"):
self.set_status()

View File

@@ -6,7 +6,7 @@ import webnotes
import webnotes.defaults
from webnotes.utils import cstr, cint, flt, comma_or, nowdate
from webnotes.model.doc import Document, addchild
from webnotes.model.doc import addchild
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint, _
@@ -20,6 +20,7 @@ class NotUpdateStockError(webnotes.ValidationError): pass
class StockOverReturnError(webnotes.ValidationError): pass
class IncorrectValuationRateError(webnotes.ValidationError): pass
class DuplicateEntryForProductionOrderError(webnotes.ValidationError): pass
class StockOverProductionError(webnotes.ValidationError): pass
from controllers.stock_controller import StockController
@@ -54,13 +55,12 @@ class DocType(StockController):
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "mtn_details")
self.update_production_order(1)
self.update_production_order()
self.make_gl_entries()
def on_cancel(self):
self.update_stock_ledger()
self.update_production_order(0)
self.update_production_order()
self.make_cancel_gl_entries()
def validate_fiscal_year(self):
@@ -325,37 +325,44 @@ class DocType(StockController):
self.make_sl_entries(sl_entries, self.doc.amended_from and 'Yes' or 'No')
def update_production_order(self, is_submit):
def update_production_order(self):
def _validate_production_order(pro_bean):
if flt(pro_bean.doc.docstatus) != 1:
webnotes.throw(_("Production Order must be submitted") + ": " +
self.doc.production_order)
if pro_bean.doc.status == 'Stopped':
msgprint(_("Transaction not allowed against stopped Production Order") + ": " +
self.doc.production_order)
if self.doc.production_order:
# first perform some validations
# (they are here coz this fn is also called during on_cancel)
pro_obj = get_obj("Production Order", self.doc.production_order)
if flt(pro_obj.doc.docstatus) != 1:
msgprint("""You cannot do any transaction against
Production Order : %s, as it's not submitted"""
% (pro_obj.doc.name), raise_exception=1)
if pro_obj.doc.status == 'Stopped':
msgprint("""You cannot do any transaction against Production Order : %s,
as it's status is 'Stopped'"""% (pro_obj.doc.name), raise_exception=1)
# update bin
if self.doc.purpose == "Manufacture/Repack":
from stock.utils import update_bin
pro_obj.doc.produced_qty = flt(pro_obj.doc.produced_qty) + \
(is_submit and 1 or -1 ) * flt(self.doc.fg_completed_qty)
args = {
"item_code": pro_obj.doc.production_item,
"warehouse": pro_obj.doc.fg_warehouse,
"posting_date": self.doc.posting_date,
"planned_qty": (is_submit and -1 or 1 ) * flt(self.doc.fg_completed_qty)
}
update_bin(args)
pro_bean = webnotes.bean("Production Order", self.doc.production_order)
_validate_production_order(pro_bean)
self.update_produced_qty(pro_bean)
self.update_planned_qty(pro_bean)
# update production order status
pro_obj.doc.status = (flt(pro_obj.doc.qty)==flt(pro_obj.doc.produced_qty)) \
and 'Completed' or 'In Process'
pro_obj.doc.save()
def update_produced_qty(self, pro_bean):
if self.doc.purpose == "Manufacture/Repack":
produced_qty = flt(pro_bean.doc.produced_qty) + \
(self.doc.docstatus==1 and 1 or -1 ) * flt(self.doc.fg_completed_qty)
if produced_qty > flt(pro_bean.doc.qty):
webnotes.throw(_("Production Order") + ": " + self.doc.production_order + "\n" +
_("Total Manufactured Qty can not be greater than Planned qty to manufacture")
+ "(%s/%s)" % (produced_qty, flt(pro_bean.doc.qty)), StockOverProductionError)
status = 'Completed' if flt(produced_qty) >= flt(pro_bean.doc.qty) else 'In Process'
webnotes.conn.sql("""update `tabProduction Order` set status=%s, produced_qty=%s
where name=%s""", (status, produced_qty, self.doc.production_order))
def update_planned_qty(self, pro_bean):
from stock.utils import update_bin
update_bin({
"item_code": pro_bean.doc.production_item,
"warehouse": pro_bean.doc.fg_warehouse,
"posting_date": self.doc.posting_date,
"planned_qty": (self.doc.docstatus==1 and -1 or 1 ) * flt(self.doc.fg_completed_qty)
})
def get_item_details(self, arg):
arg = json.loads(arg)
@@ -414,7 +421,8 @@ class DocType(StockController):
return ret
def get_items(self):
self.doclist = self.doc.clear_table(self.doclist, 'mtn_details', 1)
self.doclist = filter(lambda d: d.parentfield!="mtn_details", self.doclist)
# self.doclist = self.doc.clear_table(self.doclist, 'mtn_details')
pro_obj = None
if self.doc.production_order:
@@ -453,7 +461,7 @@ class DocType(StockController):
"stock_uom": pro_obj.doc.stock_uom
}
}, bom_no=pro_obj.doc.bom_no)
elif self.doc.purpose in ["Material Receipt", "Manufacture/Repack"]:
if self.doc.purpose=="Material Receipt":
self.doc.from_warehouse = ""
@@ -470,6 +478,7 @@ class DocType(StockController):
}, bom_no=self.doc.bom_no)
self.get_stock_and_rate()
def get_bom_raw_materials(self, qty):
from manufacturing.doctype.bom.bom import get_bom_items_as_dict

View File

@@ -3,8 +3,8 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import cint, flt, getdate, cstr
from webnotes import msgprint
from webnotes.utils import flt, getdate
from webnotes.model.controller import DocListController
class DocType(DocListController):

View File

@@ -5,7 +5,6 @@ from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, flt, validate_email_add
from webnotes.model.code import get_obj
from webnotes import msgprint, _
@@ -91,103 +90,15 @@ class DocType:
webnotes.conn.delete_doc("Account", old_warehouse_account)
from utilities.repost_stock import repost
for item_code in items:
self.repost(item_code[0], self.doc.merge_with)
repost(item_code[0], self.doc.merge_with)
webnotes.conn.auto_commit_on_many_writes = 0
msgprint("Warehouse %s merged into %s. Now you can delete warehouse: %s"
% (self.doc.name, self.doc.merge_with, self.doc.name))
def repost(self, item_code, warehouse=None):
from stock.utils import get_bin
self.repost_actual_qty(item_code, warehouse)
bin = get_bin(item_code, warehouse)
self.repost_reserved_qty(bin)
self.repost_indented_qty(bin)
self.repost_ordered_qty(bin)
self.repost_planned_qty(bin)
bin.doc.projected_qty = flt(bin.doc.actual_qty) + flt(bin.doc.planned_qty) \
+ flt(bin.doc.indented_qty) + flt(bin.doc.ordered_qty) - flt(bin.doc.reserved_qty)
bin.doc.save()
def repost_actual_qty(self, item_code, warehouse=None):
from stock.stock_ledger import update_entries_after
if not warehouse:
warehouse = self.doc.name
update_entries_after({ "item_code": item_code, "warehouse": warehouse })
def repost_reserved_qty(self, bin):
reserved_qty = webnotes.conn.sql("""
select
sum((dnpi_qty / so_item_qty) * (so_item_qty - so_item_delivered_qty))
from
(
select
qty as dnpi_qty,
(
select qty from `tabSales Order Item`
where name = dnpi.parent_detail_docname
) as so_item_qty,
(
select ifnull(delivered_qty, 0) from `tabSales Order Item`
where name = dnpi.parent_detail_docname
) as so_item_delivered_qty
from
(
select qty, parent_detail_docname
from `tabDelivery Note Packing Item` dnpi_in
where item_code = %s and warehouse = %s
and parenttype="Sales Order"
and exists (select * from `tabSales Order` so
where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
) dnpi
) tab
where
so_item_qty >= so_item_delivered_qty
""", (bin.doc.item_code, bin.doc.warehouse))
if flt(bin.doc.reserved_qty) != flt(reserved_qty[0][0]):
webnotes.conn.set_value("Bin", bin.doc.name, "reserved_qty", flt(reserved_qty[0][0]))
def repost_indented_qty(self, bin):
indented_qty = webnotes.conn.sql("""select sum(pr_item.qty - pr_item.ordered_qty)
from `tabMaterial Request Item` pr_item, `tabMaterial Request` pr
where pr_item.item_code=%s and pr_item.warehouse=%s
and pr_item.qty > pr_item.ordered_qty and pr_item.parent=pr.name
and pr.status!='Stopped' and pr.docstatus=1"""
, (bin.doc.item_code, bin.doc.warehouse))
if flt(bin.doc.indented_qty) != flt(indented_qty[0][0]):
webnotes.conn.set_value("Bin", bin.doc.name, "indented_qty", flt(indented_qty[0][0]))
def repost_ordered_qty(self, bin):
ordered_qty = webnotes.conn.sql("""
select sum((po_item.qty - po_item.received_qty)*po_item.conversion_factor)
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
where po_item.item_code=%s and po_item.warehouse=%s
and po_item.qty > po_item.received_qty and po_item.parent=po.name
and po.status!='Stopped' and po.docstatus=1"""
, (bin.doc.item_code, bin.doc.warehouse))
if flt(bin.doc.ordered_qty) != flt(ordered_qty[0][0]):
webnotes.conn.set_value("Bin", bin.doc.name, "ordered_qty", flt(ordered_qty[0][0]))
def repost_planned_qty(self, bin):
planned_qty = webnotes.conn.sql("""
select sum(qty - produced_qty) from `tabProduction Order`
where production_item = %s and fg_warehouse = %s and status != "Stopped"
and docstatus=1""", (bin.doc.item_code, bin.doc.warehouse))
if flt(bin.doc.planned_qty) != flt(planned_qty[0][0]):
webnotes.conn.set_value("Bin", bin.doc.name, "planned_qty", flt(planned_qty[0][0]))
def on_trash(self):
# delete bin
bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s", self.doc.name, as_dict=1)
@@ -209,4 +120,4 @@ class DocType:
msgprint("""Warehosue can not be deleted as stock ledger entry
exists for this warehouse.""", raise_exception=1)
else:
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)

View File

@@ -209,7 +209,7 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters):
return wlist
def validate_warehouse_user(warehouse):
if webnotes.session.user=="Administrator":
if webnotes.session.user=="Administrator" or not warehouse:
return
warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User`
where parent=%s""", warehouse)]
@@ -394,12 +394,3 @@ def notify_errors(exceptions_list):
from webnotes.profile import get_system_managers
sendmail(get_system_managers(), subject=subject, msg=msg)
def repost():
"""
Repost everything!
"""
from webnotes.model.code import get_obj
for wh in webnotes.conn.sql("select name from tabWarehouse"):
get_obj('Warehouse', wh[0]).repost_stock()