Exemplo n.º 1
0
    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
        context = context or {}
        product_uom_obj = self.pool.get('product.uom')
        partner_obj = self.pool.get('res.partner')
        product_obj = self.pool.get('product.product')
        warning = {}
        res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty,
            uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
            lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)

        if not product:
            res['value'].update({'product_packaging': False})
            return res

        #update of result obtained in super function
        res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
        res['value'].update(res_packing.get('value', {}))
        warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
        product_obj = product_obj.browse(cr, uid, product, context=context)
        res['value']['delay'] = (product_obj.sale_delay or 0.0)
        res['value']['type'] = product_obj.procure_method

        #check if product is available, and if not: raise an error
        uom2 = False
        if uom:
            uom2 = product_uom_obj.browse(cr, uid, uom)
            if product_obj.uom_id.category_id.id != uom2.category_id.id:
                uom = False
        if not uom2:
            uom2 = product_obj.uom_id
        compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
        if (product_obj.type=='product') and int(compare_qty) == -1 \
          and (product_obj.procure_method=='make_to_stock'):
            warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
                    (qty, uom2 and uom2.name or product_obj.uom_id.name,
                     max(0,product_obj.virtual_available), product_obj.uom_id.name,
                     max(0,product_obj.qty_available), product_obj.uom_id.name)
            warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"

        #update of warning messages
        if warning_msgs:
            warning = {
                       'title': _('Configuration Error!'),
                       'message' : warning_msgs
                    }
        res.update({'warning': warning})
        return res
Exemplo n.º 2
0
 def action_wait(self, cr, uid, ids, context=None):
     """
     Check if price unit for each lines is lower than block price
     if True and user not in the group on company, raise an error
     """
     if context is None:
         context = self.pool.get('res.users').context_get(cr, uid)
     user = self.pool.get('res.users').browse(cr, uid, uid)
     have_group = user.company_id.unblock_group_id.id in [z.id for z in user.groups_id]
     precision_digits = self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price')
     for so in self.browse(cr, uid, ids):
         if not have_group and [x.id for x in so.order_line if float_compare(x.price_subtotal, x.block_price_subtotal, precision_digits=precision_digits) < 0]:
             raise osv.except_osv(_('Validation Error'),
                                  _('You cannot validate the sale order, some lines have a unit price lower than minimal price'))
     return super(sale_order, self).action_wait(cr, uid, ids, context)
Exemplo n.º 3
0
    def compare_amounts(self, cr, uid, currency, amount1, amount2):
        """Compare ``amount1`` and ``amount2`` after rounding them according to the
           given currency's precision..
           An amount is considered lower/greater than another amount if their rounded
           value is different. This is not the same as having a non-zero difference!

           For example 1.432 and 1.431 are equal at 2 digits precision,
           so this method would return 0.
           However 0.006 and 0.002 are considered different (returns 1) because
           they respectively round to 0.01 and 0.0, even though
           0.006-0.002 = 0.004 which would be considered zero at 2 digits precision.

           :param browse_record currency: currency for which we are rounding
           :param float amount1: first amount to compare
           :param float amount2: second amount to compare
           :return: (resp.) -1, 0 or 1, if ``amount1`` is (resp.) lower than,
                    equal to, or greater than ``amount2``, according to
                    ``currency``'s rounding.
        """
        return float_compare(amount1, amount2, precision_rounding=currency.rounding)
Exemplo n.º 4
0
    def compare_amounts(self, cr, uid, currency, amount1, amount2):
        """Compare ``amount1`` and ``amount2`` after rounding them according to the
           given currency's precision..
           An amount is considered lower/greater than another amount if their rounded
           value is different. This is not the same as having a non-zero difference!

           For example 1.432 and 1.431 are equal at 2 digits precision,
           so this method would return 0.
           However 0.006 and 0.002 are considered different (returns 1) because
           they respectively round to 0.01 and 0.0, even though
           0.006-0.002 = 0.004 which would be considered zero at 2 digits precision.

           :param browse_record currency: currency for which we are rounding
           :param float amount1: first amount to compare
           :param float amount2: second amount to compare
           :return: (resp.) -1, 0 or 1, if ``amount1`` is (resp.) lower than,
                    equal to, or greater than ``amount2``, according to
                    ``currency``'s rounding.
        """
        return float_compare(amount1, amount2, precision_rounding=currency.rounding)
