Jitendra Prajapati (OpenERP) 2013-08-21 18:14:38 +05:30
commit 90cb02eb22
14 changed files with 156 additions and 91 deletions

View File

@ -44,7 +44,7 @@ class procurement_order(osv.osv):
rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context)
if not rule_id:
#if there isn't any specific procurement.rule defined for the product, we try to directly supply it from a supplier
if procurement.product_id.supply_method == 'manufacture' and self.check_bom_exists(cr, uid, [procurement.id], context=context):
if procurement.product_id.supply_method == 'manufacture':
rule_id = self._search_suitable_rule(cr, uid, procurement, [('action', '=', 'manufacture'), ('location_id', '=', procurement.location_id.id)], context=context)
rule_id = rule_id and rule_id[0] or False
return rule_id
@ -52,7 +52,7 @@ class procurement_order(osv.osv):
def _run(self, cr, uid, procurement, context=None):
if procurement.rule_id and procurement.rule_id.action == 'manufacture':
#make a manufacturing order for the procurement
return self.make_mo(cr, uid, [procurement.id], context=context)
return self.make_mo(cr, uid, [procurement.id], context=context)[procurement.id]
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def _check(self, cr, uid, procurement, context=None):
@ -119,32 +119,36 @@ class procurement_order(osv.osv):
move_obj = self.pool.get('stock.move')
procurement_obj = self.pool.get('procurement.order')
for procurement in procurement_obj.browse(cr, uid, ids, context=context):
res_id = procurement.move_dest_id and procurement.move_dest_id.id or False
newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0)
newdate = newdate - relativedelta(days=company.manufacturing_lead)
produce_id = production_obj.create(cr, uid, {
'origin': procurement.origin,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,
'product_uom': procurement.product_uom.id,
'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False,
'product_uos': procurement.product_uos and procurement.product_uos.id or False,
'location_src_id': procurement.location_id.id,
'location_dest_id': procurement.location_id.id,
'bom_id': procurement.bom_id and procurement.bom_id.id or False,
'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
'move_prod_id': res_id,
'company_id': procurement.company_id.id,
})
res[procurement.id] = produce_id
self.write(cr, uid, [procurement.id], {'state': 'running', 'production_id': produce_id})
bom_result = production_obj.action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
production_obj.signal_button_confirm(cr, uid, [produce_id])
if res_id:
move_obj.write(cr, uid, [res_id],
{'location_id': procurement.location_id.id})
if self.check_bom_exists(cr, uid, [procurement.id], context=context):
res_id = procurement.move_dest_id and procurement.move_dest_id.id or False
newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0)
newdate = newdate - relativedelta(days=company.manufacturing_lead)
produce_id = production_obj.create(cr, uid, {
'origin': procurement.origin,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,
'product_uom': procurement.product_uom.id,
'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False,
'product_uos': procurement.product_uos and procurement.product_uos.id or False,
'location_src_id': procurement.location_id.id,
'location_dest_id': procurement.location_id.id,
'bom_id': procurement.bom_id and procurement.bom_id.id or False,
'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'),
'move_prod_id': res_id,
'company_id': procurement.company_id.id,
})
res[procurement.id] = produce_id
self.write(cr, uid, [procurement.id], {'production_id': produce_id})
bom_result = production_obj.action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
production_obj.signal_button_confirm(cr, uid, [produce_id])
if res_id:
move_obj.write(cr, uid, [res_id],
{'location_id': procurement.location_id.id})
else:
res[procurement.id] = False
self.message_post(cr, uid, [procurement.id], body=_("No BoM exists for this product!"), context=context)
self.production_order_create_note(cr, uid, ids, context=context)
return res

View File

@ -27,6 +27,7 @@ class procurement_order(osv.osv):
def create(self, cr, uid, vals, context=None):
procurement_id = super(procurement_order, self).create(cr, uid, vals, context=context)
# TODO: maybe this is not necessary anymore as we do this already
self.run(cr, uid, [procurement_id], context=context)
self.check(cr, uid, [procurement_id], context=context)
return procurement_id

View File

