sub-contracting code refactored for po

This commit is contained in:
Nabin Hait 2013-03-01 18:51:10 +05:30
parent 73b2bb6f91
commit 54d209ffb0
5 changed files with 136 additions and 153 deletions

View File

@ -18,12 +18,10 @@ from __future__ import unicode_literals
import webnotes
from webnotes.utils import cstr, flt
from webnotes.model.doc import addchild
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint
from buying.utils import get_last_purchase_details
from setup.utils import get_company_currency
sql = webnotes.conn.sql
@ -35,7 +33,6 @@ class DocType(BuyingController):
self.tname = 'Purchase Order Item'
self.fname = 'po_details'
# Validate
def validate(self):
super(DocType, self).validate()
@ -64,6 +61,10 @@ class DocType(BuyingController):
# Check for stopped status
self.check_for_stopped_status(pc_obj)
# sub-contracting
self.validate_for_subcontracting()
self.update_raw_materials_supplied("po_raw_material_details")
def get_default_schedule_date(self):
get_obj(dt = 'Purchase Common').get_default_schedule_date(self)
@ -79,7 +80,6 @@ class DocType(BuyingController):
def get_indent_details(self):
if self.doc.indent_no:
get_obj('DocType Mapper','Material Request-Purchase Order').dt_map('Material Request','Purchase Order',self.doc.indent_no, self.doc, self.doclist, "[['Material Request','Purchase Order'],['Material Request Item', 'Purchase Order Item']]")
pcomm = get_obj('Purchase Common')
for d in getlist(self.doclist, 'po_details'):
if d.item_code and not d.purchase_rate:
last_purchase_details = get_last_purchase_details(d.item_code, self.doc.name)
@ -173,8 +173,6 @@ class DocType(BuyingController):
msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ")
raise Exception
# On Close
#-------------------------------------------------------------------------------------------------
def update_status(self, status):
self.check_modified_date()
# step 1:=> Set Status
@ -186,8 +184,6 @@ class DocType(BuyingController):
# step 3:=> Acknowledge user
msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status)))
# On Submit
def on_submit(self):
purchase_controller = webnotes.get_obj("Purchase Common")
purchase_controller.is_item_table_empty(self)
@ -207,118 +203,31 @@ class DocType(BuyingController):
# Step 6 :=> Set Status
webnotes.conn.set(self.doc,'status','Submitted')
# On Cancel
# -------------------------------------------------------------------------------------------------------
def on_cancel(self):
pc_obj = get_obj(dt = 'Purchase Common')
# 1.Check if PO status is stopped
# Check if PO status is stopped
pc_obj.check_for_stopped_status(cstr(self.doc.doctype), cstr(self.doc.name))
self.check_for_stopped_status(pc_obj)
# 2.Check if Purchase Receipt has been submitted against current Purchase Order
# Check if Purchase Receipt has been submitted against current Purchase Order
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.doc.name, detail_doctype = 'Purchase Receipt Item')
# 3.Check if Purchase Invoice has been submitted against current Purchase Order
#pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Invoice', docname = self.doc.name, detail_doctype = 'Purchase Invoice Item')
# Check if Purchase Invoice has been submitted against current Purchase Order
submitted = sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_order = '%s' and t1.docstatus = 1" % self.doc.name)
if submitted:
msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !")
raise Exception
# 4.Set Status as Cancelled
webnotes.conn.set(self.doc,'status','Cancelled')
# 5.Update Material Requests Pending Qty and accordingly it's Status
pc_obj.update_prevdoc_detail(self,is_submit = 0)
# 6.Update Bin
self.update_bin( is_submit = 0, is_stopped = 0)
# Step 7 :=> Update last purchase rate
pc_obj.update_last_purchase_rate(self, is_submit = 0)
#----------- code for Sub-contracted Items -------------------
#--------check for sub-contracted items and accordingly update PO raw material detail table--------
def update_rw_material_detail(self):
for d in getlist(self.doclist,'po_details'):
item_det = sql("select is_sub_contracted_item, is_purchase_item from `tabItem` where name = '%s'"%(d.item_code))
if item_det[0][0] == 'Yes':
if item_det[0][1] == 'Yes':
if not self.doc.is_subcontracted:
msgprint("Please enter whether purchase order to be made for subcontracting or for purchasing in 'Is Subcontracted' field .")
raise Exception
if self.doc.is_subcontracted == 'Yes':
self.add_bom(d)
else:
self.doclist = self.doc.clear_table(self.doclist,'po_raw_material_details',1)
self.doc.save()
elif item_det[0][1] == 'No':
self.add_bom(d)
self.delete_irrelevant_raw_material()
#---------------calculate amt in Purchase Order Item Supplied-------------
def add_bom(self, d):
#----- fetching default bom from Bill of Materials instead of Item Master --
bom_det = sql("""select t1.item, t2.item_code, t2.qty_consumed_per_unit,
t2.moving_avg_rate, t2.value_as_per_mar, t2.stock_uom, t2.name, t2.parent
from `tabBOM` t1, `tabBOM Item` t2
where t2.parent = t1.name and t1.item = %s
and ifnull(t1.is_default,0) = 1 and t1.docstatus = 1""", (d.item_code,))
if not bom_det:
msgprint("No default BOM exists for item: %s" % d.item_code)
raise Exception
else:
#-------------- add child function--------------------
chgd_rqd_qty = []
for i in bom_det:
if i and not sql("select name from `tabPurchase Order Item Supplied` where reference_name = '%s' and bom_detail_no = '%s' and parent = '%s' " %(d.name, i[6], self.doc.name)):
rm_child = addchild(self.doc, 'po_raw_material_details', 'Purchase Order Item Supplied', self.doclist)
rm_child.reference_name = d.name
rm_child.bom_detail_no = i and i[6] or ''
rm_child.main_item_code = i and i[0] or ''
rm_child.rm_item_code = i and i[1] or ''
rm_child.stock_uom = i and i[5] or ''
rm_child.rate = i and flt(i[3]) or flt(i[4])
rm_child.conversion_factor = d.conversion_factor
rm_child.required_qty = flt(i and flt(i[2]) or 0) * flt(d.qty) * flt(d.conversion_factor)
rm_child.amount = flt(flt(rm_child.consumed_qty)*flt(rm_child.rate))
rm_child.save()
chgd_rqd_qty.append(cstr(i[1]))
else:
act_qty = flt(i and flt(i[2]) or 0) * flt(d.qty) * flt(d.conversion_factor)
for po_rmd in getlist(self.doclist, 'po_raw_material_details'):
if i and i[6] == po_rmd.bom_detail_no and (flt(act_qty) != flt(po_rmd.required_qty) or i[1] != po_rmd.rm_item_code):
chgd_rqd_qty.append(cstr(i[1]))
po_rmd.main_item_code = i[0]
po_rmd.rm_item_code = i[1]
po_rmd.stock_uom = i[5]
po_rmd.required_qty = flt(act_qty)
po_rmd.rate = i and flt(i[3]) or flt(i[4])
po_rmd.amount = flt(flt(po_rmd.consumed_qty)*flt(po_rmd.rate))
# Delete irrelevant raw material from PR Raw material details
#--------------------------------------------------------------
def delete_irrelevant_raw_material(self):
for d in getlist(self.doclist,'po_raw_material_details'):
if not sql("select name from `tabPurchase Order Item` where name = '%s' and parent = '%s'and item_code = '%s'" % (d.reference_name, self.doc.name, d.main_item_code)):
d.parent = 'old_par:'+self.doc.name
d.save()
# On Update
# ----------------------------------------------------------------------------------------------------
def on_update(self):
self.update_rw_material_detail()
pass
def get_rate(self,arg):
return get_obj('Purchase Common').get_rate(arg,self)