Exemplo n.º 5
0
 def check_container_availability(self, cr, uid, ids, context=None):
     """
     Check if there is enough products available in selected containers
     """
     if context is None:
         context = {}
     container_obj = self.pool.get('stock.container')
     product_uom_obj = self.pool.get('product.uom')
     for line in self.browse(cr, uid, ids, context=context):
         if not line.container_id or not line.product_id:
             continue
         # Retrieve quantity available in container
         ctx = dict(context, product_id=line.product_id.id)
         container = container_obj.browse(cr, uid, line.container_id.id, context=ctx)
         qty = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uom_qty, line.product_id.uom_id.id)
         # Stock virtual is negative
         compare_qty = float_compare(container.stock_real + container.stock_virtual, qty, precision_rounding=line.product_id.uom_id.rounding)
         if container.stock_virtual > 0 and compare_qty == -1:
             raise osv.except_osv(_('Not enough quantity'),
                                  _('%s\nNot enough quantity in container %s') % (line.product_id.name, line.container_id.name))
     return True
Exemplo n.º 6
0
    def product_id_change(self,
                          cr,
                          uid,
                          ids,
                          pricelist,
                          product,
                          qty=0,
                          uom=False,
                          qty_uos=0,
                          uos=False,
                          name='',
                          partner_id=False,
                          lang=False,
                          update_tax=True,
                          date_order=False,
                          packaging=False,
                          fiscal_position=False,
                          flag=False,
                          context=None):
        context = context or {}
        lang = lang or context.get('lang', False)
        if not partner_id:
            raise osv.except_osv(
                _('No Customer Defined !'),
                _('You have to select a customer in the sales form !\nPlease set one customer before choosing a product.'
                  ))
        warning = {}
        product_uom_obj = self.pool.get('product.uom')
        partner_obj = self.pool.get('res.partner')
        product_obj = self.pool.get('product.product')
        context = {'lang': lang, 'partner_id': partner_id}
        if partner_id:
            lang = partner_obj.browse(cr, uid, partner_id).lang
        context_partner = {'lang': lang, 'partner_id': partner_id}

        if not product:
            return {
                'value': {
                    'th_weight': 0,
                    'product_packaging': False,
                    'product_uos_qty': qty
                },
                'domain': {
                    'product_uom': [],
                    'product_uos': []
                }
            }
        if not date_order:
            date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)

        res = self.product_packaging_change(cr,
                                            uid,
                                            ids,
                                            pricelist,
                                            product,
                                            qty,
                                            uom,
                                            partner_id,
                                            packaging,
                                            context=context)
        result = res.get('value', {})
        warning_msgs = res.get('warning') and res['warning']['message'] or ''
        product_obj = product_obj.browse(cr, uid, product, context=context)

        uom2 = False
        if uom:
            uom2 = product_uom_obj.browse(cr, uid, uom)
            if product_obj.uom_id.category_id.id != uom2.category_id.id:
                uom = False
        if uos:
            if product_obj.uos_id:
                uos2 = product_uom_obj.browse(cr, uid, uos)
                if product_obj.uos_id.category_id.id != uos2.category_id.id:
                    uos = False
            else:
                uos = False
        if product_obj.description_sale:
            result['notes'] = product_obj.description_sale
        fpos = fiscal_position and self.pool.get(
            'account.fiscal.position').browse(cr, uid,
                                              fiscal_position) or False
        if update_tax:  #The quantity only have changed
            result['delay'] = (product_obj.sale_delay or 0.0)
            result['tax_id'] = self.pool.get(
                'account.fiscal.position').map_tax(cr, uid, fpos,
                                                   product_obj.taxes_id)
            result.update({'type': product_obj.procure_method})

        if not flag:
            result['name'] = self.pool.get('product.product').name_get(
                cr, uid, [product_obj.id], context=context_partner)[0][1]
        domain = {}
        if (not uom) and (not uos):
            result['product_uom'] = product_obj.uom_id.id
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
                uos_category_id = product_obj.uos_id.category_id.id
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
                uos_category_id = False
            result['th_weight'] = qty * product_obj.weight
            domain = {
                'product_uom':
                [('category_id', '=', product_obj.uom_id.category_id.id)],
                'product_uos': [('category_id', '=', uos_category_id)]
            }

        elif uos and not uom:  # only happens if uom is False
            result[
                'product_uom'] = product_obj.uom_id and product_obj.uom_id.id
            result['product_uom_qty'] = qty_uos / product_obj.uos_coeff
            result[
                'th_weight'] = result['product_uom_qty'] * product_obj.weight
        elif uom:  # whether uos is set or not
            default_uom = product_obj.uom_id and product_obj.uom_id.id
            q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom)
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
            result[
                'th_weight'] = q * product_obj.weight  # Round the quantity up

        if not uom2:
            uom2 = product_obj.uom_id

        compare_qty = float_compare(
            product_obj.virtual_available * uom2.factor,
            qty * product_obj.uom_id.factor,
            precision_rounding=product_obj.uom_id.rounding)
        if (product_obj.type=='product') and int(compare_qty) == -1 \
          and (product_obj.procure_method=='make_to_stock'):
            warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
                    (qty, uom2 and uom2.name or product_obj.uom_id.name,
                     max(0,product_obj.virtual_available), product_obj.uom_id.name,
                     max(0,product_obj.qty_available), product_obj.uom_id.name)
            warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"

        # get the insulation flag and the r-value
        if product_obj.insulation:
            result['product_insulation'] = product_obj.insulation
            result['product_rvalue'] = product_obj.rvalue
            result['product_sprayfoam'] = product_obj.sprayfoam
            result['product_uos'] = product_obj.uos_id.id
            if not product_obj.sprayfoam:
                result['rvalue'] = product_obj.rvalue

        # get unit price

        if not pricelist:
            warn_msg = _(
                'You have to select a pricelist or a customer in the sales form !\n'
                'Please set one before choosing a product.')
            warning_msgs += _("No Pricelist ! : ") + warn_msg + "\n\n"
        else:
            price = self.pool.get('product.pricelist').price_get(
                cr, uid, [pricelist], product, qty or 1.0, partner_id, {
                    'uom': uom or result.get('product_uom'),
                    'date': date_order,
                })[pricelist]
            if price is False:
                warn_msg = _(
                    "Couldn't find a pricelist line matching this product and quantity.\n"
                    "You have to change either the product, the quantity or the pricelist."
                )

                warning_msgs += _(
                    "No valid pricelist line found ! :") + warn_msg + "\n\n"
            else:
                result.update({'price_unit': price})
        if warning_msgs:
            warning = {
                'title': _('Configuration Error !'),
                'message': warning_msgs
            }
        return {'value': result, 'domain': domain, 'warning': warning}