@ -154,13 +154,17 @@ class procurement_order(osv.osv):
def run(self, cr, uid, ids, context=None):
for procurement in self.browse(cr, uid, ids, context=context):
if self._assign(cr, uid, procurement, context=context):
procurement.refresh()
self._run(cr, uid, procurement, context=context or {})
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
else:
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
if procurement.state not in ("running", "done"):
if self._assign(cr, uid, procurement, context=context):
procurement.refresh()
res = self._run(cr, uid, procurement, context=context or {})
if res:
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
else:
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
else:
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
return True
def check(self, cr, uid, ids, context=None):

View File

@ -290,6 +290,7 @@ class purchase_order(osv.osv):
return {}
return {'value': {'currency_id': self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context=context).currency_id.id}}
#Destination address is used when dropshipping
def onchange_dest_address_id(self, cr, uid, ids, address_id):
if not address_id:
return {}
@ -653,7 +654,6 @@ class purchase_order(osv.osv):
def _prepare_order_picking(self, cr, uid, order, context=None):
type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'picking_type_in')[1]
type = self.pool.get("stock.picking.type").browse(cr, uid, type_id, context=context)
return {
'name': self.pool.get('ir.sequence').get_id(cr, uid, type.sequence_id.id, 'id'),
'origin': order.name + ((order.origin and (':' + order.origin)) or ''),
@ -664,11 +664,14 @@ class purchase_order(osv.osv):
'purchase_id': order.id,
'company_id': order.company_id.id,
'move_lines' : [],
'picking_type_id': type_id,
'picking_type_id': type_id,
}
def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, context=None):
''' prepare the stock move data from the PO line '''
type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'picking_type_in')[1]
type = self.pool.get("stock.picking.type").browse(cr, uid, type_id, context=context)
return {
'name': order_line.name or '',
'product_id': order_line.product_id.id,
@ -686,7 +689,8 @@ class purchase_order(osv.osv):
'state': 'draft',
'purchase_line_id': order_line.id,
'company_id': order.company_id.id,
'price_unit': order_line.price_unit,
'price_unit': order_line.price_unit,
'picking_type_id': type_id,
}
def _create_pickings(self, cr, uid, order, order_lines, picking_id=False, context=None):
@ -1112,7 +1116,7 @@ class procurement_order(osv.osv):
def _run(self, cr, uid, procurement, context=None):
if procurement.rule_id and procurement.rule_id.action == 'buy':
#make a purchase order for the procurement
return self.make_po(cr, uid, [procurement.id], context=context)
return self.make_po(cr, uid, [procurement.id], context=context)[procurement.id]
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def _check(self, cr, uid, procurement, context=None):
@ -1223,7 +1227,8 @@ class procurement_order(osv.osv):
res_id = procurement.move_dest_id and procurement.move_dest_id.id or False
partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement.
if not partner:
procurement.write({'message': _('There is no supplier associated to product %s') % (procurement.product_id.name)})
self.message_post(cr, uid, [procurement.id],_('There is no supplier associated to product %s') % (procurement.product_id.name))
res[procurement.id] = False
else:
seller_qty = procurement.product_id.seller_qty
partner_id = partner.id
@ -1273,7 +1278,7 @@ class procurement_order(osv.osv):
'payment_term_id': partner.property_supplier_payment_term.id or False,
}
res[procurement.id] = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=new_context)
self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': res[procurement.id]})
self.write(cr, uid, [procurement.id], {'purchase_id': res[procurement.id]})
pass_ids += [procurement.id]
if pass_ids:
self.message_post(cr, uid, pass_ids, body=_("Draft Purchase Order created"), context=context)

View File

@ -128,7 +128,7 @@
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search"/>
<field name="arch" type="xml">
<xpath expr="//group/filter[@string='Journal']" position="after">
<xpath expr="//group/filter[@string='Picking Type']" position="after">
<filter string="Invoice Type" domain="[]" context="{'group_by':'invoice_type_id'}"/>
</xpath>
</field>

View File

