4

I need to check in my lines, the products I have, their respective quantities, and know what is the availability of such products in warehouses, the stock.move and stock.picking do something like that, but it's old api, I need a custom method.

This is my method:

class bsi_production_order(models.Model):
_name = 'bsi.production.order'

name = fields.Char('Reference', required=True, index=True, copy=False, readonly='True', default='New')
date = fields.Date(string="Production Date")
production_type = fields.Selection([
        ('budgeted','Budgeted'),
        ('nonbudgeted','Non Budgeted'),
        ('direct','Direct Order'),
    ], string='Type of Order', index=True,  
    track_visibility='onchange', copy=False,
    help=" ")
notes = fields.Text(string="Notes")
order_lines = fields.One2many('bsi.production.order.lines', 'production_order', states={'finished': [('readonly', True)], 'cancel': [('readonly', True)]}, string="Order lines", copy=True)
print_orders = fields.One2many('bsi.print.order', 'production_orders', string="Print Orders")
warehouse_quantity = fields.Char(compute='quantity', string='Quantity per warehouse')

class bsi_production_order_lines(models.Model):
_name = 'bsi.production.order.lines'

production_order = fields.Many2one('bsi.production.order', string="Production Orders")
isbn = fields.Many2one('product.product', string="ISBN", domain="[('is_isbn', '=', True)]")
qty = fields.Integer(string="Quantity")
consumed_qty = fields.Float(string="Consumed quantity")
remaining_qty = fields.Float(string="Remaining quantity")

I need to check from bsi.production.order on the order_lines One2many field, the isbn which is a product, how much of it is available on all the locations of the system, also, compare it to the qty field, so, from there I can go to another state on the object.

Think about the stock.picking or stock.move objects. It's basically the same logic.

So far, I've tried this method, to check if there is any line on the One2many object.

@api.multi
@api.depends('order_lines', 'order_lines.isbn')
def checkit(self):
    #actual_stock = self.env['product.product'].browse(qty_available)
    for record in self:
        if self.order_lines:
            for line in self.order_lines:
                if line.isbn:
                    return line.isbn
        else:
            raise Warning(('Enter​ ​at least​ ​1​ ​ISBN to produce'))

This works so far, to check whether there is a isbn on the line, or not, I'll need to also check if there is enough on warehouse to make the calculation, and if there is, then proceed to the next stage, I'm only tuck on the stock.location part.

I've checked some other modules on stock management OCA repo, although there are similar routines, I couldn't find something really suitable to this.

There is this method, which seems quite likely what I need:

@api.multi
@api.depends('order_lines', 'order_lines.isbn')
def quantity(self):
    for record in self:
        warehouse_quantity_text = ''
        isbn = self.env['product.product'].sudo().search([('product_tmpl_id', '=', record.id)])
        if isbn:
            quant_ids = self.env['stock.quant'].sudo().search([('isbn','=',isbn[0].id),('location_id.usage','=','internal')])
            t_warehouses = {}
            for quant in quant_ids:
                if quant.location_id:
                    if quant.location_id not in t_warehouses:
                        t_warehouses.update({quant.location_id:0})
                    t_warehouses[quant.location_id] += quant.qty

            tt_warehouses = {}
            for location in t_warehouses:
                warehouse = False
                location1 = location
                while (not warehouse and location1):
                    warehouse_id = self.env['stock.warehouse'].sudo().search([('lot_stock_id','=',location1.id)])
                    if len(warehouse_id) > 0:
                        warehouse = True
                    else:
                        warehouse = False
                    location1 = location1.location_id
                if warehouse_id:
                    if warehouse_id.name not in tt_warehouses:
                        tt_warehouses.update({warehouse_id.name:0})
                    tt_warehouses[warehouse_id.name] += t_warehouses[location]

            for item in tt_warehouses:
                if tt_warehouses[item] != 0:
                    warehouse_quantity_text = warehouse_quantity_text + ' ** ' + item + ': ' + str(tt_warehouses[item])
            record.warehouse_quantity = warehouse_quantity_text

But it doesn't works since it needs a field, also, I think it's far complex, there must be an easier way to do this checking.

In a nutshell: I need to check the quantities on the system, compare it to every isbn (product) on the line, which it'll be the qty field, if not enough, do nothing, if there is, then pass to the next state.

skink
  • 5,133
  • 6
  • 37
  • 58
NeoVe
  • 3,857
  • 8
  • 54
  • 134
  • 1
    The trick on getting the real stock, which means on a specific warehouse or locaton, is to browse the product with some context variables. You really have to look into [this method](https://github.com/odoo/odoo/blob/cf8577b9d0bbe6f02ed4e88e47ab3097683d519d/addons/stock/product.py#L139). For example: if you have 2 warehouses and on sales order want to decide per customer which warehouse to choose (maybe country-wise), you need a warehouse many2one field on sales order and provide this on context, to get warnings on product selection in order lines, if there isn't enough stock. – CZoellner Oct 25 '17 at 11:21

1 Answers1

1

First if you want to check if the data is correct use @api.constrains not @api.depends, @api.depends if for computing.

From what is see isbn is many2one to product.product so just make that field required and check if order_lines is empty or not.

@api.constrains('order_lines', 'order_lines.isbn')
def checkit(self):
#actual_stock = self.env['product.product'].browse(qty_available)
for record in self:
    # inside the loop use record not self
    if self.order_lines:continue # if the order_lines contains one record go back and check the second record
         # no need for other instruction because if the field is empty this will full
         # another thing if you return the program will exit the function but you only
         # checked one record what if someone user write with mutliple record   
    else: # here order_line is empty
        raise Warning(('Enter? ?at least? ?1? ?ISBN to produce'))

but if some how you need to keep it unrequired i think will be much faster.

@api.constrains('order_lines', 'order_lines.isbn')
  def checkit(self):
    for record in self:
        # inside the loop use record not self
        if self.order_lines:
             found_isbn = False
             for line in self.order_lines:
                if line.isbn:
                     found_isbn = True
                     break # no need to check other lines.

             if not found_isbn: # after the looping the lines check if the isbn is found
                raise Warning(('Enter at least one ISBN to produce'))

        else: # here order_line is empty
            raise Warning(('Enter? ?at least? ?1? ?ISBN to produce'))

and about the the quantity i didn't understand exactly what you need but i think this answer will help you a lot.

how to get available quantity of Lot number

and what you need to do is something like this.

if you want just to show a warning to user and don't stop him from working use onchange

@api.onchange('order_lines.qty')
def check_quantity(self):
    if self.order_lines:
        for line in rec.order_lines:
            if line.qty > line.isbn.qty_available:
                # return warning or validation error if it's restricted .
                return {'warning': {
                            'title': _('Warning'),
                            'message': _('Quantity is invalid.')
                        }

but if this operation is restricted and should not be saved in database use constrains:

@api.constrains('order_lines.qty')
def check_quantity(self):
    for rec in self:
        if rec.order_lines:
            for line in rec.order_lines:
                if line.qty > line.isbn.qty_available:
                    # raise validation error to user .
Charif DZ
  • 14,415
  • 3
  • 21
  • 40
  • Thank You very much! There is some other issue, but I'll open a new question for that, Thanks again! – NeoVe Oct 27 '17 at 03:51