sub-contracting code refactored for po
This commit is contained in:
parent
73b2bb6f91
commit
54d209ffb0
@ -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)
|
||||
|
||||
|
65
buying/doctype/purchase_order/test_purchase_order.py
Normal file
65
buying/doctype/purchase_order/test_purchase_order.py
Normal 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",
|
||||
}
|
||||
],
|
||||
]
|
@ -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):
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
test_records = [
|
||||
[{
|
||||
"doctype": "Customer",
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user