Exemplo n.º 7
0
Arquivo: mrp.py Projeto: iw3hxn/addons
    def action_produce(self, cr, uid, production_id, production_qty, production_mode, context=None):
        # Taken from original mrp addon
        """ To produce final product based on production mode (consume/consume&produce).
        If Production mode is consume, all stock move lines of raw materials will be done/consumed.
        If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
        and stock move lines of final product will be also done/produced.
        @param production_id: the ID of mrp.production object
        @param production_qty: specify qty to produce
        @param production_mode: specify production mode (consume/consume&produce).
        @return: True
        """
        stock_mov_obj = self.pool.get('stock.move')
        production = self.browse(cr, uid, production_id, context=context)

        produced_qty = 0
        for produced_product in production.move_created_ids2:
            if (produced_product.scrapped) or (produced_product.product_id.id <> production.product_id.id):
                continue
            produced_qty += produced_product.product_qty

        if production_mode in ['consume', 'consume_produce']:
            consumed_data = {}

            # Calculate already consumed qtys
            for consumed in production.move_lines2:
                if consumed.scrapped:
                    continue
                if not consumed_data.get(consumed.product_id.id, False):
                    consumed_data[consumed.product_id.id] = 0
                consumed_data[consumed.product_id.id] += consumed.product_qty

            # Find product qty to be consumed and consume it
            for scheduled in production.product_lines:

                # total qty of consumed product we need after this consumption
                total_consume = ((production_qty + produced_qty) * scheduled.product_qty / production.product_qty)

                # qty available for consume and produce
                qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)

                if qty_avail <= 0.0:
                    # there will be nothing to consume for this raw material
                    continue

                raw_product = [move for move in production.move_lines if move.product_id.id == scheduled.product_id.id]
                if raw_product:
                    # qtys we have to consume
                    qty = total_consume - consumed_data.get(scheduled.product_id.id, 0.0)
                    if float_compare(qty, qty_avail, precision_rounding=scheduled.product_id.uom_id.rounding) == 1:
                        # if qtys we have to consume is more than qtys available to consume
                        # => must consume the difference, move from warehouse
                        _logger.info(
                            'action_produce: Manufacturing Order {prod.name}, Consuming {requested}, more than initial {prod.product_qty}'
                            .format(prod=production, requested=production_qty))

                    if qty <= 0.0:
                        # we already have more qtys consumed than we need
                        continue

                    consumed = 0
                    rounding = raw_product[0].product_uom.rounding

                    # sort the list by quantity, to consume smaller quantities first and avoid splitting if possible
                    raw_product.sort(key=attrgetter('product_qty'))

                    # search for exact quantity
                    for consume_line in raw_product:
                        if tools.float_compare(consume_line.product_qty, qty, precision_rounding=rounding) == 0:
                            # consume this line
                            consume_line.action_consume(qty, consume_line.location_id.id, context=context)
                            consumed = qty
                            break

                    index = 0
                    # consume the smallest quantity while we have not consumed enough
                    while tools.float_compare(consumed, qty, precision_rounding=rounding) == -1 and index < len(raw_product):
                        consume_line = raw_product[index]
                        to_consume = min(consume_line.product_qty, qty - consumed) 
                        consume_line.action_consume(to_consume, consume_line.location_id.id, context=context)
                        consumed += to_consume
                        index += 1

        if production_mode == 'consume_produce':
            # To produce remaining qty of final product
            #vals = {'state':'confirmed'}
            #final_product_todo = [x.id for x in production.move_created_ids]
            #stock_mov_obj.write(cr, uid, final_product_todo, vals)
            #stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
            produced_products = {}
            produced_products_qty = 0
            if production.move_created_ids2:
                produced_products_qty = production.move_created_ids2[0].product_qty

            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id, False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.id] += produced_product.product_qty

            for produce_product in production.move_created_ids:
                produced_qty = produced_products.get(produce_product.product_id.id, 0)
                subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
                rest_qty = (subproduct_factor * production.product_qty) - produced_qty

                if rest_qty < production_qty:
                    _logger.info(
                        'action_produce: Manufacturing Order {prod.name}, Producing {requested}, more than initial {prod.product_qty}'
                        .format(prod=production, requested=production_qty))
                    # Add and Reload
                    production = self.add_prod_qty(cr, uid, production.id, production_qty, produced_products_qty, context)

                if rest_qty > 0:
                    stock_mov_obj.action_consume(cr, uid, [produce_product.id], (subproduct_factor * production_qty), context=context)

        for raw_product in production.move_lines2:
            new_parent_ids = []
            parent_move_ids = [x.id for x in raw_product.move_history_ids]
            for final_product in production.move_created_ids2:
                if final_product.id not in parent_move_ids:
                    new_parent_ids.append(final_product.id)
            for new_parent_id in new_parent_ids:
                stock_mov_obj.write(cr, uid, [raw_product.id], {'move_history_ids': [(4, new_parent_id)]})

        wf_service = netsvc.LocalService("workflow")
        wf_service.trg_validate(uid, 'mrp.production', production_id, 'button_produce_done', cr)
        return True
