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
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
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)
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}
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 {}
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
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}
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))
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
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, }
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
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
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}
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}
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()
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
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_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)
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)
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)
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, })
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
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 _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)
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
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 }
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])], }
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
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)
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} )
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
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
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)
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
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'}
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
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
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)
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
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)
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
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)
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 }
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 {}