for r in result:
c = (context or {}).copy()
c['location'] = id
- product = self.pool.get('product.product').read(cr, uid, r['product_id'], [field_to_read, pricetype.field], context=c)
- final_value += (product[field_to_read] * product[pricetype.field])
+ product = self.pool.get('product.product').read(cr, uid, r['product_id'], [field_to_read], context=c)
+ # Compute the amount_unit in right currency
+
+ context['currency_id']=self.pool.get('res.users').browse(cr,uid,uid).company_id.currency_id.id
+ amount_unit=self.pool.get('product.product').browse(cr,uid,r['product_id']).price_get(pricetype.field, context)[r['product_id']]
+
+ final_value += (product[field_to_read] * amount_unit)
return final_value
def _product_value(self, cr, uid, ids, field_names, arg, context={}):
'stock_real_value': fields.function(_product_value, method=True, type='float', string='Real Stock Value', multi="stock"),
'stock_virtual_value': fields.function(_product_value, method=True, type='float', string='Virtual Stock Value', multi="stock"),
'company_id': fields.many2one('res.company', 'Company', required=True,select=1),
+ 'scrap_location': fields.boolean('Scrap Location', help='Check this box if the current location is a place for destroyed items'),
}
_defaults = {
'active': lambda *a: 1,
'posy': lambda *a: 0,
'posz': lambda *a: 0,
'icon': lambda *a: False,
+ 'scrap_location': lambda *a: False,
}
def chained_location_get(self, cr, uid, location, partner=None, product=None, context={}):
# Take the user company and pricetype
price_type_id=self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id
pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id)
-
+ context['currency_id']=self.pool.get('res.users').browse(cr,uid,uid).company_id.currency_id.id
+
if not product_ids:
product_ids = product_obj.search(cr, uid, [])
continue
product = products_by_id[product_id]
quantity_total += qty[product_id]
-
+
# Compute based on pricetype
# Choose the right filed standard_price to read
- amount_unit=product.price_get(pricetype.field, context)[product.id]
+ amount_unit=product.price_get(pricetype.field, context)[product.id]
price = qty[product_id] * amount_unit
# price = qty[product_id] * product.standard_price
class stock_tracking(osv.osv):
_name = "stock.tracking"
_description = "Stock Tracking Lots"
-
+
+ def get_create_tracking_lot(self, cr, uid, ids, tracking_lot):
+ tracking_lot_list = self.search(cr, uid, [('name', '=', tracking_lot)],
+ limit=1)
+ if tracking_lot_list:
+ tracking_lot = tracking_lot_list[0]
+ tracking_obj = self.browse(cr, uid, tracking_lot)
+ if not tracking_obj:
+ tracking_lot_vals = {
+ 'name': tracking_lot
+ }
+ tracking_lot = self.create(cr, uid, tracking_lot_vals)
+ return tracking_lot
def checksum(sscc):
salt = '31' * 8 + '3'
sum = 0
'min_date': fields.function(get_min_max_date, fnct_inv=_set_minimum_date, multi="min_max_date",
method=True, store=True, type='datetime', string='Expected Date', select=1, help="Expected date for Picking. Default it takes current date"),
'date': fields.datetime('Order Date', help="Date of Order"),
- 'date_done': fields.datetime('Date Done', help="Date of completion"),
+ 'date_done': fields.datetime('Date Done', help="Date of Completion"),
'max_date': fields.function(get_min_max_date, fnct_inv=_set_maximum_date, multi="min_max_date",
method=True, store=True, type='datetime', string='Max. Expected Date', select=2),
- 'move_lines': fields.one2many('stock.move', 'picking_id', 'Entry lines', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
+ 'move_lines': fields.one2many('stock.move', 'picking_id', 'Internal Moves', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
'delivery_line':fields.one2many('stock.delivery', 'picking_id', 'Delivery lines', readonly=True),
'auto_picking': fields.boolean('Auto-Picking'),
'address_id': fields.many2one('res.partner.address', 'Partner', help="Address of partner"),
# TODO: Check locations to see if in the same location ?
return True
- def button_confirm(self, cr, uid, ids, *args):
- for id in ids:
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'stock.picking', id, 'button_confirm', cr)
- self.force_assign(cr, uid, ids, *args)
- return True
+# def button_confirm(self, cr, uid, ids, *args):
+# for id in ids:
+# wf_service = netsvc.LocalService("workflow")
+# wf_service.trg_validate(uid, 'stock.picking', id, 'button_confirm', cr)
+# self.force_assign(cr, uid, ids, *args)
+# return True
def action_assign(self, cr, uid, ids, *args):
for pick in self.browse(cr, uid, ids):
context=context)
return True
- def get_currency_id(self, cursor, user, picking):
+ def get_currency_id(self, cr, uid, picking):
return False
- def _get_payment_term(self, cursor, user, picking):
+ def _get_payment_term(self, cr, uid, picking):
'''Return {'contact': address, 'invoice': address} for invoice'''
partner_obj = self.pool.get('res.partner')
partner = picking.address_id.partner_id
return partner.property_payment_term and partner.property_payment_term.id or False
- def _get_address_invoice(self, cursor, user, picking):
+ def _get_address_invoice(self, cr, uid, picking):
'''Return {'contact': address, 'invoice': address} for invoice'''
partner_obj = self.pool.get('res.partner')
partner = picking.address_id.partner_id
- return partner_obj.address_get(cursor, user, [partner.id],
+ return partner_obj.address_get(cr, uid, [partner.id],
['contact', 'invoice'])
- def _get_comment_invoice(self, cursor, user, picking):
+ def _get_comment_invoice(self, cr, uid, picking):
'''Return comment string for invoice'''
return picking.note or ''
- def _get_price_unit_invoice(self, cursor, user, move_line, type):
+ def _get_price_unit_invoice(self, cr, uid, move_line, type, context=None):
'''Return the price unit for the move line'''
+ if context is None:
+ context = {}
+
if type in ('in_invoice', 'in_refund'):
# Take the user company and pricetype
- price_type_id=self.pool.get('res.users').browse(cr,users,users).company_id.property_valuation_price_type.id
- pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id)
- amount_unit=move_line.product_id.price_get(pricetype.field, context)[move_line.product_id.id]
+ price_type_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.property_valuation_price_type.id
+ pricetype = self.pool.get('product.price.type').browse(cr, uid, price_type_id)
+ context['currency_id'] = move_line.company_id.currency_id.id
+
+ amount_unit = move_line.product_id.price_get(pricetype.field, context)[move_line.product_id.id]
return amount_unit
else:
return move_line.product_id.list_price
- def _get_discount_invoice(self, cursor, user, move_line):
+ def _get_discount_invoice(self, cr, uid, move_line):
'''Return the discount for the move line'''
return 0.0
- def _get_taxes_invoice(self, cursor, user, move_line, type):
+ def _get_taxes_invoice(self, cr, uid, move_line, type):
'''Return taxes ids for the move line'''
if type in ('in_invoice', 'in_refund'):
taxes = move_line.product_id.supplier_taxes_id
if move_line.picking_id and move_line.picking_id.address_id and move_line.picking_id.address_id.partner_id:
return self.pool.get('account.fiscal.position').map_tax(
- cursor,
- user,
+ cr,
+ uid,
move_line.picking_id.address_id.partner_id.property_account_position,
taxes
)
else:
return map(lambda x: x.id, taxes)
- def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
+ def _get_account_analytic_invoice(self, cr, uid, picking, move_line):
return False
- def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id):
+ def _invoice_line_hook(self, cr, uid, move_line, invoice_line_id):
'''Call after the creation of the invoice line'''
return
- def _invoice_hook(self, cursor, user, picking, invoice_id):
+ def _invoice_hook(self, cr, uid, picking, invoice_id):
'''Call after the creation of the invoice'''
return
- def action_invoice_create(self, cursor, user, ids, journal_id=False,
+ def action_invoice_create(self, cr, uid, ids, journal_id=False,
group=False, type='out_invoice', context=None):
'''Return ids of created invoices for the pickings'''
+ if context is None:
+ context = {}
+
invoice_obj = self.pool.get('account.invoice')
invoice_line_obj = self.pool.get('account.invoice.line')
invoices_group = {}
res = {}
- for picking in self.browse(cursor, user, ids, context=context):
+ for picking in self.browse(cr, uid, ids, context=context):
if picking.invoice_state != '2binvoiced':
continue
payment_term_id = False
if type in ('out_invoice', 'out_refund'):
account_id = partner.property_account_receivable.id
- payment_term_id = self._get_payment_term(cursor, user, picking)
+ payment_term_id = self._get_payment_term(cr, uid, picking)
else:
account_id = partner.property_account_payable.id
address_contact_id, address_invoice_id = \
- self._get_address_invoice(cursor, user, picking).values()
+ self._get_address_invoice(cr, uid, picking).values()
- comment = self._get_comment_invoice(cursor, user, picking)
+ comment = self._get_comment_invoice(cr, uid, picking)
if group and partner.id in invoices_group:
invoice_id = invoices_group[partner.id]
- invoice = invoice_obj.browse(cursor, user, invoice_id)
+ invoice = invoice_obj.browse(cr, uid, invoice_id)
invoice_vals = {
'name': (invoice.name or '') + ', ' + (picking.name or ''),
'origin': (invoice.origin or '') + ', ' + (picking.name or '') + (picking.origin and (':' + picking.origin) or ''),
'comment': (comment and (invoice.comment and invoice.comment+"\n"+comment or comment)) or (invoice.comment and invoice.comment or ''),
'date_invoice':context.get('date_inv',False)
}
- invoice_obj.write(cursor, user, [invoice_id], invoice_vals, context=context)
+ invoice_obj.write(cr, uid, [invoice_id], invoice_vals, context=context)
else:
invoice_vals = {
'name': picking.name,
'date_invoice': context.get('date_inv',False),
'company_id': picking.company_id.id,
}
- cur_id = self.get_currency_id(cursor, user, picking)
+ cur_id = self.get_currency_id(cr, uid, picking)
if cur_id:
invoice_vals['currency_id'] = cur_id
if journal_id:
invoice_vals['journal_id'] = journal_id
- invoice_id = invoice_obj.create(cursor, user, invoice_vals,
+ invoice_id = invoice_obj.create(cr, uid, invoice_vals,
context=context)
invoices_group[partner.id] = invoice_id
res[picking.id] = invoice_id
account_id = move_line.product_id.categ_id.\
property_account_expense_categ.id
- price_unit = self._get_price_unit_invoice(cursor, user,
+ price_unit = self._get_price_unit_invoice(cr, uid,
move_line, type)
- discount = self._get_discount_invoice(cursor, user, move_line)
- tax_ids = self._get_taxes_invoice(cursor, user, move_line, type)
- account_analytic_id = self._get_account_analytic_invoice(cursor,
- user, picking, move_line)
+ discount = self._get_discount_invoice(cr, uid, move_line)
+ tax_ids = self._get_taxes_invoice(cr, uid, move_line, type)
+ account_analytic_id = self._get_account_analytic_invoice(cr, uid, picking, move_line)
#set UoS if it's a sale and the picking doesn't have one
uos_id = move_line.product_uos and move_line.product_uos.id or False
if not uos_id and type in ('out_invoice', 'out_refund'):
uos_id = move_line.product_uom.id
- account_id = self.pool.get('account.fiscal.position').map_account(cursor, user, partner.property_account_position, account_id)
+ account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, partner.property_account_position, account_id)
notes = False
if move_line.sale_line_id:
notes = move_line.sale_line_id.notes
elif move_line.purchase_line_id:
notes = move_line.purchase_line_id.notes
- invoice_line_id = invoice_line_obj.create(cursor, user, {
+ invoice_line_id = invoice_line_obj.create(cr, uid, {
'name': name,
'origin': origin,
'invoice_id': invoice_id,
'account_analytic_id': account_analytic_id,
'note': notes,
}, context=context)
- self._invoice_line_hook(cursor, user, move_line, invoice_line_id)
+ self._invoice_line_hook(cr, uid, move_line, invoice_line_id)
- invoice_obj.button_compute(cursor, user, [invoice_id], context=context,
+ invoice_obj.button_compute(cr, uid, [invoice_id], context=context,
set_total=(type in ('in_invoice', 'in_refund')))
- self.write(cursor, user, [picking.id], {
+ self.write(cr, uid, [picking.id], {
'invoice_state': 'invoiced',
}, context=context)
- self._invoice_hook(cursor, user, picking, invoice_id)
- self.write(cursor, user, res.keys(), {
+ self._invoice_hook(cr, uid, picking, invoice_id)
+ self.write(cr, uid, res.keys(), {
'invoice_state': 'invoiced',
}, context=context)
return res
return True
def unlink(self, cr, uid, ids, context=None):
+ move_obj = self.pool.get('stock.move')
+ if not context:
+ context = {}
+
for pick in self.browse(cr, uid, ids, context=context):
if pick.state in ['done','cancel']:
raise osv.except_osv(_('Error'), _('You cannot remove the picking which is in %s state !')%(pick.state,))
- elif pick.state in ['confirmed','assigned']:
+ elif pick.state in ['confirmed','assigned', 'draft']:
ids2 = [move.id for move in pick.move_lines]
- context.update({'call_unlink':True})
- self.pool.get('stock.move').action_cancel(cr, uid, ids2, context)
- else:
- continue
+ ctx = context.copy()
+ ctx.update({'call_unlink':True})
+ if pick.state != 'draft':
+ #Cancelling the move in order to affect Virtual stock of product
+ move_obj.action_cancel(cr, uid, ids2, ctx)
+ #Removing the move
+ move_obj.unlink(cr, uid, ids2, ctx)
+
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
def do_partial(self, cr, uid, ids, partial_datas, context={}):
"""
- @ partial_datas : dict. contain details of partial picking
+ @ partial_datas : dict. contain details of partial picking
like partner_id, address_id, delivery_date, delivery moves with product_id, product_qty, uom
"""
res = {}
complete, too_many, too_few = [], [], []
move_product_qty = {}
for move in pick.move_lines:
- partial_data = partial_datas.get('move%s'%(move.id), False)
+ if move.state in ('done', 'cancel'):
+ continue
+ partial_data = partial_datas.get('move%s'%(move.id), False)
assert partial_data, _('Do not Found Partial data of Stock Move Line :%s' %(move.id))
product_qty = partial_data.get('product_qty',0.0)
move_product_qty[move.id] = product_qty
# Average price computation
if (pick.type == 'in') and (move.product_id.cost_method == 'average'):
product = product_obj.browse(cr, uid, move.product_id.id)
- user = users_obj.browse(cr, uid, uid)
-
+ user = users_obj.browse(cr, uid, uid)
+ context['currency_id'] = move.company_id.currency_id.id
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
pricetype = False
if user.company_id.property_valuation_price_type:
pricetype = price_type_obj.browse(cr, uid, user.company_id.property_valuation_price_type.id)
if pricetype and qty > 0:
- new_price = currency_obj.compute(cr, uid, currency,
+ new_price = currency_obj.compute(cr, uid, product_currency,
user.company_id.currency_id.id, product_price)
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
product.uom_id.id)
amount_unit = product.price_get(pricetype.field, context)[product.id]
new_std_price = ((amount_unit * product.qty_available)\
+ (new_price * qty))/(product.qty_available + qty)
-
+
# Write the field according to price type field
product_obj.write(cr, uid, [product.id],
{pricetype.field: new_std_price})
move_obj.write(cr, uid, [move.id], {'price_unit': new_price})
-
+
for move in too_few:
product_qty = move_product_qty[move.id]
if not new_picking:
'state':'draft',
})
if product_qty != 0:
-
+
new_obj = move_obj.copy(cr, uid, move.id,
{
'product_qty' : product_qty,
'product_uos_qty': product_qty, #TODO: put correct uos_qty
- 'picking_id' : new_picking,
+ 'picking_id' : new_picking,
'state': 'assigned',
- 'move_dest_id': False,
+ 'move_dest_id': False,
'price_unit': move.price_unit,
})
-
+
move_obj.write(cr, uid, [move.id],
{
'product_qty' : move.product_qty - product_qty,
'product_uos_qty':move.product_qty - product_qty, #TODO: put correct uos_qty
-
+
})
if new_picking:
'product_uos_qty': product_qty #TODO: put correct uos_qty
})
- # At first we confirm the new picking (if necessary)
+ # At first we confirm the new picking (if necessary)
if new_picking:
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
# Then we finish the good picking
delivered_pack_id = new_picking
else:
self.action_move(cr, uid, [pick.id])
- wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
+ wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr)
delivered_pack_id = pick.id
- delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
+ delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
delivery_id = delivery_obj.create(cr, uid, {
- 'name': delivered_pack.name,
+ 'name': delivered_pack.name or move.name,
'partner_id': partner_id,
'address_id': address_id,
'date': delivery_date,
- 'picking_id' : pick.id,
- 'move_delivered' : [(6,0, map(lambda x:x.id, delivered_pack.move_lines))]
- }, context=context)
+ 'picking_id' : pick.id,
+ 'move_delivered' : [(6,0, map(lambda x:x.id, delivered_pack.move_lines))]
+ }, context=context)
res[pick.id] = {'delivered_picking': delivered_pack.id or False}
return res
}
stock_production_lot_revision()
-
+
class stock_delivery(osv.osv):
-
+
""" Tracability of partialdeliveries """
-
+
_name = "stock.delivery"
_description = "Delivery"
_columns = {
- 'name': fields.char('Name', size=60, required=True),
+ 'name': fields.char('Name', size=60, required=True),
'date': fields.datetime('Date', required=True),
'partner_id': fields.many2one('res.partner', 'Partner', required=True),
'address_id': fields.many2one('res.partner.address', 'Address', required=True),
'move_delivered':fields.one2many('stock.move', 'delivered_id', 'Move Delivered'),
- 'picking_id': fields.many2one('stock.picking', 'Picking list', required=True),
-
+ 'picking_id': fields.many2one('stock.picking', 'Picking list'),
+
}
-
stock_delivery()
# ----------------------------------------------------
# Move
'date': fields.datetime('Created Date'),
'date_planned': fields.datetime('Date', required=True, help="Scheduled date for the movement of the products or real date if the move is done."),
-
+ 'date_expected': fields.datetime('Date Expected', readonly=True,required=True, help="Scheduled date for the movement of the products"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
'product_qty': fields.float('Quantity', required=True),
'origin': fields.related('picking_id','origin',type='char', size=64, relation="stock.picking", string="Origin"),
'move_stock_return_history': fields.many2many('stock.move', 'stock_move_return_history', 'move_id', 'return_move_id', 'Move Return History',readonly=True),
'delivered_id': fields.many2one('stock.delivery', 'Product delivered'),
- 'scraped': fields.boolean('Scraped'),
+ 'scraped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scraped'),
}
_constraints = [
(_check_tracking,
'location_dest_id': _default_location_destination,
'state': lambda *a: 'draft',
'priority': lambda *a: '1',
- 'scraped' : lambda *a:False,
'product_qty': lambda *a: 1.0,
+ 'scraped' : lambda *a: False,
'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
- 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.move', context=c)
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.move', context=c),
+ 'date_expected': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
}
def copy(self, cr, uid, id, default=None, context={}):
new_moves = []
for picking, todo in self._chain_compute(cr, uid, moves, context).items():
ptype = self.pool.get('stock.location').picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
+ pick_name = ''
+ if ptype == 'delivery':
+ pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.delivery')
pickid = self.pool.get('stock.picking').create(cr, uid, {
- 'name': picking.name,
+ 'name': pick_name or picking.name,
'origin': str(picking.origin or ''),
'type': ptype,
'note': picking.note,
if done:
count += len(done)
self.write(cr, uid, done, {'state': 'assigned'})
-
+
if count:
for pick_id in pickings:
wf_service = netsvc.LocalService("workflow")
for id in ids:
wf_service.trg_trigger(uid, 'stock.move', id, cr)
#self.action_cancel(cr,uid, ids2, context)
- return True
-
- def action_done(self, cr, uid, ids, context=None):
+ return True
+
+ def action_done(self, cr, uid, ids, context={}):
track_flag = False
picking_ids = []
+ product_uom_obj = self.pool.get('product.uom')
+ price_type_obj = self.pool.get('product.price.type')
+ move_obj = self.pool.get('account.move')
for move in self.browse(cr, uid, ids):
if move.picking_id: picking_ids.append(move.picking_id.id)
if move.move_dest_id.id and (move.state != 'done'):
journal_id = move.product_id.categ_id.property_stock_journal.id
if acc_src != acc_dest:
ref = move.picking_id and move.picking_id.name or False
- product_uom_obj = self.pool.get('product.uom')
default_uom = move.product_id.uom_id.id
date = time.strftime('%Y-%m-%d')
q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
amount = q * move.price_unit
# Base computation on valuation price type
else:
- company_id=move.company_id.id
-
- pricetype=self.pool.get('product.price.type').browse(cr,uid,move.company_id.property_valuation_price_type.id)
- amount_unit=move.product_id.price_get(pricetype.field, context)[move.product_id.id]
- amount=amount_unit * q or 1.0
+ company_id = move.company_id.id
+ context['currency_id'] = move.company_id.currency_id.id
+ pricetype = price_type_obj.browse(cr,uid,move.company_id.property_valuation_price_type.id)
+ amount_unit = move.product_id.price_get(pricetype.field, context)[move.product_id.id]
+ amount = amount_unit * q or 1.0
# amount = q * move.product_id.standard_price
-
+
partner_id = False
if move.picking_id:
partner_id = move.picking_id.address_id and (move.picking_id.address_id.partner_id and move.picking_id.address_id.partner_id.id or False) or False
'date': date,
'partner_id': partner_id})
]
- self.pool.get('account.move').create(cr, uid, {
+ move_obj.create(cr, uid, {
'name': move.name,
'journal_id': journal_id,
'line_id': lines,
'ref': ref,
})
- self.write(cr, uid, ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S')})
- for pick in self.pool.get('stock.picking').browse(cr, uid, picking_ids):
+ tracking_lot = False
+ if context:
+ tracking_lot = context.get('tracking_lot', False)
+ if tracking_lot:
+ rec_id = context and context.get('active_id', False)
+ tracking = self.pool.get('stock.tracking')
+ tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
+
+ self.write(cr, uid, ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S'), 'tracking_id': tracking_lot or False})
+ picking_obj = self.pool.get('stock.picking')
+ for pick in picking_obj.browse(cr, uid, picking_ids):
if all(move.state == 'done' for move in pick.move_lines):
- self.pool.get('stock.picking').action_done(cr, uid, [pick.id])
+ picking_obj.action_done(cr, uid, [pick.id])
wf_service = netsvc.LocalService("workflow")
for id in ids:
return True
def unlink(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
for move in self.browse(cr, uid, ids, context=context):
if move.state != 'draft':
raise osv.except_osv(_('UserError'),
_('You can only delete draft moves.'))
return super(stock_move, self).unlink(
- cr, uid, ids, context=context)
+ cr, uid, ids, context=context)
def _create_lot(self, cr, uid, ids, product_id, prefix=False):
prodlot_obj = self.pool.get('stock.production.lot')
if not sequence:
raise osv.except_osv(_('Error!'), _('No production sequence defined'))
prodlot_id = prodlot_obj.create(cr, uid, {'name': sequence, 'prefix': prefix}, {'product_id': product_id})
- prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
+ prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
ref = ','.join(map(lambda x:str(x),ids))
if prodlot.ref:
- ref = '%s, %s' % (prodlot.ref, ref)
+ ref = '%s, %s' % (prodlot.ref, ref)
prodlot_obj.write(cr, uid, [prodlot_id], {'ref': ref})
return prodlot_id
def action_scrap(self, cr, uid, ids, quantity, location_id, context=None):
'''
- Move the scrap/damaged product into scrap location
-
+ Move the scrap/damaged product into scrap location
+
@ param cr: the database cursor
@ param uid: the user id
@ param ids: ids of stock move object to be scraped
@ param context: context arguments
@ return: Scraped lines
- '''
+ '''
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
- res = []
- for move in self.browse(cr, uid, ids, context=context):
+ res = []
+ for move in self.browse(cr, uid, ids, context=context):
move_qty = move.product_qty
uos_qty = quantity / move_qty * move.product_uos_qty
default_val = {
- 'product_qty': quantity,
- 'product_uos_qty': uos_qty,
- 'state': move.state,
- 'scraped' : True,
+ 'product_qty': quantity,
+ 'product_uos_qty': uos_qty,
+ 'state': move.state,
+ 'scraped' : True,
'location_dest_id': location_id
}
new_move = self.copy(cr, uid, move.id, default_val)
#self.write(cr, uid, [new_move], {'move_history_ids':[(4,move.id)]}) #TODO : to track scrap moves
- res += [new_move]
+ res += [new_move]
self.action_done(cr, uid, res)
return res
def action_split(self, cr, uid, ids, quantity, split_by_qty=1, prefix=False, with_lot=True, context=None):
'''
Split Stock Move lines into production lot which specified split by quantity.
-
+
@ param cr: the database cursor
@ param uid: the user id
@ param ids: ids of stock move object to be splited
@ param context: context arguments
@ return: splited move lines
- '''
+ '''
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
res = []
- for move in self.browse(cr, uid, ids):
+ for move in self.browse(cr, uid, ids):
if split_by_qty <= 0 or quantity == 0:
return res
update_val = {
'product_qty': split_by_qty,
'product_uos_qty': uos_qty,
- }
- for idx in range(int(quantity//split_by_qty)):
+ }
+ for idx in range(int(quantity//split_by_qty)):
if not idx and move.product_qty<=quantity:
current_move = move.id
else:
update_val['prodlot_id'] = self._create_lot(cr, uid, [current_move], move.product_id.id)
self.write(cr, uid, [current_move], update_val)
-
-
- if quantity_rest > 0:
- idx = int(quantity//split_by_qty)
+
+
+ if quantity_rest > 0:
+ idx = int(quantity//split_by_qty)
update_val['product_qty'] = quantity_rest
- update_val['product_uos_qty'] = uos_qty_rest
- if not idx and move.product_qty<=quantity:
- current_move = move.id
+ update_val['product_uos_qty'] = uos_qty_rest
+ if not idx and move.product_qty<=quantity:
+ current_move = move.id
else:
- current_move = self.copy(cr, uid, move.id, {'state': move.state})
-
+ current_move = self.copy(cr, uid, move.id, {'state': move.state})
+
res.append(current_move)
-
-
- if with_lot:
+
+
+ if with_lot:
update_val['prodlot_id'] = self._create_lot(cr, uid, [current_move], move.product_id.id)
self.write(cr, uid, [current_move], update_val)
- return res
+ return res
- def action_consume(self, cr, uid, ids, quantity, location_id=False, context=None):
+ def action_consume(self, cr, uid, ids, quantity, location_id=False, context=None):
'''
Consumed product with specific quatity from specific source location
-
+
@ param cr: the database cursor
@ param uid: the user id
@ param ids: ids of stock move object to be consumed
@ param quantity : specify consume quantity
- @ param location_id : specify source location
+ @ param location_id : specify source location
@ param context: context arguments
@ return: Consumed lines
- '''
- if not context:
+ '''
+ if context is None:
context = {}
-
+
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
- res = []
- for move in self.browse(cr, uid, ids, context=context):
+ res = []
+ for move in self.browse(cr, uid, ids, context=context):
move_qty = move.product_qty
quantity_rest = move.product_qty
- quantity_rest -= quantity
- uos_qty_rest = quantity_rest / move_qty * move.product_uos_qty
+ quantity_rest -= quantity
+ uos_qty_rest = quantity_rest / move_qty * move.product_uos_qty
if quantity_rest <= 0:
- quantity_rest = 0
+ quantity_rest = 0
uos_qty_rest = 0
quantity = move.product_qty
-
+
uos_qty = quantity / move_qty * move.product_uos_qty
- if quantity_rest > 0:
+ if quantity_rest > 0:
default_val = {
- 'product_qty': quantity,
- 'product_uos_qty': uos_qty,
- 'state': move.state,
+ 'product_qty': quantity,
+ 'product_uos_qty': uos_qty,
+ 'state': move.state,
'location_id': location_id
- }
+ }
if move.product_id.track_production and location_id:
# IF product has checked track for production lot, move lines will be split by 1
res += self.action_split(cr, uid, [move.id], quantity, split_by_qty=1, context=context)
current_move = self.copy(cr, uid, move.id, default_val)
res += [current_move]
- update_val = {}
+ update_val = {}
update_val['product_qty'] = quantity_rest
- update_val['product_uos_qty'] = uos_qty_rest
- self.write(cr, uid, [move.id], update_val)
+ update_val['product_uos_qty'] = uos_qty_rest
+ self.write(cr, uid, [move.id], update_val)
- else:
- quantity_rest = quantity
+ else:
+ quantity_rest = quantity
uos_qty_rest = uos_qty
-
+
if move.product_id.track_production and location_id:
res += self.split_lines(cr, uid, [move.id], quantity_rest, split_by_qty=1, context=context)
- else:
- res += [move.id]
+ else:
+ res += [move.id]
update_val = {
'product_qty' : quantity_rest,
'product_uos_qty' : uos_qty_rest,
'location_id': location_id
- }
+ }
self.write(cr, uid, [move.id], update_val)
- self.action_done(cr, uid, res)
- return res
+ self.action_done(cr, uid, res)
+ return res
+
+ def do_partial(self, cr, uid, ids, partial_datas, context={}):
+ """
+ @ partial_datas : dict. contain details of partial picking
+ like partner_id, address_id, delivery_date, delivery moves with product_id, product_qty, uom
+ """
+ res = {}
+ picking_obj = self.pool.get('stock.picking')
+ delivery_obj = self.pool.get('stock.delivery')
+ product_obj = self.pool.get('product.product')
+ currency_obj = self.pool.get('res.currency')
+ users_obj = self.pool.get('res.users')
+ uom_obj = self.pool.get('product.uom')
+ price_type_obj = self.pool.get('product.price.type')
+ sequence_obj = self.pool.get('ir.sequence')
+ wf_service = netsvc.LocalService("workflow")
+ partner_id = partial_datas.get('partner_id', False)
+ address_id = partial_datas.get('address_id', False)
+ delivery_date = partial_datas.get('delivery_date', False)
+ tracking_lot = context.get('tracking_lot', False)
+
+ new_moves = []
+
+ complete, too_many, too_few = [], [], []
+ move_product_qty = {}
+ for move in self.browse(cr, uid, ids, context=context):
+ if move.state in ('done', 'cancel'):
+ continue
+ partial_data = partial_datas.get('move%s'%(move.id), False)
+ assert partial_data, _('Do not Found Partial data of Stock Move Line :%s' %(move.id))
+ product_qty = partial_data.get('product_qty',0.0)
+ move_product_qty[move.id] = product_qty
+ product_uom = partial_data.get('product_uom',False)
+ product_price = partial_data.get('product_price',0.0)
+ product_currency = partial_data.get('product_currency',False)
+ if move.product_qty == product_qty:
+ self.write(cr, uid, move.id,
+ {
+ 'tracking_id': tracking_lot
+ })
+ complete.append(move)
+ elif move.product_qty > product_qty:
+ too_few.append(move)
+ else:
+ too_many.append(move)
+
+ # Average price computation
+ if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
+ product = product_obj.browse(cr, uid, move.product_id.id)
+ user = users_obj.browse(cr, uid, uid)
+ context['currency_id'] = move.company_id.currency_id.id
+ qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
+ pricetype = False
+ if user.company_id.property_valuation_price_type:
+ pricetype = price_type_obj.browse(cr, uid, user.company_id.property_valuation_price_type.id)
+ if pricetype and qty > 0:
+ new_price = currency_obj.compute(cr, uid, product_currency,
+ user.company_id.currency_id.id, product_price)
+ new_price = uom_obj._compute_price(cr, uid, product_uom, new_price,
+ product.uom_id.id)
+ if product.qty_available <= 0:
+ new_std_price = new_price
+ else:
+ # Get the standard price
+ amount_unit = product.price_get(pricetype.field, context)[product.id]
+ new_std_price = ((amount_unit * product.qty_available)\
+ + (new_price * qty))/(product.qty_available + qty)
+
+ # Write the field according to price type field
+ product_obj.write(cr, uid, [product.id],
+ {pricetype.field: new_std_price})
+ self.write(cr, uid, [move.id], {'price_unit': new_price})
+
+ for move in too_few:
+ product_qty = move_product_qty[move.id]
+ if product_qty != 0:
+ new_move = self.copy(cr, uid, move.id,
+ {
+ 'product_qty' : product_qty,
+ 'product_uos_qty': product_qty,
+ 'picking_id' : move.picking_id.id,
+ 'state': 'assigned',
+ 'move_dest_id': False,
+ 'price_unit': move.price_unit,
+ 'tracking_id': tracking_lot,
+ })
+ complete.append(self.browse(cr, uid, new_move))
+ self.write(cr, uid, move.id,
+ {
+ 'product_qty' : move.product_qty - product_qty,
+ 'product_uos_qty':move.product_qty - product_qty,
+ })
+
+
+ for move in too_many:
+ self.write(cr, uid, move.id,
+ {
+ 'product_qty': move.product_qty,
+ 'product_uos_qty': move.product_qty,
+ 'tracking_id': tracking_lot
+ })
+ complete.append(move)
+
+ for move in complete:
+ self.action_done(cr, uid, [move.id], context)
+
+ # TOCHECK : Done picking if all moves are done
+ cr.execute("""
+ SELECT move.id FROM stock_picking pick
+ RIGHT JOIN stock_move move ON move.picking_id = pick.id AND move.state = %s
+ WHERE pick.id = %s""",
+ ('done', move.picking_id.id))
+ res = cr.fetchall()
+ if len(res) == len(move.picking_id.move_lines):
+ picking_obj.action_move(cr, uid, [move.picking_id.id])
+ wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr)
+
+ ref = {}
+ done_move_ids = []
+ for move in complete:
+ done_move_ids.append(move.id)
+ if move.picking_id.id not in ref:
+ delivery_id = delivery_obj.create(cr, uid, {
+ 'partner_id': partner_id,
+ 'address_id': address_id,
+ 'date': delivery_date,
+ 'name' : move.picking_id.name,
+ 'picking_id': move.picking_id.id
+ }, context=context)
+ ref[move.picking_id.id] = delivery_id
+ delivery_obj.write(cr, uid, ref[move.picking_id.id], {
+ 'move_delivered' : [(4,move.id)]
+ })
+ return done_move_ids
stock_move()
'state': lambda *a: 'draft',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c)
}
-
-
+
+
def _inventory_line_hook(self, cr, uid, inventory_line, move_vals):
'''Creates a stock move from an inventory line'''
return self.pool.get('stock.move').create(cr, uid, move_vals)
move_line = []
for line in inv.inventory_line_id:
pid = line.product_id.id
-
+
# price = line.product_id.standard_price or 0.0
amount = self.pool.get('stock.location')._product_get(cr, uid, line.location_id.id, [pid], {'uom': line.product_uom.id})[pid]
change = line.product_qty - amount
# 'partner_id': fields.many2one('res.partner', 'Owner'),
'company_id': fields.many2one('res.company','Company',required=True,select=1),
'partner_address_id': fields.many2one('res.partner.address', 'Owner Address'),
- 'lot_input_id': fields.many2one('stock.location', 'Location Input', required=True),
- 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True),
- 'lot_output_id': fields.many2one('stock.location', 'Location Output', required=True),
+ 'lot_input_id': fields.many2one('stock.location', 'Location Input', required=True, domain=[('usage','<>','view')]),
+ 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage','<>','view')]),
+ 'lot_output_id': fields.many2one('stock.location', 'Location Output', required=True, domain=[('usage','<>','view')]),
}
_defaults = {
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c),
}
-stock_warehouse()
+stock_warehouse()
# Move wizard :
if line.picking_id:
picking_obj.write(cr, uid, [line.picking_id.id], {'move_lines': [(1, line.id, {'picking_id': act['picking_id']})]})
picking_obj.write(cr, uid, [act['picking_id']], {'move_lines': [(1, line.id, {'picking_id': act['picking_id']})]})
- cr.commit()
old_picking = picking_obj.read(cr, uid, [line.picking_id.id])[0]
if not len(old_picking['move_lines']):
picking_obj.write(cr, uid, [old_picking['id']], {'state': 'done'})
tools.drop_view_if_exists(cr, 'report_products_to_received_planned')
cr.execute("""
create or replace view report_products_to_received_planned as (
- select stock.date, min(stock.id), sum(stock.product_qty) as qty, 0 as planned_qty
+ select stock.date, min(stock.id) as id, sum(stock.product_qty) as qty, 0 as planned_qty
from stock_picking picking
inner join stock_move stock
on picking.id = stock.picking_id and picking.type = 'in'
union
- select stock.date_planned, min(stock.id), 0 as actual_qty, sum(stock.product_qty) as planned_qty
+ select stock.date_planned, min(stock.id) as id, 0 as actual_qty, sum(stock.product_qty) as planned_qty
from stock_picking picking
inner join stock_move stock
on picking.id = stock.picking_id and picking.type = 'in'
tools.drop_view_if_exists(cr, 'report_delivery_products_planned')
cr.execute("""
create or replace view report_delivery_products_planned as (
- select stock.date, min(stock.id), sum(stock.product_qty) as qty, 0 as planned_qty
+ select stock.date, min(stock.id) as id, sum(stock.product_qty) as qty, 0 as planned_qty
from stock_picking picking
inner join stock_move stock
on picking.id = stock.picking_id and picking.type = 'out'