Exemple #1
0
    def compute_line_amount(self, cr, uid, id, total_amount, remaining_amount, context=None):
        """
        Compute the amount for a payment term line.
        In case of procent computation, use the payment
        term line rounding if defined

            :param total_amount: total balance to pay
            :param remaining_amount: total amount minus sum of previous lines
                computed amount
            :returns: computed amount for this line
        """
        if isinstance(id, (tuple, list)):
            assert len(id) == 1, "compute_line_amount accepts only 1 ID"
            id = id[0]
        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')
        line = self.browse(cr, uid, id, context=context)
        if line.value == 'fixed':
            return float_round(line.value_amount, precision_digits=prec)
        elif line.value == 'procent':
            amt = total_amount * line.value_amount
            if line.amount_round:
                amt = float_round(amt, precision_rounding=line.amount_round)
            return float_round(amt, precision_digits=prec)
        elif line.value == 'balance':
            amt = float_round(remaining_amount,  precision_digits=prec)
        return None
Exemple #2
0
    def _compute_usage_quarter(self):
        self.qty_usage_quarter = 0.0
        self.qty_available_quarter = 0.0
        self.qty_forcast_quarter = 0.0
        product_obj = self.env['product.product']
        domain_quant = []
        domain_move_out = []
        last_quarter = timedelta(days=-90)
        date_from = datetime.now() + last_quarter
        from_date = '%s-%s-%s' % (date_from.year, date_from.month,date_from.day)
        to_date = fields.Date.context_today(self)
        domain_products = [('product_id', '=', self.id)]
        domain_move_out += [('date','>=',from_date),('date','<=',to_date)] + \
                           [('state', '=','done')] + domain_products
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = product_obj._get_domain_locations()
        #All Activity in Warehouse
        #domain_move_out_loc = domain_quant_loc
        domain_move_out_loc = [('location_dest_id.usage','=','customer')] #Only Sending Customer
        domain_quant += domain_products
        domain_quant += domain_quant_loc

        domain_move_out += domain_move_out_loc
        moves_out = self.env['stock.move'].read_group(domain_move_out, ['product_id', 'product_qty'], ['product_id'])
        if moves_out:
            moves_count_count = moves_out
            moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_out))
            #self.qty_usage_quarter = float_round(moves_out.get(self.id, 0.0), precision_rounding=self.uom_id.rounding)

            moves_out_count = dict(map(lambda x: (x['product_id'][0], x['product_id_count']), moves_count_count))
            total = float_round(moves_out.get(self.id, 0.0), precision_rounding=self.uom_id.rounding)
            avg = float_round(total / moves_out_count.get(self.id, 1.0), precision_rounding=self.uom_id.rounding)
            self.qty_usage_quarter = avg
            self.qty_available_quarter = self.qty_available / avg
            self.qty_forcast_quarter = (self.qty_available + self.incoming_qty) / avg