View File

@ -0,0 +1,65 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import unittest
import webnotes
import webnotes.defaults
from webnotes.utils import cint
class TestPurchaseOrder(unittest.TestCase):
def test_subcontracting(self):
po = webnotes.bean(copy=test_records[0])
po.insert()
self.assertEquals(len(po.doclist.get({"parentfield": "po_raw_material_details"})), 2)
test_dependencies = ["BOM"]
test_records = [
[
{
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"doctype": "Purchase Order",
"fiscal_year": "_Test Fiscal Year 2013",
"transaction_date": "2013-02-12",
"is_subcontracted": "Yes",
"supplier": "_Test Supplier",
"supplier_name": "_Test Supplier",
"net_total": 5000.0,
"grand_total": 5000.0,
"grand_total_import": 5000.0,
},
{
"conversion_factor": 1.0,
"description": "_Test FG Item",
"doctype": "Purchase Order Item",
"item_code": "_Test FG Item",
"item_name": "_Test FG Item",
"parentfield": "po_details",
"qty": 10.0,
"import_rate": 500.0,
"amount": 5000.0,
"warehouse": "_Test Warehouse",
"stock_uom": "Nos",
"uom": "_Test UOM",
}
],
]

View File

@ -342,6 +342,67 @@ class BuyingController(AccountsController):
) / flt(d.conversion_factor)
else:
d.valuation_rate = 0.0
def validate_for_subcontracting(self):
if not self.doc.is_subcontracted and self.sub_contracted_items:
webnotes.msgprint(_("""Please enter whether %s is made for subcontracting or purchasing,
in 'Is Subcontracted' field""" % self.doc.doctype), raise_exception=1)
if self.doc.doctype == "Purchase Receipt" and self.doc.is_subcontracted=="Yes" \
and not self.doc.supplier_warehouse:
webnotes.msgprint(_("Supplier Warehouse mandatory subcontracted purchase receipt"),
raise_exception=1)
def update_raw_materials_supplied(self, raw_material_table):
self.doclist = self.doc.clear_table(self.doclist, raw_material_table)
if self.doc.is_subcontracted=="Yes":
for item in self.doclist.get({"parentfield": self.fname}):
if item.item_code in self.sub_contracted_items:
self.add_bom_items(item, raw_material_table)
def add_bom_items(self, d, raw_material_table):
bom_items = self.get_items_from_default_bom(d.item_code)
raw_materials_cost = 0
for item in bom_items:
required_qty = flt(item.qty_consumed_per_unit) * flt(d.qty) * flt(d.conversion_factor)
rm_doclist = {
"parentfield": raw_material_table,
"doctype": self.doc.doctype + " Item Supplied",
"reference_name": d.name,
"bom_detail_no": item.name,
"main_item_code": d.item_code,
"rm_item_code": item.item_code,
"stock_uom": item.stock_uom,
"required_qty": required_qty,
"conversion_factor": d.conversion_factor,
"rate": item.rate,
"amount": required_qty * flt(item.rate)
}
if self.doc.doctype == "Purchase Receipt":
rm_doclist.update({
"consumed_qty": required_qty,
"description": item.description,
})
self.doclist.append(rm_doclist)
raw_materials_cost += required_qty * flt(item.rate)
if self.doc.doctype == "Purchase Receipt":
d.rm_supp_cost = raw_materials_cost
def get_items_from_default_bom(self, item_code):
# print webnotes.conn.sql("""select name from `tabBOM` where item = '_Test FG Item'""")
bom_items = webnotes.conn.sql("""select t2.item_code, t2.qty_consumed_per_unit,
t2.rate, t2.stock_uom, t2.name, t2.description
from `tabBOM` t1, `tabBOM Item` t2
where t2.parent = t1.name and t1.item = %s and t1.is_default = 1
and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1)
if not bom_items:
msgprint(_("No default BOM exists for item: ") + item_code, raise_exception=1)
return bom_items
@property
def precision(self):

View File

@ -1,3 +1,4 @@
test_records = [
[{
"doctype": "Customer",

View File

@ -122,7 +122,7 @@ class DocType(BuyingController):
# sub-contracting
self.validate_for_subcontracting()
self.update_raw_materials_supplied()
self.update_raw_materials_supplied("pr_raw_material_details")
self.update_valuation_rate("purchase_receipt_details")
@ -289,59 +289,6 @@ class DocType(BuyingController):
self.make_gl_entries()
def validate_for_subcontracting(self):
if not self.doc.is_subcontracted and self.sub_contracted_items:
webnotes.msgprint(_("""Please enter whether Purchase Recipt is made for subcontracting
or purchasing, in 'Is Subcontracted' field"""), raise_exception=1)
if self.doc.is_subcontracted=="Yes" and not self.doc.supplier_warehouse:
webnotes.msgprint(_("Please Enter Supplier Warehouse for subcontracted Items"),
raise_exception=1)
def update_raw_materials_supplied(self):
self.doclist = self.doc.clear_table(self.doclist, 'pr_raw_material_details')
if self.doc.is_subcontracted=="Yes":
for item in self.doclist.get({"parentfield": "purchase_receipt_details"}):
if item.item_code in self.sub_contracted_items:
self.add_bom_items(item)
def add_bom_items(self, d):
bom_items = self.get_items_from_default_bom(d.item_code)
raw_materials_cost = 0
for item in bom_items:
required_qty = flt(item.qty_consumed_per_unit) * flt(d.qty) * flt(d.conversion_factor)
self.doclist.append({
"parentfield": "pr_raw_material_details",
"doctype": "Purchase Receipt Item Supplied",
"reference_name": d.name,
"bom_detail_no": item.name,
"main_item_code": d.item_code,
"rm_item_code": item.item_code,
"description": item.description,
"stock_uom": item.stock_uom,
"required_qty": required_qty,
"consumed_qty": required_qty,
"conversion_factor": d.conversion_factor,
"rate": item.rate,
"amount": required_qty * flt(item.rate)
})
raw_materials_cost += required_qty * flt(item.rate)
d.rm_supp_cost = raw_materials_cost
def get_items_from_default_bom(self, item_code):
# print webnotes.conn.sql("""select name from `tabBOM` where item = '_Test FG Item'""")
bom_items = sql("""select t2.item_code, t2.qty_consumed_per_unit,
t2.rate, t2.stock_uom, t2.name, t2.description
from `tabBOM` t1, `tabBOM Item` t2
where t2.parent = t1.name and t1.item = %s and t1.is_default = 1
and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1)
if not bom_items:
msgprint(_("No default BOM exists for item: ") + item_code, raise_exception=1)
return bom_items
def bk_flush_supp_wh(self, is_submit):
for d in getlist(self.doclist, 'pr_raw_material_details'):
# negative quantity is passed as raw material qty has to be decreased