[MERGE] merge with main branch
bzr revid: qdp-launchpad@openerp.com-20130924090225-1is038pb3sngz9qe
This commit is contained in:
@@ -229,19 +229,24 @@
|
||||
<button name="%(report_shipping)d" string="Print Delivery Order" states="confirmed,assigned" type="action"/>
|
||||
<button name="%(report_shipping)d" string="Print Delivery Order" states="done" type="action" class="oe_highlight"/>
|
||||
</xpath>
|
||||
<field name="min_date" position="after">
|
||||
<field name="carrier_id"/>
|
||||
<field name="carrier_tracking_ref"/>
|
||||
<field name="number_of_packages"/>
|
||||
</field>
|
||||
<field name="company_id" position="before">
|
||||
<label for="weight" string="Weight"/>
|
||||
<div>
|
||||
<field name="weight" class="oe_inline"/>
|
||||
<field name="weight_uom_id" nolabel="1" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="weight_net" groups="base.group_no_one"/>
|
||||
</field>
|
||||
<xpath expr="//page[@string='Additional Info']/group[last()]" position="after">
|
||||
<separator string="Carrier Informations"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="carrier_id"/>
|
||||
<field name="carrier_tracking_ref"/>
|
||||
<field name="number_of_packages"/>
|
||||
</group>
|
||||
<group>
|
||||
<label for="weight" string="Weight"/>
|
||||
<div>
|
||||
<field name="weight" class="oe_inline"/>
|
||||
<field name="weight_uom_id" nolabel="1" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="weight_net" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<field name="event_ok" on_change="onchange_event_ok(event_ok, context)"/>
|
||||
<label for="event_ok"/>
|
||||
</div>
|
||||
<div name='ean' position="after">
|
||||
<field name="event_type_id" attrs="{'readonly': [('event_ok', '=', False)]}"/>
|
||||
</div>
|
||||
<field name='type' position="after">
|
||||
<field name="event_type_id" attrs="{'readonly': [('event_ok', '=', False)], 'invisible': [('type', '!=', 'service')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
+2
-2
@@ -935,10 +935,10 @@ class mrp_production(osv.osv):
|
||||
'location_id': source_location_id,
|
||||
'location_dest_id': destination_location_id,
|
||||
'move_dest_id': production.move_prod_id.id,
|
||||
'state': 'waiting',
|
||||
'company_id': production.company_id.id,
|
||||
}
|
||||
move_id = stock_move.create(cr, uid, data, context=context)
|
||||
stock_move.action_confirm(cr, uid, [move_id], context=context)
|
||||
production.write({'move_created_ids': [(6, 0, [move_id])]}, context=context)
|
||||
return move_id
|
||||
|
||||
@@ -962,10 +962,10 @@ class mrp_production(osv.osv):
|
||||
'location_id': source_location_id,
|
||||
'location_dest_id': destination_location_id,
|
||||
'move_dest_id': parent_move_id,
|
||||
'state': 'waiting',
|
||||
'company_id': production.company_id.id,
|
||||
'procure_method': 'make_to_order',
|
||||
})
|
||||
stock_move.action_confirm(cr, uid, [move_id], context=context)
|
||||
production.write({'move_lines': [(4, move_id)]}, context=context)
|
||||
return move_id
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ This application supports complete integration and production scheduling for sto
|
||||
-->
|
||||
|
||||
<record id="route_warehouse0_manufacture" model='stock.location.route'>
|
||||
<field name="name">Your Company Manufacture</field>
|
||||
<field name="name">Manufacture</field>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ class procurement_rule(osv.osv):
|
||||
'''
|
||||
_name = 'procurement.rule'
|
||||
_description = "Procurement Rule"
|
||||
_order = "name"
|
||||
|
||||
def _get_action(self, cr, uid, context=None):
|
||||
return []
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="project_id" attrs="{'invisible':[('type','!=','service')]}" />
|
||||
</field>
|
||||
<field name="standard_price" position="after">
|
||||
<field name="auto_create_task"/>
|
||||
<field name="auto_create_task" attrs="{'invisible': [('type', '!=', 'service')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -667,10 +667,8 @@ class purchase_order(osv.osv):
|
||||
return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
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'),
|
||||
'name': self.pool.get('ir.sequence').get_id(cr, uid, order.picking_type_id.sequence_id.id, 'id'),
|
||||
'origin': order.name + ((order.origin and (':' + order.origin)) or ''),
|
||||
'date': self.date_to_datetime(cr, uid, order.date_order, context),
|
||||
'partner_id': order.dest_address_id.id or order.partner_id.id,
|
||||
@@ -679,12 +677,11 @@ 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': order.picking_type_id.id,
|
||||
}
|
||||
|
||||
def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group_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]
|
||||
price_unit = order_line.price_unit
|
||||
if order_line.product_uom.id != order_line.product_id.uom_id.id:
|
||||
price_unit *= order_line.product_uom.factor
|
||||
@@ -709,7 +706,7 @@ class purchase_order(osv.osv):
|
||||
'purchase_line_id': order_line.id,
|
||||
'company_id': order.company_id.id,
|
||||
'price_unit': price_unit,
|
||||
'picking_type_id': type_id,
|
||||
'picking_type_id': order.picking_type_id.id,
|
||||
'group_id': group_id,
|
||||
}
|
||||
|
||||
@@ -739,7 +736,7 @@ class purchase_order(osv.osv):
|
||||
stock_move = self.pool.get('stock.move')
|
||||
|
||||
new_group = False
|
||||
if any([(x.group_id == False) for x in order_lines]):
|
||||
if any([(not x.group_id) for x in order_lines]):
|
||||
new_group = self.pool.get("procurement.group").create(cr, uid, {'name':order.name, 'partner_id': order.partner_id.id}, context=context)
|
||||
|
||||
|
||||
@@ -1379,4 +1376,15 @@ class account_invoice_line(osv.Model):
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
|
||||
def _get_buy_route(self, cr, uid, context=None):
|
||||
buy_route = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'purchase', 'route_warehouse0_buy')[1]
|
||||
return [buy_route]
|
||||
|
||||
_defaults = {
|
||||
'route_ids': _get_buy_route,
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
-->
|
||||
|
||||
<record id="route_warehouse0_buy" model='stock.location.route'>
|
||||
<field name="name">Your Company Buy</field>
|
||||
<field name="name">Buy</field>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -297,6 +297,12 @@
|
||||
!python {model: stock.picking}: |
|
||||
picking_obj = self.browse(cr, uid, ref("outgoing_fifo_shipment_neg"))
|
||||
picking_obj.do_partial(context=context)
|
||||
-
|
||||
The behavior of fifo/lifo is not garantee if the quants are created at the same second, so i just wait one second
|
||||
-
|
||||
!python {model: stock.picking}: |
|
||||
import time
|
||||
time.sleep(1)
|
||||
-
|
||||
Let us create another out of 400 kg
|
||||
-
|
||||
@@ -392,4 +398,4 @@
|
||||
quant_obj = self.pool.get("stock.quant")
|
||||
quants = quant_obj.search(cr, uid, [('product_id','=',ref("product_fifo_negative"))])
|
||||
print "Quants:", [(x.qty, x.location_id.name, x.in_date, x.cost, x.id) for x in quant_obj.browse(cr, uid, quants)]
|
||||
assert self.browse(cr, uid, ref("product_fifo_negative")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_negative")).standard_price,)
|
||||
assert self.browse(cr, uid, ref("product_fifo_negative")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_negative")).standard_price,)
|
||||
|
||||
@@ -85,17 +85,6 @@
|
||||
|
||||
<!-- Inherit stock picking's tree view -->
|
||||
|
||||
<record model="ir.ui.view" id="sale_journal_picking_order_tree">
|
||||
<field name="name">stock.picking.journal.view.tree</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.vpicktree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="state" position="before">
|
||||
<field name="invoice_type_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_property_form" model="ir.ui.view">
|
||||
<field name="name">res.partner.journal.property.form.inherit</field>
|
||||
<field name="model">res.partner</field>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<field name="model">stock.location.route</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='warehouse_selectable']" position="after">
|
||||
<field name="sale_selectable"/>
|
||||
<field name="sale_selectable" string="Sale Order Lines"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -47,7 +47,7 @@ class procurement_rule(osv.osv):
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'location_id': fields.many2one('stock.location', 'Destination Location'),
|
||||
'location_id': fields.many2one('stock.location', 'Procurement Location'),
|
||||
'location_src_id': fields.many2one('stock.location', 'Source Location',
|
||||
help="Source location is action=move"),
|
||||
'route_id': fields.many2one('stock.location.route', 'Route',
|
||||
|
||||
@@ -52,9 +52,9 @@ openerp.stock = function(openerp) {
|
||||
labelFontColor: '#000',
|
||||
label: label,
|
||||
levelColors: [
|
||||
"#ff0000",
|
||||
"#a9d70b",
|
||||
"#f9c802",
|
||||
"#a9d70b"
|
||||
"#ff0000"
|
||||
],
|
||||
});
|
||||
},
|
||||
|
||||
+82
-37
@@ -215,7 +215,10 @@ class stock_quant(osv.osv):
|
||||
# add location_dest_id in parameters (False=use the destination of the move)
|
||||
def quants_move(self, cr, uid, quants, move, context=None):
|
||||
for quant, qty in quants:
|
||||
self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
#quant may be a browse record or None
|
||||
quant_record = self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
#quant_record is the quant newly created or already split
|
||||
self._quant_reconcile_negative(cr, uid, quant_record, context=context)
|
||||
|
||||
def check_preferred_location(self, cr, uid, move, context=None):
|
||||
return move.location_dest_id
|
||||
@@ -233,7 +236,6 @@ class stock_quant(osv.osv):
|
||||
'history_ids': [(4, move.id)]
|
||||
})
|
||||
quant.refresh()
|
||||
self._quant_reconcile_negative(cr, uid, quant, context=context)
|
||||
return quant
|
||||
|
||||
def quants_get(self, cr, uid, location, product, qty, domain=None, prefered_order=False, reservedcontext=None, restrict_lot_id=False, restrict_partner_id=False, context=None):
|
||||
@@ -317,19 +319,28 @@ class stock_quant(osv.osv):
|
||||
move = m
|
||||
return move
|
||||
|
||||
def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
self._quant_split(cr, uid, quant, qty, context=context)
|
||||
remaining_to_solve_quant = self._quant_split(cr, uid, to_solve_quant, qty, context=context)
|
||||
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
#if the reconciliation was not complete, we need to link together the remaining parts
|
||||
if remaining_to_solve_quant and remaining_neg_quant:
|
||||
self.write(cr, uid, remaining_to_solve_quant.id, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
#delete the reconciled quants, as it is replaced by the solving quant
|
||||
self.unlink(cr, SUPERUSER_ID, [quant_neg.id, to_solve_quant.id], context=context)
|
||||
#call move_single_quant to ensure recursivity if necessary and do the stock valuation
|
||||
self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
return remaining_to_solve_quant
|
||||
#def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
# move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
# remaining_solving_quant = self._quant_split(cr, uid, quant, qty, context=context)
|
||||
# remaining_to_solve_quant = self._quant_split(cr, uid, to_solve_quant, qty, context=context)
|
||||
# remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
# #if the reconciliation was not complete, we need to link together the remaining parts
|
||||
# if remaining_to_solve_quant and remaining_neg_quant:
|
||||
# self.write(cr, uid, remaining_to_solve_quant.id, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
# #delete the reconciled quants, as it is replaced by the solving quant
|
||||
# if remaining_neg_quant:
|
||||
# otherquant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
||||
# self.write(cr, uid, otherquant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
# self.unlink(cr, SUPERUSER_ID, [quant_neg.id, to_solve_quant.id], context=context)
|
||||
# #call move_single_quant to ensure recursivity if necessary and do the stock valuation
|
||||
# self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
# return remaining_solving_quant, remaining_to_solve_quant
|
||||
|
||||
def _quants_merge(self, cr, uid, solved_quant_ids, solving_quant, context=None):
|
||||
path = []
|
||||
for move in solving_quant.history_ids:
|
||||
path.append((4, move.id))
|
||||
self.write(cr, uid, solved_quant_ids, {'history_ids': path}, context=context)
|
||||
|
||||
def _quant_reconcile_negative(self, cr, uid, quant, context=None):
|
||||
"""
|
||||
@@ -339,18 +350,42 @@ class stock_quant(osv.osv):
|
||||
"""
|
||||
if quant.location_id.usage != 'internal':
|
||||
return False
|
||||
solving_quant = quant
|
||||
quants = self.quants_get(cr, uid, quant.location_id, quant.product_id, quant.qty, [('qty', '<', '0')], context=context)
|
||||
for quant_neg, qty in quants:
|
||||
if not quant_neg:
|
||||
continue
|
||||
to_solve_quant = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', '!=', quant.id)], context=context)
|
||||
if not to_solve_quant:
|
||||
to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
||||
if not to_solve_quant_ids:
|
||||
continue
|
||||
to_solve_quant = self.browse(cr, uid, to_solve_quant[0], context=context)
|
||||
self._reconcile_single_negative_quant(cr, uid, to_solve_quant, quant, quant_neg, qty, context=context)
|
||||
solving_qty = qty
|
||||
solved_quant_ids = []
|
||||
for to_solve_quant in self.browse(cr, uid, to_solve_quant_ids, context=context):
|
||||
if solving_qty <= 0:
|
||||
continue
|
||||
solved_quant_ids.append(to_solve_quant.id)
|
||||
self._quant_split(cr, uid, to_solve_quant, min(solving_qty, to_solve_quant.qty), context=context)
|
||||
solving_qty -= min(solving_qty, to_solve_quant.qty)
|
||||
#merge history (and cost?)
|
||||
self._quants_merge(cr, uid, solved_quant_ids, solving_quant, context=context)
|
||||
remaining_solving_quant = self._quant_split(cr, uid, solving_quant, qty, context=context)
|
||||
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
#if the reconciliation was not complete, we need to link together the remaining parts
|
||||
if remaining_neg_quant:
|
||||
remaining_to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', 'not in', solved_quant_ids)], context=context)
|
||||
if remaining_to_solve_quant_ids:
|
||||
self.write(cr, uid, remaining_to_solve_quant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
quant_cost = solving_quant.cost
|
||||
#delete the reconciled quants, as it is replaced by the solving quant
|
||||
self.unlink(cr, SUPERUSER_ID, [quant_neg.id, solving_quant.id], context=context)
|
||||
#price update + accounting entries adjustments
|
||||
self._price_update(cr, uid, solved_quant_ids, quant_cost, context=context)
|
||||
solving_quant = remaining_solving_quant
|
||||
|
||||
def _price_update(self, cr, uid, quant, newprice, context=None):
|
||||
self.write(cr, uid, [quant.id], {'cost': newprice}, context=context)
|
||||
#solving_quant, dummy = self._reconcile_single_negative_quant(cr, uid, to_solve_quant, solving_quant, quant_neg, qty, context=context)
|
||||
|
||||
def _price_update(self, cr, uid, ids, newprice, context=None):
|
||||
self.write(cr, uid, ids, {'cost': newprice}, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
#We want to trigger the move with nothing on reserved_quant_ids for the store of the remaining quantity
|
||||
@@ -379,8 +414,6 @@ class stock_quant(osv.osv):
|
||||
domain += [('product_id','=',product.id)] + domain
|
||||
res = []
|
||||
offset = 0
|
||||
#id is added at the end of the order to make sure the order is always the same for quants created at the same second
|
||||
orderby += ', id asc'
|
||||
while quantity > 0:
|
||||
quants = self.search(cr, uid, domain, order=orderby, limit=10, offset=offset, context=context)
|
||||
if not quants:
|
||||
@@ -542,7 +575,7 @@ class stock_picking(osv.osv):
|
||||
* Cancelled: has been cancelled, can't be confirmed anymore"""
|
||||
),
|
||||
'min_date': fields.function(get_min_max_date, multi="min_max_date",
|
||||
store={'stock.move': (_get_pickings, ['state', 'date_expected'], 20)}, type='datetime', string='Scheduled Time', select=1, help="Scheduled time for the first part of the shipment to be processed"),
|
||||
store={'stock.move': (_get_pickings, ['state', 'date_expected'], 20)}, type='datetime', string='Scheduled Date', select=1, help="Scheduled time for the first part of the shipment to be processed"),
|
||||
'max_date': fields.function(get_min_max_date, multi="min_max_date",
|
||||
store={'stock.move': (_get_pickings, ['state', 'date_expected'], 20)}, type='datetime', string='Max. Expected Date', select=2, help="Scheduled time for the last part of the shipment to be processed"),
|
||||
'date': fields.datetime('Commitment Date', help="Date promised for the completion of the transfer order, usually set the time of the order and revised later on.", select=True, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}),
|
||||
@@ -808,14 +841,18 @@ class stock_picking(osv.osv):
|
||||
def rereserve(self, cr, uid, picking_ids, create=False, context=None):
|
||||
"""
|
||||
This will unreserve all products and reserve the quants from the operations
|
||||
:return: tuple of dictionary with quantities of quant operation and product that can not be matched between ops and moves
|
||||
:return: Tuple (res, res2)
|
||||
res: dictionary of ops with quantity that could not be processed matching ops and moves
|
||||
res2: dictionary of moves with quantity that could not be processed
|
||||
resneg: the negative quants that should be created with ops and move (TODO)
|
||||
tuple of dictionary with quantities of quant operation and product that can not be matched between ops and moves
|
||||
and dictionary with remaining values on moves
|
||||
|
||||
"""
|
||||
quant_obj = self.pool.get("stock.quant")
|
||||
move_obj = self.pool.get("stock.move")
|
||||
op_obj = self.pool.get("stock.pack.operation")
|
||||
res = {}
|
||||
res = {} # Qty still to do from ops
|
||||
res2 = {} #what is left from moves
|
||||
for picking in self.browse(cr, uid, picking_ids, context=context):
|
||||
# unreserve everything and initialize res2
|
||||
@@ -825,14 +862,14 @@ class stock_picking(osv.osv):
|
||||
# Resort pack_operation_ids
|
||||
|
||||
orderedpackops = picking.pack_operation_ids
|
||||
#Sort packing operations such that packing operations with most specific information
|
||||
orderedpackops.sort(key = lambda x: (x.package_id and -1 or 0) + (x.lot_id and -1 or 0))
|
||||
#Sort packing operations such that only transferring packages happens first and then packing operations with most specific information
|
||||
orderedpackops.sort(key = lambda x: ((x.package_id and not x.product_id) and -3 or 0) + (x.package_id and -1 or 0) + (x.lot_id and -1 or 0))
|
||||
|
||||
for ops in orderedpackops:
|
||||
#Find moves that correspond
|
||||
if ops.product_id:
|
||||
#TODO: Should have order such that things with lots and packings are searched first
|
||||
move_ids = move_obj.search(cr, uid, [('picking_id','=',picking.id), ('product_id', '=', ops.product_id.id), ('remaining_qty', '>', 0.0)], context=context)
|
||||
move_ids = move_obj.search(cr, uid, [('picking_id','=',picking.id), ('product_id', '=', ops.product_id.id), ('remaining_qty', '>', 0.0), ('state', '=', 'assigned')], context=context)
|
||||
qty_to_do = ops.product_qty
|
||||
while qty_to_do > 0 and move_ids:
|
||||
move = move_obj.browse(cr, uid, move_ids.pop(), context=context)
|
||||
@@ -862,8 +899,9 @@ class stock_picking(osv.osv):
|
||||
else:
|
||||
#Quants get
|
||||
prefered_order = "reservation_id IS NOT NULL"
|
||||
domain = op_obj._get_domain(cr, uid, ops, context=context)
|
||||
quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, qty, domain=domain, prefered_order=prefered_order, context=context)
|
||||
dom = op_obj._get_domain(cr, uid, ops, context=context)
|
||||
dom = dom + [('reservation_id', 'not in', [x.id for x in picking.move_lines])]
|
||||
quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, qty, domain=dom, prefered_order=prefered_order, context=context)
|
||||
quant_obj.quants_reserve(cr, uid, quants, move, context=context)
|
||||
#In the end, move quants in correct package
|
||||
if create:
|
||||
@@ -873,6 +911,7 @@ class stock_picking(osv.osv):
|
||||
res[ops.id][ops.product_id.id] = qty_to_do
|
||||
elif ops.package_id:
|
||||
quants = ops.package_id.quant_ids #_get_package_lines
|
||||
|
||||
for quant in quants:
|
||||
move_ids = move_obj.search(cr, uid, [('picking_id', '=', picking.id), ('product_id', '=', quant.product_id.id), ('remaining_qty', '>', 0.0)])
|
||||
qty_to_do = quant.qty
|
||||
@@ -908,6 +947,9 @@ class stock_picking(osv.osv):
|
||||
#First thing that needs to happen is rereserving the quants
|
||||
res = self.rereserve(cr, uid, [picking.id], create = True, context = context) #This time, quants need to be created
|
||||
orig_moves = picking.move_lines
|
||||
orig_qtys = {}
|
||||
for orig in orig_moves:
|
||||
orig_qtys[orig.id] = orig.product_qty
|
||||
#Add moves that operations need extra
|
||||
extra_moves = []
|
||||
for ops in res[0].keys():
|
||||
@@ -926,16 +968,19 @@ class stock_picking(osv.osv):
|
||||
'location_dest_id': picking.location_dest_id.id,
|
||||
'picking_id': picking.id,
|
||||
'reserved_quant_ids': quant and [(4, quant.id)] or [],
|
||||
'picking_type_id': picking.picking_type_id.id
|
||||
'picking_type_id': picking.picking_type_id.id,
|
||||
'group_id': picking.group_id.id,
|
||||
}, context=context)
|
||||
extra_moves.append(move_id)
|
||||
res2 = res[1]
|
||||
for move in res2.keys():
|
||||
if res2[move] > 0:
|
||||
mov = stock_move_obj.browse(cr, uid, move, context=context)
|
||||
stock_move_obj.split(cr, uid, mov, res2[move], context=context)
|
||||
new_move = stock_move_obj.split(cr, uid, mov, res2[move], context=context)
|
||||
#Assign move as it was assigned before
|
||||
stock_move_obj.action_assign(cr, uid, [new_move])
|
||||
todo = []
|
||||
orig_moves = [x for x in orig_moves if x.reserved_quant_ids]
|
||||
orig_moves = [x for x in orig_moves if res[1][x.id] < orig_qtys[x.id]]
|
||||
for move in orig_moves + stock_move_obj.browse(cr, uid, extra_moves, context=context):
|
||||
if move.state == 'draft':
|
||||
self.pool.get('stock.move').action_confirm(cr, uid, [move.id],
|
||||
@@ -1533,7 +1578,6 @@ class stock_move(osv.osv):
|
||||
"""
|
||||
context = context or {}
|
||||
quant_obj = self.pool.get("stock.quant")
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
done = []
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.state not in ('confirmed', 'waiting'):
|
||||
@@ -1548,7 +1592,7 @@ class stock_move(osv.osv):
|
||||
for q in m2.quant_ids:
|
||||
dp.append(str(q.id))
|
||||
qty -= q.qty
|
||||
domain = ['|', ('reservation_id', '=', False), ('reservation_id', '=', move.id)]
|
||||
domain = ['|', ('reservation_id', '=', False), ('reservation_id', '=', move.id), ('qty', '>', 0)]
|
||||
quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, qty, domain=domain, prefered_order = dp and ('id not in ('+','.join(dp)+')') or False, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
|
||||
#Will only reserve physical quants, no negative
|
||||
quant_obj.quants_reserve(cr, uid, quants, move, context=context)
|
||||
@@ -1802,7 +1846,7 @@ class stock_inventory(osv.osv):
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Inventory Reference', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Inventory Name."),
|
||||
'date': fields.datetime('Creation Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Inventory Create Date."),
|
||||
'date': fields.datetime('Inventory Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Inventory Create Date."),
|
||||
'date_done': fields.datetime('Date done', help="Inventory Validation Date."),
|
||||
'line_ids': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', readonly=False, states={'done': [('readonly', True)]}, help="Inventory Lines."),
|
||||
'move_ids': fields.one2many('stock.move', 'inventory_id', 'Created Moves', help="Inventory Moves."),
|
||||
@@ -1814,6 +1858,7 @@ class stock_inventory(osv.osv):
|
||||
'partner_id': fields.many2one('res.partner', 'Owner', readonly=True, states={'draft': [('readonly', False)]}, help="Specify Owner to focus your inventory on a particular Owner."),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Lot/Serial Number', readonly=True, states={'draft': [('readonly', False)]}, help="Specify Lot/Serial Number to focus your inventory on a particular Lot/Serial Number."),
|
||||
'move_ids_exist': fields.function(_get_move_ids_exist, type='boolean', string=' Stock Move Exists?', help='technical field for attrs in view'),
|
||||
'filter': fields.selection([('product', 'Product'), ('owner', 'Owner'), ('product_owner','Product & Owner'), ('lot','Lot/Serial Number'), ('pack','Pack'), ('none', 'None')], 'Selection Filter'),
|
||||
}
|
||||
|
||||
def _default_stock_location(self, cr, uid, context=None):
|
||||
|
||||
+83
-121
@@ -8,15 +8,14 @@
|
||||
groups="group_stock_manager,group_stock_user"
|
||||
sequence="70"/>
|
||||
|
||||
<menuitem id="menu_stock_warehouse_mgmt" name="Receive/Deliver By Orders" parent="menu_stock_root" sequence="1"/>
|
||||
<menuitem id="menu_stock_products_moves" name="Receive/Deliver Products" parent="menu_stock_root" sequence="2"/>
|
||||
<menuitem id="menu_stock_warehouse_mgmt" name="Operations" parent="menu_stock_root" sequence="1"/>
|
||||
<menuitem id="menu_stock_product" name="Products" parent="menu_stock_root" sequence="6"/>
|
||||
<menuitem name="Products by Category" id="menu_product_by_category_stock_form" action="product.product_category_action"
|
||||
parent="stock.menu_stock_product" sequence="0"/>
|
||||
<menuitem action="product.product_normal_action" id="menu_stock_products_menu" parent="menu_stock_product" sequence="1"/>
|
||||
<menuitem id="menu_stock_configuration" name="Configuration" parent="menu_stock_root" sequence="15" groups="group_stock_manager"/>
|
||||
<menuitem id="menu_warehouse_config" name="Warehouse Management" parent="menu_stock_configuration" sequence="40" groups="base.group_no_one"/>
|
||||
<menuitem id="menu_stock_inventory_control" name="Inventory Control" parent="menu_stock_root" sequence="4"/>
|
||||
<menuitem id="menu_stock_inventory_control" name="Inventory Control" parent="menu_stock_root" sequence="2"/>
|
||||
<menuitem
|
||||
id="menu_product_in_config_stock" name="Products"
|
||||
parent="stock.menu_stock_configuration" sequence="45" groups="base.group_no_one"/>
|
||||
@@ -100,7 +99,7 @@
|
||||
<field name="name">stock.inventory.form</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Physical Inventory" version="7.0">
|
||||
<form string="Inventory Adjustment" version="7.0">
|
||||
<header>
|
||||
<button name="prepare_inventory" states="draft" string="Start Inventory" type="object" class="oe_highlight" groups="stock.group_stock_user"/>
|
||||
<button name="action_done" states="confirm" string="Validate Inventory" type="object" class="oe_highlight" groups="stock.group_stock_manager"/>
|
||||
@@ -119,16 +118,20 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
<div class="oe_grey" colspan="4">Specify filters to focus your inventory a on particular product, lot, pack and product's owner.</div>
|
||||
<group>
|
||||
<field name="product_id" domain="[('type','=','product')]"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<label for="filter"/>
|
||||
<div colspan="4">
|
||||
<field name="filter" widget='radio'/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="partner_id"/>
|
||||
<field name="package_id"/>
|
||||
<field name="product_id" domain="[('type','=','product')]" attrs="{'invisible': [('filter', 'not in', ('product', 'product_owner'))]}"/>
|
||||
<field name="lot_id" attrs="{'invisible': [('filter', '!=', 'lot')]}"/>
|
||||
<field name="partner_id" attrs="{'invisible': [('filter', 'not in', ('owner', 'product_owner'))]}"/>
|
||||
<field name="package_id" attrs="{'invisible': [('filter', '!=', 'pack')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook attrs="{'invisible':[('state','=','draft')]}">
|
||||
@@ -148,8 +151,27 @@
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Stock Moves" attrs="{'invisible': [('state', '!=', 'done')]}">
|
||||
<field name="move_ids"/>
|
||||
<page string="Inventory Adjustments" attrs="{'invisible': [('state', '!=', 'done')]}">
|
||||
<field name="move_ids">
|
||||
<tree colors="grey:scrapped == True" string="Stock Moves">
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"/>
|
||||
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
|
||||
<field name="product_uos" groups="product.group_uos"/>
|
||||
<field name="picking_id" invisible="1" />
|
||||
<field name="create_date" invisible="1" />
|
||||
<field name="date_expected" invisible="1" />
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="Scrap Products" type="action"
|
||||
icon="terp-gtk-jump-to-ltr" context="{'scrap': True}"
|
||||
states="draft,waiting,confirmed,assigned"
|
||||
groups="base.group_user"/>
|
||||
<field name="scrapped" invisible="1"/>
|
||||
<field name="location_id" groups="stock.group_locations"/>
|
||||
<field name="location_dest_id" groups="stock.group_locations"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
@@ -158,7 +180,7 @@
|
||||
</record>
|
||||
|
||||
<record id="action_inventory_form" model="ir.actions.act_window">
|
||||
<field name="name">Physical Inventories</field>
|
||||
<field name="name">Inventories Adjustment</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">stock.inventory</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -177,14 +199,6 @@
|
||||
</record>
|
||||
<menuitem action="action_inventory_form" id="menu_action_inventory_form" parent="menu_stock_inventory_control" sequence="30"/>
|
||||
|
||||
<record id="action_inventory_form_draft" model="ir.actions.act_window">
|
||||
<field name="name">Draft Physical Inventories</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">stock.inventory</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_traceability" name="Traceability" parent="menu_stock_root"
|
||||
sequence="3"/>
|
||||
@@ -460,7 +474,7 @@
|
||||
<field name="res_model">stock.move</field>
|
||||
</record>
|
||||
<record id="action_location_tree" model="ir.actions.act_window">
|
||||
<field name="name">Location Structure</field>
|
||||
<field name="name">Inventory by Location</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="domain">[('location_id','=',False)]</field>
|
||||
@@ -489,11 +503,11 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Warehouse" version="7.0">
|
||||
<sheet>
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<label for="name" class="oe_edit_only" string="Warehouse Short Name"/>
|
||||
<h1><field name="name"/></h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="lot_stock_id" groups="stock.group_locations"/>
|
||||
<field name="lot_stock_id" groups="stock.group_locations" string="Inventory Location"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
@@ -606,7 +620,7 @@
|
||||
<tree editable="top">
|
||||
<field name="product_id"/>
|
||||
<field name="product_uom_id" groups="product.group_uom"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="lot_id" domain="[('product_id','=?', product_id)]" context="{'product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="package_id" groups="stock.group_tracking_lot"/>
|
||||
<field name="owner_id" groups="stock.group_tracking_owner"/>
|
||||
<field name="product_qty" attrs="{'required': [('product_id', '!=', False)]}"/>
|
||||
@@ -1095,19 +1109,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_move_reception_picking_tree">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_move_tree_reception_picking"/>
|
||||
<field name="act_window_id" ref="action_reception_picking_move"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_move_reception_picking_form">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_move_form"/>
|
||||
<field name="act_window_id" ref="action_reception_picking_move"/>
|
||||
</record>
|
||||
|
||||
<!-- Stock incoterms -->
|
||||
<record id="view_incoterms_tree" model="ir.ui.view">
|
||||
<field name="name">stock.incoterms.tree</field>
|
||||
@@ -1166,47 +1167,6 @@
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="action_out_picking_move" model="ir.actions.act_window">
|
||||
<field name="name">Deliver Products</field>
|
||||
<field name="res_model">stock.move</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain" eval="['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&',('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">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to register a product delivery.
|
||||
</p>
|
||||
<p>
|
||||
You will find in this list all products you have to deliver to
|
||||
your customers. You can process the deliveries directly from
|
||||
this list using the buttons on the right of each line. You can
|
||||
filter the products to deliver by customer, products or sale
|
||||
order (using the Origin field).
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_move_out_picking_tree">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_move_tree_reception_picking"/>
|
||||
<field name="act_window_id" ref="action_out_picking_move"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_move_out_picking_form">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="view_move_form"/>
|
||||
<field name="act_window_id" ref="action_out_picking_move"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_reception_picking_move" id="menu_action_pdct_in" parent="menu_stock_products_moves" sequence="1"/>
|
||||
<menuitem action="action_out_picking_move" id="menu_action_pdct_out" parent="menu_stock_products_moves" sequence="2"/>
|
||||
|
||||
|
||||
<record id="view_pickingtype_filter" model="ir.ui.view">
|
||||
<field name="name">stock.picking.type.filter</field>
|
||||
<field name="model">stock.picking.type</field>
|
||||
@@ -1264,7 +1224,7 @@
|
||||
<field name="name">stock.picking.type.kanban</field>
|
||||
<field name="model">stock.picking.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban version="7.0" class="oe_background_grey">
|
||||
<kanban version="7.0" class="oe_background_grey" create="0">
|
||||
<field name="complete_name"/>
|
||||
<field name="color"/>
|
||||
<field name="count_picking_ready"/>
|
||||
@@ -1296,16 +1256,6 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_items_list oe_kanban_ellipsis">
|
||||
<div>
|
||||
<a name="%(action_picking_tree_draft)d" type="action">
|
||||
<field name="count_picking_draft"/> Draft
|
||||
</a>
|
||||
<t t-if="record.count_picking_draft.raw_value > 0">
|
||||
<a name="%(action_picking_tree_draft)d" type="action">
|
||||
<field name="weekly_picking" widget="stock_sparkline">Weekly Moves</field>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
<div>
|
||||
<a name="%(action_picking_tree_ready)d" type="action">
|
||||
<field name="count_picking_ready"/> Ready
|
||||
@@ -1316,14 +1266,6 @@
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="record.count_picking_waiting.raw_value > 0">
|
||||
<a name="%(action_picking_tree_waiting)d" type="action">
|
||||
<field name="count_picking_waiting"/> Waiting
|
||||
</a>
|
||||
<a name="%(action_picking_tree_waiting)d" type="action" class="oe_sparkline_bar_link">
|
||||
<field name="latest_picking_waiting" widget="stock_sparkline" options="{'type': 'tristate'}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div t-if="record.count_picking_late.raw_value > 0">
|
||||
<a name="%(action_picking_tree_late)d" type="action">
|
||||
<field name="count_picking_late"/> Late
|
||||
@@ -1340,6 +1282,21 @@
|
||||
<field name="latest_picking_backorders" widget="stock_sparkline" options="{'type': 'tristate'}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div t-if="record.count_picking_waiting.raw_value > 0">
|
||||
<a name="%(action_picking_tree_waiting)d" type="action">
|
||||
<field name="count_picking_waiting"/> Waiting
|
||||
</a>
|
||||
<a name="%(action_picking_tree_waiting)d" type="action" class="oe_sparkline_bar_link">
|
||||
<field name="latest_picking_waiting" widget="stock_sparkline" options="{'type': 'tristate'}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<t t-if="record.count_picking_draft.raw_value > 0">
|
||||
<a name="%(action_picking_tree_draft)d" type="action">
|
||||
<field name="count_picking_draft"/> Draft
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_center oe_stock_justgage">
|
||||
<field name="rate_picking_late" widget="stock_gage" style="width:160px; height: 120px;">Late (%%)</field>
|
||||
@@ -1355,7 +1312,7 @@
|
||||
</record>
|
||||
|
||||
<record id="action_picking_type_form" model="ir.actions.act_window">
|
||||
<field name="name">Inventory Moves</field>
|
||||
<field name="name">All Operations</field>
|
||||
<field name="res_model">stock.picking.type</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -1371,11 +1328,14 @@
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
action="action_picking_type_form"
|
||||
id="menu_action_picking_type_form"
|
||||
parent="menu_stock_warehouse_mgmt" sequence="1"/>
|
||||
|
||||
|
||||
|
||||
<!-- Order Point -->
|
||||
<record id="view_warehouse_orderpoint_tree" model="ir.ui.view">
|
||||
<field name="name">stock.warehouse.orderpoint.tree</field>
|
||||
@@ -1528,25 +1488,27 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Procurement Rules" version="7.0">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<label string="Name"/>
|
||||
<field name="name" class="oe_inline"/>
|
||||
</h1>
|
||||
</div>
|
||||
<separator string="Pull Rule"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="location_src_id" attrs="{'invisible': [('action', '!=', 'move')]}"/>
|
||||
<field name="location_id"/>
|
||||
<field name="route_id"/>
|
||||
<field name="route_sequence"/>
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="action"/>
|
||||
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="Informations"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="procure_method" attrs="{'invisible': [('action', '!=', 'move')]}"/>
|
||||
<field name="group_id"/>
|
||||
<field name="location_src_id" attrs="{'invisible': [('action', '!=', 'move')]}"/>
|
||||
<field name="location_id"/>
|
||||
|
||||
</group>
|
||||
<group>
|
||||
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
|
||||
<field name="route_id"/>
|
||||
<field name="group_id" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
@@ -1645,7 +1607,7 @@
|
||||
<menuitem action="procurement.procurement_exceptions" id="menu_stock_procurement_action" parent="menu_stock_sched" sequence="50" groups="stock.group_stock_manager"/>
|
||||
<menuitem id="menu_stock_procurement" name="Automatic Procurements" parent="stock.menu_stock_configuration" sequence="5"/>
|
||||
<menuitem action="action_orderpoint_form" id="menu_stock_order_points" parent="stock.menu_stock_configuration" sequence="10"/>
|
||||
<menuitem id="menu_quants" name="Current Inventory Situation" parent="stock.menu_stock_inventory_control" sequence="20" action="quantsact"/>
|
||||
<menuitem id="menu_quants" name="Current Inventory" parent="stock.menu_stock_inventory_control" sequence="20" action="quantsact"/>
|
||||
<menuitem id="menu_procurement_rules" name="Procurement Rules" parent="stock.menu_stock_configuration" action="procrules" groups="base.group_no_one"/>
|
||||
|
||||
|
||||
@@ -1870,15 +1832,15 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Route" version="7.0">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<label string="Route name"/>
|
||||
</h1>
|
||||
<h2>
|
||||
<field name="name" class="oe_inline"/>
|
||||
</h2>
|
||||
</div>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
<group string="Route">
|
||||
|
||||
<group>
|
||||
<field name="name" class="oe_inline"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="sequence" string="Sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Pull Rules" colspan="4" >
|
||||
<field name="pull_ids" colspan="4" nolabel="1"/>
|
||||
</group>
|
||||
|
||||
@@ -148,8 +148,6 @@
|
||||
backorder = self.search(cr, uid, [('backorder_id.id', '=', picking.id)], context=context)
|
||||
assert backorder, "Backorder should have been created"
|
||||
backorder_id = self.browse(cr, uid, backorder, context=context)
|
||||
self.action_confirm(cr, uid, backorder, context=context)
|
||||
self.action_assign(cr, uid, backorder)
|
||||
self.do_prepare_partial(cr, uid, backorder, context=context)
|
||||
stock_pack = self.pool.get('stock.pack.operation').create(cr, uid, {'picking_id': backorder_id[0].id, 'product_qty': 20})
|
||||
-
|
||||
|
||||
@@ -59,27 +59,41 @@ class stock_quant(osv.osv):
|
||||
return line.cost * line.qty
|
||||
return super(stock_quant, self)._get_inventory_value(cr, uid, line, prodbrow, context=context)
|
||||
|
||||
# FP Note: this is where we should post accounting entries for adjustment
|
||||
def _price_update(self, cr, uid, quant, newprice, context=None):
|
||||
super(stock_quant, self)._price_update(cr, uid, quant, newprice, context=context)
|
||||
# TODO: generate accounting entries
|
||||
def _price_update(self, cr, uid, quant_ids, newprice, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
super(stock_quant, self)._price_update(cr, uid, quant_ids, newprice, context=context)
|
||||
ctx = context.copy()
|
||||
for quant in self.browse(cr, uid, quant_ids, context=context):
|
||||
move = self._get_latest_move(cr, uid, quant, context=context)
|
||||
ctx['force_valuation_amount'] = newprice - quant.cost
|
||||
# this is where we post accounting entries for adjustment
|
||||
self._account_entry_move(cr, uid, quant, move, context=ctx)
|
||||
#update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
#1) the product cost's method is 'real'
|
||||
#2) we just fixed a negative quant caused by an outgoing shipment
|
||||
if quant.product_id.cost_method == 'real' and quant.location_id.usage != 'internal':
|
||||
self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
|
||||
"""
|
||||
Accounting Valuation Entries
|
||||
|
||||
location_from: can be None if it's a new quant
|
||||
"""
|
||||
def _account_entry_move(self, cr, uid, quant, location_from, location_to, move, context=None):
|
||||
def _account_entry_move(self, cr, uid, quant, move, context=None):
|
||||
location_from = move.location_id
|
||||
location_to = move.location_dest_id
|
||||
if context is None:
|
||||
context = {}
|
||||
if quant.product_id.valuation != 'real_time':
|
||||
return False
|
||||
if quant.lot_id and quant.lot_id.partner_id:
|
||||
if quant.owner_id:
|
||||
#if the quant isn't owned by the company, we don't make any valuation entry
|
||||
return False
|
||||
if quant.qty <= 0 or quant.propagated_from_id:
|
||||
#we don't make any stock valuation for negative quants because we may not know the real cost price.
|
||||
#The valuation will be made at the time of the reconciliation of the negative quant.
|
||||
if quant.qty <= 0:
|
||||
#we don't make any stock valuation for negative quants because the valuation is already made for the counterpart.
|
||||
#At that time the valuation will be made at the product cost price and afterward there will be new accounting entries
|
||||
#to make the adjustments when we know the real cost price.
|
||||
return False
|
||||
company_from = self._location_owner(cr, uid, quant, location_from, context=context)
|
||||
company_to = self._location_owner(cr, uid, quant, location_to, context=context)
|
||||
@@ -109,11 +123,9 @@ class stock_quant(osv.osv):
|
||||
self._create_account_move_line(cr, uid, quant, move, acc_valuation, acc_dest, journal_id, context=ctx)
|
||||
|
||||
def move_single_quant(self, cr, uid, quant, qty, move, context=None):
|
||||
location_from = quant and quant.location_id or False
|
||||
quant = super(stock_quant, self).move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
quant.refresh()
|
||||
self._account_entry_move(cr, uid, quant, location_from, quant.location_id, move, context=context)
|
||||
return quant
|
||||
quant_record = super(stock_quant, self).move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
self._account_entry_move(cr, uid, quant_record, move, context=context)
|
||||
return quant_record
|
||||
|
||||
def _get_accounting_data_for_valuation(self, cr, uid, move, context=None):
|
||||
"""
|
||||
@@ -153,7 +165,12 @@ class stock_quant(osv.osv):
|
||||
Generate the account.move.line values to post to track the stock valuation difference due to the
|
||||
processing of the given quant.
|
||||
"""
|
||||
valuation_amount = quant.product_id.cost_method == 'real' and quant.cost or quant.product_id.standard_price
|
||||
if context is None:
|
||||
context = {}
|
||||
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
|
||||
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,
|
||||
@@ -163,7 +180,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 * quant.qty,
|
||||
'debit': valuation_amount > 0 and valuation_amount * quant.qty or 0,
|
||||
'credit': valuation_amount < 0 and -valuation_amount * quant.qty or 0,
|
||||
'account_id': debit_account_id,
|
||||
}
|
||||
credit_line_vals = {
|
||||
@@ -174,7 +192,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,
|
||||
'credit': valuation_amount * quant.qty,
|
||||
'credit': valuation_amount > 0 and valuation_amount * quant.qty or 0,
|
||||
'debit': valuation_amount < 0 and -valuation_amount * quant.qty or 0,
|
||||
'account_id': credit_account_id,
|
||||
}
|
||||
res = [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
|
||||
@@ -187,16 +206,17 @@ class stock_quant(osv.osv):
|
||||
'line_id': move_lines,
|
||||
'ref': move.picking_id and move.picking_id.name}, context=context)
|
||||
|
||||
def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
quant_neg_position = quant_neg.negative_dest_location_id.usage
|
||||
remaining_to_solve_quant = super(stock_quant, self)._reconcile_single_negative_quant(cr, uid, to_solve_quant, quant, quant_neg, qty, context=context)
|
||||
#update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
#1) there isn't any negative quant anymore
|
||||
#2) the product cost's method is 'real'
|
||||
#3) we just fixed a negative quant caused by an outgoing shipment
|
||||
if not remaining_to_solve_quant and move.product_id.cost_method == 'real' and quant_neg_position != 'internal':
|
||||
self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
#def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
# move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
# quant_neg_position = quant_neg.negative_dest_location_id.usage
|
||||
# remaining_solving_quant, remaining_to_solve_quant = super(stock_quant, self)._reconcile_single_negative_quant(cr, uid, to_solve_quant, quant, quant_neg, qty, context=context)
|
||||
# #update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
# #1) there isn't any negative quant anymore
|
||||
# #2) the product cost's method is 'real'
|
||||
# #3) we just fixed a negative quant caused by an outgoing shipment
|
||||
# if not remaining_to_solve_quant and move.product_id.cost_method == 'real' and quant_neg_position != 'internal':
|
||||
# self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
# return remaining_solving_quant, remaining_to_solve_quant
|
||||
|
||||
class stock_move(osv.osv):
|
||||
_inherit = "stock.move"
|
||||
|
||||
@@ -41,15 +41,16 @@ class stock_location_route(osv.osv):
|
||||
class stock_warehouse(osv.osv):
|
||||
_inherit = 'stock.warehouse'
|
||||
_columns = {
|
||||
'route_id': fields.many2one('stock.location.route', 'Default Route', domain="[('warehouse_selectable', '=', True)]", help='Default route through the warehouse'),
|
||||
'route_id': fields.many2one('stock.location.route', 'Default Delivery Route', domain="[('warehouse_selectable', '=', True)]", help='Default route through the warehouse'),
|
||||
}
|
||||
|
||||
|
||||
class stock_location_path(osv.osv):
|
||||
_name = "stock.location.path"
|
||||
_description = "Pushed Flows"
|
||||
_order = "name"
|
||||
_columns = {
|
||||
'name': fields.char('Operation', size=64, required=True),
|
||||
'name': fields.char('Operation Name', size=64, required=True),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'route_id': fields.many2one('stock.location.route', 'Route'),
|
||||
'location_from_id': fields.many2one('stock.location', 'Source Location', ondelete='cascade', select=1, required=True),
|
||||
@@ -60,7 +61,7 @@ class stock_location_path(osv.osv):
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Status",
|
||||
required=True,),
|
||||
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True, help="This is the picking type associated with the different pickings"),
|
||||
'picking_type_id': fields.many2one('stock.picking.type', 'Type of the new Operation', required=True, 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')],
|
||||
'Automatic Move',
|
||||
@@ -113,7 +114,7 @@ class procurement_rule(osv.osv):
|
||||
_inherit = 'procurement.rule'
|
||||
|
||||
_columns = {
|
||||
'delay': fields.integer('Number of Hours'),
|
||||
'delay': fields.integer('Number of Days'),
|
||||
'partner_address_id': fields.many2one('res.partner', 'Partner Address'),
|
||||
'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'),
|
||||
}
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
<field name="model">procurement.rule</field>
|
||||
<field name="inherit_id" ref="stock.view_procurement_rule_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="location_id" position="after">
|
||||
<field name="delay"/>
|
||||
<field name="propagate"/>
|
||||
<field name="group_id" position="after">
|
||||
<field name="propagate"/>
|
||||
<label for="delay" string="Delay"/>
|
||||
<div>
|
||||
<field name="delay" class="oe_inline"/>days
|
||||
</div>
|
||||
</field>
|
||||
<field name="group_id" position="before">
|
||||
<field name="location_id" position="after">
|
||||
<field name="partner_address_id"/>
|
||||
</field>
|
||||
</field>
|
||||
@@ -101,15 +104,20 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Location Paths" version="7.0">
|
||||
<group col="4">
|
||||
<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="picking_type_id"/>
|
||||
<field name="auto"/>
|
||||
<field name="delay"/>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="location_from_id"/>
|
||||
<field name="location_dest_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
<field name="picking_type_id"/>
|
||||
<field name="auto"/>
|
||||
<label for="delay" string="Delay"/>
|
||||
<div>
|
||||
<field name="delay" class="oe_inline"/>days
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
@@ -125,7 +133,6 @@
|
||||
<group string="Routes" colspan="4">
|
||||
<div class="oe_inline">
|
||||
<p attrs="{'invisible':[('route_ids','=',False)]}">
|
||||
The routes on this category are:
|
||||
<field name="route_ids" nolabel="1" widget="many2many_tags" class="oe_inline"/>
|
||||
</p>
|
||||
<p attrs="{'invisible':[('parent_id','=',False)]}">
|
||||
@@ -140,7 +147,7 @@
|
||||
Removal strategies define the method used for suggesting the
|
||||
location to take the products from
|
||||
</p>
|
||||
<field name="removal_strategy_ids" class ="oe_inline">
|
||||
<field name="removal_strategy_ids">
|
||||
<tree editable="bottom" string="removal">
|
||||
<field name="location_id"/>
|
||||
<field name="method"/>
|
||||
@@ -156,7 +163,7 @@
|
||||
Putaway strategies define the method used for suggesting the
|
||||
location to put the products
|
||||
</p>
|
||||
<field name="putaway_strategy_ids" class="oe_inline">
|
||||
<field name="putaway_strategy_ids">
|
||||
<tree string="Put Away" editable="bottom">
|
||||
<field name="location_id"/>
|
||||
<field name="method"/>
|
||||
@@ -175,7 +182,10 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="route_id" attrs="{'invisible': [('route_id', '=', False)]}"/>
|
||||
<button name="%(action_view_stock_configure_wh)d" string="Configure this warehouse" type="action" attrs="{'invisible': [('route_id', '!=', False)]}"/>
|
||||
|
||||
</xpath>
|
||||
<xpath expr="//group[last()]" position="after">
|
||||
<button name="%(action_view_stock_configure_wh)d" class="oe_right oe_highlight" string="Configure this warehouse" type="action" attrs="{'invisible': [('route_id', '!=', False)]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -199,14 +209,16 @@
|
||||
<field name="model">stock.location.route</field>
|
||||
<field name="inherit_id" ref="stock.stock_location_route_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='sequence']" position="after">
|
||||
<group>
|
||||
<xpath expr="//group[@string='Pull Rules']" position="before">
|
||||
<separator string="Applicable On"/>
|
||||
<p class="oe_grey">Check these box so that the user can select this route during the following operations</p>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_categ_selectable"/>
|
||||
<field name="product_selectable"/>
|
||||
<field name="product_categ_selectable" string="Product Categories"/>
|
||||
<field name="product_selectable" string="Products"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="warehouse_selectable"/>
|
||||
<field name="warehouse_selectable" string="Warehouses"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Push Rules" colspan="4" >
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
-
|
||||
!context
|
||||
noupdate: 1
|
||||
-
|
||||
Create Two Customers
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user