Exemplo n.º 8
0
    def product_id_change(self,
                          cr,
                          uid,
                          ids,
                          pricelist,
                          product,
                          qty=0,
                          uom=False,
                          qty_uos=0,
                          uos=False,
                          name='',
                          partner_id=False,
                          lang=False,
                          update_tax=True,
                          date_order=False,
                          packaging=False,
                          fiscal_position=False,
                          flag=False,
                          context=None):
        context = context or {}
        lang = lang or context.get('lang',False)
        if not  partner_id:
            raise osv.except_osv(_('No Customer Defined !'), _('You have to select a customer in the sales form !\nPlease set one customer before choosing a product.'))
        warning = {}
        product_uom_obj = self.pool.get('product.uom')
        partner_obj = self.pool.get('res.partner')
        product_obj = self.pool.get('product.product')
        context = {'lang': lang, 'partner_id': partner_id}
        if partner_id:
            lang = partner_obj.browse(cr, uid, partner_id).lang
        context_partner = {'lang': lang, 'partner_id': partner_id}

        if not product:
            return {'value': {'th_weight': 0, 'product_packaging': False,
                'product_uos_qty': qty}, 'domain': {'product_uom': [],
                   'product_uos': []}}
        if not date_order:
            date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)

        res = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
        result = res.get('value', {})
        warning_msgs = res.get('warning') and res['warning']['message'] or ''
        product_obj = product_obj.browse(cr, uid, product, context=context)

        uom2 = False
        if uom:
            uom2 = product_uom_obj.browse(cr, uid, uom)
            if product_obj.uom_id.category_id.id != uom2.category_id.id:
                uom = False
        if uos:
            if product_obj.uos_id:
                uos2 = product_uom_obj.browse(cr, uid, uos)
                if product_obj.uos_id.category_id.id != uos2.category_id.id:
                    uos = False
            else:
                uos = False
        fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
        if update_tax: #The quantity only have changed
            result['delay'] = (product_obj.sale_delay or 0.0)
            result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)
            result.update({'type': product_obj.procure_method})

        if not flag:
            result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context_partner)[0][1]
        domain = {}
        if (not uom) and (not uos):
            result['product_uom'] = product_obj.uom_id.id
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
                uos_category_id = product_obj.uos_id.category_id.id
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
                uos_category_id = False
            result['th_weight'] = qty * product_obj.weight
            domain = {'product_uom':
                        [('category_id', '=', product_obj.uom_id.category_id.id)],
                        'product_uos':
                        [('category_id', '=', uos_category_id)]}

        elif uos and not uom: # only happens if uom is False
            result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id
            result['product_uom_qty'] = qty_uos / product_obj.uos_coeff
            result['th_weight'] = result['product_uom_qty'] * product_obj.weight
        elif uom: # whether uos is set or not
            default_uom = product_obj.uom_id and product_obj.uom_id.id
            q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom)
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
            result['th_weight'] = q * product_obj.weight        # Round the quantity up

        if not uom2:
            uom2 = product_obj.uom_id

        compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
        if (product_obj.type=='product') and int(compare_qty) == -1 \
          and (product_obj.procure_method=='make_to_stock'):
            warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
                    (qty, uom2 and uom2.name or product_obj.uom_id.name,
                     max(0,product_obj.virtual_available), product_obj.uom_id.name,
                     max(0,product_obj.qty_available), product_obj.uom_id.name)
            warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"

        # get the insulation flag and the r-value
        if product_obj.insulation:
            result['product_insulation'] = product_obj.insulation
            result['product_rvalue'] = product_obj.rvalue
            result['product_sprayfoam'] = product_obj.sprayfoam
            result['product_uos'] = product_obj.uos_id.id
            if not product_obj.sprayfoam:
                result['rvalue'] = product_obj.rvalue
            
        # get unit price

        if not pricelist:
            warn_msg = _('You have to select a pricelist or a customer in the sales form !\n'
                    'Please set one before choosing a product.')
            warning_msgs += _("No Pricelist ! : ") + warn_msg +"\n\n"
        else:
            price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist],
                    product, qty or 1.0, partner_id, {
                        'uom': uom or result.get('product_uom'),
                        'date': date_order,
                        })[pricelist]
            if price is False:
                warn_msg = _("Couldn't find a pricelist line matching this product and quantity.\n"
                        "You have to change either the product, the quantity or the pricelist.")

                warning_msgs += _("No valid pricelist line found ! :") + warn_msg +"\n\n"
            else:
                result.update({'price_unit': price})
        if warning_msgs:
            warning = {
                       'title': _('Configuration Error !'),
                       'message' : warning_msgs
                    }
        return {'value': result, 'domain': domain, 'warning': warning}
