[MERGE] Merge with main branch trunk-wms

bzr revid: jke@openerp.com-20131105190918-cosbl68i4bzqxc7i
This commit is contained in:
jke-openerp
2013-11-05 20:09:18 +01:00
9 changed files with 122 additions and 65 deletions
+7
View File
@@ -240,6 +240,13 @@ class stock_warehouse(osv.osv):
all_routes += [warehouse.manufacture_pull_id.route_id.id]
return all_routes
def _handle_renaming(self, cr, uid, warehouse, name, context=None):
res = super(stock_warehouse, self)._handle_renaming(cr, uid, warehouse, name, context=context)
pull_obj = self.pool.get('procurement.rule')
#change the manufacture pull rule name
pull_obj.write(cr, uid, warehouse.manufacture_pull_id.id, {'name': warehouse.manufacture_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
return res
def _get_all_products_to_resupply(self, cr, uid, warehouse, context=None):
res = super(stock_warehouse, self)._get_all_products_to_resupply(cr, uid, warehouse, context=context)
if warehouse.manufacture_pull_id and warehouse.manufacture_pull_id.route_id:
+2 -1
View File
@@ -662,7 +662,8 @@ class purchase_order(osv.osv):
if order_line.product_uom.id != order_line.product_id.uom_id.id:
price_unit *= order_line.product_uom.factor
if order.currency_id.id != order.company_id.currency_id.id:
price_unit = self.pool.get('res.currency').compute(cr, uid, order.currency_id.id, order.company_id.currency_id.id, price_unit, context=context)
#we don't round the price_unit, as we may want to store the standard price with more digits than allowed by the currency
price_unit = self.pool.get('res.currency').compute(cr, uid, order.currency_id.id, order.company_id.currency_id.id, price_unit, round=False, context=context)
return {
'name': order_line.name or '',
+7
View File
@@ -148,6 +148,13 @@ class stock_warehouse(osv.osv):
break
return res
def _handle_renaming(self, cr, uid, warehouse, name, context=None):
res = super(stock_warehouse, self)._handle_renaming(cr, uid, warehouse, name, context=context)
pull_obj = self.pool.get('procurement.rule')
#change the buy pull rule name
pull_obj.write(cr, uid, warehouse.buy_pull_id.id, {'name': warehouse.buy_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
return res
def change_route(self, cr, uid, ids, warehouse, new_reception_step=False, new_delivery_step=False, context=None):
res = super(stock_warehouse, self).change_route(cr, uid, ids, warehouse, new_reception_step=new_reception_step, new_delivery_step=new_delivery_step, context=context)
if warehouse.in_type_id.default_location_dest_id != warehouse.buy_pull_id.location_id:
@@ -119,15 +119,12 @@ class purchase_requisition(osv.osv):
context = {}
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'purchase_requisition', 'purchase_line_tree', context=context)
res['context'] = context
po_ids_browse = self.browse(cr, uid, ids, context=context)[0].po_line_ids
po_ids = []
for po in po_ids_browse:
po_ids.append(po.id)
res['context'].update({
po_lines = self.browse(cr, uid, ids, context=context)[0].po_line_ids
res['context'] = {
'search_default_groupby_product': True,
'search_default_hide_cancelled': True,
})
res['domain'] = [('id', 'in', po_ids)]
}
res['domain'] = [('id', 'in', [line.id for line in po_lines])]
return res
def open_rfq(self, cr, uid, ids, context=None):
@@ -212,6 +209,27 @@ class purchase_requisition(osv.osv):
return False
return True
def _prepare_po_from_tender(self, cr, uid, tender, context=None):
""" Prepare the values to write in the purchase order
created from a tender.
:param tender: the source tender from which we generate a purchase order
"""
return {'order_line': [],
'requisition_id': tender.id,
'origin': tender.name}
def _prepare_po_line_from_tender(self, cr, uid, tender, line, purchase_id, context=None):
""" Prepare the values to write in the purchase order line
created from a line of the tender.
:param tender: the source tender from which we generate a purchase order
:param line: the source tender's line from which we generate a line
:param purchase_id: the id of the new purchase
"""
return {'product_qty': line.quantity_bid,
'order_id': purchase_id}
def generate_po(self, cr, uid, ids, context=None):
"""
Generate all purchase order based on selected lines, should only be called on one tender at a time
@@ -255,10 +273,12 @@ class purchase_requisition(osv.osv):
for supplier, product_line in id_per_supplier.items():
#copy a quotation for this supplier and change order_line then validate it
quotation_id = po.search(cr, uid, [('requisition_id', '=', tender.id), ('partner_id', '=', supplier)], limit=1)[0]
new_po = po.copy(cr, uid, quotation_id, default={'order_line': [], 'requisition_id': tender.id, 'origin': tender.name}, context=ctx)
vals = self._prepare_po_from_tender(cr, uid, tender, context=context)
new_po = po.copy(cr, uid, quotation_id, default=vals, context=ctx)
#duplicate po_line and change product_qty if needed and associate them to newly created PO
for line in product_line:
poline.copy(cr, uid, line.id, default={'product_qty': line.quantity_bid, 'order_id': new_po}, context=context)
vals = self._prepare_po_line_from_tender(cr, uid, tender, line, new_po, context=context)
poline.copy(cr, uid, line.id, default=vals, context=context)
#use workflow to set new PO state to confirm
po.signal_purchase_confirm(cr, uid, [new_po])
-6
View File
@@ -70,12 +70,6 @@
<field name="group_stock_multiple_locations" class="oe_inline"/>
<label for="group_stock_multiple_locations"/>
</div>
<!-- TODOJKE TO REMOVE
<div>
<field name="module_stock_location" class="oe_inline"/>
<label for="module_stock_location"/>
</div>
-->
<div>
<field name="module_claim_from_delivery" class="oe_inline"/>
<label for="module_claim_from_delivery"/>
+63 -39
View File
@@ -2285,8 +2285,9 @@ class stock_warehouse(osv.osv):
def onchange_filter_default_resupply_wh_id(self, cr, uid, ids, default_resupply_wh_id, resupply_wh_ids, context=None):
resupply_wh_ids = set([x['id'] for x in (self.resolve_2many_commands(cr, uid, 'resupply_wh_ids', resupply_wh_ids, ['id']))])
resupply_wh_ids.add(default_resupply_wh_id)
resupply_wh_ids = list(resupply_wh_ids)
if default_resupply_wh_id: #If we are removing the default resupply, we don't have default_resupply_wh_id
resupply_wh_ids.add(default_resupply_wh_id)
resupply_wh_ids = list(resupply_wh_ids)
return {'value': {'resupply_wh_ids': resupply_wh_ids}}
def _get_inter_wh_location(self, cr, uid, warehouse, context=None):
@@ -2305,6 +2306,10 @@ class stock_warehouse(osv.osv):
product_ids = self._get_all_products_to_resupply(cr, uid, warehouse, context=context)
self.pool.get('product.product').write(cr, uid, product_ids, {'route_ids': [(4, inter_wh_route_id)]}, context=context)
def _unassign_route_on_products(self, cr, uid, warehouse, inter_wh_route_id, context=None):
product_ids = self._get_all_products_to_resupply(cr, uid, warehouse, context=context)
self.pool.get('product.product').write(cr, uid, product_ids, {'route_ids': [(3, inter_wh_route_id)]}, context=context)
def _get_inter_wh_route(self, cr, uid, warehouse, wh, context=None):
return {
'name': _('%s: Supply Product from %s') % (warehouse.name, wh.name),
@@ -2332,13 +2337,15 @@ class stock_warehouse(osv.osv):
output_loc = wh.lot_stock_id
inter_wh_route_vals = self._get_inter_wh_route(cr, uid, warehouse, wh, context=context)
inter_wh_route_id = route_obj.create(cr, uid, vals=inter_wh_route_vals, context=context)
values = [(output_loc, inter_wh_location, wh.out_type_id.id), (inter_wh_location, input_loc, warehouse.in_type_id.id)]
dummy, pull_rules_list = self._get_push_pull_rules(cr, uid, warehouse, True, values, inter_wh_route_id, context=context)
values = [(output_loc, inter_wh_location, wh.out_type_id.id, wh), (inter_wh_location, input_loc, warehouse.in_type_id.id, warehouse)]
pull_rules_list = self._get_supply_pull_rules(cr, uid, warehouse, values, inter_wh_route_id, context=context)
for pull_rule in pull_rules_list:
pull_obj.create(cr, uid, vals=pull_rule, context=context)
#if the warehouse is also set as default resupply method, assign this route automatically to all product
if default_resupply_wh and default_resupply_wh.id == wh.id:
self._assign_route_on_products(cr, uid, warehouse, inter_wh_route_id, context=context)
#finally, save the route on the warehouse
self.write(cr, uid, [warehouse.id], {'route_ids': [(4, inter_wh_route_id)]}, context=context)
def _default_stock_id(self, cr, uid, context=None):
#lot_input_stock = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock')
@@ -2414,6 +2421,21 @@ class stock_warehouse(osv.osv):
'sequence': 10,
}
def _get_supply_pull_rules(self, cr, uid, supplied_warehouse, values, new_route_id, context=None):
pull_rules_list = []
for from_loc, dest_loc, pick_type_id, warehouse in values:
pull_rules_list.append({
'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context),
'location_src_id': from_loc.id,
'location_id': dest_loc.id,
'route_id': new_route_id,
'action': 'move',
'picking_type_id': pick_type_id,
'procure_method': 'make_to_order',
'warehouse_id': supplied_warehouse.id,
})
return pull_rules_list
def _get_push_pull_rules(self, cr, uid, warehouse, active, values, new_route_id, context=None):
first_rule = True
push_rules_list = []
@@ -2522,7 +2544,7 @@ class stock_warehouse(osv.osv):
#create route selectable on the product to resupply the warehouse from another one
self._create_resupply_routes(cr, uid, warehouse, warehouse.resupply_wh_ids, warehouse.default_resupply_wh_id, context=context)
#return routes and mto pull rule for warehouse
#return routes and mto pull rule to store on the warehouse
return {
'route_ids': wh_route_ids,
'mto_pull_id': mto_pull_id,
@@ -2738,17 +2760,32 @@ class stock_warehouse(osv.osv):
'pick_pack_ship': (_('Pick + Pack + Ship'), [(warehouse.lot_stock_id, warehouse.wh_pack_stock_loc_id, warehouse.int_type_id.id), (warehouse.wh_pack_stock_loc_id, warehouse.wh_output_stock_loc_id, warehouse.pack_type_id.id), (warehouse.wh_output_stock_loc_id, customer_loc, warehouse.out_type_id.id)]),
}
def _handle_renaming(self, cr, uid, warehouse, name, context=None):
location_obj = self.pool.get('stock.location')
route_obj = self.pool.get('stock.location.route')
pull_obj = self.pool.get('procurement.rule')
push_obj = self.pool.get('stock.location.path')
#rename location
location_id = warehouse.lot_stock_id.location_id.id
location_obj.write(cr, uid, location_id, {'name': name}, context=context)
#rename route and push-pull rules
for route in warehouse.route_ids:
route_obj.write(cr, uid, route.id, {'name': route.name.replace(warehouse.name, name, 1)}, context=context)
for pull in route.pull_ids:
pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context)
for push in route.push_ids:
push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context)
#change the mto pull rule name
pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
seq_obj = self.pool.get('ir.sequence')
location_obj = self.pool.get('stock.location')
route_obj = self.pool.get('stock.location.route')
warehouse_obj = self.pool.get('stock.warehouse')
pull_obj = self.pool.get('procurement.rule')
push_obj = self.pool.get('stock.location.path')
context_with_inactive = context.copy()
context_with_inactive['active_test'] = False
@@ -2764,48 +2801,40 @@ class stock_warehouse(osv.osv):
#rename sequence
if vals.get('name'):
name = vals.get('name')
#rename location
location_id = warehouse.lot_stock_id.location_id.id
location_obj.write(cr, uid, location_id, {'name': name}, context=context_with_inactive)
#rename route and push-pull rules
for route in warehouse.route_ids:
route_obj.write(cr, uid, route.id, {'name': route.name.replace(warehouse.name, name, 1)}, context=context_with_inactive)
for pull in route.pull_ids:
pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive)
for push in route.push_ids:
push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context_with_inactive)
#change the mto pull rule name
pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context_with_inactive)
self._handle_renaming(cr, uid, warehouse, name, context=context_with_inactive)
seq_obj.write(cr, uid, warehouse.in_type_id.sequence_id.id, {'name': name + _(' Sequence in'), 'prefix': vals.get('code', warehouse.code) + '\IN\\'}, context=context)
seq_obj.write(cr, uid, warehouse.out_type_id.sequence_id.id, {'name': name + _(' Sequence out'), 'prefix': vals.get('code', warehouse.code) + '\OUT\\'}, context=context)
seq_obj.write(cr, uid, warehouse.pack_type_id.sequence_id.id, {'name': name + _(' Sequence packing'), 'prefix': vals.get('code', warehouse.code) + '\PACK\\'}, context=context)
seq_obj.write(cr, uid, warehouse.pick_type_id.sequence_id.id, {'name': name + _(' Sequence picking'), 'prefix': vals.get('code', warehouse.code) + '\PICK\\'}, context=context)
seq_obj.write(cr, uid, warehouse.int_type_id.sequence_id.id, {'name': name + _(' Sequence internal'), 'prefix': vals.get('code', warehouse.code) + '\INT\\'}, context=context)
if vals.get('resupply_wh_ids') and not vals.get('resupply_route_ids'):
for cmd in vals.get('resupply_wh_ids'):
if cmd[0] == 6:
new_ids = set(cmd[2])
old_ids = set([wh.id for wh in warehouse.resupply_wh_ids])
to_add_wh_ids = new_ids - old_ids
supplier_warehouses = warehouse_obj.browse(cr, uid, list(to_add_wh_ids), context=context)
self._create_resupply_routes(cr, uid, warehouse, supplier_warehouses, warehouse.default_resupply_wh_id, context=context)
if to_add_wh_ids:
supplier_warehouses = warehouse_obj.browse(cr, uid, list(to_add_wh_ids), context=context)
self._create_resupply_routes(cr, uid, warehouse, supplier_warehouses, warehouse.default_resupply_wh_id, context=context)
to_remove_wh_ids = old_ids - new_ids
to_remove_route_ids = route_obj.search(cr, uid, [('supplied_wh_id', '=', warehouse.id), ('supplier_wh_id', 'in', list(to_remove_wh_ids))], context=context)
route_obj.unlink(cr, uid, to_remove_route_ids, context=context)
if to_remove_wh_ids:
to_remove_route_ids = route_obj.search(cr, uid, [('supplied_wh_id', '=', warehouse.id), ('supplier_wh_id', 'in', list(to_remove_wh_ids))], context=context)
if to_remove_route_ids:
route_obj.unlink(cr, uid, to_remove_route_ids, context=context)
else:
#not implemented
pass
if 'default_resupply_wh_id' in vals:
if warehouse.default_resupply_wh_id:
#remove the existing resupplying route on all products
to_remove_route_ids = route_obj.search(cr, uid, [('supplied_wh_id', '=', warehouse.id), ('supplier_wh_id', '=', warehouse.default_resupply_wh_id.id)], context=context)
route_obj.unlink(cr, uid, to_remove_route_ids, context=context)
self._create_resupply_routes(cr, uid, warehouse, [warehouse.default_resupply_wh_id], False, context=context)
for inter_wh_route_id in to_remove_route_ids:
self._unassign_route_on_products(cr, uid, warehouse, inter_wh_route_id, context=context)
if vals.get('default_resupply_wh_id'):
to_remove_route_ids = route_obj.search(cr, uid, [('supplied_wh_id', '=', warehouse.id), ('supplier_wh_id', '=', vals.get('default_resupply_wh_id'))], context=context)
route_obj.unlink(cr, uid, to_remove_route_ids, context=context)
def_supplier_wh = warehouse_obj.browse(cr, uid, vals['default_resupply_wh_id'], context=context)
self._create_resupply_routes(cr, uid, warehouse, [def_supplier_wh], def_supplier_wh, context=context)
#assign the new resupplying route on all products
to_assign_route_ids = route_obj.search(cr, uid, [('supplied_wh_id', '=', warehouse.id), ('supplier_wh_id', '=', vals.get('default_resupply_wh_id'))], context=context)
for inter_wh_route_id in to_assign_route_ids:
self._assign_route_on_products(cr, uid, warehouse, inter_wh_route_id, context=context)
return super(stock_warehouse, self).write(cr, uid, ids, vals=vals, context=context)
@@ -2814,13 +2843,8 @@ class stock_warehouse(osv.osv):
return super(stock_warehouse, self).unlink(cr, uid, ids, context=context)
def get_all_routes_for_wh(self, cr, uid, warehouse, context=None):
all_routes = []
all_routes += [warehouse.crossdock_route_id.id]
all_routes += [warehouse.reception_route_id.id]
all_routes += [warehouse.delivery_route_id.id]
all_routes = [route.id for route in warehouse.route_ids]
all_routes += [warehouse.mto_pull_id.route_id.id]
all_routes += [route.id for route in warehouse.resupply_route_ids]
all_routes += [route.id for route in warehouse.route_ids]
return all_routes
def view_all_routes_for_wh(self, cr, uid, ids, context=None):
@@ -2853,7 +2877,7 @@ class stock_location_path(osv.osv):
if context is None:
context = {}
context_with_inactive = context.copy()
context_with_inactive['active_test']=False
context_with_inactive['active_test'] = False
for route in self.pool.get('stock.location.route').browse(cr, uid, ids, context=context_with_inactive):
for push_rule in route.push_ids:
result[push_rule.id] = True
@@ -3464,7 +3488,7 @@ class stock_picking_type(osv.osv):
'color': fields.related('warehouse_id', 'color', type='integer', string='Color Index'),
'delivery': fields.boolean('Print delivery'),
'sequence_id': fields.many2one('ir.sequence', 'Sequence', required=True),
'sequence_id': fields.many2one('ir.sequence', 'Reference Sequence', required=True),
'default_location_src_id': fields.many2one('stock.location', 'Default Source Location'),
'default_location_dest_id': fields.many2one('stock.location', 'Default Destination Location'),
#TODO: change field name to "code" as it's not a many2one anymore
+3 -2
View File
@@ -744,14 +744,15 @@
<field name="arch" type="xml">
<tree colors="blue:state == 'draft';grey:state == 'cancel';red:state not in ('cancel', 'done') and date &lt; current_date" string="Picking list">
<field name="name"/>
<field name="origin"/>
<field name="location_dest_id"/>
<field name="date"/>
<field name="min_date"/>
<field name="backorder_id"/>
<field name="group_id"/>
<field name="state"/>
<field name="priority"/>
<field name="picking_type_id" invisible="1"/>
<field name="group_id" invisible="1"/>
<field name="origin" invisible="1"/>
</tree>
</field>
</record>
+10 -7
View File
@@ -172,10 +172,14 @@ class stock_quant(osv.osv):
"""
if context is None:
context = {}
currency_obj = self.pool.get('res.currency')
if context.get('force_valuation_amount'):
valuation_amount = context.get('force_valuation_amount')
else:
valuation_amount = quant.product_id.cost_method == 'real' and quant.cost or quant.product_id.standard_price
#the standard_price of the product may be in another decimal precision, or not compatible with the coinage of
#the company currency... so we need to use round() before creating the accounting entries.
valuation_amount = currency_obj.round(cr, uid, quant.company_id.currency_id, valuation_amount * quant.qty)
partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
debit_line_vals = {
'name': move.name,
@@ -185,8 +189,8 @@ class stock_quant(osv.osv):
'ref': move.picking_id and move.picking_id.name or False,
'date': time.strftime('%Y-%m-%d'),
'partner_id': partner_id,
'debit': valuation_amount > 0 and valuation_amount * quant.qty or 0,
'credit': valuation_amount < 0 and -valuation_amount * quant.qty or 0,
'debit': valuation_amount > 0 and valuation_amount or 0,
'credit': valuation_amount < 0 and -valuation_amount or 0,
'account_id': debit_account_id,
}
credit_line_vals = {
@@ -197,12 +201,11 @@ class stock_quant(osv.osv):
'ref': move.picking_id and move.picking_id.name or False,
'date': time.strftime('%Y-%m-%d'),
'partner_id': partner_id,
'credit': valuation_amount > 0 and valuation_amount * quant.qty or 0,
'debit': valuation_amount < 0 and -valuation_amount * quant.qty or 0,
'credit': valuation_amount > 0 and valuation_amount or 0,
'debit': valuation_amount < 0 and -valuation_amount or 0,
'account_id': credit_account_id,
}
res = [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
return res
return [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
def _create_account_move_line(self, cr, uid, quant, move, credit_account_id, debit_account_id, journal_id, context=None):
move_obj = self.pool.get('account.move')
@@ -260,7 +263,7 @@ class stock_move(osv.osv):
new_std_price = move.price_unit
else:
# Get the standard price
amount_unit = product.price_get('standard_price', context=ctx)[product.id]
amount_unit = product.standard_price
new_std_price = ((amount_unit * product_avail) + (move.price_unit * move.product_qty)) / (product_avail + move.product_qty)
# Write the standard price, as SUPERUSER_ID because a warehouse manager may not have the right to write on products
product_obj.write(cr, SUPERUSER_ID, [product.id], {'standard_price': new_std_price}, context=context)
@@ -12,7 +12,7 @@
<record id="picking_type_dropship" model="stock.picking.type">
<field name="name">dropship</field>
<field name="name">Dropship</field>
<field name="sequence_id" ref="seq_picking_type_dropship"/>
<field name="code_id">incoming</field>
<field name="default_location_dest_id" ref="stock.stock_location_suppliers"/>