|
@@ -0,0 +1,178 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+from openerp import models, fields, api, _
|
|
|
+from openerp.exceptions import Warning
|
|
|
+from openerp.tools import float_compare
|
|
|
+import logging
|
|
|
+
|
|
|
+_logger = logging.getLogger(__name__)
|
|
|
+
|
|
|
+
|
|
|
+class StockWarehouseTransfer(models.Model):
|
|
|
+ _name = 'stock.warehouse.transfer'
|
|
|
+ _description = 'Stock Warehouse Transfer'
|
|
|
+ _inherit = ['mail.thread', 'ir.needaction_mixin']
|
|
|
+
|
|
|
+ @api.model
|
|
|
+ def _get_default_name(self):
|
|
|
+ return self.env['ir.sequence'].get('stock.warehouse.transfer')
|
|
|
+
|
|
|
+ @api.model
|
|
|
+ def _get_default_date(self):
|
|
|
+ return fields.Date.context_today(self)
|
|
|
+
|
|
|
+ @api.model
|
|
|
+ def _get_default_state(self):
|
|
|
+ return 'draft'
|
|
|
+
|
|
|
+ @api.multi
|
|
|
+ @api.depends('pickings.state')
|
|
|
+ def _calc_transfer_state(self):
|
|
|
+ for rec in self:
|
|
|
+ if rec.pickings:
|
|
|
+ picking_states = [p.state for p in rec.pickings]
|
|
|
+ if 'done' in picking_states:
|
|
|
+ rec.state = 'done'
|
|
|
+ else:
|
|
|
+ rec.state = 'draft'
|
|
|
+
|
|
|
+ name = fields.Char(
|
|
|
+ string='Referencia',
|
|
|
+ default=_get_default_name)
|
|
|
+ date = fields.Date(
|
|
|
+ string='Fecha',
|
|
|
+ default=_get_default_date)
|
|
|
+ source_warehouse = fields.Many2one(
|
|
|
+ comodel_name='stock.warehouse',
|
|
|
+ string='Déposito de Origen')
|
|
|
+ dest_warehouse = fields.Many2one(
|
|
|
+ comodel_name='stock.warehouse',
|
|
|
+ string='Déposito de Destino')
|
|
|
+ state = fields.Selection(
|
|
|
+ selection=[
|
|
|
+ ('draft', 'Borrador'),
|
|
|
+ ('done', 'Hecho')],
|
|
|
+ string='Status',
|
|
|
+ default=_get_default_state,
|
|
|
+ store=True,
|
|
|
+ compute=_calc_transfer_state)
|
|
|
+ lines = fields.One2many(
|
|
|
+ comodel_name='stock.warehouse.transfer.line',
|
|
|
+ inverse_name='transfer',
|
|
|
+ string='Lineas de Transferencia')
|
|
|
+ pickings = fields.One2many(
|
|
|
+ comodel_name='stock.picking',
|
|
|
+ inverse_name='transfer',
|
|
|
+ string='Transferencia Relacionada')
|
|
|
+ company_id = fields.Many2one(
|
|
|
+ comodel_name='res.company', string='Compania', required=True,
|
|
|
+ default=lambda self: self.env['res.company']._company_default_get(
|
|
|
+ 'stock.warehouse.transfer'))
|
|
|
+
|
|
|
+
|
|
|
+ def get_transfer_picking_type(self):
|
|
|
+ self.ensure_one()
|
|
|
+
|
|
|
+ picking_types = self.env['stock.picking.type'].search(
|
|
|
+ [
|
|
|
+ ('default_location_src_id', '=', self.source_warehouse.lot_stock_id.id),
|
|
|
+ ('code', '=', 'outgoing')
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ if not picking_types:
|
|
|
+ _logger.error("No picking type found")
|
|
|
+
|
|
|
+
|
|
|
+ return picking_types and picking_types[0]
|
|
|
+
|
|
|
+ @api.multi
|
|
|
+ def get_picking_vals(self):
|
|
|
+ self.ensure_one()
|
|
|
+ picking_type = self.get_transfer_picking_type()
|
|
|
+ picking_vals = {
|
|
|
+ 'picking_type_id' : picking_type.id,
|
|
|
+ 'transfer' : self.id,
|
|
|
+ 'origin': self.name
|
|
|
+ }
|
|
|
+
|
|
|
+ return picking_vals
|
|
|
+
|
|
|
+ @api.multi
|
|
|
+ def action_create_picking(self):
|
|
|
+ for rec in self:
|
|
|
+ picking_vals = rec.get_picking_vals()
|
|
|
+ _logger.debug("Picking Vals: %s", picking_vals)
|
|
|
+ picking = rec.pickings.create(picking_vals)
|
|
|
+ if not picking:
|
|
|
+ _logger.error("Error Creating Picking")
|
|
|
+
|
|
|
+
|
|
|
+ pc_group = rec._get_procurement_group()
|
|
|
+
|
|
|
+ for line in rec.lines:
|
|
|
+ move_vals = line.get_move_vals(picking, pc_group)
|
|
|
+ if move_vals:
|
|
|
+ _logger.debug("Move Vals: %s", move_vals)
|
|
|
+
|
|
|
+ product = self.env['product.product'].browse(move_vals['product_id'])
|
|
|
+ location = self.env['stock.location'].browse(move_vals['location_id'])
|
|
|
+ uom = self.env['stock.location'].browse(move_vals['location_id'])
|
|
|
+ if product.type == 'product':
|
|
|
+ uom_record = product.uom_id
|
|
|
+ qty_available = self.get_location_qty(product.id, move_vals['location_id'])
|
|
|
+ compare_qty = float_compare(qty_available, move_vals['product_uom_qty'], precision_rounding=uom_record.rounding)
|
|
|
+ if compare_qty == -1:
|
|
|
+ warn_msg = _('Estas intentando transferir %.2f %s de %s pero el déposito de origen posee %.2f %s disponible!') % \
|
|
|
+ (move_vals['product_uom_qty'], uom_record.name,
|
|
|
+ product.name,
|
|
|
+ max(0,qty_available), uom_record.name)
|
|
|
+ raise Warning(_("No hay stock suficiente: "),_(warn_msg))
|
|
|
+ move_id = self.env['stock.move'].create(move_vals)
|
|
|
+ move_id.action_done()
|
|
|
+
|
|
|
+ @api.multi
|
|
|
+ def get_location_qty(self, product_id, location_id):
|
|
|
+ location_ids = self.env['stock.location'].search([('active','=',True),('usage','=','internal')])
|
|
|
+ for id in location_ids:
|
|
|
+ suma = 0
|
|
|
+ quant_ids = self.env['stock.quant'].search([('product_id','=', product_id),('location_id','=',location_id)])
|
|
|
+ if quant_ids:
|
|
|
+ for quant_id in quant_ids:
|
|
|
+ suma = suma + quant_id.qty
|
|
|
+ return suma
|
|
|
+
|
|
|
+ @api.model
|
|
|
+ def _prepare_procurement_group(self):
|
|
|
+ return {'name': self.name}
|
|
|
+
|
|
|
+ @api.model
|
|
|
+ def _get_procurement_group(self):
|
|
|
+ pc_groups = self.env['procurement.group'].search(
|
|
|
+ [
|
|
|
+ ('name', '=', self.name)
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ if pc_groups:
|
|
|
+ pc_group = pc_groups[0]
|
|
|
+ else:
|
|
|
+ pc_vals = self._prepare_procurement_group()
|
|
|
+ pc_group = self.env['procurement.group'].create(pc_vals)
|
|
|
+ return pc_group or False
|