Exemplo n.º 9
0
    def action_produce(self, cr, uid, production_id, production_qty, production_mode, context=None):
        """ To produce final product based on production mode (consume/consume&produce).
        If Production mode is consume, all stock move lines of raw materials will be done/consumed.
        If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
        and stock move lines of final product will be also done/produced.
        @param production_id: the ID of mrp.production object
        @param production_qty: specify qty to produce
        @param production_mode: specify production mode (consume/consume&produce).
        @return: True
        """
        stock_mov_obj = self.pool.get('stock.move')
        production = self.browse(cr, uid, production_id, context=context)

        produced_qty = 0
        for produced_product in production.move_created_ids2:
            if (produced_product.scrapped) or (produced_product.product_id.id <> production.product_id.id):
                continue
            produced_qty += produced_product.product_qty

        if production_mode in ['consume','consume_produce']:
            consumed_data = {}

            # Calculate already consumed qtys
            for consumed in production.move_lines2:
                if consumed.scrapped:
                    continue
                if not consumed_data.get(consumed.product_id.id, False):
                    consumed_data[consumed.product_id.id] = 0
                consumed_data[consumed.product_id.id] += consumed.product_qty

            # Find product qty to be consumed and consume it
            for scheduled in production.product_lines:

                # total qty of consumed product we need after this consumption
                total_consume = ((production_qty + produced_qty) * scheduled.product_qty / production.product_qty)

                # qty available for consume and produce
                qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)

                if qty_avail <= 0.0:
                    # there will be nothing to consume for this raw material
                    continue

                raw_product = [move for move in production.move_lines if move.product_id.id==scheduled.product_id.id]
                if raw_product:
                    # qtys we have to consume
                    qty = total_consume - consumed_data.get(scheduled.product_id.id, 0.0)
                    if float_compare(qty, qty_avail, precision_rounding=scheduled.product_id.uom_id.rounding) == 1:
                        # if qtys we have to consume is more than qtys available to consume
                        prod_name = scheduled.product_id.name_get()[0][1]
                        raise osv.except_osv(_('Warning!'), _('You are going to consume total %s quantities of "%s".\nBut you can only consume up to total %s quantities.') % (qty, prod_name, qty_avail))
                    if qty <= 0.0:
                        # we already have more qtys consumed than we need 
                        continue

                    consumed = 0
                    rounding = raw_product[0].product_uom.rounding

                    # sort the list by quantity, to consume smaller quantities first and avoid splitting if possible
                    raw_product.sort(key=attrgetter('product_qty'))

                    # search for exact quantity
                    for consume_line in raw_product:
                        if tools.float_compare(consume_line.product_qty, qty, precision_rounding=rounding) == 0:
                            # consume this line
                            consume_line.action_consume(qty, consume_line.location_id.id, context=context)
                            consumed = qty
                            break

                    index = 0                        
                    # consume the smallest quantity while we have not consumed enough
                    while tools.float_compare(consumed, qty, precision_rounding=rounding) == -1 and index < len(raw_product):
                        consume_line = raw_product[index]
                        to_consume = min(consume_line.product_qty, qty - consumed) 
                        consume_line.action_consume(to_consume, consume_line.location_id.id, context=context)
                        consumed += to_consume
                        index += 1

        if production_mode == 'consume_produce':
            # To produce remaining qty of final product
            #vals = {'state':'confirmed'}
            #final_product_todo = [x.id for x in production.move_created_ids]
            #stock_mov_obj.write(cr, uid, final_product_todo, vals)
            #stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
            produced_products = {}
            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id, False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.id] += produced_product.product_qty

            for produce_product in production.move_created_ids:
                produced_qty = produced_products.get(produce_product.product_id.id, 0)
                subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
                rest_qty = (subproduct_factor * production.product_qty) - produced_qty

                if rest_qty < production_qty:
                    self.write(cr,uid,[production_id],{'product_qty': production_qty})  
                    move_ids = stock_mov_obj.search(cr, uid,[('production_id','=', production.id)],limit=1,context=context)
                    if move_ids:
                        stock_mov_obj.write(cr,uid,move_ids,{'product_qty': production_qty}) 
                        move_ids = stock_mov_obj.search(cr, uid,[('move_dest_id','=', move_ids[0])],context=context)
                        if move_ids:
                            for move in stock_mov_obj.browse(cr,uid,move_ids,context=context):
                                new_qty = (production_qty * move.product_qty) / rest_qty
                                stock_mov_obj.write(cr,uid,[move.id],{'product_qty': new_qty}) 
                                move2_ids = stock_mov_obj.search(cr, uid,[('move_dest_id','=', move.id)],limit=1,context=context)
                                if move2_ids:
                                    move2 = stock_mov_obj.browse(cr,uid,move2_ids[0],context=context)
                                    new_qty = (production_qty * move2.product_qty) / rest_qty
                                    stock_mov_obj.write(cr,uid,[move2.id],{'product_qty': new_qty}) 

        
        return super(mrp_production, self).action_produce(cr, uid, production_id, production_qty, production_mode, context=context)