Exemple #3
0
    def _count_incoming_contained_qty(self):
        ctx = dict(self._context or {})
        domain_products = [('product_id', 'in', self.ids)]
        domain_quant, domain_move_in, domain_move_out = [], [], []
        domain_move_in_contain = []
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = self.with_context(ctx)._get_domain_locations()
        domain_move_in += self.with_context(ctx)._get_domain_dates() + [('state', 'not in', ('done', 'cancel', 'draft')), ('is_related_co', '=', False)] + domain_products
        domain_move_in_contain += self.with_context(ctx)._get_domain_dates() + [('state', 'not in', ('done', 'cancel', 'draft')), ('is_related_co', '=', True)] + domain_products

        if self._context.get('owner_id'):
            owner_domain = ('restrict_partner_id', '=', self._context['owner_id'])
            domain_move_in.append(owner_domain)
            domain_move_in_contain.append(owner_domain)

        domain_move_in += domain_move_in_loc
        domain_move_in_contain += domain_move_in_loc
        moves_in = self.env['stock.move'].read_group(domain_move_in, ['product_id', 'product_qty'], ['product_id'])
        moves_in_contain = self.env['stock.move'].read_group(domain_move_in_contain, ['product_id', 'product_qty'], ['product_id'])

        moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in))
        moves_in_contain = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in_contain))
        res = {}
        for product in self:
            id = product.id
            self.incoming_contained_qty = float_round(moves_in_contain.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            self.incoming_not_contained_qty = float_round(moves_in.get(id, 0.0), precision_rounding=product.uom_id.rounding)
Exemple #4
0
 def _quant_split(self, cr, uid, quant, qty, context=None):
     context = context or {}
     rounding = quant.product_id.uom_id.rounding
     if float_compare(abs(quant.qty), abs(qty), precision_rounding=rounding) <= 0: # if quant <= qty in abs, take it entirely
         return False
     qty_round = float_round(qty, precision_rounding=rounding)
     new_qty_round = float_round(quant.qty - qty, precision_rounding=rounding)
     # Fetch the history_ids manually as it will not do a join with the stock moves then (=> a lot faster)
     cr.execute("""SELECT move_id FROM stock_quant_move_rel WHERE quant_id = %s""", (quant.id,))
     res = cr.fetchall()
     new_quant = self.copy(cr, SUPERUSER_ID, quant.id, default={'qty': new_qty_round, 'history_ids': [(4, x[0]) for x in res]}, context=context)
     self.write(cr, SUPERUSER_ID, quant.id, {'qty': qty_round}, context=context)
     return self.browse(cr, uid, new_quant, context=context)
 def check_qty(self):
     for record in self:
         if record.line_ids:
             move = self.env['stock.move'].browse(
                 self.env.context['active_id'])
             if float_round(record.lines_qty,
                     precision_rounding=move.product_uom.rounding,
                     rounding_method='UP') != float_round(
                     move.product_uom_qty,
                     precision_rounding=move.product_uom.rounding,
                     rounding_method='UP'):
                 raise exceptions.Warning(
                     _('Quantity is different than the needed one'))
 def trans_rec_get(self):
     context = self._context or {}
     credit = debit = 0
     lines = self.env['account.move.line'].browse(context.get('active_ids', []))
     for line in lines:
         if not line.reconciled:
             credit += line.credit
             debit += line.debit
     precision = self.company_id.currency_id.decimal_places
     writeoff = float_round(debit - credit, precision_digits=precision)
     credit = float_round(credit, precision_digits=precision)
     debit = float_round(debit, precision_digits=precision)
     return {'trans_nbr': len(lines), 'credit': credit, 'debit': debit, 'writeoff': writeoff}
Exemple #7
0
    def _compute_swedish_rounding(self, cr, uid, invoice, amounts,
                                  context=None):
        """
        Depending on the method defined, we add an invoice line or adapt the
        tax lines to have a rounded total amount on the invoice

        :param invoice: invoice browse record
        :param amounts: unrounded computed totals for the invoice
        :return dict: updated values for _amount_all

        """
        obj_precision = self.pool.get('decimal.precision')

        # avoid recusivity
        if 'swedish_write' in context:
            return {}

        company = invoice.company_id
        round_method = company.tax_calculation_rounding_method

        if round_method[:7] != 'swedish':
            return {}

        prec = obj_precision.precision_get(cr, uid, 'Account')
        rounding_prec = company.tax_calculation_rounding
        rounded_total = float_round(amounts['amount_total'],
                                    precision_rounding=rounding_prec)

        if float_compare(rounded_total, amounts['amount_total'],
                         precision_digits=prec) == 0:
            return {}

        # To avoid recursivity as we need to write on invoice or
        # on objects triggering computation of _amount_all
        ctx = context.copy()
        ctx['swedish_write'] = True

        delta = float_round(amounts['amount_total'] - rounded_total,
                            precision_digits=prec)

        if round_method == 'swedish_add_invoice_line':
            return self._swedish_add_invoice_line(cr, uid, invoice, amounts,
                                                  rounded_total, delta,
                                                  context=ctx)
        elif round_method == 'swedish_round_globally':
            return self._swedish_round_globally(cr, uid, invoice, amounts,
                                                rounded_total, delta,
                                                context=ctx)
        return {}
Exemple #8
0
    def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None):
        context = context or {}
        field_names = field_names or []

        domain_products = [('product_id', 'in', ids)]
        domain_quant, domain_move_in, domain_move_out = [], [], []
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = self._get_domain_locations(cr, uid, ids, context=context)
        domain_move_in += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_move_out += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_quant += domain_products

        if context.get('lot_id'):
            domain_quant.append(('lot_id', '=', context['lot_id']))
        if context.get('owner_id'):
            domain_quant.append(('owner_id', '=', context['owner_id']))
            owner_domain = ('restrict_partner_id', '=', context['owner_id'])
            domain_move_in.append(owner_domain)
            domain_move_out.append(owner_domain)
        if context.get('package_id'):
            domain_quant.append(('package_id', '=', context['package_id']))

        domain_move_in += domain_move_in_loc
        domain_move_out += domain_move_out_loc
        moves_in = self.pool.get('stock.move').read_group(cr, uid, domain_move_in, ['product_id', 'product_qty'], ['product_id'], context=context)
        moves_out = self.pool.get('stock.move').read_group(cr, uid, domain_move_out, ['product_id', 'product_qty'], ['product_id'], context=context)

        domain_quant += domain_quant_loc
        quants = self.pool.get('stock.quant').read_group(cr, uid, domain_quant, ['product_id', 'qty'], ['product_id'], context=context)
        quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))

        moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in))
        moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_out))
        res = {}
        ctx = context.copy()
        ctx.update({'prefetch_fields': False})
        for product in self.browse(cr, uid, ids, context=ctx):
            id = product.id
            qty_available = float_round(quants.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            incoming_qty = float_round(moves_in.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            outgoing_qty = float_round(moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            virtual_available = float_round(quants.get(id, 0.0) + moves_in.get(id, 0.0) - moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            res[id] = {
                'qty_available': qty_available,
                'incoming_qty': incoming_qty,
                'outgoing_qty': outgoing_qty,
                'virtual_available': virtual_available,
            }
        return res
Exemple #9
0
    def onchange_uos_quantity(self, cr, uid, ids, product_id, product_uos_qty,
                          product_uos, product_uom):
        """ On change of product quantity finds UoM and UoS quantities
        @param product_id: Product id
        @param product_uos_qty: Changed UoS Quantity of product
        @param product_uom: Unit of measure of product
        @param product_uos: Unit of sale of product
        @return: Dictionary of values
        """
        result = {
            'product_uom_qty': 0.00
        }

        if (not product_id) or (product_uos_qty <= 0.0):
            result['product_uos_qty'] = 0.0
            return {'value': result}

        product_obj = self.pool.get('product.product')
        uos_coeff = product_obj.read(cr, uid, product_id, ['uos_coeff'])

        # No warning if the quantity was decreased to avoid double warnings:
        # The clients should call onchange_quantity too anyway

        if product_uos and product_uom and (product_uom != product_uos):
            precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Product Unit of Measure')
            result['product_uom_qty'] = float_round(product_uos_qty / uos_coeff['uos_coeff'], precision_digits=precision)
        else:
            result['product_uom_qty'] = product_uos_qty
        return {'value': result}
Exemple #10
0
 def action_accept_ready_qty(self):
     self.with_incidences = False
     new_moves = []
     for move in self.move_lines:
         if move.state in ('done', 'cancel'):
             # ignore stock moves cancelled or already done
             continue
         precision = move.product_uom.rounding
         remaining_qty = move.product_uom_qty - move.qty_ready
         remaining_qty = float_round(remaining_qty,
                                     precision_rounding=precision)
         if float_compare(remaining_qty, 0,
                          precision_rounding=precision) > 0 and \
             float_compare(remaining_qty, move.product_qty,
                           precision_rounding=precision) < 0:
             new_move = move.split(move, remaining_qty)
             new_moves.append(new_move)
     if new_moves:
         new_moves = self.env['stock.move'].browse(new_moves)
         self._create_backorder(self, backorder_moves=new_moves)
         new_moves.write({'qty_ready': 0.0})
         self.do_unreserve()
         self.recheck_availability()
     self.message_post(body=_("User %s accepted ready quantities.") %
                       (self.env.user.name))
Exemple #11
0
    def _swedish_add_invoice_line(self, cr, uid, invoice, amounts,
                                  rounded_total, delta, context=None):
        """ Create a invoice_line with the diff of rounding """
        invoice_line_obj = self.pool.get('account.invoice.line')
        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')

        company = invoice.company_id
        if not invoice.global_round_line_id:
            new_invoice_line = {
                'name': _('Rounding'),
                'price_unit': -delta,
                'account_id': company.tax_calculation_rounding_account_id.id,
                'invoice_id': invoice.id,
                'is_rounding': True,
            }
            invoice_line_obj.create(cr, uid, new_invoice_line, context=context)
        elif float_compare(invoice.global_round_line_id.price_unit, -delta,
                           precision_digits=prec) != 0:
            invoice_line_obj.write(
                cr, uid, invoice.global_round_line_id.id,
                {'price_unit': -delta}, context=context)

        amount_untaxed = float_round(amounts['amount_untaxed'] - delta,
                                     precision_digits=prec)
        return {'amount_total': rounded_total,
                'amount_untaxed': amount_untaxed}
    def _swedish_round_globally(self, cr, uid, invoice,
                                rounded_total, delta, context=None):
        """ Add the diff to the biggest tax line
        This ajustment must be done only after all tax are computed
        """
        # Here we identify that all taxe lines have been computed
        if not self._all_invoice_tax_line_computed(invoice):
            return {}

        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')
        inv_tax_obj = self.pool.get('account.invoice.tax')

        ajust_line = None
        for tax_line in invoice.tax_line:
            if not ajust_line or tax_line.amount > ajust_line.amount:
                ajust_line = tax_line
        if ajust_line:
            amount = ajust_line.amount - delta
            vals = inv_tax_obj.amount_change(
                cr, uid, [ajust_line.id],
                amount,
                currency_id=invoice.currency_id.id,
                company_id=invoice.company_id.id,
                date_invoice=invoice.date_invoice)['value']
            ajust_line.write({'amount': amount,
                              'tax_amount': vals['tax_amount']})

            amount_tax = float_round(invoice.amount_tax - delta,
                                     precision_digits=prec)
            return {'amount_total': rounded_total,
                    'amount_tax': amount_tax}
        return {}
    def show_special_quantity(self,product_id,qty):
        logging.info('producto %s',product_id.uom_id.category_id.name)
        amount = qty/product_id.uom_id.factor


        amount = amount * product_id.uos_id.factor
        return  str(float_round(amount, precision_rounding=product_id.uos_id.rounding)) + ' ' + product_id.uos_id.name 
Exemple #14
0
    def compute_all_included(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
        """
        RETURN: {
                'total': 0.0,                # Total without taxes
                'total_included: 0.0,        # Total with taxes
                'taxes': []                  # List of taxes, see compute for the format
            }
        """

        # By default, for each tax, tax amount will first be computed
        # and rounded at the 'Account' decimal precision for each
        # PO/SO/invoice line and then these rounded amounts will be
        # summed, leading to the total amount for that tax. But, if the
        # company has tax_calculation_rounding_method = round_globally,
        # we still follow the same method, but we use a much larger
        # precision when we round the tax amount for each line (we use
        # the 'Account' decimal precision + 5), and that way it's like
        # rounding after the sum of the tax amounts of each line
        precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
        tax_compute_precision = precision
        if taxes and taxes[0].company_id.tax_calculation_rounding_method == 'round_globally':
            tax_compute_precision += 5
        totalin = totalex = totalin2 = totalex2 = float_round(price_unit * quantity, precision)
        tin = []
        tex = []
        tin2 = []
        tex2 = []
        
        for tax in taxes:
            tin.append(tax)
            if not tax.price_include:
                tex2.append(tax)
            else:
                tin2.append(tax)
        tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner, precision=tax_compute_precision)
        tin2 = self.compute_inv(cr, uid, tin2, price_unit, quantity, product=product, partner=partner, precision=tax_compute_precision)
        for r in tin:
            totalex -= r.get('amount', 0.0)
        for r in tin2:
            totalex2 += r.get('amount', 0.0)
        totlex_qty = 0.0
        totlex_qty2 = 0.0
        try:
            totlex_qty = totalex/quantity
            totlex_qty2 = totalex2/quantity
        except:
            pass
        tex = self._compute(cr, uid, tex, totlex_qty, quantity, product=product, partner=partner, precision=tax_compute_precision)
        tex2 = self._compute(cr, uid, tex2, totalex, quantity, product=product, partner=partner, precision=tax_compute_precision)
        for r in tex:
            totalin += r.get('amount', 0.0)
        for r in tex2:
            totalin2 -= r.get('amount', 0.0)
        return {
            'total': totalex,
            'total_included': totalin,
            'taxes': tin + tex,
            'price_unit': totalin2,
        }
Exemple #15
0
 def uos_qty(self):
     if self.product_uom and self.product_id.uom_id and (self.product_uom != self.product_id.uom_id):
         res = self.quantity * self.product_id.uom_id.factor
         res = res / self.product_uom.factor
         res = float_round(res, precision_rounding=self.product_uom.rounding, rounding_method="UP")
     else:
         res = self.quantity
     return res
 def _compute_qties(self):
     move = self.env['stock.move'].browse(self.env.context['active_id'])
     lines_qty = sum(self.line_ids.filtered(
         lambda r: r.use_qty > 0).mapped('use_qty'))
     self.lines_qty = lines_qty
     self.move_qty = float_round(
         move.product_uom_qty, precision_rounding=move.product_uom.rounding,
         rounding_method='UP') - lines_qty
Exemple #17
0
    def _product_quantity_available(self, field_names=None, arg=False):
        """
        - Available for Sales = Quantity On Hand - Outgoing
        """
        context = self._context.copy() or {}
        field_names = field_names or []

        domain_products = [('product_id', 'in', self.ids)]
        domain_quant, domain_move_in, domain_move_out = [], [], []
        domain_quant_loc, domain_move_in_loc, domain_move_out_loc = \
            self._get_domain_locations()
        domain_move_in += \
            self._get_domain_dates() + \
            [('state', 'not in', ('done', 'cancel', 'draft'))] + \
            domain_products
        domain_move_out += \
            self._get_domain_dates() + \
            [('state', 'not in', ('done', 'cancel', 'draft'))] + \
            domain_products
        domain_quant += domain_products

        if context.get('lot_id'):
            domain_quant.append(('lot_id', '=', context['lot_id']))
        if context.get('owner_id'):
            domain_quant.append(('owner_id', '=', context['owner_id']))
            owner_domain = ('restrict_partner_id', '=', context['owner_id'])
            domain_move_in.append(owner_domain)
            domain_move_out.append(owner_domain)
        if context.get('package_id'):
            domain_quant.append(('package_id', '=', context['package_id']))

        domain_move_in += domain_move_in_loc
        domain_move_out += domain_move_out_loc
        moves_in = self.env['stock.move'].read_group(
            domain_move_in, ['product_id', 'product_qty'], ['product_id'])
        moves_out = self.env['stock.move'].read_group(
            domain_move_out, ['product_id', 'product_qty'], ['product_id'])

        domain_quant += domain_quant_loc
        quants = self.env['stock.quant'].read_group(
            domain_quant, ['product_id', 'qty'], ['product_id'])
        quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))

        moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']),
                            moves_in))
        moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']),
                             moves_out))
        res = {}
        for product in self:
            id = product.id
            sale_available = float_round(
                quants.get(id, 0.0) - moves_out.get(id, 0.0),
                precision_rounding=product.uom_id.rounding)
            product.sale_available = sale_available
            res[id] = {
                'sale_available': sale_available,
            }
        return res
