sub-contracting rewrite with testcases
This commit is contained in:
parent
a1d4b78fbe
commit
5418d71fc0
@ -320,6 +320,7 @@ class DocType(BuyingController):
|
||||
self.doc.posting_date,'Posting Date')
|
||||
|
||||
self.validate_write_off_account()
|
||||
self.update_raw_material_cost()
|
||||
|
||||
def check_prev_docstatus(self):
|
||||
for d in getlist(self.doclist,'entries'):
|
||||
@ -494,3 +495,16 @@ class DocType(BuyingController):
|
||||
def on_update(self):
|
||||
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)
|
@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-01-29 20:53:00",
|
||||
"creation": "2013-02-11 10:54:51",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-02-08 14:06:17",
|
||||
"modified": "2013-02-27 18:10:04",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -282,6 +282,35 @@
|
||||
"search_index": 0,
|
||||
"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,
|
||||
"doctype": "DocField",
|
||||
|
@ -232,7 +232,7 @@ class BuyingController(AccountsController):
|
||||
else:
|
||||
self.doc.grand_total = flt(self.doc.net_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.precision.main.grand_total_import)
|
||||
|
||||
@ -336,3 +336,25 @@ class BuyingController(AccountsController):
|
||||
self._precision.tax = self.meta.get_precision_map(parentfield = \
|
||||
"purchase_tax_details")
|
||||
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
|
@ -18,130 +18,164 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
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")
|
||||
|
||||
|
||||
def load_data():
|
||||
|
||||
# create default warehouse
|
||||
if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
|
||||
webnotes.insert({"doctype": "Warehouse",
|
||||
"warehouse_name": "Default Warehouse",
|
||||
"warehouse_type": "Stores"})
|
||||
|
||||
# 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
|
||||
test_records = [
|
||||
[
|
||||
{
|
||||
"doctype": "BOM",
|
||||
"item": "_Test FG Item",
|
||||
"quantity": 1.0,
|
||||
"is_active": 1,
|
||||
"is_default": 1,
|
||||
"docstatus": 1
|
||||
},
|
||||
{
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
"parentfield": "bom_materials",
|
||||
"qty": 1.0,
|
||||
"rate": 5000.0,
|
||||
"amount": 5000.0,
|
||||
"stock_uom": "No."
|
||||
},
|
||||
{
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"parentfield": "bom_materials",
|
||||
"qty": 2.0,
|
||||
"rate": 1000.0,
|
||||
"amount": 2000.0,
|
||||
"stock_uom": "No."
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
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()
|
||||
|
||||
|
||||
# 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")
|
||||
#
|
||||
#
|
||||
# def load_data():
|
||||
#
|
||||
# # create default warehouse
|
||||
# if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
|
||||
# webnotes.insert({"doctype": "Warehouse",
|
||||
# "warehouse_name": "Default Warehouse",
|
||||
# "warehouse_type": "Stores"})
|
||||
#
|
||||
# # 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()
|
@ -17,64 +17,8 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
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 = [
|
||||
[{
|
||||
@ -164,4 +108,23 @@ test_records = [
|
||||
"is_sub_contracted_item": "No",
|
||||
"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"
|
||||
}],
|
||||
]
|
@ -18,10 +18,10 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cstr, flt, cint
|
||||
from webnotes.model.doc import addchild
|
||||
from webnotes.model.bean import getlist
|
||||
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
|
||||
|
||||
@ -89,8 +89,6 @@ class DocType(BuyingController):
|
||||
webnotes.msgprint("Another Purchase Receipt using the same Challan No. already exists.\
|
||||
Please enter a valid Challan No.", raise_exception=1)
|
||||
|
||||
|
||||
# update valuation rate
|
||||
def update_valuation_rate(self):
|
||||
for d in self.doclist.get({"parentfield": "purchase_receipt_details"}):
|
||||
if d.qty:
|
||||
@ -99,8 +97,6 @@ class DocType(BuyingController):
|
||||
else:
|
||||
d.valuation_rate = 0.0
|
||||
|
||||
#check in manage account if purchase order required or not.
|
||||
# ====================================================================================
|
||||
def po_required(self):
|
||||
res = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'po_required'")
|
||||
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)
|
||||
raise Exception
|
||||
|
||||
|
||||
# validate
|
||||
def validate(self):
|
||||
super(DocType, self).validate()
|
||||
|
||||
@ -136,16 +130,15 @@ class DocType(BuyingController):
|
||||
|
||||
# update valuation rate
|
||||
self.update_valuation_rate()
|
||||
# sub-contracting
|
||||
self.validate_for_subcontracting()
|
||||
self.update_raw_materials_supplied()
|
||||
|
||||
|
||||
# On Update
|
||||
# ----------------------------------------------------------------------------------------------------
|
||||
def on_update(self):
|
||||
if self.doc.rejected_warehouse:
|
||||
for d in getlist(self.doclist,'purchase_receipt_details'):
|
||||
d.rejected_warehouse = self.doc.rejected_warehouse
|
||||
|
||||
self.update_rw_material_detail()
|
||||
get_obj('Stock Ledger').scrub_serial_nos(self)
|
||||
self.scrub_rejected_serial_nos()
|
||||
|
||||
@ -303,118 +296,66 @@ class DocType(BuyingController):
|
||||
|
||||
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'):
|
||||
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 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
|
||||
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 t2.docstatus =1 and t1.is_active = 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:
|
||||
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
|
||||
|
||||
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):
|
||||
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)
|
||||
self.make_sl_entry(d, self.doc.supplier_warehouse, flt(consumed_qty), 0, is_submit)
|
||||
|
||||
|
||||
# get current_stock
|
||||
# ----------------
|
||||
def get_current_stock(self):
|
||||
for d in getlist(self.doclist, 'pr_raw_material_details'):
|
||||
if self.doc.supplier_warehouse:
|
||||
|
@ -64,6 +64,17 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
self.assertEquals(expected_values[i][2], gle.credit)
|
||||
|
||||
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 = [
|
||||
[
|
||||
@ -129,4 +140,36 @@ test_records = [
|
||||
"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",
|
||||
}
|
||||
],
|
||||
]
|
Loading…
Reference in New Issue
Block a user