Exemplo n.º 10
0
    def action_produce(self,
                       cr,
                       uid,
                       production_id,
                       production_qty,
                       production_mode,
                       context=None):
        """ To produce final product based on production mode (consume/consume&produce).
        If Production mode is consume, all stock move lines of raw materials will be done/consumed.
        If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
        and stock move lines of final product will be also done/produced.
        @param production_id: the ID of mrp.production object
        @param production_qty: specify qty to produce
        @param production_mode: specify production mode (consume/consume&produce).
        @return: True
        """
        stock_mov_obj = self.pool.get('stock.move')
        production = self.browse(cr, uid, production_id, context=context)

        produced_qty = 0
        for produced_product in production.move_created_ids2:
            if (produced_product.scrapped) or (produced_product.product_id.id
                                               <> production.product_id.id):
                continue
            produced_qty += produced_product.product_qty

        if production_mode in ['consume', 'consume_produce']:
            consumed_data = {}

            # Calculate already consumed qtys
            for consumed in production.move_lines2:
                if consumed.scrapped:
                    continue
                if not consumed_data.get(consumed.product_id.id, False):
                    consumed_data[consumed.product_id.id] = 0
                consumed_data[consumed.product_id.id] += consumed.product_qty

            # Find product qty to be consumed and consume it
            for scheduled in production.product_lines:

                # total qty of consumed product we need after this consumption
                total_consume = ((production_qty + produced_qty) *
                                 scheduled.product_qty /
                                 production.product_qty)

                # qty available for consume and produce
                qty_avail = scheduled.product_qty - consumed_data.get(
                    scheduled.product_id.id, 0.0)

                if qty_avail <= 0.0:
                    # there will be nothing to consume for this raw material
                    continue

                raw_product = [
                    move for move in production.move_lines
                    if move.product_id.id == scheduled.product_id.id
                ]
                if raw_product:
                    # qtys we have to consume
                    qty = total_consume - consumed_data.get(
                        scheduled.product_id.id, 0.0)
                    if float_compare(qty,
                                     qty_avail,
                                     precision_rounding=scheduled.product_id.
                                     uom_id.rounding) == 1:
                        # if qtys we have to consume is more than qtys available to consume
                        prod_name = scheduled.product_id.name_get()[0][1]
                        raise osv.except_osv(
                            _('Warning!'),
                            _('You are going to consume total %s quantities of "%s".\nBut you can only consume up to total %s quantities.'
                              ) % (qty, prod_name, qty_avail))
                    if qty <= 0.0:
                        # we already have more qtys consumed than we need
                        continue

                    consumed = 0
                    rounding = raw_product[0].product_uom.rounding

                    # sort the list by quantity, to consume smaller quantities first and avoid splitting if possible
                    raw_product.sort(key=attrgetter('product_qty'))

                    # search for exact quantity
                    for consume_line in raw_product:
                        if tools.float_compare(
                                consume_line.product_qty,
                                qty,
                                precision_rounding=rounding) == 0:
                            # consume this line
                            consume_line.action_consume(
                                qty,
                                consume_line.location_id.id,
                                context=context)
                            consumed = qty
                            break

                    index = 0
                    # consume the smallest quantity while we have not consumed enough
                    while tools.float_compare(
                            consumed, qty, precision_rounding=rounding
                    ) == -1 and index < len(raw_product):
                        consume_line = raw_product[index]
                        to_consume = min(consume_line.product_qty,
                                         qty - consumed)
                        consume_line.action_consume(
                            to_consume,
                            consume_line.location_id.id,
                            context=context)
                        consumed += to_consume
                        index += 1

        if production_mode == 'consume_produce':
            # To produce remaining qty of final product
            #vals = {'state':'confirmed'}
            #final_product_todo = [x.id for x in production.move_created_ids]
            #stock_mov_obj.write(cr, uid, final_product_todo, vals)
            #stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
            produced_products = {}
            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id,
                                             False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.
                                  id] += produced_product.product_qty

            for produce_product in production.move_created_ids:
                produced_qty = produced_products.get(
                    produce_product.product_id.id, 0)
                subproduct_factor = self._get_subproduct_factor(
                    cr,
                    uid,
                    production.id,
                    produce_product.id,
                    context=context)
                rest_qty = (subproduct_factor *
                            production.product_qty) - produced_qty

                if rest_qty < production_qty:
                    self.write(cr, uid, [production_id],
                               {'product_qty': production_qty})
                    move_ids = stock_mov_obj.search(
                        cr,
                        uid, [('production_id', '=', production.id)],
                        limit=1,
                        context=context)
                    if move_ids:
                        stock_mov_obj.write(cr, uid, move_ids,
                                            {'product_qty': production_qty})
                        move_ids = stock_mov_obj.search(
                            cr,
                            uid, [('move_dest_id', '=', move_ids[0])],
                            context=context)
                        if move_ids:
                            for move in stock_mov_obj.browse(cr,
                                                             uid,
                                                             move_ids,
                                                             context=context):
                                new_qty = (production_qty *
                                           move.product_qty) / rest_qty
                                stock_mov_obj.write(cr, uid, [move.id],
                                                    {'product_qty': new_qty})
                                move2_ids = stock_mov_obj.search(
                                    cr,
                                    uid, [('move_dest_id', '=', move.id)],
                                    limit=1,
                                    context=context)
                                if move2_ids:
                                    move2 = stock_mov_obj.browse(
                                        cr, uid, move2_ids[0], context=context)
                                    new_qty = (production_qty *
                                               move2.product_qty) / rest_qty
                                    stock_mov_obj.write(
                                        cr, uid, [move2.id],
                                        {'product_qty': new_qty})

        return super(mrp_production, self).action_produce(cr,
                                                          uid,
                                                          production_id,
                                                          production_qty,
                                                          production_mode,
                                                          context=context)