Exemple #18
0
 def trans_rec_get(self, cr, uid, ids, context=None):
     account_move_line_obj = self.pool.get('account.move.line')
     if context is None:
         context = {}
     credit = debit = 0
     account_id = False
     count = 0
     for line in account_move_line_obj.browse(cr, uid, context['active_ids'], context=context):
         if not line.reconcile_id and not line.reconcile_id.id:
             count += 1
             credit += line.credit
             debit += line.debit
             account_id = line.account_id.id
     precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Account')
     writeoff = float_round(debit-credit, precision_digits=precision)
     credit = float_round(credit, precision_digits=precision)
     debit = float_round(debit, precision_digits=precision)
     return {'trans_nbr': count, 'account_id': account_id, 'credit': credit, 'debit': debit, 'writeoff': writeoff}
Exemple #19
0
 def trans_rec_get(self, cr, uid, ids, context=None):
     account_move_line_obj = self.pool.get("account.move.line")
     if context is None:
         context = {}
     credit = debit = 0
     account_id = False
     count = 0
     for line in account_move_line_obj.browse(cr, uid, context["active_ids"], context=context):
         if not line.reconcile_id and not line.reconcile_id.id:
             count += 1
             credit += line.credit
             debit += line.debit
             account_id = line.account_id.id
     precision = self.pool["decimal.precision"].precision_get(cr, uid, "Account")
     writeoff = float_round(debit - credit, precision_digits=precision)
     credit = float_round(credit, precision_digits=precision)
     debit = float_round(debit, precision_digits=precision)
     return {"trans_nbr": count, "account_id": account_id, "credit": credit, "debit": debit, "writeoff": writeoff}
Exemple #20
0
 def _average_consumption(self):
     ctx = dict(self.env.context).copy()
     cr, uid = self.env.cr, self.env.uid
     location_ids = []
     consumtion_obj = self.env['product.consumption']
     location_obj = self.pool.get('stock.location')
     warehouse_obj = self.pool.get('stock.warehouse')
     res_users_obj = self.env['res.users']
     user_brw = res_users_obj.browse(uid)
     warehouse = user_brw.default_section_id.default_warehouse
     if warehouse:
         ctx.update({'warehouse': warehouse.id})
     if ctx.get('warehouse', False):
         if isinstance(ctx['warehouse'], (int, long)):
             wids = [ctx['warehouse']]
         elif isinstance(ctx['warehouse'], basestring):
             domain = [('name', 'ilike', ctx['warehouse'])]
             if ctx.get('force_company', False):
                 domain += [('company_id', '=', ctx['force_company'])]
             wids = warehouse_obj.search(cr, uid, domain, context=ctx)
         else:
             wids = ctx['warehouse']
     else:
         wids = warehouse_obj.search(cr, uid, [], context=ctx)
     for w in warehouse_obj.browse(cr, uid, wids, context=ctx):
         location_ids.append(w.view_location_id.id)
     #_logger.info("Teke ctx %s:%s" % (ctx, location_ids))
     for product in self:
         if product.consumption_calculation_method == 'moves':
             for location in location_obj.browse(cr,
                                                 uid,
                                                 location_ids,
                                                 context=self.env.context):
                 out_qty = 0
                 move_out_id = consumtion_obj.search([
                     ('location_id', "=", location.id),
                     ('product_id', '=', product.id)
                 ])
                 if move_out_id:
                     for consumtion in consumtion_obj.browse(
                             move_out_id.id):
                         _logger.info("Consumption %s:%s" %
                                      (consumtion, move_out_id))
                         out_qty += consumtion.outgoing_qty
                         nb_days = consumtion.nb_days
                     #product._average_consumption_moves()
                     outgoing_qty = float_round(
                         out_qty,
                         precision_rounding=product.uom_id.rounding)
                     product.average_consumption = (nb_days and
                                                    (outgoing_qty / nb_days)
                                                    or False)
                     product.total_consumption = outgoing_qty or False
                     product.nb_days = nb_days or False
                     self._displayed_average_consumption()