@ -205,16 +205,20 @@ class sale_order(osv.osv):
write_done_ids = []
write_cancel_ids = []
for order in self.browse(cr, uid, ids, context={}):
#TODO: Need to rethink what happens when cancelling
for line in order.order_line:
for procurement in line.procurement_ids:
if procurement.state != 'done':
write_done_ids.append(line.id)
else:
finished = False
if (procurement.state == 'cancel'):
canceled = True
if line.state != 'exception':
states = [x.state for x in line.procurement_ids]
cancel = all([x == 'cancel' for x in states])
doneorcancel = all([x in ('done', 'cancel') for x in states])
if cancel:
canceled = True
if line.state != 'exception':
write_cancel_ids.append(line.id)
if not doneorcancel:
finished = False
if doneorcancel and not cancel:
write_done_ids.append(line.id)
if write_done_ids:
self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
if write_cancel_ids:
@ -256,8 +260,7 @@ class sale_order(osv.osv):
res = []
for order in self.browse(cr, uid, ids, context={}):
for line in order.order_line:
if line.procurement_id:
res.append(line.procurement_id.id)
res += [x.id for x in line.procurement_ids]
return res
class sale_order_line(osv.osv):

View File

@ -22,6 +22,7 @@
from openerp.osv import fields, osv
from openerp.tools.translate import _
class stock_picking(osv.osv):
_inherit = 'stock.picking'
def __get_invoice_state(self, cr, uid, ids, name, arg, context=None):
@ -45,16 +46,24 @@ class stock_picking(osv.osv):
result[move.picking_id.id] = True
return result.keys()
def __get_picking_move(self, cr, uid, ids, context={}):
res = []
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
if move.picking_id:
res.append(move.picking_id.id)
return res
_columns = {
'invoice_state': fields.function(__get_invoice_state, type='selection', selection=[
("invoiced", "Invoiced"),
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")
], string="Invoice Control", required=True,
store={
'procurement.order': (__get_picking_procurement, ['invoice_state'], 10),
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10)
},
], string="Invoice Control", required=True,
store={
'procurement.order': (__get_picking_procurement, ['invoice_state'], 10),
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10),
'stock.move': (__get_picking_move, ['picking_id'], 10),
},
),
}
_defaults = {

View File

@ -48,7 +48,7 @@
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('picking_type_id','=',ref("picking_type_in")), ('location_id.usage','!=','internal'), ('location_dest_id.usage', '=', 'internal')]</field>
<field name="domain" eval="[('picking_type_id','=',ref('picking_type_in')), ('location_id.usage','!=','internal'), ('location_dest_id.usage', '=', 'internal')]"/>
<field name="view_id" ref="view_move_tree_reception_picking"/>
<field name="context" eval="'{\'search_default_product_id\': [active_id]}'"/>
<field name="help" type="html">
@ -69,7 +69,7 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_move_tree_reception_picking"/>
<field name="domain">[('picking_type_id','=',ref("picking_type_out")), ('location_id.usage','=','internal'), ('location_dest_id.usage', '!=', 'internal')]</field>
<field name="domain" eval="[('picking_type_id','=',ref('picking_type_out')), ('location_id.usage','=','internal'), ('location_dest_id.usage', '!=', 'internal')]"/>
<field name="context" eval="'{\'search_default_product_id\': [active_id]}'"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">

View File

