commit
7b32559e22
|
@ -746,7 +746,7 @@
|
|||
<field name="move_lines2" nolabel="1" options="{'reload_on_button': true}">
|
||||
<tree colors="red:scrapped==True;blue:state == 'draft';black:state in ('confirmed','ready','in_production');gray:state == 'cancel' " string="Consumed Products" editable="bottom">
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="restrict_lot_id" context="{'product_id': product_id}" groups="stock.group_tracking_lot"/>
|
||||
<field name="restrict_lot_id" context="{'product_id': product_id}" groups="stock.group_production_lot"/>
|
||||
<field name="product_qty" readonly="1"/>
|
||||
<field name="product_uom" readonly="1" string="Unit of Measure" groups="product.group_uom"/>
|
||||
<field name="state" invisible="1"/>
|
||||
|
@ -774,7 +774,7 @@
|
|||
<tree colors="red:scrapped==True;blue:state == 'draft';black:state in('confirmed','ready','in_production');gray:state in('cancel','done') " string="Finished Products">
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="product_qty" readonly="1"/>
|
||||
<field name="restrict_lot_id" groups="stock.group_tracking_lot"/>
|
||||
<field name="restrict_lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="product_uom" readonly="1" string="Unit of Measure" groups="product.group_uom"/>
|
||||
<field name="location_dest_id" readonly="1" string="Destination Loc." widget="selection" groups="stock.group_locations"/>
|
||||
<field name="scrapped" invisible="1"/>
|
||||
|
|
|
@ -18,16 +18,16 @@
|
|||
<field name="lot_id" domain="[('product_id', '=', product_id)]"
|
||||
context="{'default_product_id':product_id}"
|
||||
attrs="{'required': [('track_production', '=', True), ('mode', '=', 'consume_produce')]}"
|
||||
groups="stock.group_tracking_lot"/>
|
||||
groups="stock.group_production_lot"/>
|
||||
</group>
|
||||
<group string="To Consume">
|
||||
<field name="consume_lines">
|
||||
<field name="consume_lines" nolabel="1">
|
||||
<tree string="Consume Lines" editable="top">
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="lot_id" domain="[('product_id', '=', product_id)]"
|
||||
context="{'default_product_id':product_id}"
|
||||
groups="stock.group_tracking_lot"/>
|
||||
groups="stock.group_production_lot"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<field name="product_qty" class="oe_inline"/>
|
||||
<field name="product_uom" class="oe_inline" readonly="1" groups="product.group_uom"/>
|
||||
</div>
|
||||
<field name="restrict_lot_id" domain="[('product_id','=',product_id)]" groups="stock.group_tracking_lot"
|
||||
<field name="restrict_lot_id" domain="[('product_id','=',product_id)]" groups="stock.group_production_lot"
|
||||
context="{'default_product_id': product_id}"/>
|
||||
<field name="location_id" groups="stock.group_locations"/>
|
||||
</group>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<h2>
|
||||
<span t-if="o.state != 'draft'">Repair Order N°:</span>
|
||||
<span t-if="o.state == 'draft'">Repair Quotation N°:</span>
|
||||
<span t-if="o.state == 'draft'">Repair Quotation N°:</span>
|
||||
<span t-field="o.name"/>
|
||||
</h2>
|
||||
|
||||
|
@ -41,7 +41,9 @@
|
|||
</div>
|
||||
<div class="col-xs-3" groups="stock.group_production_lot">
|
||||
<strong>Lot Number</strong>
|
||||
<span t-field="o.prodlot_id.name"/>
|
||||
<t t-if="o.lot_id">
|
||||
<span t-field="o.lot_id.name"/>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="o.guarantee_limit" class="col-xs-3">
|
||||
<strong>Guarantee Limit:</strong>
|
||||
|
|
|
@ -64,7 +64,7 @@ class procurement_group(osv.osv):
|
|||
}
|
||||
_defaults = {
|
||||
'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').get(cr, uid, 'procurement.group') or '',
|
||||
'move_type': lambda self, cr, uid, c: 'one'
|
||||
'move_type': lambda self, cr, uid, c: 'direct'
|
||||
}
|
||||
|
||||
class procurement_rule(osv.osv):
|
||||
|
@ -267,7 +267,7 @@ class procurement_order(osv.osv):
|
|||
#
|
||||
# Scheduler
|
||||
#
|
||||
def run_scheduler(self, cr, uid, use_new_cursor=False, context=None):
|
||||
def run_scheduler(self, cr, uid, use_new_cursor=False, company_id = False, context=None):
|
||||
'''
|
||||
Call the scheduler to check the procurement order. This is intented to be done for all existing companies at
|
||||
the same time, so we're running all the methods as SUPERUSER to avoid intercompany and access rights issues.
|
||||
|
@ -288,8 +288,11 @@ class procurement_order(osv.osv):
|
|||
cr = openerp.registry(cr.dbname).cursor()
|
||||
|
||||
# Run confirmed procurements
|
||||
dom = [('state', '=', 'confirmed')]
|
||||
if company_id:
|
||||
dom += [('company_id', '=', company_id)]
|
||||
while True:
|
||||
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'confirmed')], context=context)
|
||||
ids = self.search(cr, SUPERUSER_ID, dom, context=context)
|
||||
if not ids:
|
||||
break
|
||||
self.run(cr, SUPERUSER_ID, ids, context=context)
|
||||
|
@ -298,8 +301,11 @@ class procurement_order(osv.osv):
|
|||
|
||||
# Check if running procurements are done
|
||||
offset = 0
|
||||
dom = [('state', '=', 'running')]
|
||||
if company_id:
|
||||
dom += [('company_id', '=', company_id)]
|
||||
while True:
|
||||
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'running')], offset=offset, context=context)
|
||||
ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context)
|
||||
if not ids:
|
||||
break
|
||||
done = self.check(cr, SUPERUSER_ID, ids, context=context)
|
||||
|
|
|
@ -37,8 +37,12 @@ class procurement_compute_all(osv.osv_memory):
|
|||
"""
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
#As this function is in a new thread, i need to open a new cursor, because the old one may be closed
|
||||
|
||||
new_cr = self.pool.cursor()
|
||||
proc_obj.run_scheduler(new_cr, uid, use_new_cursor=new_cr.dbname, context=context)
|
||||
user = self.pool.get('res.users').browse(new_cr, uid, uid, context=context)
|
||||
comps = [x.id for x in user.company_ids]
|
||||
for comp in comps:
|
||||
proc_obj.run_scheduler(new_cr, uid, use_new_cursor=new_cr.dbname, company_id = comp, context=context)
|
||||
#close the new cursor
|
||||
new_cr.close()
|
||||
return {}
|
||||
|
|
|
@ -92,7 +92,7 @@ class stock_quant(osv.osv):
|
|||
|
||||
def apply_removal_strategy(self, cr, uid, location, product, qty, domain, removal_strategy, context=None):
|
||||
if removal_strategy == 'fefo':
|
||||
order = 'removal_date, id'
|
||||
order = 'removal_date, in_date, id'
|
||||
return self._quants_get_order(cr, uid, location, product, qty, domain, order, context=context)
|
||||
return super(stock_quant, self).apply_removal_strategy(cr, uid, location, product, qty, domain, removal_strategy, context=context)
|
||||
|
||||
|
|
|
@ -700,6 +700,7 @@ class purchase_order(osv.osv):
|
|||
'origin': order.name,
|
||||
'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [],
|
||||
'warehouse_id':order.picking_type_id.warehouse_id.id,
|
||||
'invoice_state': order.invoice_method == 'picking' and '2binvoiced' or 'none'
|
||||
}
|
||||
|
||||
diff_quantity = order_line.product_qty
|
||||
|
@ -709,9 +710,10 @@ class purchase_order(osv.osv):
|
|||
tmp.update({
|
||||
'product_uom_qty': min(procurement_qty, diff_quantity),
|
||||
'product_uos_qty': min(procurement_qty, diff_quantity),
|
||||
'move_dest_id': procurement.move_dest_id.id, # blabla
|
||||
'group_id': procurement.group_id.id or group_id, # blabla to check ca devrait etre bon et groupé dans le meme picking qd meme
|
||||
'move_dest_id': procurement.move_dest_id.id, #move destination is same as procurement destination
|
||||
'group_id': procurement.group_id.id or group_id, #move group is same as group of procurements if it exists, otherwise take another group
|
||||
'procurement_id': procurement.id,
|
||||
'invoice_state': procurement.rule_id.invoice_state or (procurement.location_id and procurement.location_id.usage == 'customer' and procurement.invoice_state) or (order.invoice_method == 'picking' and '2binvoiced') or 'none', #dropship case takes from sale
|
||||
})
|
||||
diff_quantity -= min(procurement_qty, diff_quantity)
|
||||
res.append(tmp)
|
||||
|
@ -1299,6 +1301,7 @@ class procurement_order(osv.osv):
|
|||
res[procurement.id] = False
|
||||
else:
|
||||
schedule_date = self._get_purchase_schedule_date(cr, uid, procurement, company, context=context)
|
||||
purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context)
|
||||
line_vals = self._get_po_line_values_from_proc(cr, uid, procurement, partner, company, schedule_date, context=context)
|
||||
#look for any other draft PO for the same supplier, to attach the new line on instead of creating a new draft one
|
||||
available_draft_po_ids = po_obj.search(cr, uid, [
|
||||
|
@ -1306,6 +1309,10 @@ class procurement_order(osv.osv):
|
|||
('location_id', '=', procurement.location_id.id), ('company_id', '=', procurement.company_id.id), ('dest_address_id', '=', procurement.partner_dest_id.id)], context=context)
|
||||
if available_draft_po_ids:
|
||||
po_id = available_draft_po_ids[0]
|
||||
po_rec = po_obj.browse(cr, uid, po_id, context=context)
|
||||
#if the product has to be ordered earlier those in the existing PO, we replace the purchase date on the order to avoid ordering it too late
|
||||
if datetime.strptime(po_rec.date_order, DEFAULT_SERVER_DATE_FORMAT) > purchase_date:
|
||||
po_obj.write(cr, uid, [po_id], {'date_order': purchase_date}, context=context)
|
||||
#look for any other PO line in the selected PO with same product and UoM to sum quantities instead of creating a new po line
|
||||
available_po_line_ids = po_line_obj.search(cr, uid, [('order_id', '=', po_id), ('product_id', '=', line_vals['product_id']), ('product_uom', '=', line_vals['product_uom'])], context=context)
|
||||
if available_po_line_ids:
|
||||
|
@ -1318,7 +1325,6 @@ class procurement_order(osv.osv):
|
|||
po_line_id = po_line_obj.create(cr, SUPERUSER_ID, line_vals, context=context)
|
||||
linked_po_ids.append(procurement.id)
|
||||
else:
|
||||
purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context)
|
||||
name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name
|
||||
po_vals = {
|
||||
'name': name,
|
||||
|
@ -1363,6 +1369,13 @@ class product_template(osv.Model):
|
|||
_name = 'product.template'
|
||||
_inherit = 'product.template'
|
||||
|
||||
def _get_buy_route(self, cr, uid, context=None):
|
||||
|
||||
buy_route = self.pool.get('ir.model.data').xmlid_to_res_id(cr, uid, 'purchase.route_warehouse0_buy')
|
||||
if buy_route:
|
||||
return [buy_route]
|
||||
return []
|
||||
|
||||
def _purchase_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
for template in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -1374,6 +1387,7 @@ class product_template(osv.Model):
|
|||
}
|
||||
_defaults = {
|
||||
'purchase_ok': 1,
|
||||
'route_ids': _get_buy_route,
|
||||
}
|
||||
|
||||
class product_product(osv.Model):
|
||||
|
@ -1451,15 +1465,9 @@ class account_invoice_line(osv.Model):
|
|||
readonly=True),
|
||||
}
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = "product.product"
|
||||
class product_template(osv.osv):
|
||||
_inherit = "product.template"
|
||||
|
||||
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:
|
||||
|
|
|
@ -55,6 +55,33 @@ class stock_move(osv.osv):
|
|||
})
|
||||
return super(stock_move, self).copy(cr, uid, id, default, context)
|
||||
|
||||
|
||||
def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None):
|
||||
invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context)
|
||||
if move.purchase_line_id:
|
||||
purchase_line = move.purchase_line_id
|
||||
self.pool.get('purchase.order.line').write(cr, uid, [purchase_line.id], {
|
||||
'invoice_lines': [(4, invoice_line_id)]
|
||||
}, context=context)
|
||||
self.pool.get('purchase.order').write(cr, uid, [purchase_line.order_id.id], {
|
||||
'invoice_ids': [(4, invoice_line_vals['invoice_id'])],
|
||||
})
|
||||
return invoice_line_id
|
||||
|
||||
def _get_master_data(self, cr, uid, move, company, context=None):
|
||||
if move.purchase_line_id:
|
||||
purchase_order = move.purchase_line_id.order_id
|
||||
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.pricelist_id.currency_id.id
|
||||
return super(stock_move, self)._get_master_data(cr, uid, move, company, context=context)
|
||||
|
||||
def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
|
||||
res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
|
||||
if move.purchase_line_id:
|
||||
purchase_line = move.purchase_line_id
|
||||
res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
|
||||
res['price_unit'] = purchase_line.price_unit
|
||||
return res
|
||||
|
||||
class stock_picking(osv.osv):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
|
|
|
@ -388,7 +388,7 @@ class stock_move(osv.osv):
|
|||
return super(stock_move, self).action_cancel(cr, uid, ids, context=context)
|
||||
|
||||
def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None):
|
||||
invoice_line_id = self.pool.get('account.invoice.line').create(cr, uid, invoice_line_vals, context=context)
|
||||
invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context)
|
||||
if move.procurement_id and move.procurement_id.sale_line_id:
|
||||
sale_line = move.procurement_id.sale_line_id
|
||||
self.pool.get('sale.order.line').write(cr, uid, [sale_line.id], {
|
||||
|
|
|
@ -261,7 +261,7 @@ class procurement_order(osv.osv):
|
|||
result['domain'] = "[('group_id','in',[" + ','.join(map(str, list(group_ids))) + "])]"
|
||||
return result
|
||||
|
||||
def run_scheduler(self, cr, uid, use_new_cursor=False, context=None):
|
||||
def run_scheduler(self, cr, uid, use_new_cursor=False, company_id=False, context=None):
|
||||
'''
|
||||
Call the scheduler in order to check the running procurements (super method), to check the minimum stock rules
|
||||
and the availability of moves. This function is intended to be run for all the companies at the same time, so
|
||||
|
@ -286,8 +286,7 @@ class procurement_order(osv.osv):
|
|||
move_obj = self.pool.get('stock.move')
|
||||
|
||||
#Minimum stock rules
|
||||
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
|
||||
self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company.id, context=context)
|
||||
self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company_id, context=context)
|
||||
|
||||
#Search all confirmed stock_moves and try to assign them
|
||||
confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed')], limit=None, order='priority desc, date_expected asc', context=context)
|
||||
|
@ -331,7 +330,7 @@ class procurement_order(osv.osv):
|
|||
[order_point.product_id.id],
|
||||
context={'location': order_point.location_id.id})[order_point.product_id.id]['virtual_available']
|
||||
|
||||
def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id=False, context=None):
|
||||
def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id = False, context=None):
|
||||
'''
|
||||
Create procurement based on Orderpoint
|
||||
|
||||
|
@ -341,14 +340,15 @@ class procurement_order(osv.osv):
|
|||
if context is None:
|
||||
context = {}
|
||||
if use_new_cursor:
|
||||
cr = openerp.registry(cr.dbname).db.cursor()
|
||||
cr = openerp.registry(cr.dbname).cursor()
|
||||
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
||||
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
offset = 0
|
||||
ids = [1]
|
||||
dom = company_id and [('company_id', '=', company_id)] or []
|
||||
while ids:
|
||||
ids = orderpoint_obj.search(cr, uid, [('company_id', '=', company_id)], offset=offset, limit=100)
|
||||
ids = orderpoint_obj.search(cr, uid, dom, offset=offset, limit=100)
|
||||
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
|
||||
prods = self._product_virtual_get(cr, uid, op)
|
||||
if prods is None:
|
||||
|
|
|
@ -171,13 +171,13 @@ class product_product(osv.osv):
|
|||
def _product_available_text(self, cr, uid, ids, field_names=None, arg=False, context=None):
|
||||
res = {}
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
res[product.id] = str(product.qty_available) + _(" In Stock")
|
||||
res[product.id] = str(product.qty_available) + _(" On Hand")
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'),
|
||||
'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'),
|
||||
'qty_in_stock': fields.function(_product_available_text, type='char'),
|
||||
'qty_available_text': fields.function(_product_available_text, type='char'),
|
||||
'qty_available': fields.function(_product_available, multi='qty_available',
|
||||
type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
string='Quantity On Hand',
|
||||
|
@ -277,6 +277,12 @@ class product_product(osv.osv):
|
|||
res['fields']['qty_available']['string'] = _('Produced Qty')
|
||||
return res
|
||||
|
||||
|
||||
def action_view_routes(self, cr, uid, ids, context=None):
|
||||
template_obj = self.pool.get("product.template")
|
||||
templ_ids = list(set([x.product_tmpl_id.id for x in self.browse(cr, uid, ids, context=context)]))
|
||||
return template_obj.action_view_routes(cr, uid, templ_ids, context=context)
|
||||
|
||||
class product_template(osv.osv):
|
||||
_name = 'product.template'
|
||||
_inherit = 'product.template'
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
<field name="inherit_id" ref="product.product_normal_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="status" position="before">
|
||||
<group name="lot" groups="stock.group_tracking_lot,stock.group_production_lot" string="Lots">
|
||||
<group name="lot" groups="stock.group_production_lot" string="Lots">
|
||||
<field name="track_all" groups="stock.group_production_lot"/>
|
||||
<field name="track_incoming" groups="stock.group_production_lot" attrs="{'invisible': [('track_all', '=', True)]}"/>
|
||||
<field name="track_outgoing" groups="stock.group_production_lot" attrs="{'invisible': [('track_all', '=', True)]}"/>
|
||||
|
@ -202,13 +202,13 @@
|
|||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button class="oe_stat_button"
|
||||
name="%(product_open_quants)d"
|
||||
icon="fa-bank"
|
||||
icon="fa-building-o"
|
||||
type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations">
|
||||
<div><field name="qty_in_stock"/></div>
|
||||
<div><field name="qty_available_text"/></div>
|
||||
</button>
|
||||
<button class="oe_inline oe_stat_button" string="Moves" name= "%(act_product_stock_move_open)d" type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/>
|
||||
<button class="oe_inline oe_stat_button" name="%(product_open_orderpoint)d" type="action"
|
||||
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-pinterest" string="Reordering Rules"/>
|
||||
attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-refresh" string="Reordering Rules"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -60,7 +60,7 @@ access_stock_location_path_internal_user,stock location path internal user,model
|
|||
access_stock_location_path_sale_manager,stock.location.path partner salemanager,model_stock_location_path,base.group_sale_manager,1,1,1,1
|
||||
access_stock_location_path_stock_user,stock.location.path stock user,model_stock_location_path,stock.group_stock_user,1,1,1,1
|
||||
access_stock_location_path,stock.location.path,model_stock_location_path,base.group_sale_salesman,1,0,0,0
|
||||
access_stock_location_route,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1
|
||||
access_stock_location_route_stock_manager,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1
|
||||
access_stock_location_route,stock.location.route,model_stock_location_route,base.group_user,1,0,0,0
|
||||
access_procurement_rule,procurement.rule.flow,model_procurement_rule,base.group_sale_salesman,1,0,0,0
|
||||
access_procurement_rule_internal,procurement.rule.flow internal,model_procurement_rule,base.group_user,1,0,0,0
|
||||
|
|
|
|
@ -50,7 +50,7 @@
|
|||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="stock_picking_rule">
|
||||
<record model="ir.rule" id="stock_picking_type_rule">
|
||||
<field name="name">Stock Picking Type multi-company</field>
|
||||
<field name="model_id" search="[('model','=','stock.picking.type')]" model="ir.model"/>
|
||||
<field name="global" eval="True"/>
|
||||
|
|
|
@ -272,27 +272,28 @@ class stock_quant(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.function(_get_quant_name, type='char', string='Identifier'),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, ondelete="restrict"),
|
||||
'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="restrict"),
|
||||
'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product"),
|
||||
'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant"),
|
||||
'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', store=True),
|
||||
'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="The move the quant is reserved for"),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Lot'),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, ondelete="restrict", readonly=True),
|
||||
'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="restrict", readonly=True),
|
||||
'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product", readonly=True),
|
||||
'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant", readonly=True),
|
||||
'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', readonly=True, store=True),
|
||||
'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="The move the quant is reserved for", readonly=True),
|
||||
'lot_id': fields.many2one('stock.production.lot', 'Lot', readonly=True),
|
||||
'cost': fields.float('Unit Cost'),
|
||||
'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant"),
|
||||
'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant", readonly=True),
|
||||
|
||||
'create_date': fields.datetime('Creation Date'),
|
||||
'in_date': fields.datetime('Incoming Date'),
|
||||
'create_date': fields.datetime('Creation Date', readonly=True),
|
||||
'in_date': fields.datetime('Incoming Date', readonly=True),
|
||||
|
||||
'history_ids': fields.many2many('stock.move', 'stock_quant_move_rel', 'quant_id', 'move_id', 'Moves', help='Moves that operate(d) on this quant'),
|
||||
'company_id': fields.many2one('res.company', 'Company', help="The company to which the quants belong", required=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', help="The company to which the quants belong", required=True, readonly=True),
|
||||
'inventory_value': fields.function(_calc_inventory_value, string="Inventory Value", type='float', readonly=True),
|
||||
|
||||
# Used for negative quants to reconcile after compensated by a new positive one
|
||||
'propagated_from_id': fields.many2one('stock.quant', 'Linked Quant', help='The negative quant this is coming from'),
|
||||
'negative_move_id': fields.many2one('stock.move', 'Move Negative Quant', help='If this is a negative quant, this will be the move that caused this negative quant.'),
|
||||
'negative_dest_location_id': fields.related('negative_move_id', 'location_dest_id', type='many2one', relation='stock.location', string="Negative Destination Location", help="Technical field used to record the destination location of a move that created a negative quant"),
|
||||
'propagated_from_id': fields.many2one('stock.quant', 'Linked Quant', help='The negative quant this is coming from', readonly=True),
|
||||
'negative_move_id': fields.many2one('stock.move', 'Move Negative Quant', help='If this is a negative quant, this will be the move that caused this negative quant.', readonly=True),
|
||||
'negative_dest_location_id': fields.related('negative_move_id', 'location_dest_id', type='many2one', relation='stock.location', string="Negative Destination Location", readonly=True,
|
||||
help="Technical field used to record the destination location of a move that created a negative quant"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
@ -606,7 +607,6 @@ class stock_quant(osv.osv):
|
|||
raise osv.except_osv(_('Error'), _('You cannot move to a location of type view %s.') % (location.name))
|
||||
return True
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Stock Picking
|
||||
#----------------------------------------------------------
|
||||
|
@ -1248,6 +1248,7 @@ class stock_picking(osv.osv):
|
|||
'''
|
||||
move_obj = self.pool.get('stock.move')
|
||||
operation_obj = self.pool.get('stock.pack.operation')
|
||||
moves = []
|
||||
for op in picking.pack_operation_ids:
|
||||
for product_id, remaining_qty in operation_obj._get_remaining_prod_quantities(cr, uid, op, context=context).items():
|
||||
if remaining_qty > 0:
|
||||
|
@ -1260,9 +1261,12 @@ class stock_picking(osv.osv):
|
|||
'product_uom': product.uom_id.id,
|
||||
'product_uom_qty': remaining_qty,
|
||||
'name': _('Extra Move: ') + product.name,
|
||||
'state': 'confirmed',
|
||||
'state': 'draft',
|
||||
}
|
||||
move_obj.create(cr, uid, vals, context=context)
|
||||
moves.append(move_obj.create(cr, uid, vals, context=context))
|
||||
if moves:
|
||||
move_obj.action_confirm(cr, uid, moves, context=context)
|
||||
return moves
|
||||
|
||||
def rereserve_quants(self, cr, uid, picking, move_ids=[], context=None):
|
||||
""" Unreserve quants then try to reassign quants."""
|
||||
|
@ -1289,11 +1293,13 @@ class stock_picking(osv.osv):
|
|||
else:
|
||||
need_rereserve, all_op_processed = self.picking_recompute_remaining_quantities(cr, uid, picking, context=context)
|
||||
#create extra moves in the picking (unexpected product moves coming from pack operations)
|
||||
todo_move_ids = []
|
||||
if not all_op_processed:
|
||||
self._create_extra_moves(cr, uid, picking, context=context)
|
||||
todo_move_ids += self._create_extra_moves(cr, uid, picking, context=context)
|
||||
|
||||
picking.refresh()
|
||||
#split move lines eventually
|
||||
todo_move_ids = []
|
||||
|
||||
toassign_move_ids = []
|
||||
for move in picking.move_lines:
|
||||
remaining_qty = move.remaining_qty
|
||||
|
@ -1371,7 +1377,7 @@ class stock_picking(osv.osv):
|
|||
op = operation
|
||||
if (operation.qty_done < operation.product_qty):
|
||||
new_operation = stock_operation_obj.copy(cr, uid, operation.id, {'product_qty': operation.qty_done,'qty_done': operation.qty_done}, context=context)
|
||||
stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0}, context=context)
|
||||
stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0, 'lot_id': False}, context=context)
|
||||
op = stock_operation_obj.browse(cr, uid, new_operation, context=context)
|
||||
pack_operation_ids.append(op.id)
|
||||
for record in op.linked_move_operation_ids:
|
||||
|
@ -1783,7 +1789,7 @@ class stock_move(osv.osv):
|
|||
'move_dest_id': move.id,
|
||||
'group_id': group_id,
|
||||
'route_ids': [(4, x.id) for x in move.route_ids],
|
||||
'warehouse_id': move.warehouse_id and move.warehouse_id.id or False,
|
||||
'warehouse_id': move.warehouse_id.id or (move.picking_type_id and move.picking_type_id.warehouse_id.id or False),
|
||||
'priority': move.priority,
|
||||
}
|
||||
|
||||
|
@ -3521,7 +3527,6 @@ class stock_location_path(osv.osv):
|
|||
# -------------------------
|
||||
|
||||
from openerp.report import report_sxw
|
||||
report_sxw.report_sxw('report.stock.quant.package.barcode', 'stock.quant.package', 'addons/stock/report/package_barcode.rml')
|
||||
|
||||
class stock_package(osv.osv):
|
||||
"""
|
||||
|
@ -3818,8 +3823,8 @@ class stock_pack_operation(osv.osv):
|
|||
if pack_op.qty_done < pack_op.product_qty:
|
||||
# we split the operation in two
|
||||
op = self.copy(cr, uid, pack_op.id, {'product_qty': pack_op.qty_done, 'qty_done': pack_op.qty_done}, context=context)
|
||||
self.write(cr, uid, ids, {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0}, context=context)
|
||||
processed_ids.append(op)
|
||||
self.write(cr, uid, [pack_op.id], {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0, 'lot_id': False}, context=context)
|
||||
processed_ids.append(op)
|
||||
self.write(cr, uid, processed_ids, {'processed': 'true'}, context=context)
|
||||
|
||||
def create_and_assign_lot(self, cr, uid, id, name, context=None):
|
||||
|
@ -3828,10 +3833,16 @@ class stock_pack_operation(osv.osv):
|
|||
obj = self.browse(cr,uid,id,context)
|
||||
product_id = obj.product_id.id
|
||||
val = {'product_id': product_id}
|
||||
new_lot_id = False
|
||||
if name:
|
||||
lots = self.pool.get('stock.production.lot').search(cr, uid, ['&', ('name', '=', name), ('product_id', '=', product_id)], context=context)
|
||||
if lots:
|
||||
new_lot_id = lots[0]
|
||||
val.update({'name': name})
|
||||
|
||||
if not obj.lot_id:
|
||||
new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context)
|
||||
if not new_lot_id:
|
||||
new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context)
|
||||
self.write(cr, uid, id, {'lot_id': new_lot_id}, context=context)
|
||||
|
||||
def _search_and_increment(self, cr, uid, picking_id, domain, filter_visible=False, visible_op_ids=False, increment=True, context=None):
|
||||
|
@ -3869,11 +3880,15 @@ class stock_pack_operation(osv.osv):
|
|||
self.write(cr, uid, [operation_id], {'qty_done': qty}, context=context)
|
||||
else:
|
||||
#no existing operation found for the given domain and picking => create a new one
|
||||
picking_obj = self.pool.get("stock.picking")
|
||||
picking = picking_obj.browse(cr, uid, picking_id, context=context)
|
||||
values = {
|
||||
'picking_id': picking_id,
|
||||
'product_qty': 0,
|
||||
'location_id': picking.location_id.id,
|
||||
'location_dest_id': picking.location_dest_id.id,
|
||||
'qty_done': 1,
|
||||
}
|
||||
}
|
||||
for key in domain:
|
||||
var_name, dummy, value = key
|
||||
uom_id = False
|
||||
|
|
|
@ -355,7 +355,7 @@
|
|||
<record model="ir.actions.act_window" id="location_open_quants">
|
||||
<field name="context">{'search_default_productgroup': 1}</field>
|
||||
<field name="domain">[('location_id', 'child_of', active_ids)]</field>
|
||||
<field name="name">Quants</field>
|
||||
<field name="name">Current Stock</field>
|
||||
<field name="res_model">stock.quant</field>
|
||||
</record>
|
||||
|
||||
|
@ -1356,6 +1356,7 @@
|
|||
<field name="model">stock.picking.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Picking Types">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="warehouse_id"/>
|
||||
<field name="sequence_id"/>
|
||||
|
@ -1794,7 +1795,7 @@
|
|||
</record>
|
||||
<record model="ir.actions.act_window" id="product_open_quants">
|
||||
<field name="context">{'search_default_internal_loc': 1, 'search_default_product_id': active_id, 'search_default_locationgroup':1}</field>
|
||||
<field name="name">Quants</field>
|
||||
<field name="name">Current Stock</field>
|
||||
<field name="res_model">stock.quant</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -7,18 +7,15 @@
|
|||
<t>
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<img class="image" t-att-src="'data:image/png;base64,%s' % res_company.logo" style="border:auto;"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6 mt6">
|
||||
<table class="table table-condensed" style="border-bottom: 3px solid black !important;"><thead><th> </th></thead></table>
|
||||
<img t-if="not o.loc_barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.name, 600, 100)" style="width:300px;height:50px"/>
|
||||
<img t-if="o.loc_barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.loc_barcode, 600, 100)" style="width:300px;height:50px"/>
|
||||
<p class="text-center" t-if="not o.loc_barcode" t-field="o.name"></p>
|
||||
<p class="text-center" t-if="o.loc_barcode" t-field="o.loc_barcode"></p>
|
||||
<p>
|
||||
<span t-if="not o.loc_barcode" t-field="o.name"/>
|
||||
<span t-if="o.loc_barcode" t-field="o.loc_barcode"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<div class="row"><div class="col-xs-4 pull-right">
|
||||
<img t-att-src="'/report/barcode/Code128/%s' % o.name"/>
|
||||
<img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.name, 600, 100)" style="width:300px;height:50px;"/>
|
||||
</div></div>
|
||||
<div t-if="o.picking_type_id.code=='incoming'">
|
||||
<div t-if="o.picking_type_id.code=='incoming' and o.partner_id">
|
||||
<span><strong>Supplier Address:</strong></span>
|
||||
</div>
|
||||
<div t-if="o.picking_type_id.code=='internal'">
|
||||
<div t-if="o.picking_type_id.code=='internal' and o.partner_id">
|
||||
<span><strong>Warehouse Address:</strong></span>
|
||||
</div>
|
||||
<div t-if="o.picking_type_id.code=='outgoing'">
|
||||
<div t-if="o.picking_type_id.code=='outgoing' and o.partner_id">
|
||||
<span><strong>Customer Address:</strong></span>
|
||||
</div>
|
||||
<div t-if="o.partner_id" name="partner_header">
|
||||
|
@ -73,7 +73,7 @@
|
|||
<t t-if="o.picking_type_id.code != 'incoming'"><td><span t-field="move.location_id"/></td></t>
|
||||
<td>
|
||||
<span t-if="move.product_id and move.product_id.ean13">
|
||||
<img t-att-src="'/report/barcode/EAN13/%s' % move.product_id.ean13"/>
|
||||
<img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', move.product_id.ean13, 600, 100)" style="width:300px;height:50px"/>
|
||||
</span>
|
||||
</td>
|
||||
<t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="move.location_dest_id"/></td></t>
|
||||
|
@ -104,13 +104,13 @@
|
|||
</t>
|
||||
<td>
|
||||
<span t-if="pack_operation.lot_id">
|
||||
<img t-att-src="'/report/barcode/Code128/%s' % pack_operation.lot_id.name"/>
|
||||
<img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', pack_operation.lot_id.name, 600, 100)" style="width:300px;height:50px"/>
|
||||
</span>
|
||||
<span t-if="pack_operation.product_id and not pack_operation.lot_id and pack_operation.product_id.ean13">
|
||||
<img t-att-src="'/report/barcode/EAN13/%s' % pack_operation.product_id.ean13"/>
|
||||
<img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', pack_operation.product_id.ean13, 600, 100)" style="width:300px;height:50px"/>
|
||||
</span>
|
||||
<span t-if="pack_operation.package_id and not pack_operation.product_id">
|
||||
<img t-att-src="'/report/barcode/Code128/%s' % pack_operation.package_id.name"/>
|
||||
<img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', pack_operation.package_id.name, 600, 100)" style="width:300px;height:50px"/>
|
||||
</span>
|
||||
</td>
|
||||
<t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="pack_operation.location_dest_id"/>
|
||||
|
|
|
@ -43,8 +43,10 @@ class procurement_compute(osv.osv_memory):
|
|||
proc_obj = self.pool.get('procurement.order')
|
||||
#As this function is in a new thread, I need to open a new cursor, because the old one may be closed
|
||||
new_cr = self.pool.cursor()
|
||||
for proc in self.browse(new_cr, uid, ids, context=context):
|
||||
proc_obj._procure_orderpoint_confirm(new_cr, uid, use_new_cursor=new_cr.dbname, context=context)
|
||||
user_obj = self.pool.get('res.users')
|
||||
user = user_obj.browse(new_cr, uid, uid, context=context)
|
||||
for comp in user.company_ids:
|
||||
proc_obj._procure_orderpoint_confirm(new_cr, uid, use_new_cursor=new_cr.dbname, company_id = comp.id, context=context)
|
||||
#close the new cursor
|
||||
new_cr.close()
|
||||
return {}
|
||||
|
|
|
@ -53,6 +53,7 @@ Dashboard / Reports for Warehouse Management includes:
|
|||
'wizard/stock_change_standard_price_view.xml',
|
||||
'wizard/stock_invoice_onshipping_view.xml',
|
||||
'wizard/stock_valuation_history_view.xml',
|
||||
'wizard/stock_return_picking_view.xml',
|
||||
'product_data.xml',
|
||||
'product_view.xml',
|
||||
'stock_account_view.xml',
|
||||
|
|
|
@ -30,11 +30,7 @@
|
|||
<field name="property_stock_account_input" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="property_stock_account_output" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
</group>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='standard_price']" position='replace'>
|
||||
<field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}"/>
|
||||
<field name="cost_method" groups="stock_account.group_inventory_valuation"/>
|
||||
</xpath>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -27,11 +27,10 @@ class stock_location_path(osv.osv):
|
|||
'invoice_state': fields.selection([
|
||||
("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Status",
|
||||
required=True,),
|
||||
("none", "Not Applicable")], "Invoice Status",),
|
||||
}
|
||||
_defaults = {
|
||||
'invoice_state': 'none',
|
||||
'invoice_state': '',
|
||||
}
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
@ -43,11 +42,10 @@ class procurement_rule(osv.osv):
|
|||
'invoice_state': fields.selection([
|
||||
("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")], "Invoice Status",
|
||||
required=True),
|
||||
("none", "Not Applicable")], "Invoice Status",),
|
||||
}
|
||||
_defaults = {
|
||||
'invoice_state': 'none',
|
||||
'invoice_state': '',
|
||||
}
|
||||
|
||||
#----------------------------------------------------------
|
||||
|
@ -61,16 +59,16 @@ class procurement_order(osv.osv):
|
|||
'invoice_state': fields.selection([("invoiced", "Invoiced"),
|
||||
("2binvoiced", "To Be Invoiced"),
|
||||
("none", "Not Applicable")
|
||||
], "Invoice Control", required=True),
|
||||
], "Invoice Control"),
|
||||
}
|
||||
|
||||
def _run_move_create(self, cr, uid, procurement, context=None):
|
||||
res = super(procurement_order, self)._run_move_create(cr, uid, procurement, context=context)
|
||||
res.update({'invoice_state': (procurement.rule_id.invoice_state in ('none', False) and procurement.invoice_state or procurement.rule_id.invoice_state) or 'none'})
|
||||
res.update({'invoice_state': procurement.rule_id.invoice_state or procurement.invoice_state or 'none'})
|
||||
return res
|
||||
|
||||
_defaults = {
|
||||
'invoice_state': 'none'
|
||||
'invoice_state': ''
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,7 +90,7 @@ class stock_move(osv.osv):
|
|||
}
|
||||
|
||||
def _get_master_data(self, cr, uid, move, company, context=None):
|
||||
''' returns a tupple (browse_record(res.partner), ID(res.users), ID(res.currency)'''
|
||||
''' returns a tuple (browse_record(res.partner), ID(res.users), ID(res.currency)'''
|
||||
return move.picking_id.partner_id, uid, company.currency_id.id
|
||||
|
||||
def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None):
|
||||
|
@ -204,7 +202,7 @@ class stock_picking(osv.osv):
|
|||
for picking in self.browse(cr, uid, ids, context=context):
|
||||
key = group and picking.id or True
|
||||
for move in picking.move_lines:
|
||||
if move.procurement_id and (move.procurement_id.invoice_state == '2binvoiced') or move.invoice_state == '2binvoiced':
|
||||
if move.invoice_state == '2binvoiced':
|
||||
if (move.state != 'cancel') and not move.scrapped:
|
||||
todo.setdefault(key, [])
|
||||
todo[key].append(move)
|
||||
|
@ -259,12 +257,7 @@ class stock_picking(osv.osv):
|
|||
invoice_line_vals['origin'] = origin
|
||||
|
||||
move_obj._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context)
|
||||
|
||||
move_obj.write(cr, uid, move.id, {'invoice_state': 'invoiced'}, context=context)
|
||||
if move.procurement_id:
|
||||
self.pool.get('procurement.order').write(cr, uid, [move.procurement_id.id], {
|
||||
'invoice_state': 'invoiced',
|
||||
}, context=context)
|
||||
|
||||
invoice_obj.button_compute(cr, uid, invoices.values(), context=context, set_total=(inv_type in ('in_invoice', 'in_refund')))
|
||||
return invoices.values()
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[@name='do_partial_open_barcode']" position="after">
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','invoiced')]}" type="action" class="oe_highlight" groups="base.group_user" context="{'inv_type': 'out_refund'}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_type']" position="after">
|
||||
<field name="invoice_state" groups="account.group_account_invoice"/>
|
||||
|
|
|
@ -22,3 +22,4 @@
|
|||
import stock_change_standard_price
|
||||
import stock_invoice_onshipping
|
||||
import stock_valuation_history
|
||||
import stock_return_picking
|
||||
|
|
|
@ -24,34 +24,48 @@ from openerp.tools.translate import _
|
|||
|
||||
class stock_invoice_onshipping(osv.osv_memory):
|
||||
def _get_journal(self, cr, uid, context=None):
|
||||
res = self._get_journal_id(cr, uid, context=context)
|
||||
if res:
|
||||
return res[0][0]
|
||||
return False
|
||||
|
||||
def _get_journal_id(self, cr, uid, context=None):
|
||||
journal_obj = self.pool.get('account.journal')
|
||||
journal_type = self._get_journal_type(cr, uid, context=context)
|
||||
journals = journal_obj.search(cr, uid, [('type', '=', journal_type)])
|
||||
return journals and journals[0] or False
|
||||
|
||||
def _get_journal_type(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
journal_obj = self.pool.get('account.journal')
|
||||
value = journal_obj.search(cr, uid, [('type', 'in',('sale','sale_Refund'))])
|
||||
res_ids = context and context.get('active_ids', [])
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
pickings = pick_obj.browse(cr, uid, res_ids, context=context)
|
||||
vals = []
|
||||
for jr_type in journal_obj.browse(cr, uid, value, context=context):
|
||||
t1 = jr_type.id,jr_type.name
|
||||
if t1 not in vals:
|
||||
vals.append(t1)
|
||||
return vals
|
||||
pick = pickings and pickings[0]
|
||||
if not pick or not pick.move_lines:
|
||||
return 'sale'
|
||||
src_usage = pick.move_lines[0].location_id.usage
|
||||
dest_usage = pick.move_lines[0].location_dest_id.usage
|
||||
type = pick.picking_type_id.code
|
||||
if type == 'outgoing' and dest_usage == 'supplier':
|
||||
journal_type = 'purchase_refund'
|
||||
elif type == 'outgoing' and dest_usage == 'customer':
|
||||
journal_type = 'sale'
|
||||
elif type == 'incoming' and src_usage == 'supplier':
|
||||
journal_type = 'purchase'
|
||||
elif type == 'incoming' and src_usage == 'customer':
|
||||
journal_type = 'sale_refund'
|
||||
else:
|
||||
journal_type = 'sale'
|
||||
return journal_type
|
||||
|
||||
_name = "stock.invoice.onshipping"
|
||||
_description = "Stock Invoice Onshipping"
|
||||
_columns = {
|
||||
'journal_id': fields.selection(_get_journal_id, 'Destination Journal',required=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Destination Journal', required=True),
|
||||
'journal_type': fields.selection([('purchase_refund', 'Refund Purchase'), ('purchase', 'Create Supplier Invoice'),
|
||||
('sale_refund', 'Refund Sale'), ('sale', 'Create Customer Invoice')], 'Journal Type', readonly=True),
|
||||
'group': fields.boolean("Group by partner"),
|
||||
'inv_type': fields.selection([('out_invoice','Create Invoice'),('out_refund','Refund Invoice')], "Invoice Type"),
|
||||
'invoice_date': fields.date('Invoice Date'),
|
||||
}
|
||||
_defaults = {
|
||||
'journal_type': _get_journal_type,
|
||||
'journal_id' : _get_journal,
|
||||
'inv_type': lambda self,cr,uid,ctx: ctx.get('inv_type', 'out_invoice')
|
||||
}
|
||||
|
||||
def view_init(self, cr, uid, fields_list, context=None):
|
||||
|
@ -71,24 +85,30 @@ class stock_invoice_onshipping(osv.osv_memory):
|
|||
def open_invoice(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
invoice_ids = self.create_invoice(cr, uid, ids, context=context)
|
||||
if not invoice_ids:
|
||||
raise osv.except_osv(_('Error!'), _('No invoice created!'))
|
||||
|
||||
onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date', 'inv_type'])
|
||||
inv_type = onshipdata_obj[0]['inv_type']
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
|
||||
action_model = False
|
||||
action = {}
|
||||
|
||||
|
||||
journal2type = {'sale':'out_invoice', 'purchase':'in_invoice' , 'sale_refund':'out_refund', 'purchase_refund':'in_refund'}
|
||||
inv_type = journal2type.get(data.journal_type) or 'out_invoice'
|
||||
data_pool = self.pool.get('ir.model.data')
|
||||
if inv_type == "out_refund":
|
||||
action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree3")
|
||||
elif inv_type == "out_invoice":
|
||||
action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree1")
|
||||
if inv_type == "out_invoice":
|
||||
action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree1')
|
||||
elif inv_type == "in_invoice":
|
||||
action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree2')
|
||||
elif inv_type == "out_refund":
|
||||
action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree3')
|
||||
elif inv_type == "in_refund":
|
||||
action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree4')
|
||||
|
||||
if action_model:
|
||||
action_pool = self.pool[action_model]
|
||||
if action_id:
|
||||
action_pool = self.pool['ir.actions.act_window']
|
||||
action = action_pool.read(cr, uid, action_id, context=context)
|
||||
action['domain'] = "[('id','in', ["+','.join(map(str,invoice_ids))+"])]"
|
||||
return action
|
||||
|
@ -97,18 +117,17 @@ class stock_invoice_onshipping(osv.osv_memory):
|
|||
def create_invoice(self, cr, uid, ids, context=None):
|
||||
context = context or {}
|
||||
picking_pool = self.pool.get('stock.picking')
|
||||
onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date', 'inv_type'])
|
||||
|
||||
context['date_inv'] = onshipdata_obj[0]['invoice_date']
|
||||
inv_type = onshipdata_obj[0]['inv_type']
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
journal2type = {'sale':'out_invoice', 'purchase':'in_invoice', 'sale_refund':'out_refund', 'purchase_refund':'in_refund'}
|
||||
context['date_inv'] = data.invoice_date
|
||||
acc_journal = self.pool.get("account.journal")
|
||||
inv_type = journal2type.get(data.journal_type) or 'out_invoice'
|
||||
context['inv_type'] = inv_type
|
||||
|
||||
active_ids = context.get('active_ids', [])
|
||||
if isinstance(onshipdata_obj[0]['journal_id'], tuple):
|
||||
onshipdata_obj[0]['journal_id'] = onshipdata_obj[0]['journal_id'][0]
|
||||
res = picking_pool.action_invoice_create(cr, uid, active_ids,
|
||||
journal_id = onshipdata_obj[0]['journal_id'],
|
||||
group = onshipdata_obj[0]['group'],
|
||||
journal_id = data.journal_id.id,
|
||||
group = data.group,
|
||||
type = inv_type,
|
||||
context=context)
|
||||
return res
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Create invoice">
|
||||
<h1>
|
||||
<field name="inv_type" readonly="1"/>
|
||||
<field name="journal_type" readonly="1"/>
|
||||
</h1>
|
||||
<group>
|
||||
<field name="journal_id"/>
|
||||
<field name="journal_id" domain="[('type','=',journal_type)]"/>
|
||||
<field name="group"/>
|
||||
<field name="invoice_date" />
|
||||
</group>
|
||||
|
@ -23,17 +23,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<act_window name="Create Invoice"
|
||||
res_model="stock.invoice.onshipping"
|
||||
src_model="stock.picking"
|
||||
key2="client_action_multi"
|
||||
multi="True"
|
||||
view_mode="form"
|
||||
view_type="form"
|
||||
target="new"
|
||||
id="action_stock_invoice_onshipping"/>
|
||||
|
||||
<act_window name="Create Draft Invoices"
|
||||
res_model="stock.invoice.onshipping"
|
||||
src_model="stock.picking"
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class stock_return_picking(osv.osv_memory):
|
||||
_inherit = 'stock.return.picking'
|
||||
_columns = {
|
||||
'invoice_state': fields.selection([('2binvoiced', 'To be refunded/invoiced'), ('none', 'No invoicing')], 'Invoicing',required=True),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
res = super(stock_return_picking, self).default_get(cr, uid, fields, context=context)
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
pick = pick_obj.browse(cr, uid, record_id, context=context)
|
||||
if pick:
|
||||
if 'invoice_state' in fields:
|
||||
if pick.invoice_state=='invoiced':
|
||||
res.update({'invoice_state': '2binvoiced'})
|
||||
else:
|
||||
res.update({'invoice_state': 'none'})
|
||||
return res
|
||||
|
||||
|
||||
|
||||
def _create_returns(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
new_picking, picking_type_id = super(stock_return_picking, self)._create_returns(cr, uid, ids, context=context)
|
||||
if data.invoice_state == '2binvoiced':
|
||||
pick_obj = self.pool.get("stock.picking")
|
||||
move_obj = self.pool.get("stock.move")
|
||||
move_ids = [x.id for x in pick_obj.browse(cr, uid, new_picking, context=context).move_lines]
|
||||
move_obj.write(cr, uid, move_ids, {'invoice_state': '2binvoiced'})
|
||||
return new_picking, picking_type_id
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,14 @@
|
|||
<openerp>
|
||||
<data>
|
||||
<record id="view_stock_return_picking_form_inherit" model="ir.ui.view">
|
||||
<field name="name">Return lines</field>
|
||||
<field name="model">stock.return.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_return_picking_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_return_moves" position="after">
|
||||
<field name="invoice_state"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -55,12 +55,13 @@ class stock_history(osv.osv):
|
|||
product_tmpl_obj = self.pool.get("product.template")
|
||||
lines_rec = self.browse(cr, uid, lines, context=context)
|
||||
for line_rec in lines_rec:
|
||||
if not line_rec.product_id.id in prod_dict:
|
||||
if line_rec.product_id.cost_method == 'real':
|
||||
prod_dict[line_rec.product_id.id] = line_rec.price_unit_on_quant
|
||||
else:
|
||||
if line_rec.product_id.cost_method == 'real':
|
||||
price = line_rec.price_unit_on_quant
|
||||
else:
|
||||
if not line_rec.product_id.id in prod_dict:
|
||||
prod_dict[line_rec.product_id.id] = product_tmpl_obj.get_history_price(cr, uid, line_rec.product_id.product_tmpl_id.id, line_rec.company_id.id, date=date, context=context)
|
||||
inv_value += prod_dict[line_rec.product_id.id] * line_rec.quantity
|
||||
price = prod_dict[line_rec.product_id.id]
|
||||
inv_value += price * line_rec.quantity
|
||||
line['inventory_value'] = inv_value
|
||||
return res
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<record id="picking_type_dropship" model="stock.picking.type">
|
||||
<field name="name">Dropship</field>
|
||||
<field name="sequence_id" ref="seq_picking_type_dropship"/>
|
||||
<field name="code">incoming</field>
|
||||
<field name="code">outgoing</field>
|
||||
<field name="default_location_src_id" ref="stock.stock_location_suppliers"/>
|
||||
<field name="default_location_dest_id" ref="stock.stock_location_customers"/>
|
||||
</record>
|
||||
|
@ -37,7 +37,6 @@
|
|||
<field name="procure_method">make_to_stock</field>
|
||||
<field name="route_id" ref="route_drop_shipping"/>
|
||||
<field name="picking_type_id" ref="picking_type_dropship"/>
|
||||
</record>
|
||||
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
Loading…
Reference in New Issue