sub-contracting rewrite with testcases

This commit is contained in:
Nabin Hait 2013-02-27 18:11:17 +05:30
parent a1d4b78fbe
commit 5418d71fc0
7 changed files with 344 additions and 298 deletions

View File

@ -320,6 +320,7 @@ class DocType(BuyingController):
self.doc.posting_date,'Posting Date') self.doc.posting_date,'Posting Date')
self.validate_write_off_account() self.validate_write_off_account()
self.update_raw_material_cost()
def check_prev_docstatus(self): def check_prev_docstatus(self):
for d in getlist(self.doclist,'entries'): for d in getlist(self.doclist,'entries'):
@ -494,3 +495,16 @@ class DocType(BuyingController):
def on_update(self): def on_update(self):
pass pass
def update_raw_material_cost(self):
if self.sub_contracted_items:
for d in self.doclist.get({"parentfield": "entries"}):
rm_cost = webnotes.conn.sql(""" select raw_material_cost / quantity
from `tabBOM` where item = %s and is_default = 1 and docstatus = 1
and is_active = 1 """, (d.item_code,))
rm_cost = rm_cost and flt(rm_cost[0][0]) or 0
d.conversion_factor = d.conversion_factor or webnotes.conn.get_value(
"UOM Conversion Detail", {"parent": d.item_code, "uom": d.uom},
"conversion_factor") or 1
d.rm_supp_cost = rm_cost * flt(d.qty) * flt(d.conversion_factor)

View File