Exemplo n.º 11
0
    def action_produce(self,
                       cr,
                       uid,
                       production_id,
                       production_qty,
                       production_mode,
                       context=None):
        # Taken from original mrp addon
        """ To produce final product based on production mode (consume/consume&produce).
        If Production mode is consume, all stock move lines of raw materials will be done/consumed.
        If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
        and stock move lines of final product will be also done/produced.
        @param production_id: the ID of mrp.production object
        @param production_qty: specify qty to produce
        @param production_mode: specify production mode (consume/consume&produce).
        @return: True
        """
        stock_mov_obj = self.pool.get('stock.move')
        production = self.browse(cr, uid, production_id, context=context)

        produced_qty = 0
        for produced_product in production.move_created_ids2:
            if (produced_product.scrapped) or (produced_product.product_id.id
                                               <> production.product_id.id):
                continue
            produced_qty += produced_product.product_qty

        if production_mode in ['consume', 'consume_produce']:
            consumed_data = {}

            # Calculate already consumed qtys
            for consumed in production.move_lines2:
                if consumed.scrapped:
                    continue
                if not consumed_data.get(consumed.product_id.id, False):
                    consumed_data[consumed.product_id.id] = 0
                consumed_data[consumed.product_id.id] += consumed.product_qty

            # Find product qty to be consumed and consume it
            for scheduled in production.product_lines:

                # total qty of consumed product we need after this consumption
                total_consume = ((production_qty + produced_qty) *
                                 scheduled.product_qty /
                                 production.product_qty)

                # qty available for consume and produce
                qty_avail = scheduled.product_qty - consumed_data.get(
                    scheduled.product_id.id, 0.0)

                if qty_avail <= 0.0:
                    # there will be nothing to consume for this raw material
                    continue

                raw_product = [
                    move for move in production.move_lines
                    if move.product_id.id == scheduled.product_id.id
                ]
                if raw_product:
                    # qtys we have to consume
                    qty = total_consume - consumed_data.get(
                        scheduled.product_id.id, 0.0)
                    if float_compare(qty,
                                     qty_avail,
                                     precision_rounding=scheduled.product_id.
                                     uom_id.rounding) == 1:
                        # if qtys we have to consume is more than qtys available to consume
                        # => must consume the difference, move from warehouse
                        _logger.info(
                            'action_produce: Manufacturing Order {prod.name}, Consuming {requested}, more than initial {prod.product_qty}'
                            .format(prod=production, requested=production_qty))

                    if qty <= 0.0:
                        # we already have more qtys consumed than we need
                        continue

                    consumed = 0
                    rounding = raw_product[0].product_uom.rounding

                    # sort the list by quantity, to consume smaller quantities first and avoid splitting if possible
                    raw_product.sort(key=attrgetter('product_qty'))

                    # search for exact quantity
                    for consume_line in raw_product:
                        if tools.float_compare(
                                consume_line.product_qty,
                                qty,
                                precision_rounding=rounding) == 0:
                            # consume this line
                            consume_line.action_consume(
                                qty,
                                consume_line.location_id.id,
                                context=context)
                            consumed = qty
                            break

                    index = 0
                    # consume the smallest quantity while we have not consumed enough
                    while tools.float_compare(
                            consumed, qty, precision_rounding=rounding
                    ) == -1 and index < len(raw_product):
                        consume_line = raw_product[index]
                        to_consume = min(consume_line.product_qty,
                                         qty - consumed)
                        consume_line.action_consume(
                            to_consume,
                            consume_line.location_id.id,
                            context=context)
                        consumed += to_consume
                        index += 1

        if production_mode == 'consume_produce':
            # To produce remaining qty of final product
            #vals = {'state':'confirmed'}
            #final_product_todo = [x.id for x in production.move_created_ids]
            #stock_mov_obj.write(cr, uid, final_product_todo, vals)
            #stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
            produced_products = {}
            produced_products_qty = 0
            if production.move_created_ids2:
                produced_products_qty = production.move_created_ids2[
                    0].product_qty

            for produced_product in production.move_created_ids2:
                if produced_product.scrapped:
                    continue
                if not produced_products.get(produced_product.product_id.id,
                                             False):
                    produced_products[produced_product.product_id.id] = 0
                produced_products[produced_product.product_id.
                                  id] += produced_product.product_qty

            for produce_product in production.move_created_ids:
                produced_qty = produced_products.get(
                    produce_product.product_id.id, 0)
                subproduct_factor = self._get_subproduct_factor(
                    cr,
                    uid,
                    production.id,
                    produce_product.id,
                    context=context)
                rest_qty = (subproduct_factor *
                            production.product_qty) - produced_qty

                if rest_qty < production_qty:
                    _logger.info(
                        'action_produce: Manufacturing Order {prod.name}, Producing {requested}, more than initial {prod.product_qty}'
                        .format(prod=production, requested=production_qty))
                    # Add and Reload
                    production = self.add_prod_qty(cr, uid, production.id,
                                                   production_qty,
                                                   produced_products_qty,
                                                   context)

                if rest_qty > 0:
                    stock_mov_obj.action_consume(
                        cr,
                        uid, [produce_product.id],
                        (subproduct_factor * production_qty),
                        context=context)

        for raw_product in production.move_lines2:
            new_parent_ids = []
            parent_move_ids = [x.id for x in raw_product.move_history_ids]
            for final_product in production.move_created_ids2:
                if final_product.id not in parent_move_ids:
                    new_parent_ids.append(final_product.id)
            for new_parent_id in new_parent_ids:
                stock_mov_obj.write(cr, uid, [raw_product.id],
                                    {'move_history_ids': [(4, new_parent_id)]})

        wf_service = netsvc.LocalService("workflow")
        wf_service.trg_validate(uid, 'mrp.production', production_id,
                                'button_produce_done', cr)
        return True