Exemple #21
0
    def _get_stock_move_price_unit(self):
        # price_unit = super(PurchaseOrderLine, self)._get_stock_move_price_unit()
        # SuperCopyCheck
        self.ensure_one()
        amount_ex = 0.0
        line = self[0]
        order = line.order_id
        price_unit = line.price_unit
        if line.taxes_id:
            taxes_all = line.taxes_id.with_context(round=False).compute_all(
                price_unit, currency=line.order_id.currency_id, quantity=1.0)
            price_unit = taxes_all['total_excluded']
            for atax in taxes_all['taxes']:
                tax = self.env['account.tax'].browse(atax['id'])
                if tax and tax.price_include and tax.cost_include:
                    price_unit += atax['amount']
                    amount_ex += atax['amount']

        if line.product_uom.id != line.product_id.uom_id.id:
            price_unit *= line.product_uom.factor / line.product_id.uom_id.factor
        if order.currency_id != order.company_id.currency_id:
            price_unit = order.currency_id.compute(
                price_unit, order.company_id.currency_id, round=False)

        # Check rounding issue. Ocurre cuando este costo calculado por impuesto unitario no cuadra con los montos calculados en la factura como totales
        # Anticipar los calculos que hara la Factura para asegurar que finalmente la cuenta puente de Inventarios por facturar si cuadre
        if line.taxes_id:
            precision = self.env['decimal.precision'].precision_get('Account')
            price_total = float_round(price_unit * line.product_qty,
                                      precision_digits=precision)
            cost_ex = float_round(amount_ex * line.product_qty,
                                  precision_digits=precision)
            cost_add = float_round(taxes_all['total_excluded'] *
                                   line.product_qty,
                                   precision_digits=precision)
            total_cost = cost_ex + cost_add
            if total_cost != price_total and abs(total_cost -
                                                 price_total) < 0.1:
                # Aplicar solo en caso de diferencia minima
                price_unit = total_cost / line.product_qty

        return price_unit
Exemple #22
0
 def uos_qty(self):
     if self.product_uom and self.product_id.uom_id and \
             (self.product_uom != self.product_id.uom_id):
         res = self.quantity * self.product_id.uom_id.factor
         res = res / self.product_uom.factor
         res = float_round(res,
                           precision_rounding=self.product_uom.rounding,
                           rounding_method='UP')
     else:
         res = self.quantity
     return res
Exemple #23
0
 def _compute_deposit_available(self):
     domain_quant_loc = self.with_context(
         deposit_locations=True)._get_domain_locations()[0]
     domain_quant = domain_quant_loc + [('product_id', 'in', self.ids)]
     quants = self.env['stock.quant'].read_group(
         domain_quant, ['product_id', 'qty'], ['product_id'])
     quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))
     for product in self:
         product.deposit_available = float_round(
             quants.get(product.id, 0.0),
             precision_rounding=product.uom_id.rounding)
