[IMP] product, mrp:
added new function field 'seller_id' to get main supplier who has highet priority in Supplier Information also 'seller_qty'. added new function 'price_get' in 'product.supplierinfo' model to get price from supplier pricelist. improved and clean product cost structure report in product form. bzr revid: hmo@tinyerp.com-20100723131730-hx8nw4tkotmfj4ov
This commit is contained in:
parent
6e5270d4e3
commit
3b6ba554a3
|
@ -48,10 +48,10 @@ class mrp_workcenter(osv.osv):
|
|||
'time_cycle': fields.float('Time for 1 cycle (hour)', help="Time in hours for doing one cycle."),
|
||||
'time_start': fields.float('Time before prod.', help="Time in hours for the setup."),
|
||||
'time_stop': fields.float('Time after prod.', help="Time in hours for the cleaning."),
|
||||
'costs_hour': fields.float('Cost per hour'),
|
||||
'costs_hour': fields.float('Cost per hour', help="Specify Cost of Workcenter per hour."),
|
||||
'costs_hour_account_id': fields.many2one('account.analytic.account', 'Hour Account', domain=[('type','<>','view')],
|
||||
help="Complete this only if you want automatic analytic accounting entries on production orders."),
|
||||
'costs_cycle': fields.float('Cost per cycle'),
|
||||
'costs_cycle': fields.float('Cost per cycle', help="Specify Cost of Workcenter per cycle."),
|
||||
'costs_cycle_account_id': fields.many2one('account.analytic.account', 'Cycle Account', domain=[('type','<>','view')],
|
||||
help="Complete this only if you want automatic analytic accounting entries on production orders."),
|
||||
'costs_journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal'),
|
||||
|
|
|
@ -31,53 +31,46 @@ from tools.translate import _
|
|||
class report_custom(report_rml):
|
||||
def create_xml(self, cr, uid, ids, datas, context={}):
|
||||
number = (datas.get('form', False) and datas['form']['number']) or 1
|
||||
|
||||
def process_bom(bom, currency_id):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
product_pool = pool.get('product.product')
|
||||
product_uom_pool = pool.get('product.uom')
|
||||
supplier_info_pool = pool.get('product.supplierinfo')
|
||||
workcenter_pool = pool.get('mrp.workcenter')
|
||||
user_pool = pool.get('res.users')
|
||||
bom_pool = pool.get('mrp.bom')
|
||||
def process_bom(bom, currency_id, factor=1):
|
||||
xml = '<row>'
|
||||
sum = 0
|
||||
sum_strd = 0
|
||||
prod = pooler.get_pool(cr.dbname).get('product.product').browse(cr, uid, bom['product_id'])
|
||||
prod = product_pool.browse(cr, uid, bom['product_id'])
|
||||
|
||||
prod_name = bom['name']
|
||||
prod_qtty = bom['product_qty']
|
||||
prod_uom = prod.uom_id.name
|
||||
prod_qtty = factor * bom['product_qty']
|
||||
product_uom = product_uom_pool.browse(cr, uid, bom['product_uom'], context=context)
|
||||
level = 1
|
||||
main_sp_price = ''
|
||||
main_sp_name = ''
|
||||
main_strd_price = ''
|
||||
main_strd_price = ''
|
||||
if prod.seller_ids and prod.seller_ids[0] :
|
||||
main_sp_name = '<b>' + prod.seller_ids[0].name.name + '</b>\r\n'
|
||||
pricelist_id = prod.seller_ids[0].name.property_product_pricelist_purchase.id
|
||||
if pricelist_id:
|
||||
pricelist_obj = pooler.get_pool(cr.dbname).get('product.pricelist')
|
||||
price = pricelist_obj.price_get(cr,uid,[pricelist_id], prod.id, number*prod_qtty or 1.0).setdefault(pricelist_id, 0)
|
||||
price = pooler.get_pool(cr.dbname).get('res.currency').compute(cr, uid, pricelist_obj.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
|
||||
else:
|
||||
price = 0
|
||||
main_sp_price = '%.2f' % price + '\r\n'
|
||||
main_sp_price, main_sp_name , main_strd_price = '','',''
|
||||
sellers, sellers_price = '',''
|
||||
|
||||
if prod.seller_id:
|
||||
main_sp_name = "<b>%s</b>\r\n" %(prod.seller_id.name)
|
||||
price = supplier_info_pool.price_get(cr, uid, prod.seller_id.id, prod.id, number*prod_qtty)[prod.seller_id.id]
|
||||
price = product_uom_pool._compute_price(cr, uid, prod.uom_id.id, price, to_uom_id=product_uom.id)
|
||||
main_sp_price = '%s\r\n' %(str(price))
|
||||
sum += prod_qtty*price
|
||||
std_price = product_uom_pool._compute_price(cr, uid, prod.uom_id.id, prod.standard_price, to_uom_id=product_uom.id)
|
||||
main_strd_price = str(std_price) + '\r\n'
|
||||
sum_strd = prod_qtty*std_price
|
||||
|
||||
main_strd_price = '%.2f' % prod.standard_price + '\r\n'
|
||||
sum_strd = prod_qtty*prod.standard_price
|
||||
|
||||
sellers = ''
|
||||
sellers_price = ''
|
||||
for seller_id in prod.seller_ids:
|
||||
sellers += '- <i>'+ seller_id.name.name +'</i>\r\n'
|
||||
pricelist_id = seller_id.name.property_product_pricelist_purchase.id
|
||||
if pricelist_id:
|
||||
pricelist_obj = pooler.get_pool(cr.dbname).get('product.pricelist')
|
||||
price = pricelist_obj.price_get(cr,uid,[pricelist_id], prod.id, number*prod_qtty or 1.0).setdefault(pricelist_id, 0)
|
||||
price = pooler.get_pool(cr.dbname).get('res.currency').compute(cr, uid, pricelist_obj.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
|
||||
else:
|
||||
price = 0
|
||||
sellers_price += '%.2f' % price + '\r\n'
|
||||
price = supplier_info_pool.price_get(cr, uid, seller_id.name.id, prod.id, number*prod_qtty)[seller_id.name.id]
|
||||
price = product_uom_pool._compute_price(cr, uid, prod.uom_id.id, price, to_uom_id=product_uom.id)
|
||||
sellers_price += str(price) + '\r\n'
|
||||
|
||||
xml += "<col para='yes'>" + prod_name + '</col>'
|
||||
xml += "<col para='no'>" + main_sp_name + sellers + '</col>'
|
||||
xml += "<col para='yes'>" + str(prod_qtty) + '</col>'
|
||||
xml += "<col para='yes'>" + prod_uom + '</col>'
|
||||
xml += "<col para='yes'>" + product_uom.name + '</col>'
|
||||
xml += "<col para='yes'>" + main_strd_price + '</col>'
|
||||
xml += "<col para='no'>" + main_sp_price + sellers_price + '</col>'
|
||||
|
||||
|
@ -88,9 +81,9 @@ class report_custom(report_rml):
|
|||
def process_workcenter(wrk):
|
||||
xml = '<row>'
|
||||
|
||||
workcenter = pooler.get_pool(cr.dbname).get('mrp.workcenter').browse(cr, uid, wrk['workcenter_id'])
|
||||
workcenter = workcenter_pool.browse(cr, uid, wrk['workcenter_id'])
|
||||
|
||||
xml += "<col para='yes'>" + wrk['name'] + '</col>'
|
||||
xml += "<col para='yes'>" + workcenter.name + '</col>'
|
||||
xml += "<col para='yes'>" + '</col>'
|
||||
xml += "<col para='no'>" + '</col>'
|
||||
xml += "<col/>"
|
||||
|
@ -150,22 +143,23 @@ class report_custom(report_rml):
|
|||
</lines>
|
||||
""" % (_('Product name'), _('Product supplier'), _('Product Quantity'), _('Product uom'), _('Product Standard Price'), _('Unit Product Price'))
|
||||
|
||||
company_currency = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid).company_id.currency_id.id
|
||||
company_currency = user_pool.browse(cr, uid, uid).company_id.currency_id.id
|
||||
first = True
|
||||
for prod_id in ids:
|
||||
bom_ids = pooler.get_pool(cr.dbname).get('mrp.bom').search(cr, uid, [('product_id','=',prod_id)])
|
||||
prod = pooler.get_pool(cr.dbname).get('product.product').browse(cr, uid, prod_id)
|
||||
|
||||
for bom_id in bom_ids:
|
||||
bom = pooler.get_pool(cr.dbname).get('mrp.bom').browse(cr, uid, bom_id)
|
||||
|
||||
sub_boms = pooler.get_pool(cr.dbname).get('mrp.bom')._bom_explode(cr, uid, bom, number, [])
|
||||
for product in product_pool.browse(cr, uid, ids, context=context):
|
||||
bom_ids = bom_pool.search(cr, uid, [('product_id','=',product.id)])
|
||||
for bom in bom_pool.browse(cr, uid, bom_ids, context=context):
|
||||
sub_boms = bom_pool._bom_explode(cr, uid, bom, number, [])
|
||||
total = 0
|
||||
total_strd = 0
|
||||
parent_bom = {'product_qty': bom.product_qty, 'name': bom.product_id.name, 'product_uom': bom.product_id.uom_id.factor, 'product_id': bom.product_id.id}
|
||||
parent_bom = {
|
||||
'product_qty': bom.product_qty,
|
||||
'name': bom.product_id.name,
|
||||
'product_uom': bom.product_uom.id,
|
||||
'product_id': bom.product_id.id
|
||||
}
|
||||
xml_tmp = ''
|
||||
for sub_bom in (sub_boms and sub_boms[0]) or [parent_bom]:
|
||||
txt, sum, sum_strd = process_bom(sub_bom, company_currency)
|
||||
txt, sum, sum_strd = process_bom(sub_bom, company_currency, factor=1/bom.product_qty)
|
||||
xml_tmp += txt
|
||||
total += sum
|
||||
total_strd += sum_strd
|
||||
|
@ -187,7 +181,7 @@ class report_custom(report_rml):
|
|||
|
||||
first = False
|
||||
|
||||
xml = '<?xml version="1.0" ?><report>' + config_start + '<report-header>%s\n\r' % (_('Product Cost Structure')) + prod.name + '</report-header>'+ config_stop + header + xml + '</report>'
|
||||
xml = '<?xml version="1.0" ?><report>' + config_start + '<report-header>%s\n\r' % (_('Product Cost Structure')) + product.name + '</report-header>'+ config_stop + header + xml + '</report>'
|
||||
|
||||
return xml
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ class mrp_price(osv.osv_memory):
|
|||
_columns = {
|
||||
'number': fields.integer('Quantity', required=True, help="Specify quantity of products to produce. Report of Cost structure will be displayed base on this qunatity."),
|
||||
}
|
||||
_defaults = {
|
||||
'number': 1,
|
||||
}
|
||||
|
||||
def print_report(self, cr, uid, ids, context=None):
|
||||
""" To print the report of Product cost structure
|
||||
|
|
|
@ -291,8 +291,7 @@ class procurement_order(osv.osv):
|
|||
if not procurement.product_id.seller_ids:
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (_('No supplier defined for this product !'), procurement.id))
|
||||
return False
|
||||
partner_list = sorted([(partner_id.sequence, partner_id) for partner_id in procurement.product_id.seller_ids if partner_id and partner_id.sequence])
|
||||
partner = partner_list and partner_list[0] and partner_list[0][1] and partner_list[0][1].name or False
|
||||
partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement.
|
||||
|
||||
if user.company_id and user.company_id.partner_id:
|
||||
if partner.id == user.company_id.partner_id.id:
|
||||
|
|
|
@ -59,7 +59,7 @@ class product_uom(osv.osv):
|
|||
|
||||
def _factor_inv_write(self, cursor, user, id, name, value, arg, context):
|
||||
return self.write(cursor, user, id, {'factor': self._compute_factor_inv(value)}, context=context)
|
||||
|
||||
|
||||
def create(self, cr, uid, data, context={}):
|
||||
if 'factor_inv' in data:
|
||||
if data['factor_inv'] <> 1:
|
||||
|
@ -180,7 +180,7 @@ class product_category(osv.osv):
|
|||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
|
||||
'type': fields.selection([('view','View'), ('normal','Normal')], 'Category Type'),
|
||||
}
|
||||
|
||||
|
||||
|
||||
_defaults = {
|
||||
'type' : lambda *a : 'normal',
|
||||
|
@ -212,14 +212,18 @@ product_category()
|
|||
class product_template(osv.osv):
|
||||
_name = "product.template"
|
||||
_description = "Product Template"
|
||||
def _calc_seller_delay(self, cr, uid, ids, name, arg, context={}):
|
||||
def _calc_seller(self, cr, uid, ids, fields, arg, context={}):
|
||||
result = {}
|
||||
for product in self.browse(cr, uid, ids, context):
|
||||
for field in fields:
|
||||
result[product.id] = {field:False}
|
||||
result[product.id]['seller_delay'] = 1
|
||||
if product.seller_ids:
|
||||
partner_list = sorted([(partner_id.sequence, partner_id) for partner_id in product.seller_ids if partner_id and partner_id.sequence])
|
||||
result[product.id] = partner_list and partner_list[0] and partner_list[0][1] and partner_list[0][1].delay or False
|
||||
else:
|
||||
result[product.id] = 1
|
||||
main_supplier = partner_list and partner_list[0] and partner_list[0][1] or False
|
||||
result[product.id]['seller_delay'] = main_supplier and main_supplier.delay or 1
|
||||
result[product.id]['seller_qty'] = main_supplier and main_supplier.qty or 0.0
|
||||
result[product.id]['seller_id'] = main_supplier and main_supplier.name.id or False
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
|
@ -254,7 +258,9 @@ class product_template(osv.osv):
|
|||
help='Coefficient to convert UOM to UOS\n'
|
||||
' uos = uom * coeff'),
|
||||
'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True),
|
||||
'seller_delay': fields.function(_calc_seller_delay, method=True, type='integer', string='Supplier Lead Time', help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
|
||||
'seller_delay': fields.function(_calc_seller, method=True, type='integer', string='Supplier Lead Time', multi="seller_delay", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
|
||||
'seller_qty': fields.function(_calc_seller, method=True, type='float', string='Supplier Quantity', multi="seller_qty", help="This is minimum quantity to purchase from Main Supplier."),
|
||||
'seller_id': fields.function(_calc_seller, method=True, type='many2one', relation="res.partner", string='Main Supplier', help="Main Supplier who has highest priority in Supplier List.", multi="seller_id"),
|
||||
'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'),
|
||||
'loc_rack': fields.char('Rack', size=16),
|
||||
'loc_row': fields.char('Row', size=16),
|
||||
|
@ -633,6 +639,46 @@ class product_supplierinfo(osv.osv):
|
|||
'delay': lambda *a: 1,
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.supplierinfo', context=c)
|
||||
}
|
||||
def price_get(self, cr, uid, supplier_ids, product_id, product_qty=1, context=None):
|
||||
"""
|
||||
Calculate price from supplier pricelist.
|
||||
@param supplier_ids: Ids of res.partner object.
|
||||
@param product_id: Id of product.
|
||||
@param product_qty: specify quantity to purchase.
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
if type(supplier_ids) in (int,long,):
|
||||
supplier_ids = [supplier_ids]
|
||||
res = {}
|
||||
product_pool = self.pool.get('product.product')
|
||||
partner_pool = self.pool.get('res.partner')
|
||||
pricelist_pool = self.pool.get('product.pricelist')
|
||||
currency_pool = self.pool.get('res.currency')
|
||||
currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
|
||||
for supplier in partner_pool.browse(cr, uid, supplier_ids, context=context):
|
||||
# Compute price from standard price of product
|
||||
price = product_pool.price_get(cr, uid, [product_id], 'standard_price')[product_id]
|
||||
|
||||
# Compute price from Purchase pricelist of supplier
|
||||
pricelist_id = supplier.property_product_pricelist_purchase.id
|
||||
if pricelist_id:
|
||||
price = pricelist_pool.price_get(cr, uid, [pricelist_id], product_id, product_qty).setdefault(pricelist_id, 0)
|
||||
price = currency_pool.compute(cr, uid, pricelist_pool.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
|
||||
|
||||
# Compute price from supplier pricelist which are in Supplier Information
|
||||
supplier_info_ids = self.search(cr, uid, [('name','=',supplier.id),('product_id','=',product_id)])
|
||||
if supplier_info_ids:
|
||||
cr.execute('SELECT * ' \
|
||||
'FROM pricelist_partnerinfo ' \
|
||||
'WHERE suppinfo_id IN %s' \
|
||||
'AND min_quantity <= %s ' \
|
||||
'ORDER BY min_quantity DESC LIMIT 1', (tuple(supplier_info_ids),product_qty,))
|
||||
res2 = cr.dictfetchone()
|
||||
if res2:
|
||||
price = res2['price']
|
||||
res[supplier.id] = price
|
||||
return res
|
||||
_order = 'sequence'
|
||||
product_supplierinfo()
|
||||
|
||||
|
|
|
@ -149,6 +149,8 @@
|
|||
<newline/>
|
||||
<field groups="base.group_extended" name="cost_method"/>
|
||||
<newline/>
|
||||
<field groups="base.group_extended" name="seller_id"/>
|
||||
<newline/>
|
||||
<field colspan="4" name="seller_ids" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Descriptions">
|
||||
|
|
|
@ -746,23 +746,24 @@ class procurement_order(osv.osv):
|
|||
po_obj = self.pool.get('purchase.order')
|
||||
for procurement in self.browse(cr, uid, ids):
|
||||
res_id = procurement.move_id.id
|
||||
partner = procurement.product_id.seller_ids[0].name
|
||||
partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement.
|
||||
seller_qty = procurement.product_id.seller_qty
|
||||
seller_delay = int(procurement.product_id.seller_delay)
|
||||
partner_id = partner.id
|
||||
partner_rec = procurement.product_id.seller_ids[0]
|
||||
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
|
||||
pricelist_id = partner.property_product_pricelist_purchase.id
|
||||
|
||||
uom_id = procurement.product_id.uom_po_id.id
|
||||
|
||||
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
|
||||
if procurement.product_id.seller_ids[0].qty:
|
||||
qty = max(qty,partner_rec.qty)
|
||||
if seller_qty:
|
||||
qty = max(qty,seller_qty)
|
||||
|
||||
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, False, {'uom': uom_id})[pricelist_id]
|
||||
|
||||
newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
|
||||
newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
|
||||
newdate = newdate - partner_rec.delay
|
||||
newdate = newdate - seller_delay
|
||||
|
||||
#Passing partner_id to context for purchase order line integrity of Line name
|
||||
context.update({'lang': partner.lang, 'partner_id': partner_id})
|
||||
|
|
Loading…
Reference in New Issue