@ -61,7 +61,7 @@ class stock_location(osv.osv):
_order = 'parent_left'
def name_get(self, cr, uid, ids, context=None):
res = self._complete_name(cr, uid, ids, 'complete_name', None, context=context)
return res.items()
return res.items()
def _complete_name(self, cr, uid, ids, name, args, context=None):
""" Forms complete name of location from parent location to child location.
@ -432,7 +432,7 @@ class stock_picking(osv.osv):
res[pick.id] = 'done'
continue
order = {'confirmed':0, 'auto':1, 'assigned':2}
order = {'confirmed':0, 'waiting':1, 'assigned':2}
order_inv = dict(zip(order.values(),order.keys()))
lst = [order[x.state] for x in pick.move_lines if x.state not in ('cancel','done')]
if pick.move_lines == 'one':
@ -467,7 +467,7 @@ class stock_picking(osv.osv):
'stock.move': (_get_pickings, ['state', 'picking_id'], 20)}, selection = [
('draft', 'Draft'),
('cancel', 'Cancelled'),
('auto', 'Waiting Another Operation'),
('waiting', 'Waiting Another Operation'),
('confirmed', 'Waiting Availability'),
('assigned', 'Ready to Transfer'),
('done', 'Transferred'),
@ -697,7 +697,8 @@ class stock_picking(osv.osv):
self.action_done(cr, uid, [picking.id], context=context)
continue
for op in picking.pack_operation_ids:
if op.package_id:
#TODO: op.package_id can not work as quants_get is not defined on quant package => gives traceback
if op.package_id:
for quant in quant_package_obj.quants_get(cr, uid, op.package_id, context=context):
self._do_partial_product_move(cr, uid, picking, quant.product_id, quant.qty, quant, context=context)
op.package_id.write(cr, uid, {
@ -705,12 +706,14 @@ class stock_picking(osv.osv):
}, context=context)
elif op.product_id:
moves = self._do_partial_product_move(cr, uid, picking, op.product_id, op.product_qty, op.quant_id, context=context)
quants = []
for m in moves:
for quant in m.quant_ids:
quants.append(quant.id)
quant_obj.write(cr, uid, quants, {
'package_id': op.result_package_id.id
}, context=context)
self._create_backorder(cr, uid, picking, context=context)
@ -1199,7 +1202,7 @@ class stock_move(osv.osv):
('group_id', '=', move.group_id.id),
('location_id', '=', move.location_id.id),
('location_dest_id', '=', move.location_dest_id.id),
('state', 'in', ['confirmed', 'auto'])], context=context)
('state', 'in', ['confirmed', 'waiting'])], context=context)
if picks:
pick = picks[0]
else:
@ -1506,7 +1509,7 @@ class stock_move(osv.osv):
self.write(cr, uid, [move.id], {
'product_uom_qty': move.product_uom_qty - uom_qty,
'product_uos_qty': move.product_uos_qty - uos_qty,
'reserved_quant_ids': []
'reserved_quant_ids': [(6,0,[])]
}, context=context)
return new_move
@ -1932,7 +1935,6 @@ class stock_pack_operation(osv.osv):
'lot_id': fields.many2one('stock.production.lot', 'Lot/Serial Number'),
'result_package_id': fields.many2one('stock.quant.package', 'Container Package', help="If set, the operations are packed into this package", required=False, ondelete='cascade'),
'date': fields.datetime('Date', required=True),
#'lot_id': fields.many2one('stock.production.lot', 'Serial Number', ondelete='CASCADE'),
#'update_cost': fields.boolean('Need cost update'),
'cost': fields.float("Cost", help="Unit Cost for this product line"),
'currency': fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'),

View File

@ -1046,7 +1046,7 @@
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">['|','&amp;',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&amp;',('picking_id','!=',False)]</field>
<field name="domain" eval="['|','&amp;',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&amp;',('picking_id','!=',False),('picking_type_id','=',ref('picking_type_in'))]"/>
<field name="view_id" ref="view_move_tree_reception_picking"/>
<field name="context">{'product_receive': True, 'search_default_future': True}</field>
<field name="help" type="html">
@ -1141,7 +1141,7 @@
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">['|','&amp;',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&amp;',('picking_id','!=',False)]</field>
<field name="domain" eval="['|','&amp;',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&amp;',('picking_id','!=',False),('picking_type_id','=',ref('picking_type_out'))]"/>
<field name="view_id" ref="view_move_tree_reception_picking"/>
<field name="context">{'search_default_future': True}</field>
<field name="help" type="html">

View File

@ -0,0 +1,37 @@
-
Create product with no seller_ids
-
-
Create a sales order with 1 piece for that product and route crossdock
-
!record{sale.order}
-
Confirm sales order
-
!python {
-
Check there is a procurement in exception that has the procurement group of the sales order
-
!python {
assert
-
Adjust the product that it has at least one seller_id
-
!record{id: model: product.product) or in !python
-
Run the Scheduler
-
!python
-
Check the status changed there is no procurement order in exception any more from that procurement group
-
!python{model: procurement.order}
search procurement from
-
Check a purchase quotation was created
-

View File

@ -52,9 +52,6 @@ class stock_location_path(osv.osv):
'name': fields.char('Operation', size=64),
'company_id': fields.many2one('res.company', 'Company'),
'route_id': fields.many2one('stock.location.route', 'Route'),
'product_id' : fields.many2one('product.product', 'Products', ondelete='cascade', select=1),
'location_from_id' : fields.many2one('stock.location', 'Source Location', ondelete='cascade', select=1, required=True),
'location_dest_id' : fields.many2one('stock.location', 'Destination Location', ondelete='cascade', select=1, required=True),
'delay': fields.integer('Delay (days)', help="Number of days to do this transition"),
@ -62,7 +59,7 @@ class stock_location_path(osv.osv):
("invoiced", "Invoiced"),
("2binvoiced", "To Be Invoiced"),
("none", "Not Applicable")], "Invoice Status",
required=True,),
required=True,),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This is the picking type associated with the different pickings"),
'auto': fields.selection(
[('auto','Automatic Move'), ('manual','Manual Operation'),('transparent','Automatic No Step Added')],
@ -254,14 +251,15 @@ class stock_move(osv.osv):
def _push_apply(self, cr, uid, moves, context):
for move in moves:
for route in move.product_id.route_ids:
found = False
for rule in route.push_ids:
if rule.location_from_id.id == move.location_dest_id.id:
self.pool.get('stock.location.path')._apply(cr, uid, rule, move, context=context)
found = True
break
if found: break
if not move.move_dest_id:
for route in move.product_id.route_ids:
found = False
for rule in route.push_ids:
if rule.location_from_id.id == move.location_dest_id.id:
self.pool.get('stock.location.path')._apply(cr, uid, rule, move, context=context)
found = True
break
if found: break
return True
# Create the stock.move.putaway records
@ -272,16 +270,16 @@ class stock_move(osv.osv):
if putaway:
# Should call different methods here in later versions
# TODO: take care of lots
if putaway.method == 'fixed' and putaway.location_id:
if putaway.method == 'fixed' and putaway.location_spec_id:
moveputaway_obj.create(cr, uid, {'move_id': move.id,
'location_id': putaway.location_id.id,
'location_id': putaway.location_spec_id.id,
'quantity': move.product_uom_qty}, context=context)
return True
def action_assign(self, cr, uid, ids, context=None):
result = super(stock_move, self).action_assign(cr, uid, ids, context=context)
self._putaway_apply(cr, uid, ids, context=context)
return result
result = super(stock_move, self).action_assign(cr, uid, ids, context=context)
self._putaway_apply(cr, uid, ids, context=context)
return result
def action_confirm(self, cr, uid, ids, context=None):
result = super(stock_move, self).action_confirm(cr, uid, ids, context)
@ -289,6 +287,8 @@ class stock_move(osv.osv):
self._push_apply(cr, uid, moves, context=context)
return result
def _create_procurement(self, cr, uid, move, context=None):
"""
Next to creating the procurement order, it will propagate the routes

View File

@ -21,7 +21,6 @@
-
!record {model: stock.location.path, id: push_pick}:
name: Pick List
product_id: product.product_product_10
location_from_id: stock.stock_location_output
location_dest_id: location_pack_zone
picking_type_id: stock.picking_type_internal

View File

@ -87,14 +87,15 @@
<field name="arch" type="xml">
<form string="Location Paths" version="7.0">
<group col="4">
<field name="name" />
<field name="name"/>
<newline />
<field name="company_id" groups="base.group_multi_company" />
<newline />
<field name="location_from_id" />
<field name="location_dest_id" />
<field name="auto" />
<field name="delay" />
<field name="location_from_id"/>
<field name="location_dest_id"/>
<field name="picking_type_id"/>
<field name="auto"/>
<field name="delay"/>
</group>
</form>
</field>