Exemple #24
0
    def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None):
        context = context or {}
        field_names = field_names or []

        domain_products = [('product_id', 'in', ids)]
        domain_quant, domain_move_in, domain_move_out = self._get_domain_locations(cr, uid, ids, context=context)
        domain_move_in += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_move_out += self._get_domain_dates(cr, uid, ids, context=context) + [('state', 'not in', ('done', 'cancel', 'draft'))] + domain_products
        domain_quant += domain_products
        if context.get('lot_id') or context.get('owner_id') or context.get('package_id'):
            if context.get('lot_id'):
                domain_quant.append(('lot_id', '=', context['lot_id']))
            if context.get('owner_id'):
                domain_quant.append(('owner_id', '=', context['owner_id']))
            if context.get('package_id'):
                domain_quant.append(('package_id', '=', context['package_id']))
            moves_in = []
            moves_out = []
        else:
            moves_in = self.pool.get('stock.move').read_group(cr, uid, domain_move_in, ['product_id', 'product_qty'], ['product_id'], context=context)
            moves_out = self.pool.get('stock.move').read_group(cr, uid, domain_move_out, ['product_id', 'product_qty'], ['product_id'], context=context)

        quants = self.pool.get('stock.quant').read_group(cr, uid, domain_quant, ['product_id', 'qty'], ['product_id'], context=context)
        quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants))

        moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in))
        moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_out))
        res = {}
        for product in self.browse(cr, uid, ids, context=context):
            id = product.id
            qty_available = float_round(quants.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            incoming_qty = float_round(moves_in.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            outgoing_qty = float_round(moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            virtual_available = float_round(quants.get(id, 0.0) + moves_in.get(id, 0.0) - moves_out.get(id, 0.0), precision_rounding=product.uom_id.rounding)
            res[id] = {
                'qty_available': qty_available,
                'incoming_qty': incoming_qty,
                'outgoing_qty': outgoing_qty,
                'virtual_available': virtual_available,
            }
        return res
    def _quant_create(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False,
                      force_location_from=False, force_location_to=False, context=None):
        '''Create a quant in the destination location and create a negative quant in the source location if it's an internal location.
        '''
        if context is None:
            context = {}
        price_unit = self.pool.get('stock.move').get_price_unit(cr, uid, move, context=context)
        location = force_location_to or move.location_dest_id
        rounding = move.product_id.uom_id.rounding
        vals = {
            'product_id': move.product_id.id,
            'location_id': location.id,
            'qty': float_round(qty, precision_rounding=rounding),
            'cost': price_unit,
            'history_ids': [(4, move.id)],
            'in_date': datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
            'company_id': move.company_id.id,
            'lot_id': lot_id,
            'owner_id': owner_id,
            'package_id': dest_package_id,
            'local_carrier_cost': move.unit_local_c_cost * qty or '',
            'international_c_cost':move.unit_inter_c_cost * qty or '',
            'unit_lc_cost':move.unit_lc_cost * qty or '',
        }
        self.pool.get('product.product').write(cr,uid,move.product_id.id,{'local_carrier_cost':move.unit_local_c_cost,'international_c_cost':move.unit_inter_c_cost,'unit_lc_cost':move.unit_lc_cost})

        if move.location_id.usage == 'internal':
            #if we were trying to move something from an internal location and reach here (quant creation),
            #it means that a negative quant has to be created as well.
            negative_vals = vals.copy()
            negative_vals['location_id'] = force_location_from and force_location_from.id or move.location_id.id
            negative_vals['qty'] = float_round(-qty, precision_rounding=rounding)
            negative_vals['cost'] = price_unit
            negative_vals['negative_move_id'] = move.id
            negative_vals['package_id'] = src_package_id
            negative_quant_id = self.create(cr, SUPERUSER_ID, negative_vals, context=context)
            vals.update({'propagated_from_id': negative_quant_id})

        #create the quant as superuser, because we want to restrict the creation of quant manually: we should always use this method to create quants
        quant_id = self.create(cr, SUPERUSER_ID, vals, context=context)
        return self.browse(cr, uid, quant_id, context=context)
Exemple #26
0
 def update_account_move_line(cr, move_lines, full_reconcile_id):
     """Update move lines."""
     for line in move_lines:
         # Compute reconciled similar to what happens in model, but using
         # data retrieved using SQL:
         reconciled = False
         digits_rounding_precision = line.company_currency_rounding
         if float_is_zero(line.amount_residual,
                          precision_rounding=digits_rounding_precision):
             if line.line_currency_id and line.amount_residual_currency:
                 # if there is an amount in another currency, it must
                 # be zero as well:
                 currency_zero = float_is_zero(
                     line.amount_residual_currency,
                     precision_rounding=line.line_currency_rounding)
                 if currency_zero:
                     reconciled = True
             else:
                 # no currency involved:
                 reconciled = True
         cr.execute(
             """
             UPDATE account_move_line SET
                 amount_residual = %s,
                 amount_residual_currency = %s,
                 reconciled = %s,
                 balance = %s,
                 company_currency_id = %s,
                 full_reconcile_id = %s,
                 write_date = CURRENT_TIMESTAMP,
                 write_uid = %s
             WHERE id = %s
             """,
             params=(float_round(
                 line.amount_residual,
                 precision_rounding=line.company_currency_rounding),
                     float_round(
                         line.amount_residual_currency,
                         precision_rounding=line.company_currency_rounding),
                     reconciled, line.balance, line.company_currency_id,
                     full_reconcile_id or None, SUPERUSER_ID, line.id))
 def product_uos_qty_onchange(self):
     """
     We change the product_uom_qty
     """
     product = self.product_id
     if product:
         uos_id = self.uos_id.id
         uos_qty = float_round(self.uos_qty,
                               precision_rounding=self.uos_id.rounding,
                               rounding_method='UP')
         self.uos_qty = uos_qty
         self.qty = product.uos_qty_to_uom_qty(uos_qty, uos_id)
Exemple #28
0
 def action_calculate_manage_fee(self):
     self.ensure_one()
     management_lines = self.order_line.filtered(
         lambda r: r.manage_fee_percent > 0)
     if management_lines:
         amount = self.amount_before_management_fee
         for line in management_lines:
             fee = float_round(amount * line.manage_fee_percent / 100, 2)
             line.write({
                 'price_unit': fee,
                 'product_uom_qty': 1.0,
             })
Exemple #29
0
 def get_daily_total_working_hour(self, date):
     total = 0.0
     if date:
         daily_working_hour_objs = self.search([('user_id', '=', self._uid),
                                                ('date', '=', date)])
         for daily_wh in daily_working_hour_objs:
             if daily_wh.id in self.ids:
                 total += self.duration_hour
             else:
                 total += daily_wh.duration_hour
         total = float_utils.float_round(total, precision_rounding=.001)
     return total
Exemple #30
0
    def compute_line_amount(self, total_amount, remaining_amount):
        """Compute the amount for a payment term line.
        In case of procent computation, use the payment
        term line rounding if defined

            :param total_amount: total balance to pay
            :param remaining_amount: total amount minus sum of previous lines
                computed amount
            :returns: computed amount for this line
        """
        self.ensure_one()
        prec = self.env['decimal.precision'].precision_get('Account')
        if self.value == 'fixed':
            return float_round(self.value_amount, precision_digits=prec)
        elif self.value == 'procent':
            amt = total_amount * self.value_amount
            if self.amount_round:
                amt = float_round(amt, precision_rounding=self.amount_round)
            return float_round(amt, precision_digits=prec)
        elif self.value == 'balance':
            return float_round(remaining_amount, precision_digits=prec)
        return None
Exemple #31
0
    def _check_uoc_qty(self):
        if not self.product_id:
            return
        if self._context.get('tm', False):
            if self.last_tm == self._context['tm']:
                return
            self.last_tm = self._context['tm']

        mantles = self._conv_boxes_logis('mantles') * self.product_uoc_qty
        palets = self._conv_boxes_logis('palets') * self.product_uoc_qty

        self.mantles = float_round(mantles, 2)
        self.palets = float_round(palets, 2)
        product_id = self.product_id
        self.product_qty = product_id._conv_units(self.product_uoc.id,
                                                  product_id.uom_id.id,
                                                  self.supplier_id.id)
        supplier_id = self.supplier_id
        supp = product_id.get_product_supp_record(supplier_id.id)
        self.boxes = self.mantles * supp.supp_ca_ma
        self.unitskg = self.product_uoc_qty
        return
 def _paid_amount_in_company_currency(self):
     ctx = self.env.context.copy()
     for v in self:
         ctx.update({'date': v.date})
         # make a new call to browse in order to have the right date in the context, to get the right currency rate
         voucher = v
         ctx.update({
           'voucher_special_currency': voucher.payment_rate_currency_id and voucher.payment_rate_currency_id.id or False,
           'voucher_special_currency_rate': voucher.currency_id.rate * voucher.payment_rate, })
         if voucher.rate_pr == 1.0 or float_compare(voucher.currency_id.rate, voucher.rate_pr, precision_digits=6) == 0:
             voucher.paid_amount_in_company_currency = self.pool.get('res.currency').compute(self.env.cr, self.env.uid, voucher.currency_id.id, voucher.company_id.currency_id.id, voucher.amount, context=ctx)
         else:
             voucher.paid_amount_in_company_currency = float_round(voucher.amount/voucher.rate_pr, 2)
Exemple #33
0
    def compute_line_amount(self, total_amount, remaining_amount):
        """Compute the amount for a payment term line.
        In case of procent computation, use the payment
        term line rounding if defined

            :param total_amount: total balance to pay
            :param remaining_amount: total amount minus sum of previous lines
                computed amount
            :returns: computed amount for this line
        """
        self.ensure_one()
        prec = self.env['decimal.precision'].precision_get('Account')
        if self.value == 'fixed':
            return float_round(self.value_amount, precision_digits=prec)
        elif self.value == 'procent':
            amt = total_amount * self.value_amount
            if self.amount_round:
                amt = float_round(amt, precision_rounding=self.amount_round)
            return float_round(amt, precision_digits=prec)
        elif self.value == 'balance':
            return float_round(remaining_amount,  precision_digits=prec)
        return None
 def _quant_split(self, quant, qty):
     prec = quant.product_id.uom_id.rounding
     result = super(StockQuant, self)._quant_split(quant, qty)
     old_neg = float_compare(float_round(quant.qty,
                                         precision_rounding=prec),
                             0,
                             precision_rounding=prec) <= 0
     new_neg = False
     if result:
         new_neg = float_compare(float_round(result.qty,
                                             precision_rounding=prec),
                                 0,
                                 precision_rounding=prec) <= 0
     if not config["test_enable"] and (old_neg or new_neg):
         raise ValueError(
             _("Quant split: you are not allowed to create a negative or null quant. "
               "Product: %s, Quant qty: %s, Required reduction to: %s, Location: %s,"
               " Lot: %s, Package: %s") %
             (quant.product_id.display_name, quant.qty, qty,
              quant.location_id.complete_name, quant.lot_id.name
              or '-', quant.package_id.name or '-'))
     return result
Exemple #35
0
    def compute_all(self, cr, uid, taxes, standard_price, quantity, product=None, force_excluded=False):
        """
        :param force_excluded: boolean used to say that we don't want to consider the value of field price_include of
            tax. It's used in encoding by line where you don't matter if you encoded a tax with that boolean to True or
            False
        RETURN: {
                'total': 0.0,                # Total without taxes
                'total_included: 0.0,        # Total with taxes
                'taxes': []                  # List of taxes, see compute for the format
            }
        """
  
        # By default, for each tax, tax amount will first be computed
        # and rounded at the 'Account' decimal precision for each
        # PO/SO/invoice line and then these rounded amounts will be
        # summed, leading to the total amount for that tax. But, if the
        # company has tax_calculation_rounding_method = round_globally,
        # we still follow the same method, but we use a much larger
        # precision when we round the tax amount for each line (we use
        # the 'Account' decimal precision + 5), and that way it's like
        # rounding after the sum of the tax amounts of each line
  
        precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
        

        totalin = totalex = float_round(standard_price * quantity, precision)
        
        quantity = 1
        tin = []
        tex = []
        for tax in taxes:
            if not tax.price_include or force_excluded:
                tex.append(tax)
            else:
                tin.append(tax)
        tin = self.compute_inv(cr, uid, tin, standard_price, quantity, product=product)
        for r in tin:
            totalex -= r.get('amount', 0.0)
        totlex_qty = 0.0
        try:
            totlex_qty = totalex/quantity
        except:
            pass
        tex = self._compute(cr, uid, tex, totlex_qty, quantity, product=product)
        for r in tex:
            totalin += r.get('amount', 0.0)
        return {
            'total': totalex,
            'total_included': totalin,
            'taxes': tin + tex
        }
Exemple #36
0
    def _quant_create(self, cr, uid, qty, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False,
                      force_location_from=False, force_location_to=False, context=None):
        '''Create a quant in the destination location and create a negative quant in the source location if it's an internal location.
        '''
        if context is None:
            context = {}
        price_unit = self.pool.get('stock.move').get_price_unit(cr, uid, move, context=context)
        location = force_location_to or move.location_dest_id
        rounding = move.product_id.uom_id.rounding
        vals = {
            'product_id': move.product_id.id,
            'location_id': location.id,
            'qty': float_round(qty, precision_rounding=rounding),
            'cost': price_unit,
            'history_ids': [(4, move.id)],
            'in_date': datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
            'company_id': move.company_id.id,
            'lot_id': lot_id,
            'owner_id': owner_id,
            'package_id': dest_package_id,
            'amazon_fnsku': move.amazon_fnsku,
        }

        if move.location_id.usage == 'internal':
            #if we were trying to move something from an internal location and reach here (quant creation),
            #it means that a negative quant has to be created as well.
            negative_vals = vals.copy()
            negative_vals['location_id'] = force_location_from and force_location_from.id or move.location_id.id
            negative_vals['qty'] = float_round(-qty, precision_rounding=rounding)
            negative_vals['cost'] = price_unit
            negative_vals['negative_move_id'] = move.id
            negative_vals['package_id'] = src_package_id
            negative_quant_id = self.create(cr, SUPERUSER_ID, negative_vals, context=context)
            vals.update({'propagated_from_id': negative_quant_id})

        #create the quant as superuser, because we want to restrict the creation of quant manually: we should always use this method to create quants
        quant_id = self.create(cr, SUPERUSER_ID, vals, context=context)
        return self.browse(cr, uid, quant_id, context=context)
 def get_shipping_line_data(self, shipping_price):
     precision = self.env['decimal.precision'].precision_get(
         'Product Price')
     taxs = self.fiscal_position.map_tax(self.shipping_product_id.taxes_id)
     amount_taxs = sum(tax.amount for tax in taxs)
     price_without_taxs = float_round(shipping_price / (1 + amount_taxs),
                                      precision)
     return {
         'name': self.shipping_product_id.name,
         'product_id': self.shipping_product_id.id,
         'price_unit': price_without_taxs,
         'product_uom_qty': 1,
         'tax_id': [(6, 0, [t.id for t in taxs])],
     }
Exemple #38
0
 def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, round=True, rounding_method='UP', context=None):
     if context is None:
         context = {}
     if from_unit.category_id.id != to_unit.category_id.id:
         if context.get('raise-exception', True):
             raise osv.except_osv(_('Error!'), _('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (from_unit.name,to_unit.name,))
         else:
             return qty
     amount = qty/from_unit.factor
     if to_unit:
         amount = amount * to_unit.factor
         if round:
             amount = float_round(amount, precision_rounding=to_unit.rounding, rounding_method=rounding_method)
     return amount
Exemple #39
0
 def create(self, values):
     dest_location = values.get('location_id', False) and self.env['stock.location'].browse(
         values.get('location_id')) or False
     product = values.get('product_id', False) and self.env['product.product'].browse(
         values.get('product_id')) or False
     if dest_location and dest_location.usage == 'internal' and product and product.type == 'product':
         prec = product.uom_id.rounding
         qty = float_compare(float_round(values.get('qty', 0), precision_rounding=prec), 0,
                             precision_rounding=prec) <= 0
         if (not config["test_enable"] or self.env.context.get('force_forbid_negative_quants')) and qty:
             raise exceptions.except_orm(_("Error !"),
                                         _("Impossible to create quant product in internal location with non "
                                           "positiv quantity."))
     return super(StockQuant, self).create(values)
Exemple #40
0
 def update_supply_chain_control(self):
     available_quantities = self._product_available()
     available_quantities = self.get_available_qty_supply_control(available_quantities)
     for product in self:
         draft_orders_qty = 0
         virtual_available = available_quantities.get(product.id) and \
             available_quantities[product.id].get('virtual_available', 0)
         draft_lines = self.env['purchase.order.line']. \
             search([('order_id.state', 'in', ['draft', 'bid', 'sent', 'confirmed']),
                     ('product_id', '=', product.id)])
         done_uoms = []
         for line in draft_lines:
             uom = line.product_uom
             if uom not in done_uoms:
                 done_uoms += [uom]
                 lines_uom = self.env['purchase.order.line'].search([('id', 'in', draft_lines.ids),
                                                                     ('product_uom', '=', uom.id)])
                 lines_uom_qty = sum([line.product_qty for line in lines_uom])
                 if uom == product.uom_id:
                     draft_orders_qty += lines_uom_qty
                 else:
                     draft_orders_qty += self.env['product.uom']._compute_qty(uom.id, lines_uom_qty,
                                                                              product.uom_id.id)
         prec = product.uom_id.rounding
         missing_date = product.get_missing_date()
         main_supplierinfo, seller_defined, scheduler_active_for_seller = product.get_supplier_scheduler_data()
         self.env['supply.chain.control'].create(
             {'product_id': product.id,
              'seller_defined': seller_defined,
              'main_seller_id': main_supplierinfo and main_supplierinfo.name.id or False,
              'scheduler_active_for_seller': scheduler_active_for_seller,
              'virtual_available': float_round(virtual_available, precision_rounding=prec),
              'draft_orders_qty': float_round(draft_orders_qty, precision_rounding=prec),
              'oversupply_qty': float_round(min(draft_orders_qty + virtual_available, draft_orders_qty),
                                            precision_rounding=prec),
              'missing_date': missing_date}
         )
Exemple #41
0
    def _product_available(self,
                           cr,
                           uid,
                           ids,
                           field_names=None,
                           arg=False,
                           context=None):
        context = context or {}
        field_names = field_names or []

        res = super(product_product_makeover,
                    self)._product_available(cr,
                                             uid,
                                             ids,
                                             field_names=field_names,
                                             arg=arg,
                                             context=context)
        if res:
            domain_products = [('product_id', 'in', ids)]
            domain_quant = []
            domain_quant_loc, domain_move_in_loc, domain_move_out_loc = self._get_domain_locations(
                cr, uid, ids, context=context)
            domain_quant += domain_products

            if context.get('lot_id'):
                domain_quant.append(('lot_id', '=', context['lot_id']))
            if context.get('owner_id'):
                domain_quant.append(('owner_id', '=', context['owner_id']))
            if context.get('package_id'):
                domain_quant.append(('package_id', '=', context['package_id']))

            domain_quant += domain_quant_loc
            quants = self.pool.get('stock.quant').read_group(
                cr,
                uid,
                domain_quant, ['product_id', 'qty'], ['product_id'],
                context=context)
            quants = dict(map(lambda x: (x['product_id'][0], x['qty']),
                              quants))

            for product in self.browse(cr, uid, ids, context=context):
                id = product.id
                virtual_available = float_round(
                    quants.get(id, 0.0),
                    precision_rounding=product.uom_id.rounding)
                res[id].update({
                    'virtual_available': virtual_available,
                })
        return res
Exemple #42
0
 def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, context = None):
     if context is None:
         context = {}
     if from_unit.category_id.id <> to_unit.category_id.id:
         if context.get('raise-exception', True):
             raise osv.except_osv(_('Error!'), _('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (from_unit.name, to_unit.name,))
         else:
             return qty
     # First round to the precision of the original unit, so that
     # float representation errors do not bias the following ceil()
     # e.g. with 1 / (1/12) we could get 12.0000048, ceiling to 13!
     amount = float_round(qty / from_unit.factor, precision_rounding = from_unit.rounding)
     if to_unit:
         amount = ceiling(amount * to_unit.factor, to_unit.rounding)
     return amount
 def _product_available(self):
     res = {}
     for rec in self:
         qty = 0.0
         incoming_qty = 0.0
         outgoing_qty = 0.0
         virtual_available = 0.0
         if rec.product_tmpl_id.purchase_ok and rec.seller_ids:
             supplier = self.env['import.supplier.pricelist'].get_cheapest_supplier_or_value({'1':[rec]}, return_value=False)
             parent_location = self.env['import.supplier.pricelist'].get_parent_location(supplier.name)
             if parent_location:
                 quants = self.env['stock.quant'].search([('location_id', 'child_of', parent_location.id),('product_id','=',rec.id)])
                 for quant in quants:
                     qty += quant.qty
                 domain_move_inout_loc = ['&', ('location_dest_id', 'child_of', parent_location.id), '!', ('location_id', 'child_of', parent_location.id)]
                 domain_move_in = self._get_domain_dates() + [('state', 'not in', ('done', 'cancel', 'draft'))] + [('product_id', '=', rec.id)]
                 domain_move_out = self._get_domain_dates() + [('state', 'not in', ('done', 'cancel', 'draft'))] + [('product_id', '=', rec.id)]
                 domain_move_in += domain_move_inout_loc
                 domain_move_out += domain_move_inout_loc
                 moves_in = self.env['stock.move'].read_group(domain_move_in, ['product_id', 'product_qty'], ['product_id'])
                 moves_out = self.env['stock.move'].read_group(domain_move_out, ['product_id', 'product_qty'], ['product_id'])
                 moves_in = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_in))
                 moves_out = dict(map(lambda x: (x['product_id'][0], x['product_qty']), moves_out))
                 incoming_qty = float_round(moves_in.get(rec.id, 0.0), precision_rounding=rec.uom_id.rounding)
                 outgoing_qty = float_round(moves_out.get(rec.id, 0.0), precision_rounding=rec.uom_id.rounding)
                 virtual_available = float_round(qty + incoming_qty - outgoing_qty, precision_rounding=rec.uom_id.rounding)
                 rec.qty_available = qty
                 rec.incoming_qty = incoming_qty
                 rec.outgoing_qty = outgoing_qty
                 rec.virtual_available = virtual_available
         res[rec.id]={ 'qty_available': qty,
                       'incoming_qty': incoming_qty,
                       'outgoing_qty': outgoing_qty,
                       'virtual_available': virtual_available,
                       }
     return res
Exemple #44
0
    def write(self, values):
        if values.get('type', False):
            new_type = values.get('type')
            if new_type == 'product':
                for rec in self:
                    if rec.type == 'consu':
                        for variant in rec.product_variant_ids:
                            quants = self.env['stock.quant'].search([
                                ('product_id', '=', variant.id)
                            ])
                            for quant in quants:
                                quant.cost = 0.0
                        rec.standard_price = 0.0
        if values.get('cost_method', False):
            new_method = values.get('cost_method')
            if new_method == 'real':
                for rec in self:
                    type = values.get('type', False) or rec.type
                    if type == 'product':
                        for variant in rec.product_variant_ids:
                            quants = self.env['stock.quant'].search([
                                ('product_id', '=', variant.id),
                                ('location_id.usage', '=', 'internal')
                            ])
                            quants.write({'cost': rec.standard_price})
            elif new_method != 'real':
                for rec in self:
                    if rec.cost_method == 'real':
                        total_cost = 0.0
                        total_qty = 0.0
                        rounding = rec.uom_id.rounding
                        for variant in rec.product_variant_ids:
                            quants = self.env['stock.quant'].search([
                                ('product_id', '=', variant.id),
                                ('location_id.usage', '=', 'internal')
                            ])

                            for quant in quants:
                                total_cost += quant.cost * quant.qty
                                total_qty += quant.qty
                        if total_qty:
                            avg_cost = total_cost / total_qty
                        else:
                            avg_cost = 0.0
                        rec.standard_price = float_round(
                            avg_cost, precision_rounding=rounding)

        return super(ProductTemplate, self).write(values)
Exemple #45
0
 def _product_availability_warehouse(self, warehouse_id):
     # search avalailability for stokable products
     if self.type != 'product':
         return True
     domain_quant = []
     product = self
     domain_quant += [('product_id', 'in', [product.id])]
     domain_quant_loc = product.with_context(
         warehouse=warehouse_id.id)._get_domain_locations()[0]
     domain_quant += domain_quant_loc
     quants = self.env['stock.quant'].read_group(domain_quant,
                                                 ['product_id', 'qty'],
                                                 ['product_id'])
     quants = dict([(x['product_id'][0], x['qty']) for x in quants])
     qty_available = float_round(quants.get(product.id, 0.0),
                                 precision_rounding=product.uom_id.rounding)
     return qty_available
Exemple #46
0
 def calculate_management_fee(self):
     self.ensure_one()
     order_line = self.env['sale.order.line'].browse(
         self._context['order_line_id'])
     quote = self.env['sale.order'].browse(order_line.order_id.id)
     # if order_line.sale_layout_custom_group_id:
     #     fee = float_round(quote._get_amount_by_custom_group(
     #         order_line.sale_layout_custom_group_id) * \
     #         self.percent_rate / 100, 2)
     # else:
     #     fee = float_round(
     #         quote.amount_before_management_fee * self.percent_rate / 100, 2
     #     )
     fee = float_round(
         quote.amount_before_management_fee * self.percent_rate / 100, 2)
     order_line.write({'price_unit': fee})
     return {'type': 'ir.actions.act_window_close'}
Exemple #47
0
    def _swedish_round_globally(self,
                                cr,
                                uid,
                                invoice,
                                amounts,
                                rounded_total,
                                delta,
                                context=None):
        """ Add the diff to the biggest tax line

        This ajustment must be done only after all tax are computed

        """
        # Here we identify that all taxe lines have been computed
        if not self._all_invoice_tax_line_computed(invoice):
            return {}

        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')
        inv_tax_obj = self.pool.get('account.invoice.tax')

        ajust_line = None
        for tax_line in invoice.tax_line:
            if not ajust_line or tax_line.amount > ajust_line.amount:
                ajust_line = tax_line
        if ajust_line:
            amount = ajust_line.amount - delta
            vals = inv_tax_obj.amount_change(
                cr,
                uid, [ajust_line.id],
                amount,
                currency_id=invoice.currency_id.id,
                company_id=invoice.company_id.id,
                date_invoice=invoice.date_invoice)['value']
            ajust_line.write(
                {
                    'amount': amount,
                    'tax_amount': vals['tax_amount']
                },
                context=context)

            amount_tax = float_round(amounts['amount_tax'] - delta,
                                     precision_digits=prec)
            return {'amount_total': rounded_total, 'amount_tax': amount_tax}
        return {}
    def _convert_amount(self, amount, voucher_id):
        '''
        This function convert the amount given in company currency. It takes either the rate in the voucher (if the
        payment_rate_currency_id is relevant) either the rate encoded in the system.

        :param amount: float. The amount to convert
        :param voucher: id of the voucher on which we want the conversion
        :param context: to context to use for the conversion. It may contain the key 'date' set to the voucher date
            field in order to select the good rate to use.
        :return: the amount in the currency of the voucher's company
        :rtype: float
        '''
        currency_obj = self.pool.get('res.currency')
        voucher = self.browse(voucher_id)
        if voucher.rate_pr == 1.0 or float_compare(voucher.currency_id.rate, voucher.rate_pr, precision_digits=6) == 0:
            return currency_obj.compute(self.env.cr, self.env.uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=self.env.context)
        else:
            return float_round(amount/voucher.rate_pr, 2)
 def _compute_passed(self):
     for analysis in self:
         passed = False
         if analysis.analysis_type == 'boolean':
             if analysis.expected_result_boolean == analysis.result_boolean:
                 passed = True
         elif analysis.analysis_type == 'expr' and \
                 analysis.expected_result_expr and analysis.result_str:
             try:
                 x = float_round(
                     float(analysis.result_str),
                     precision_rounding=analysis.decimal_precision)
                 passed = eval(analysis.expected_result_expr,
                               locals_dict={'x': x, 'X': x})
             except Exception, e:
                 analysis.expr_error = str(e)
         elif analysis.analysis_type == 'free':
             passed = True
Exemple #50
0
    def on_change_date_duration(self):
        if not self.duration_hour:
            self.duration_hour = 0
        if self.date:
            daily_working_hour_objs = self.search([('user_id', '=', self._uid),
                                                   ('date', '=', self.date)])
            if self.ids:
                total = 0
            else:
                total = self.duration_hour
            for daily_wh in daily_working_hour_objs:
                if daily_wh.id in self.ids:
                    total += self.duration_hour
                else:
                    total += daily_wh.duration_hour

            total = float_utils.float_round(total, precision_rounding=.001)
            self.daily_total = total
Exemple #51
0
 def write(self, values):
     val_location_id = values.get('location_id', False)
     val_qty = values.get('qty', 0)
     val_product_id = values.get('product_id', False)
     for rec in self:
         location_id = val_location_id and self.env['stock.location'].browse(val_location_id) or \
             rec.location_id or False
         qty = val_qty or rec.qty
         product_id = val_product_id and self.env['product.product'].browse(val_product_id) or \
             rec.product_id or False
         prec = product_id.uom_id.rounding
         if location_id and location_id.usage == 'internal' and product_id and \
                 product_id.type == 'product':
             neg = float_compare(float_round(qty, precision_rounding=prec), 0, precision_rounding=prec) <= 0
             if (not config["test_enable"] or self.env.context.get('force_forbid_negative_quants')) and neg:
                 raise exceptions.except_orm(_("Error !"),
                                             _("Impossible to edit quant product in internal location with non "
                                               "positiv quantity."))
     return super(StockQuant, self).write(values)
Exemple #52
0
 def product_uos_qty_onchange(self):
     """
     We change the product_uom_qty
     """
     product = self.product_id
     if product:
         if self.do_onchange:
             #qty = self.product_uos_qty
             uos_id = self.product_uos.id
             qty = float_round(self.product_uos_qty,
                               precision_rounding=self.product_uos.rounding,
                               rounding_method='UP')
             self.product_uos_qty = qty
             #conv = product.get_unit_conversions(qty, uos_id)
             # base, unit, or box
             #log_unit = product.get_uom_logistic_unit()
             #self.product_uom_qty = conv[log_unit]
             self.product_uom_qty = product.uos_qty_to_uom_qty(qty, uos_id)
         else:
             self.do_onchange = True
Exemple #53
0
 def _check_price(self, cr, uid, ids, context=None):
     precision = self.pool.get('decimal.precision').precision_get(
         cr, uid, 'Account')
     for sol in self.browse(cr, uid, ids, context=context):
         price_unit = sol.price_unit
         original_price = sol.original_price
         if original_price != 0:
             computed_discount_dummy = float_round(
                 (float(original_price) - price_unit) / original_price *
                 100, precision)
             if ((original_price != 0) and (not sol.sample) and
                 (not float_eq(sol.discount_dummy, computed_discount_dummy,
                               precision))):
                 _logger.debug(
                     "X: discount/100 != (original_price-final_price)/original_price, precision)"
                     "\n%s != %s, precision : %s" %
                     (sol.discount_dummy, computed_discount_dummy,
                      precision))
                 return False
     return True
 def _product_availability_warehouse(self, warehouse_id):
     # search avalailability for stokable products
     if self.type not in('product'):
         return True
     domain_quant = []
     product = self
     domain_quant += [('product_id', 'in', [product.id])]
     domain_quant_loc, domain_move_in_loc,\
         domain_move_out_loc = product.with_context(
             warehouse=warehouse_id.id)._get_domain_locations()
     domain_quant += domain_quant_loc
     quants = self.env['stock.quant'].read_group(
         domain_quant, ['product_id', 'qty'],
         ['product_id'])
     quants = dict(
         map(lambda x: (x['product_id'][0], x['qty']), quants))
     qty_available = float_round(
         quants.get(product.id, 0.0),
         precision_rounding=product.uom_id.rounding)
     return qty_available
    def test_2016_fed_income_withholding_single(self):
        salary = 6000.00
        schedule_pay = 'monthly'
        w4_allowances = 3
        w4_allowance_amt = 337.50 * w4_allowances
        adjusted_salary = salary - w4_allowance_amt  # should be 4987.50, but would work over a wide value for the rate
        ###
        # Single MONTHLY form Publication 15
        expected_withholding = float_round(-(431.95 + ((adjusted_salary - 3325) * 0.25)), self.payroll_digits)

        employee = self._createEmployee()
        contract = self._createContract(employee, salary, schedule_pay, w4_allowances, 'single')

        self._log('2016 fed income single payslip: adjusted_salary: ' + str(adjusted_salary))
        payslip = self._createPayslip(employee, '2016-01-01', '2016-01-31')

        payslip.compute_sheet()

        cats = self._getCategories(payslip)

        self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
    def test_2016_fed_income_withholding_married(self):
        salary = 14000.00
        schedule_pay = 'bi-weekly'
        w4_allowances = 2
        w4_allowance_amt = 155.80 * w4_allowances
        adjusted_salary = salary - w4_allowance_amt  # should be 1368.84, but would work over a wide value for the rate
        ###
        # Single MONTHLY form Publication 15
        expected_withholding = float_round(-(1992.05 + ((adjusted_salary - 9231) * 0.33)), self.payroll_digits)

        employee = self._createEmployee()
        contract = self._createContract(employee, salary, schedule_pay, w4_allowances, 'married')

        self._log('2016 fed income married payslip: adjusted_salary: ' + str(adjusted_salary))
        payslip = self._createPayslip(employee, '2016-01-01', '2016-01-31')

        payslip.compute_sheet()

        cats = self._getCategories(payslip)

        self.assertPayrollEqual(cats['FED_INC_WITHHOLD'], expected_withholding)
Exemple #57
0
 def _quant_create(self,
                   qty,
                   move,
                   lot_id=False,
                   owner_id=False,
                   src_package_id=False,
                   dest_package_id=False,
                   force_location_from=False,
                   force_location_to=False):
     positive_quant = super(stock_quant,
                            self)._quant_create(qty,
                                                move,
                                                lot_id=False,
                                                owner_id=False,
                                                src_package_id=False,
                                                dest_package_id=False,
                                                force_location_from=False,
                                                force_location_to=False)
     if move.location_id.usage == 'supplier':
         price_unit = self.env['stock.move'].get_price_unit(move)
         negative_vals = {
             'product_id': positive_quant.product_id.id,
             'history_ids': [(4, move.id)],
             'in_date': positive_quant.in_date,
             'company_id': positive_quant.company_id.id,
             'lot_id': positive_quant.lot_id.id,
             'owner_id': positive_quant.owner_id.id,
         }
         rounding = move.product_id.uom_id.rounding
         negative_vals[
             'location_id'] = force_location_from and force_location_from.id or move.location_id.id
         negative_vals['qty'] = float_round(-qty,
                                            precision_rounding=rounding)
         negative_vals['cost'] = price_unit
         negative_vals['negative_move_id'] = move.id
         negative_vals['package_id'] = src_package_id
         negative_quant_id = self.env['stock.quant'].sudo().create(
             negative_vals)
         positive_quant.write({'propagated_from_id': negative_quant_id.id})
     return positive_quant
Exemple #58
0
    def value_to_html(self, value, options):
        if 'decimal_precision' in options:
            precision = self.env['decimal.precision'].search([('name', '=', options['decimal_precision'])]).digits
        else:
            precision = options['precision']

        if precision is None:
            fmt = '%f'
        else:
            value = float_utils.float_round(value, precision_digits=precision)
            fmt = '%.{precision}f'.format(precision=precision)

        formatted = self.user_lang().format(fmt, value, grouping=True)

        # %f does not strip trailing zeroes. %g does but its precision causes
        # it to switch to scientific notation starting at a million *and* to
        # strip decimals. So use %f and if no precision was specified manually
        # strip trailing 0.
        if precision is None:
            formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)

        return unicodifier(formatted)
Exemple #59
0
    def _swedish_add_invoice_line(self,
                                  cr,
                                  uid,
                                  invoice,
                                  rounded_total,
                                  delta,
                                  context=None):
        """ Create a invoice_line with the diff of rounding """

        invoice_line_obj = self.pool.get('account.invoice.line')
        obj_precision = self.pool.get('decimal.precision')
        prec = obj_precision.precision_get(cr, uid, 'Account')

        company = invoice.company_id
        if not invoice.global_round_line_id.id:
            new_invoice_line = {
                'name': _('Rounding'),
                'price_unit': -delta,
                'account_id': company.tax_calculation_rounding_account_id.id,
                'invoice_id': invoice.id,
                'is_rounding': True,
            }
            invoice_line_obj.create(cr, uid, new_invoice_line, context=context)
        elif float_compare(invoice.global_round_line_id.price_unit,
                           -delta,
                           precision_digits=prec) != 0:
            invoice_line_obj.write(cr,
                                   uid,
                                   invoice.global_round_line_id.id,
                                   {'price_unit': -delta},
                                   context=context)

        amount_untaxed = float_round(invoice.amount_untaxed - delta,
                                     precision_digits=prec)
        return {
            'amount_total': rounded_total,
            'amount_untaxed': amount_untaxed
        }
Exemple #60
0
    def _swedish_round_globally(self, invoice, rounded_total, delta):
        """ Add the diff to the biggest tax line
        This ajustment must be done only after all tax are computed
        """
        # Here we identify that all taxe lines have been computed
        if not self._all_invoice_tax_line_computed(invoice):
            return {}

        obj_precision = self.env['decimal.precision']
        prec = obj_precision.precision_get('Account')

        ajust_line = None
        for tax_line in invoice.tax_line_ids:
            if not ajust_line or tax_line.amount > ajust_line.amount:
                ajust_line = tax_line
        if ajust_line:
            amount = ajust_line.amount - delta
            ajust_line.write({'amount': amount})

            amount_tax = float_round(invoice.amount_tax - delta,
                                     precision_digits=prec)
            return {'amount_total': rounded_total, 'amount_tax': amount_tax}
        return {}