@ -1,8 +1,8 @@
[ [
{ {
"creation": "2013-01-29 20:53:00", "creation": "2013-02-11 10:54:51",
"docstatus": 0, "docstatus": 0,
"modified": "2013-02-08 14:06:17", "modified": "2013-02-27 18:10:04",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
@ -282,6 +282,35 @@
"search_index": 0, "search_index": 0,
"width": "150px" "width": "150px"
}, },
{
"doctype": "DocField",
"fieldname": "valuation_rate",
"fieldtype": "Currency",
"hidden": 1,
"label": "Valuation Rate",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "conversion_factor",
"fieldtype": "Float",
"label": "Conversion Factor",
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "rm_supp_cost",
"fieldtype": "Currency",
"hidden": 1,
"label": "Raw Materials Supplied Cost",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{ {
"allow_on_submit": 1, "allow_on_submit": 1,
"doctype": "DocField", "doctype": "DocField",

View File

@ -232,7 +232,7 @@ class BuyingController(AccountsController):
else: else:
self.doc.grand_total = flt(self.doc.net_total, self.doc.grand_total = flt(self.doc.net_total,
self.precision.main.grand_total) self.precision.main.grand_total)
self.doc.grand_total_print = flt( self.doc.grand_total_import = flt(
self.doc.grand_total / self.doc.conversion_rate, self.doc.grand_total / self.doc.conversion_rate,
self.precision.main.grand_total_import) self.precision.main.grand_total_import)
@ -336,3 +336,25 @@ class BuyingController(AccountsController):
self._precision.tax = self.meta.get_precision_map(parentfield = \ self._precision.tax = self.meta.get_precision_map(parentfield = \
"purchase_tax_details") "purchase_tax_details")
return self._precision return self._precision
@property
def sub_contracted_items(self):
if not hasattr(self, "_sub_contracted_items"):
item_codes = list(set(item.item_code for item in
self.doclist.get({"parentfield": self.fname})))
self._sub_contracted_items = [r[0] for r in webnotes.conn.sql("""select name
from `tabItem` where name in (%s) and is_sub_contracted_item='Yes'""" % \
(", ".join((["%s"]*len(item_codes))),), item_codes)]
return self._sub_contracted_items
@property
def purchase_items(self):
if not hasattr(self, "_purchase_items"):
item_codes = list(set(item.item_code for item in
self.doclist.get({"parentfield": self.fname})))
self._purchase_items = [r[0] for r in webnotes.conn.sql("""select name
from `tabItem` where name in (%s) and is_purchase_item='Yes'""" % \
(", ".join((["%s"]*len(item_codes))),), item_codes)]
return self._purchase_items

View File

@ -18,130 +18,164 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
import webnotes import webnotes
import webnotes.model
from webnotes.utils import nowdate, flt
from accounts.utils import get_fiscal_year
from webnotes.model.doclist import DocList
import copy
company = webnotes.conn.get_default("company") test_records = [
[
{
def load_data(): "doctype": "BOM",
"item": "_Test FG Item",
# create default warehouse "quantity": 1.0,
if not webnotes.conn.exists("Warehouse", "Default Warehouse"): "is_active": 1,
webnotes.insert({"doctype": "Warehouse", "is_default": 1,
"warehouse_name": "Default Warehouse", "docstatus": 1
"warehouse_type": "Stores"}) },
{
# create UOM: Nos. "doctype": "BOM Item",
if not webnotes.conn.exists("UOM", "Nos"): "item_code": "_Test Item",
webnotes.insert({"doctype": "UOM", "uom_name": "Nos"}) "parentfield": "bom_materials",
"qty": 1.0,
from webnotes.tests import insert_test_data "rate": 5000.0,
# create item groups and items "amount": 5000.0,
insert_test_data("Item Group", "stock_uom": "No."
sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name'))) },
insert_test_data("Item") {
"doctype": "BOM Item",
base_bom_fg = [ "item_code": "_Test Item Home Desktop 100",
{"doctype": "BOM", "item": "Android Jack D", "quantity": 1, "parentfield": "bom_materials",
"is_active": "Yes", "is_default": 1, "uom": "Nos"}, "qty": 2.0,
{"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations", "rate": 1000.0,
"opn_description": "Development", "hour_rate": 10, "time_in_mins": 90}, "amount": 2000.0,
{"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1, "stock_uom": "No."
"qty": 2, "rate": 20, "stock_uom": "Nos", "parentfield": "bom_materials"},
{"doctype": "BOM Item", "item_code": "Home Desktop 100", "operation_no": 1,
"qty": 1, "rate": 300, "stock_uom": "Nos", "parentfield": "bom_materials"},
{"doctype": "BOM Item", "item_code": "Nebula 7", "operation_no": 1,
"qty": 5, "stock_uom": "Nos", "parentfield": "bom_materials"},
]
base_bom_child = [
{"doctype": "BOM", "item": "Nebula 7", "quantity": 5,
"is_active": "Yes", "is_default": 1, "uom": "Nos"},
{"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
"opn_description": "Development"},
{"doctype": "BOM Item", "item_code": "Android Jack S", "operation_no": 1,
"qty": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
]
base_bom_grandchild = [
{"doctype": "BOM", "item": "Android Jack S", "quantity": 1,
"is_active": "Yes", "is_default": 1, "uom": "Nos"},
{"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
"opn_description": "Development"},
{"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1,
"qty": 3, "rate": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
]
class TestPurchaseReceipt(unittest.TestCase):
def setUp(self):
webnotes.conn.begin()
load_data()
def test_bom_validation(self):
# show throw error bacause bom no missing for sub-assembly item
bom_fg = copy.deepcopy(base_bom_fg)
self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
# main item is not a manufacturing item
bom_fg = copy.deepcopy(base_bom_fg)
bom_fg[0]["item"] = "Home Desktop 200"
bom_fg.pop(4)
self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
# operation no mentioed in material table not matching with operation table
bom_fg = copy.deepcopy(base_bom_fg)
bom_fg.pop(4)
bom_fg[2]["operation_no"] = 2
self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
def test_bom(self):
gc_wrapper = webnotes.insert(DocList(base_bom_grandchild))
gc_wrapper.submit()
bom_child = copy.deepcopy(base_bom_child)
bom_child[2]["bom_no"] = gc_wrapper.doc.name
child_wrapper = webnotes.insert(DocList(bom_child))
child_wrapper.submit()
bom_fg = copy.deepcopy(base_bom_fg)
bom_fg[4]["bom_no"] = child_wrapper.doc.name
fg_wrapper = webnotes.insert(DocList(bom_fg))
fg_wrapper.load_from_db()
self.check_bom_cost(fg_wrapper)
self.check_flat_bom(fg_wrapper, child_wrapper, gc_wrapper)
def check_bom_cost(self, fg_wrapper):
expected_values = {
"operating_cost": 15,
"raw_material_cost": 640,
"total_cost": 655
} }
]
]
for key in expected_values:
self.assertEqual(flt(expected_values[key]), flt(fg_wrapper.doc.fields.get(key)))
# import webnotes.model
def check_flat_bom(self, fg_wrapper, child_wrapper, gc_wrapper): # from webnotes.utils import nowdate, flt
expected_flat_bom_items = { # from accounts.utils import get_fiscal_year
("Home Desktop 300", fg_wrapper.doc.name): (2, 20), # from webnotes.model.doclist import DocList
("Home Desktop 100", fg_wrapper.doc.name): (1, 300), # import copy
("Home Desktop 300", gc_wrapper.doc.name): (30, 10) #
} # company = webnotes.conn.get_default("company")
#
self.assertEqual(len(fg_wrapper.doclist.get({"parentfield": "flat_bom_details"})), 3) #
# def load_data():
for key, val in expected_flat_bom_items.items(): #
flat_bom = fg_wrapper.doclist.get({"parentfield": "flat_bom_details", # # create default warehouse
"item_code": key[0], "parent_bom": key[1]})[0] # if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
self.assertEqual(val, (flat_bom.qty, flat_bom.rate)) # webnotes.insert({"doctype": "Warehouse",
# "warehouse_name": "Default Warehouse",
# "warehouse_type": "Stores"})
def tearDown(self): #
webnotes.conn.rollback() # # create UOM: Nos.
# if not webnotes.conn.exists("UOM", "Nos"):
# webnotes.insert({"doctype": "UOM", "uom_name": "Nos"})
#
# from webnotes.tests import insert_test_data
# # create item groups and items
# insert_test_data("Item Group",
# sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name')))
# insert_test_data("Item")
#
# base_bom_fg = [
# {"doctype": "BOM", "item": "Android Jack D", "quantity": 1,
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
# "opn_description": "Development", "hour_rate": 10, "time_in_mins": 90},
# {"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1,
# "qty": 2, "rate": 20, "stock_uom": "Nos", "parentfield": "bom_materials"},
# {"doctype": "BOM Item", "item_code": "Home Desktop 100", "operation_no": 1,
# "qty": 1, "rate": 300, "stock_uom": "Nos", "parentfield": "bom_materials"},
# {"doctype": "BOM Item", "item_code": "Nebula 7", "operation_no": 1,
# "qty": 5, "stock_uom": "Nos", "parentfield": "bom_materials"},
# ]
#
# base_bom_child = [
# {"doctype": "BOM", "item": "Nebula 7", "quantity": 5,
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
# "opn_description": "Development"},
# {"doctype": "BOM Item", "item_code": "Android Jack S", "operation_no": 1,
# "qty": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
# ]
#
# base_bom_grandchild = [
# {"doctype": "BOM", "item": "Android Jack S", "quantity": 1,
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
# "opn_description": "Development"},
# {"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1,
# "qty": 3, "rate": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
# ]
#
#
# class TestPurchaseReceipt(unittest.TestCase):
# def setUp(self):
# webnotes.conn.begin()
# load_data()
#
# def test_bom_validation(self):
# # show throw error bacause bom no missing for sub-assembly item
# bom_fg = copy.deepcopy(base_bom_fg)
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
#
# # main item is not a manufacturing item
# bom_fg = copy.deepcopy(base_bom_fg)
# bom_fg[0]["item"] = "Home Desktop 200"
# bom_fg.pop(4)
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
#
# # operation no mentioed in material table not matching with operation table
# bom_fg = copy.deepcopy(base_bom_fg)
# bom_fg.pop(4)
# bom_fg[2]["operation_no"] = 2
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
#
#
# def test_bom(self):
# gc_wrapper = webnotes.insert(DocList(base_bom_grandchild))
# gc_wrapper.submit()
#
# bom_child = copy.deepcopy(base_bom_child)
# bom_child[2]["bom_no"] = gc_wrapper.doc.name
# child_wrapper = webnotes.insert(DocList(bom_child))
# child_wrapper.submit()
#
# bom_fg = copy.deepcopy(base_bom_fg)
# bom_fg[4]["bom_no"] = child_wrapper.doc.name
# fg_wrapper = webnotes.insert(DocList(bom_fg))
# fg_wrapper.load_from_db()
#
# self.check_bom_cost(fg_wrapper)
#
# self.check_flat_bom(fg_wrapper, child_wrapper, gc_wrapper)
#
# def check_bom_cost(self, fg_wrapper):
# expected_values = {
# "operating_cost": 15,
# "raw_material_cost": 640,
# "total_cost": 655
# }
#
# for key in expected_values:
# self.assertEqual(flt(expected_values[key]), flt(fg_wrapper.doc.fields.get(key)))
#
# def check_flat_bom(self, fg_wrapper, child_wrapper, gc_wrapper):
# expected_flat_bom_items = {
# ("Home Desktop 300", fg_wrapper.doc.name): (2, 20),
# ("Home Desktop 100", fg_wrapper.doc.name): (1, 300),
# ("Home Desktop 300", gc_wrapper.doc.name): (30, 10)
# }
#
# self.assertEqual(len(fg_wrapper.doclist.get({"parentfield": "flat_bom_details"})), 3)
#
# for key, val in expected_flat_bom_items.items():
# flat_bom = fg_wrapper.doclist.get({"parentfield": "flat_bom_details",
# "item_code": key[0], "parent_bom": key[1]})[0]
# self.assertEqual(val, (flat_bom.qty, flat_bom.rate))
#
#
# def tearDown(self):
# webnotes.conn.rollback()

View File

@ -17,64 +17,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
import webnotes import webnotes
import copy
from webnotes.model.bean import Bean
from webnotes.model.doc import Document
from webnotes.utils import flt
sql = webnotes.conn.sql
class TestItem(unittest.TestCase):
def setUp(self):
webnotes.conn.begin()
def tearDown(self):
webnotes.conn.rollback()
def testInsert(self):
d = Bean()
count_before = flt(sql("select count(*) from tab"+_doctype)[0][0])
if docok:
for i in docok:
d.doc = i
d.children = None
d.doc.fields['__islocal']=1
d.save(1)
count_after = flt(sql("select count(*) from tab"+_doctype)[0][0])
self.assertTrue(count_before+len(docok)==count_after)
def testFailAssert(self):
if docnotok:
with self.assertRaises(Exception) as context:
d = Bean()
d.doc = docnotok[0]
d.children = None
d.doc.fields['__islocal']=1
d.save(1)
# Test Data
tabOK = [
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Ink', 'default_warehouse': None, 'item_name': 'Gel Ink', 'item_group': 'Ink', 'item_code': 'GELINK', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'},
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Refill', 'default_warehouse': None, 'item_name': 'Gel Refill', 'item_group': 'Refill', 'item_code': 'GELREF', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'},
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Pen', 'default_warehouse': None, 'item_name': 'Gel Pen', 'item_group': 'Pen', 'item_code': 'GELPEN', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'}
]
tabNotOK = [
{'is_purchase_item': None, 'is_pro_applicable': None, 'is_manufactured_item': None, 'description': 'F Ink', 'default_warehouse': None, 'item_name': 'F Ink', 'item_group': 'F Ink', 'item_code': None, 'is_sub_contracted_item': None, 'is_stock_item': 'No', 'stock_uom': 'Nos', 'docstatus': '0'}
]
_doctype = 'Item'
for i in tabOK: i['doctype']=_doctype
for i in tabNotOK: i['doctype']=_doctype
docok = [Document(fielddata=r) for r in tabOK]
docnotok = [Document(fielddata=r) for r in tabNotOK]
test_ignore = ["BOM"]
test_records = [ test_records = [
[{ [{
@ -164,4 +108,23 @@ test_records = [
"is_sub_contracted_item": "No", "is_sub_contracted_item": "No",
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM"
}], }],
[{
"doctype": "Item",
"item_code": "_Test FG Item",
"item_name": "_Test FG Item",
"description": "_Test FG Item",
"item_group": "_Test Item Group Desktops",
"is_stock_item": "Yes",
"is_asset_item": "No",
"has_batch_no": "No",
"has_serial_no": "No",
"is_purchase_item": "Yes",
"is_sales_item": "Yes",
"is_service_item": "No",
"is_sample_item": "No",
"inspection_required": "No",
"is_pro_applicable": "Yes",
"is_sub_contracted_item": "Yes",
"stock_uom": "_Test UOM"
}],
] ]

View File

@ -18,10 +18,10 @@ from __future__ import unicode_literals
import webnotes import webnotes
from webnotes.utils import cstr, flt, cint from webnotes.utils import cstr, flt, cint
from webnotes.model.doc import addchild
from webnotes.model.bean import getlist from webnotes.model.bean import getlist
from webnotes.model.code import get_obj from webnotes.model.code import get_obj
from webnotes import msgprint from webnotes.model.doc import Document
from webnotes import msgprint, _
sql = webnotes.conn.sql sql = webnotes.conn.sql
@ -89,8 +89,6 @@ class DocType(BuyingController):
webnotes.msgprint("Another Purchase Receipt using the same Challan No. already exists.\ webnotes.msgprint("Another Purchase Receipt using the same Challan No. already exists.\
Please enter a valid Challan No.", raise_exception=1) Please enter a valid Challan No.", raise_exception=1)
# update valuation rate
def update_valuation_rate(self): def update_valuation_rate(self):
for d in self.doclist.get({"parentfield": "purchase_receipt_details"}): for d in self.doclist.get({"parentfield": "purchase_receipt_details"}):
if d.qty: if d.qty:
@ -99,8 +97,6 @@ class DocType(BuyingController):
else: else:
d.valuation_rate = 0.0 d.valuation_rate = 0.0
#check in manage account if purchase order required or not.
# ====================================================================================
def po_required(self): def po_required(self):
res = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'po_required'") res = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'po_required'")
if res and res[0][0]== 'Yes': if res and res[0][0]== 'Yes':
@ -109,8 +105,6 @@ class DocType(BuyingController):
msgprint("Purchse Order No. required against item %s"%d.item_code) msgprint("Purchse Order No. required against item %s"%d.item_code)
raise Exception raise Exception
# validate
def validate(self): def validate(self):
super(DocType, self).validate() super(DocType, self).validate()
@ -136,16 +130,15 @@ class DocType(BuyingController):
# update valuation rate # update valuation rate
self.update_valuation_rate() self.update_valuation_rate()
# sub-contracting
self.validate_for_subcontracting()
self.update_raw_materials_supplied()
# On Update
# ----------------------------------------------------------------------------------------------------
def on_update(self): def on_update(self):
if self.doc.rejected_warehouse: if self.doc.rejected_warehouse:
for d in getlist(self.doclist,'purchase_receipt_details'): for d in getlist(self.doclist,'purchase_receipt_details'):
d.rejected_warehouse = self.doc.rejected_warehouse d.rejected_warehouse = self.doc.rejected_warehouse
self.update_rw_material_detail()
get_obj('Stock Ledger').scrub_serial_nos(self) get_obj('Stock Ledger').scrub_serial_nos(self)
self.scrub_rejected_serial_nos() self.scrub_rejected_serial_nos()
@ -303,118 +296,66 @@ class DocType(BuyingController):
self.make_gl_entries() self.make_gl_entries()
def validate_for_subcontracting(self):
if self.sub_contracted_items and self.purchase_items and not self.doc.is_subcontracted:
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 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.sub_contracted_items:
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 update_rw_material_detail(self): 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
for d in getlist(self.doclist,'purchase_receipt_details'): def get_items_from_default_bom(self, item_code):
item_det = sql("select is_sub_contracted_item, is_purchase_item from `tabItem` where name = '%s'"%(d.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,
if item_det[0][0] == 'Yes': t2.rate, t2.stock_uom, t2.name, t2.description
if item_det[0][1] == 'Yes':
if not self.doc.is_subcontracted:
msgprint("Please enter whether purchase receipt to be made for subcontracting or for purchase in 'Is Subcontracted' field .")
raise Exception
if self.doc.is_subcontracted == 'Yes':
if not self.doc.supplier_warehouse:
msgprint("Please Enter Supplier Warehouse for subcontracted Items")
raise Exception
self.add_bom(d)
else:
self.doclist = self.doc.clear_table(self.doclist,'pr_raw_material_details',1)
self.doc.save()
elif item_det[0][1] == 'No':
if not self.doc.supplier_warehouse:
msgprint("Please Enter Supplier Warehouse for subcontracted Items")
raise Exception
self.add_bom(d)
self.delete_irrelevant_raw_material()
#---------------calculate amt in Purchase Receipt Item Supplied-------------
self.calculate_amount(d)
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.description
from `tabBOM` t1, `tabBOM Item` t2 from `tabBOM` t1, `tabBOM Item` t2
where t2.parent = t1.name and t1.item = %s and t1.is_default = 1 where t2.parent = t1.name and t1.item = %s and t1.is_default = 1
and t1.docstatus = 1 and t2.docstatus =1 and t1.is_active = 1""", d.item_code) and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1)
if not bom_det: if not bom_items:
msgprint("No default BOM exists for item: %s" % d.item_code) msgprint(_("No default BOM exists for item: ") + item_code, raise_exception=1)
raise Exception
else: return bom_items
#-------------- add child function--------------------
chgd_rqd_qty = []
for i in bom_det:
if i and not sql("select name from `tabPurchase Receipt 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, 'pr_raw_material_details', 'Purchase Receipt 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.description = i and i[7] 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.consumed_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 pr_rmd in getlist(self.doclist, 'pr_raw_material_details'):
if i and i[6] == pr_rmd.bom_detail_no and (flt(act_qty) != flt(pr_rmd.required_qty) or i[1] != pr_rmd.rm_item_code or i[7] != pr_rmd.description):
chgd_rqd_qty.append(cstr(i[1]))
pr_rmd.main_item_code = i[0]
pr_rmd.rm_item_code = i[1]
pr_rmd.description = i[7]
pr_rmd.stock_uom = i[5]
pr_rmd.required_qty = flt(act_qty)
pr_rmd.consumed_qty = flt(act_qty)
pr_rmd.rate = i and flt(i[3]) or flt(i[4])
pr_rmd.amount = flt(flt(pr_rmd.consumed_qty)*flt(pr_rmd.rate))
pr_rmd.save()
if chgd_rqd_qty:
msgprint("Please check consumed quantity for Raw Material Item Code: '%s'in Raw materials Detail Table" % ((len(chgd_rqd_qty) > 1 and ','.join(chgd_rqd_qty[:-1]) +' and ' + cstr(chgd_rqd_qty[-1:][0]) ) or cstr(chgd_rqd_qty[0])))
# Delete irrelevant raw material from PR Raw material details
#--------------------------------------------------------------
def delete_irrelevant_raw_material(self):
for d in getlist(self.doclist,'pr_raw_material_details'):
if not sql("select name from `tabPurchase Receipt 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()
def calculate_amount(self, d):
amt = 0
for i in getlist(self.doclist,'pr_raw_material_details'):
if(i.reference_name == d.name):
#if i.consumed_qty == 0:
# msgprint("consumed qty cannot be 0. Please Enter consumed qty ")
#raise Exception
i.amount = flt(i.consumed_qty)* flt(i.rate)
amt += i.amount
d.rm_supp_cost = amt
d.save()
# --------------- Back Flush function called on submit and on cancel from update stock
def bk_flush_supp_wh(self, is_submit): def bk_flush_supp_wh(self, is_submit):
for d in getlist(self.doclist, 'pr_raw_material_details'): for d in getlist(self.doclist, 'pr_raw_material_details'):
#--------- -ve quantity is passed as raw material qty has to be decreased when PR is submitted and it has to be increased when PR is cancelled # negative quantity is passed as raw material qty has to be decreased
# when PR is submitted and it has to be increased when PR is cancelled
consumed_qty = - flt(d.consumed_qty) consumed_qty = - flt(d.consumed_qty)
self.make_sl_entry(d, self.doc.supplier_warehouse, flt(consumed_qty), 0, is_submit) self.make_sl_entry(d, self.doc.supplier_warehouse, flt(consumed_qty), 0, is_submit)
# get current_stock
# ----------------
def get_current_stock(self): def get_current_stock(self):
for d in getlist(self.doclist, 'pr_raw_material_details'): for d in getlist(self.doclist, 'pr_raw_material_details'):
if self.doc.supplier_warehouse: if self.doc.supplier_warehouse:

View File

@ -64,6 +64,17 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertEquals(expected_values[i][2], gle.credit) self.assertEquals(expected_values[i][2], gle.credit)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0) webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def test_subcontracting(self):
pr = webnotes.bean(copy=test_records[1])
pr.run_method("calculate_taxes_and_totals")
pr.insert()
self.assertEquals(pr.doclist[1].rm_supp_cost, 70000.0)
self.assertEquals(len(pr.doclist.get({"parentfield": "pr_raw_material_details"})), 2)
test_dependencies = ["BOM"]
test_records = [ test_records = [
[ [
@ -129,4 +140,36 @@ test_records = [
"tax_amount": 150.0, "tax_amount": 150.0,
}, },
], ],
[
{
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"doctype": "Purchase Receipt",
"fiscal_year": "_Test Fiscal Year 2013",
"posting_date": "2013-02-12",
"posting_time": "15:33:30",
"is_subcontracted": "Yes",
"supplier_warehouse": "_Test Warehouse",
"supplier": "_Test Supplier",
"net_total": 5000.0,
"grand_total": 5000.0,
},
{
"conversion_factor": 1.0,
"description": "_Test FG Item",
"doctype": "Purchase Receipt Item",
"item_code": "_Test FG Item",
"item_name": "_Test FG Item",
"parentfield": "purchase_receipt_details",
"received_qty": 10.0,
"qty": 10.0,
"rejected_qty": 0.0,
"import_rate": 500.0,
"amount": 5000.0,
"warehouse": "_Test Warehouse",
"stock_uom": "Nos",
"uom": "_Test UOM",
}
],
] ]