def _check_invoice_plan(self): if self.use_invoice_plan: obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') for order_line in self.order_line: subtotal = self.price_include and \ order_line.product_uom_qty * order_line.price_unit or \ order_line.price_subtotal invoice_lines = self.env['sale.invoice.plan'].search( [('order_line_id', '=', order_line.id)]) total_amount = 0.0 for line in invoice_lines: total_amount += line.invoice_amount # Validate percent if round(line.invoice_percent/100 * subtotal, prec) != \ round(line.invoice_amount, prec): raise except_orm( _('Invoice Plan Percent Mismatch!'), _("%s on installment %s") % (order_line.name, line.installment)) if round(total_amount, prec) != round(subtotal, prec): raise except_orm( _('Invoice Plan Amount Mismatch!'), _("%s, plan amount %d not equal to line amount %d!") % (order_line.name, total_amount, subtotal)) return True
def _onchange_deposit_amount(self): subtotal = (self.order_id.price_include and self.order_id.amount_total or self.order_id.amount_untaxed) new_val = subtotal and (self.deposit_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.deposit_percent, 6): self.deposit_percent = new_val
def _compute_price(self): # ORG: #price = self.price_unit * (1 - (self.discount or 0.0) / 100.0) #taxes = self.invoice_line_tax_id.compute_all(price, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id) #self.price_subtotal = taxes['total'] #if self.invoice_id: # self.price_subtotal = self.invoice_id.currency_id.round(self.price_subtotal) total = round(self.price_unit * self.quantity, 2) discount = round(total * (self.discount or 0.0) / 100.0, 2) st = total - discount #discount = round((self.discount or 0.0) / 100.0, 2) #price -= discount #taxes = self.invoice_line_tax_id.compute_all( # price, self.quantity, product=self.product_id, # partner=self.invoice_id.partner_id) taxes = self.invoice_line_tax_id.compute_all( st, 1.0, product=self.product_id, partner=self.invoice_id.partner_id) self.price_subtotal = taxes['total'] if self.invoice_id: self.price_subtotal = self.invoice_id.currency_id.round( self.price_subtotal)
def _check_invoice_plan(self): if self.use_invoice_plan: # kittiu: problem with decimal, so we dicide to test with 0 # obj_precision = self.env['decimal.precision'] # prec = obj_precision.precision_get('Account') prec = 0 # -- for order_line in self.order_line: subtotal = self.price_include and \ order_line.product_uom_qty * order_line.price_unit or \ order_line.price_subtotal invoice_lines = self.env['sale.invoice.plan'].search([ ('order_line_id', '=', order_line.id) ]) total_amount = 0.0 for line in invoice_lines: total_amount += line.invoice_amount # Validate percent if round(line.invoice_percent / 100 * subtotal, prec) != \ round(line.invoice_amount, prec): raise except_orm( _('Invoice Plan Percent Mismatch!'), _("%s on installment %s") % (order_line.name, line.installment)) if round(total_amount, prec) != round(subtotal, prec): raise except_orm( _('Invoice Plan Amount Mismatch!'), _("%s, plan amount %s not equal to line amount %s!") % (order_line.name, '{:,.2f}'.format(total_amount), '{:,.2f}'.format(subtotal))) return True
def calculate_installment(self): # Remove lines for rec in self: rec.installment_ids.unlink() # Compute for rec in self: rec.compute() # Fill Installment for rec in self: if not rec.rate_type or not rec.rate: continue num_line = len(rec.installment_ids) sum_amount = 0.0 i = 0 while i < num_line: line = rec.installment_ids[i] date_start = datetime.strptime(line.date_start, '%Y-%m-%d') date_end = datetime.strptime(line.date_end, '%Y-%m-%d') + \ relativedelta(days=1) days = (date_end - date_start).days r = relativedelta(date_end, date_start) if rec.rate_type == 'daily': line.amount = round(days * rec.rate, 2) if rec.rate_type == 'monthly': line.amount = \ round((r.years * 12 + r.months) * rec.rate, 2) if rec.rate_type == 'yearly': line.amount = round(r.years * rec.rate, 2) sum_amount += line.amount i += 1 if i == num_line: line.amount = \ (rec.amount_loan_total - sum_amount) + line.amount # Delete line with amount = 0.0 rec.installment_ids.filtered(lambda l: not l.amount).unlink() # Assign Installment Number i = 1 for line in rec.installment_ids.sorted(key=lambda l: l.date_start): line.installment = i i += 1 # Calculate default income for rec in self: total_income = rec.amount_income total_loan = rec.amount_loan_total i = 0 accum_income = 0.0 for line in rec.installment_ids: i += 1 if i == len(rec.installment_ids): # Last installment line.income = total_income - accum_income continue if not total_loan: line.income = 0.0 else: line.income = \ round((total_income / total_loan) * line.amount, 2) accum_income += line.income return
def _onchange_invoice_amount(self): subtotal = (self.order_id.price_include and (self.order_line_id.product_uom_qty * self.order_line_id.price_unit) or self.order_line_id.price_subtotal) new_val = subtotal and (self.invoice_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.invoice_percent, 6): self.invoice_percent = new_val
def _onchange_amount(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') if not self.order_amount: raise Warning(_('Order amount equal to 0.0!')) new_val = self.amount / self.order_amount * 100 if round(new_val, prec) != round(self.percent, prec): self.percent = new_val
def _validate_total_amount(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') amount_total = sum([x.installment > 0 and x.amount or 0.0 for x in self.installment_ids]) if round(amount_total, prec) != round(self.order_amount, prec): raise except_orm( _('Amount Mismatch!'), _("Total installment amount %d not equal to order amount %d!") % (amount_total, self.order_amount))
def do_create_invoice_plan(self): self._validate_total_amount() self.env['sale.invoice.plan']._validate_installment_date( self.installment_ids) order = self.env['sale.order'].browse(self._context['active_id']) order.invoice_plan_ids.unlink() lines = [] obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') if self.use_deposit: self._check_deposit_account() base_amount = (order.price_include and order.amount_total or order.amount_untaxed) lines.append({ 'order_id': order.id, 'order_line_id': False, 'installment': 0, 'date_invoice': self.installment_ids[0].date_invoice, 'deposit_percent': self.installment_ids[0].percent, 'deposit_amount': round(self.installment_ids[0].percent / 100 * base_amount, prec) }) for install in self.installment_ids: if install.installment > 0: for order_line in order.order_line: subtotal = order.price_include and \ (order_line.product_uom_qty * order_line.price_unit) or order_line.price_subtotal lines.append({ 'order_id': order.id, 'order_line_id': order_line.id, 'installment': install.installment, 'date_invoice': install.date_invoice, 'invoice_percent': install.percent, 'invoice_amount': round(install.percent / 100 * subtotal, prec), }) order.invoice_plan_ids = lines order.use_deposit = self.use_deposit order.invoice_mode = self.invoice_mode
def compute_interest(self, value, date_ref=False): if date_ref: date_ref = fields.Date.from_string(date_ref) else: date_ref = datetime.today().date() amount = value result = [] lines_total = 0.0 precision_model = self.env['decimal.precision'] # The computation of the amount for each term is the exact same # than the one in 'account_payment_term.compute()', this is # required to ensure that the interest fees are based on the # same amounts. This is why the 'account' precision is used: # this is the one used in 'account_payment_term.compute()'. prec = precision_model.precision_get('Account') for line in self.line_ids: if line.value == 'fixed': line_amount = round(line.value_amount, precision_digits=prec) elif line.value == 'procent': line_amount = round(value * line.value_amount, precision_digits=prec) elif line.value == 'balance': line_amount = round(amount, prec) if not line_amount: continue next_date = date_ref + relativedelta(days=line.days) if line.days2 < 0: # Getting 1st of next month next_first_date = next_date + relativedelta(day=1, months=1) next_date = (next_first_date + relativedelta(days=line.days2)) if line.days2 > 0: next_date += relativedelta(day=line.days2, months=1) interest = 0.0 if line.interest_rate: days = (next_date - date_ref).days rate = line.interest_rate / 100 / (12 * 30) # %/(months*days) interest = line_amount * rate * days result.append((fields.Date.to_string(next_date), line_amount, interest)) amount -= line_amount lines_total += line_amount dist = round(value - lines_total, precision_digits=prec) if dist: result.append((fields.Date.today(), dist, 0.0)) return result
def _get_pe_qrcode(self): res = [] for invoice_id in self: if invoice_id.internal_number and qr_mod: res.append( invoice_id.company_id.vat and invoice_id.company_id.vat[2:] or '') res.append(invoice_id.journal_id.sunat_payment_type or '') res.append(invoice_id.internal_number or '') precision = self.env['decimal.precision'].precision_get( 'Account') res.append( str( round( invoice_id.amount_tax * (invoice_id.discount and (1 - invoice_id.discount / 100) or 1), precision)) or '') res.append(str(invoice_id.amount_total)) res.append(invoice_id.date_invoice) if invoice_id.partner_id.doc_type and invoice_id.partner_id.doc_number: res.append(invoice_id.partner_id.doc_type) res.append(invoice_id.partner_id.doc_number) qr_string = '|'.join(res) qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_Q) qr.add_data(qr_string) qr.make(fit=True) qr_pic = qr.make_image() f = tempfile.TemporaryFile(mode="r+") qr_pic.save(f, 'png') f.seek(0) invoice_id.sunat_qr_code = base64.encodestring(f.read())
def adjust_price_sale_order_line(self, amount_price): self.ensure_one() order_line = self.order_plan_ids if order_line and self.sale_order_mode: if self.sale_order_mode == 'change_quantity': for line in self.order_line: new_quantity = amount_price / self.amount_untaxed \ if self.amount_price != 0 else amount_price line.write({ 'product_uom_qty': new_quantity, 'purchase_price': 0.0, }) elif self.sale_order_mode == 'change_price': lines = self.order_line[:-1] last_line = self.order_line[-1] line_amount = 0 for line in lines: new_price_unit = \ line.price_unit * line.product_uom_qty * \ round((amount_price / self.amount_untaxed), 2) line_amount += new_price_unit line.write({ 'price_unit': new_price_unit, 'purchase_price': 0.0, 'product_uom_qty': 1, }) last_price_unit = amount_price - line_amount last_line.write({ 'price_unit': last_price_unit, 'purchase_price': 0.0, 'product_uom_qty': 1, }) self._amount_all()
def _onchange_deposit_percent(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = (self.order_id.price_include and self.order_id.amount_total or self.order_id.amount_untaxed) self.deposit_amount = round( subtotal and self.deposit_percent / 100 * subtotal or 0.0, prec)
def _check_pack_error_q_x_pack(self, cr, uid, ids, fields, args, context=None): ''' Fields function for calculate ''' res = {} for sol in self.browse(cr, uid, ids, context=context): product = sol.product_id q_x_pack = product.q_x_pack res[sol.id] = { 'error_pack': False, 'product_q_x_pack': q_x_pack, } if not product: continue product_uom_qty = sol.product_uom_qty if round(product_uom_qty, 0) != product_uom_qty or not q_x_pack: continue if product_uom_qty % q_x_pack != 0: res[sol.id]['error_pack'] = True # no correct split return res
def set_force_value(self, cr, uid, ids, context=None): ''' ''' assert len(ids) == 1, 'Force once order a time!' order_proxy = self.browse(cr, uid, ids, context=context)[0] force_value = order_proxy.force_value or 0.0 # default 100% # pool used: sol_pool = self.pool.get('sale.order.line') # Search line used: sol_ids = sol_pool.search(cr, uid, [ ('order_id', '=', ids[0]), ], context=context) # Update line quantity: sol_update = {} for line in sol_pool.browse(cr, uid, sol_ids, context=context): sol_update[line.id] = round( line.product_uom_qty * force_value / 100.0, 0) for item_id in sol_update: # upate context to force CL (SL?) sol_pool.write(cr, uid, [item_id], { 'product_uom_force_qty': sol_update[item_id], }, context=context) self.write(cr, uid, ids, { 'force_value': False}, context=context) return True
def _onchange_deposit_percent(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = (self.order_id.price_include and self.order_id.amount_total or self.order_id.amount_untaxed) self.deposit_amount = round(subtotal and self.deposit_percent/100 * subtotal or 0.0, prec)
def _get_price(self, cr, uid, inv, company_currency, i_line, price_unit): cur_obj = self.pool.get('res.currency') decimal_precision = self.pool.get('decimal.precision') if inv.currency_id.id != company_currency: price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={'date': inv.date_invoice}) else: price = price_unit * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, 'Account'))
def _compute_installment_details(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') if self.installment_ids: installment_date =\ datetime.strptime(self.installment_date, "%Y-%m-%d") count = 0 remaning_installment_amount = self.order_amount last_line = False for i in self.installment_ids: if i.is_advance_installment or i.is_deposit_installment: i.date_invoice = self.installment_date continue interval = self.interval if count == 0: interval = 0 if self.interval_type == 'month': installment_date =\ installment_date + relativedelta(months=+interval) elif self.interval_type == 'year': installment_date =\ installment_date + relativedelta(years=+interval) else: installment_date =\ installment_date + relativedelta(days=+interval) count += 1 i.date_invoice = installment_date if remaning_installment_amount > self.installment_amount: i.amount = self.installment_amount elif remaning_installment_amount < 0: i.amount = 0 else: i.amount = remaning_installment_amount remaning_installment_amount = (remaning_installment_amount - self.installment_amount) new_val = i.amount / self.order_amount * 100 if round(new_val, prec) != round(i.percent, prec): i.percent = new_val last_line = i if last_line and remaning_installment_amount > 0: last_line.amount = (last_line.amount + remaning_installment_amount) new_val = last_line.amount / self.order_amount * 100 if round(new_val, prec) != round(last_line.percent, prec): last_line.percent = new_val
def _onchange_invoice_percent(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = (self.order_id.price_include and (self.order_line_id.product_uom_qty * self.order_line_id.price_unit) or self.order_line_id.price_subtotal) self.invoice_amount = round( subtotal and self.invoice_percent / 100 * subtotal or 0.0, prec)
def _onchange_invoice_percent(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = (self.order_id.price_include and (self.order_line_id.product_uom_qty * self.order_line_id.price_unit) or self.order_line_id.price_subtotal) self.invoice_amount = round(subtotal and self.invoice_percent/100 * subtotal or 0.0, prec)
def do_create_invoice_plan(self): self._validate_total_amount() self.env['sale.invoice.plan']._validate_installment_date( self.installment_ids) order = self.env['sale.order'].browse(self._context['active_id']) order.invoice_plan_ids.unlink() lines = [] obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') if self.use_deposit: self._check_deposit_account() base_amount = (order.price_include and order.amount_total or order.amount_untaxed) lines.append({ 'order_id': order.id, 'order_line_id': False, 'installment': 0, 'date_invoice': self.installment_ids[0].date_invoice, 'deposit_percent': self.installment_ids[0].percent, 'deposit_amount': round(self.installment_ids[0].percent/100 * base_amount, prec) }) for install in self.installment_ids: if install.installment > 0: for order_line in order.order_line: subtotal = order.price_include and \ (order_line.product_uom_qty * order_line.price_unit) or order_line.price_subtotal lines.append({ 'order_id': order.id, 'order_line_id': order_line.id, 'installment': install.installment, 'date_invoice': install.date_invoice, 'invoice_percent': install.percent, 'invoice_amount': round(install.percent/100 * subtotal, prec), }) order.invoice_plan_ids = lines order.use_deposit = self.use_deposit order.invoice_mode = self.invoice_mode
def _fnt_contratos(self, cr, uid, ids, field_name, arg, context=None): cur_obj = self.pool.get('res.currency') res = {} for project in self.browse(cr, uid, ids, context=context): #print 'order', order.poreserva res[project.id] = { 'costos': 0.00, 'utilidad_costos': 0.00, 'utilidad_ingresos': 0.00, } val = val1 = 0.00 for line in project.project_budget_ids: val1 += line.presupuesto_aprobado res[project.id]['costos'] = val1 if project.valor_contrato: res[project.id]['utilidad_costos'] = round((project.valor_contrato - val1)/ val1,2)*100 res[project.id]['utilidad_ingresos'] = round((project.valor_contrato - val1)/ project.valor_contrato,2)*100 return res
def test_interest_lines(self): total_amount = remaining_amount = 469.35 terms = self.term.compute_interest(remaining_amount, date_ref='2015-03-13') self.assertEquals(len(terms), 3) terms = sorted(terms, key=itemgetter(0)) line1, line2, line3 = terms precision = self.precision term_amount = total_amount * 0.3333 # Odoo rounds the remaining amount between each term remaining_amount -= round(term_amount, precision_digits=precision) self.assertAlmostEqual(line1[1], term_amount, places=precision) self.assertAlmostEqual(line1[2], 0.0, places=precision) remaining_amount -= round(term_amount, precision_digits=precision) self.assertAlmostEqual(line2[1], term_amount, places=precision) self.assertAlmostEqual( line2[2], (term_amount * # due amount (15 / 100 / # annual interest rate (12 * 30) # (months / days) get a daily rate ) * 40 # multiply by the number of term days ), places=precision) self.assertAlmostEqual(line3[1], remaining_amount, places=precision) self.assertAlmostEqual( line3[2], (remaining_amount * # due amount (15 / 100 / # annual interest rate (12 * 30) # (months / days) get a daily rate ) * 70 # multiply by the number of term days ), places=precision)
def test_interest_lines(self): total_amount = remaining_amount = 469.35 terms = self.term.compute_interest(remaining_amount, date_ref='2015-03-13') self.assertEquals(len(terms), 3) terms = sorted(terms, key=itemgetter(0)) line1, line2, line3 = terms precision = self.precision term_amount = total_amount * 0.3333 # Odoo rounds the remaining amount between each term remaining_amount -= round(term_amount, precision_digits=precision) self.assertAlmostEqual(line1[1], term_amount, places=precision) self.assertAlmostEqual(line1[2], 0.0, places=precision) remaining_amount -= round(term_amount, precision_digits=precision) self.assertAlmostEqual(line2[1], term_amount, places=precision) self.assertAlmostEqual( line2[2], ( term_amount * # due amount ( 15 / 100 / # annual interest rate (12 * 30) # (months / days) get a daily rate ) * 40 # multiply by the number of term days ), places=precision) self.assertAlmostEqual(line3[1], remaining_amount, places=precision) self.assertAlmostEqual( line3[2], ( remaining_amount * # due amount ( 15 / 100 / # annual interest rate (12 * 30) # (months / days) get a daily rate ) * 70 # multiply by the number of term days ), places=precision)
def compute(self, cr, uid, id, value, date_ref=False, context=None): if not date_ref: date_ref = datetime.now().strftime('%Y-%m-%d') pt = self.browse(cr, uid, id, context=context) amount = value result = [] obj_precision = self.pool.get('decimal.precision') prec = obj_precision.precision_get(cr, uid, 'Account') for line in pt.line_ids: if line.value == 'fixed': amt = round(line.value_amount, prec) elif line.value == 'procent': amt = round(value * line.value_amount, prec) elif line.value == 'balance': amt = round(amount, prec) if amt: next_date = (datetime.strptime(date_ref, '%Y-%m-%d') + relativedelta(days=line.days)) if line.days2 < 0: next_first_date = next_date + relativedelta( day=1, months=1) #Getting 1st of next month next_date = next_first_date + relativedelta( days=line.days2) if line.days2 > 0: next_date_computed = next_date + relativedelta( day=line.days2, months=0) if next_date_computed < next_date: next_date += relativedelta(day=line.days2, months=1) else: next_date = next_date_computed result.append((next_date.strftime('%Y-%m-%d'), amt)) amount -= amt amount = reduce(lambda x, y: x + y[1], result, 0.0) dist = round(value - amount, prec) if dist: result.append((time.strftime('%Y-%m-%d'), dist)) return result
def _prepare_installment_line(self, order, order_line, install): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = order_line.price_subtotal data = { 'order_id': order.id, 'order_line_id': order_line.id, 'description': order_line.name, 'installment': install.installment, 'date_invoice': install.date_invoice, 'invoice_percent': install.percent, 'invoice_amount': round(install.percent / 100 * subtotal, prec), } return data
def _compute_amount(self): if not self.price_per or not self.price: self.amount = self.startup_costs return if self.price_per == 'total': self.amount = self.price + self.startup_costs return qty = self.env['s2u.baseproduct.abstract'].parse_qty(self.qty) if not qty: self.amount = 0.0 return if self.price_per == 'item': self.amount = round(qty * self.price, 2) + self.startup_costs return if self.price_per in ['10', '100', '1000']: qty = qty / float(self.price_per) self.amount = round(qty * self.price, 2) + self.startup_costs return
def get_price(cr, uid, inv, company_currency, i_line, price_unit): cur_obj = self.pool.get("res.currency") decimal_precision = self.pool.get("decimal.precision") if inv.currency_id.id != company_currency: price = cur_obj.compute( cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={"date": inv.date_invoice}, ) else: price = price_unit * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, "Account"))
def _prepare_installment_line(self, order, order_line, install): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') subtotal = order_line.price_subtotal data = { 'order_id': order.id, 'order_line_id': order_line.id, 'description': order_line.name, 'installment': install.installment, 'date_invoice': install.date_invoice, 'invoice_percent': install.percent, 'invoice_amount': round(install.percent/100 * subtotal, prec), } return data
def _prepare_advance_deposit_line(self, order, install, advance, deposit): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') base_amount = order.amount_untaxed data = { 'order_id': order.id, 'order_line_id': False, 'installment': 0, 'description': install.description, 'is_advance_installment': advance, 'is_deposit_installment': deposit, 'date_invoice': install.date_invoice, 'deposit_percent': install.percent, 'deposit_amount': round(install.percent / 100 * base_amount, prec) } return data
def _prepare_advance_deposit_line(self, order, install, advance, deposit): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') base_amount = order.amount_untaxed data = { 'order_id': order.id, 'order_line_id': False, 'installment': 0, 'description': install.description, 'is_advance_installment': advance, 'is_deposit_installment': deposit, 'date_invoice': install.date_invoice, 'deposit_percent': install.percent, 'deposit_amount': round(install.percent/100 * base_amount, prec) } return data
def round_interger_order(self, number, approx=1, mode='over'): """ Approx function for order quantity: Approx number to value approx (integer > 1) Mode = 'normal' (nothing is done) 'over' (to the next approx level exceeded) 'under' (to the next approx level exceeded) """ if approx <= 1: return number if mode == 'over': extra = (approx if number % approx > 0.001 else 0) return (number // approx) * approx + extra elif mode == 'under': return (number // approx) * approx elif mode == 'normal': return round(number / approx, 0) * approx else: return number
def _onchange_invoice_amount(self): subtotal = self.order_line_id.price_subtotal new_val = subtotal and (self.invoice_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.invoice_percent, 6): self.invoice_percent = new_val
def _compute_interest(self): precision = self.env['decimal.precision'].precision_get('Account') self.amount_interest = round( self.amount_currency * (self.percent_interest / 100), precision)
def _onchange_percent(self): obj_precision = self.env['decimal.precision'] prec = obj_precision.precision_get('Account') self.amount = round(self.order_amount * self.percent / 100, prec)
def _onchange_deposit_percent(self): obj_precision = self.env["decimal.precision"] prec = obj_precision.precision_get("Account") subtotal = self.order_id.amount_untaxed self.deposit_amount = round(subtotal and self.deposit_percent / 100 * subtotal or 0.0, prec)
def check_almost_ready_order(self, cr, uid, context=None): ''' Check if order is almost ready to delivery (procuced or delivered) ''' # --------------------------------------------------------------------- # Utility: # --------------------------------------------------------------------- def get_yet_used(): ''' Read store file ''' filename = os.path.expanduser(self._pickle_order_line) try: f = open(filename, 'rb') res = pickle.load(f) f.close() return res except: return [] def set_yet_used(yet_used): ''' Save store file ''' filename = os.path.expanduser(self._pickle_order_line) f = open(filename, 'wb') pickle.dump(yet_used, f) f.close() return True def write_xls_mrp_line(WS, row, line): ''' Write line in excel file ''' col = 0 for record in line: if len(record) == 2: # Normal text, format WS.write(row, col, *record) else: # Rich format WS.write_rich_string(row, col, *record) col += 1 return True # --------------------------------------------------------------------- # Start prepare XLS file: # --------------------------------------------------------------------- error_range = 0.01 num_format = '0.#0' #num_format_0 = '0.#0' filename = '/tmp/check_discount_rate.xlsx' _logger.info('Start create file %s' % filename) WB = xlsxwriter.Workbook(filename) WS = WB.add_worksheet('Sconti') WS1 = WB.add_worksheet('Segnalati in precedenza') # Format columns width: WS.set_column('A:A', 15) WS.set_column('B:B', 30) WS.set_column('C:C', 20) WS.set_column('D:G', 10) WS1.set_column('A:A', 15) WS1.set_column('B:B', 30) WS1.set_column('C:C', 20) WS1.set_column('D:G', 10) xls_format_db = { 'header': WB.add_format({ 'bold': True, 'font_color': 'black', 'font_name': 'Courier 10 pitch', # 'Arial' 'font_size': 9, 'align': 'center', 'valign': 'vcenter', 'bg_color': '#cfcfcf', # gray 'border': 1, }), 'text': WB.add_format({ 'font_color': 'black', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'left', 'border': 1, }), 'number': WB.add_format({ 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), # ------------------------------------------------------------- # With text color: # ------------------------------------------------------------- 'heat1': WB.add_format({ 'font_color': 'black', 'bg_color': '#ec4e4e', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), 'heat2': WB.add_format({ 'font_color': 'black', 'bg_color': '#f69999', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), 'heat3': WB.add_format({ 'font_color': 'black', 'bg_color': '#f1bcbc', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), 'heat4': WB.add_format({ 'font_color': 'black', 'bg_color': '#f3dfdf', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), 'heat5': WB.add_format({ 'font_color': 'black', 'font_name': 'Courier 10 pitch', 'font_size': 9, 'align': 'right', 'border': 1, 'num_format': num_format, }), } # --------------------------------------------------------------------- # Search data order line: # --------------------------------------------------------------------- line_pool = self.pool.get('sale.order.line') # Generate domain: domain = [ ('order_id.state', 'not in', ('draft', 'cancel', 'sent')), ('order_id.mx_closed', '=', False), ('mx_closed', '=', False), ] if 'pricelist_order' in self._columns: domain.append(('order_id.pricelist_order', '=', False)) if 'forecasted_production_id' in self._columns: domain.append(('order_id.forecasted_production_id', '=', False)) _logger.info('Domain: %s' % (domain, )) line_ids = line_pool.search(cr, uid, domain, context=None) # Write header: header = [ ('Ordine', xls_format_db['header']), ('Partner', xls_format_db['header']), ('Prodotto', xls_format_db['header']), ('Netto vend.', xls_format_db['header']), ('Netto part.', xls_format_db['header']), ('% Delta', xls_format_db['header']), ('Delta', xls_format_db['header']), ] write_xls_mrp_line(WS, 0, header) write_xls_mrp_line(WS1, 0, header) yet_used = get_yet_used() or [] _logger.info('Pickle previous list: %s' % len(yet_used)) over_ids = [] row = 0 row1 = 0 for line in line_pool.browse( cr, uid, line_ids, context=context): partner_discount_rate = line.order_id.partner_id.discount_value total = line.product_uom_qty * line.price_unit net_partner = round( total * (100.0 - partner_discount_rate) / 100.0, 3) net_sale = round(line.price_subtotal, 3) delta = round(net_partner - net_sale, 3) if total: delta_rate = 100.0 * ( (total - net_sale) / total) - partner_discount_rate else: delta_rata = 'ERR' if delta <= error_range: # sale < partner continue if line.id in yet_used: WS_use = WS1 row1 += 1 position = row1 else: WS_use = WS row += 1 position = row over_ids.append(line.id) if delta >= 200: format_heat = xls_format_db['heat1'] elif delta >= 50: format_heat = xls_format_db['heat2'] elif delta >= 20: format_heat = xls_format_db['heat3'] elif delta >= 10: format_heat = xls_format_db['heat4'] else: format_heat = xls_format_db['heat5'] data = [ (line.order_id.name, xls_format_db['text']), (line.order_id.partner_id.name, xls_format_db['text']), (line.product_id.default_code or '', xls_format_db['text']), (partner_discount_rate, xls_format_db['number']), (line.product_uom_qty or '', xls_format_db['number']), (net_sale, xls_format_db['number']), (net_partner, xls_format_db['number']), (delta_rate, xls_format_db['number']), (delta, format_heat), ] write_xls_mrp_line(WS_use, position, data) # Write pickle for current selection: set_yet_used(over_ids) _logger.info('Save pickle list: %s' % len(over_ids)) WB.close() # --------------------------------------------------------------------- # Send mail to group: # --------------------------------------------------------------------- xlsx_raw = open(filename, 'rb').read() #b64 = xlsx_raw.encode('base64') attachments = [('Extra_sconti.xlsx', xlsx_raw)] _logger.info('Sending status via mail: %s' % filename) # Send mail with attachment: group_pool = self.pool.get('res.groups') model_pool = self.pool.get('ir.model.data') thread_pool = self.pool.get('mail.thread') server_pool = self.pool.get('ir.mail_server') group_id = model_pool.get_object_reference( cr, uid, 'sale_order_over_discount_check', 'group_over_discount_mail')[1] partner_ids = [] for user in group_pool.browse( cr, uid, group_id, context=context).users: partner_ids.append(user.partner_id.id) if row: # there's record in first sheet: _logger.info('Mail: there are records in sheet 1') subject = 'Invio automatico stato extra sconto: %s' % ( datetime.now().strftime(DEFAULT_SERVER_DATE_FORMAT), ) else: _logger.info('No mail: empty sheet 1') subject = 'NESSUNA VARIAZIONE EXTRA SCONTO: %s' % ( datetime.now().strftime(DEFAULT_SERVER_DATE_FORMAT), ) thread_pool = self.pool.get('mail.thread') thread_pool.message_post(cr, uid, False, type='email', body=_('Notifica extra sconti ordini attivi'), subject=subject, partner_ids=[(6, 0, partner_ids)], attachments=attachments, context=context, ) return True
def _anglo_saxon_purchase_move_lines(self, cr, uid, i_line, res, context=None): """Return the additional move lines for purchase invoices and refunds. i_line: An account.invoice.line object. res: The move line entries produced so far by the parent move_line_get. """ inv = i_line.invoice_id company_currency = inv.company_id.currency_id.id if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get(cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: #for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get('stock.move') valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit if inv.currency_id.id != company_currency: valuation_price_unit = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={'date': inv.date_invoice}) if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: # price with discount and without tax included price_unit = self.pool['account.tax'].compute_all(cr, uid, line['taxes'], i_line.price_unit * (1-(i_line.discount or 0.0)/100.0), line['quantity'])['total'] price_line = round(valuation_price_unit * line['quantity'], account_prec) price_diff = round(price_unit - price_line, account_prec) line.update({'price': price_line}) diff_res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': round(price_diff / line['quantity'], account_prec), 'quantity': line['quantity'], 'price': price_diff, 'account_id': acc, 'product_id': line['product_id'], 'uos_id': line['uos_id'], 'account_analytic_id': line['account_analytic_id'], 'taxes': line.get('taxes', []), }) return diff_res return []
def move_line_get(self, cr, uid, invoice_id, context=None): res = super(account_invoice_line, self).move_line_get(cr, uid, invoice_id, context=context) inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context) company_currency = inv.company_id.currency_id.id def get_price(cr, uid, inv, company_currency, i_line, price_unit): cur_obj = self.pool.get('res.currency') decimal_precision = self.pool.get('decimal.precision') if inv.currency_id.id != company_currency: price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={'date': inv.date_invoice}) else: price = price_unit * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, 'Account')) if inv.type in ('out_invoice', 'out_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': # debit account dacc will be the output account # first check the product, if empty check the category dacc = i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id if not dacc: dacc = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id # in both cases the credit account cacc will be the expense account # first check the product, if empty check the category cacc = i_line.product_id.property_account_expense and i_line.product_id.property_account_expense.id if not cacc: cacc = i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id if dacc and cacc: price_unit = i_line.move_id and i_line.move_id.price_unit or i_line.product_id.standard_price res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': price_unit, 'quantity': i_line.quantity, 'price': get_price(cr, uid, inv, company_currency, i_line, price_unit), 'account_id': dacc, 'product_id': i_line.product_id.id, 'uos_id': i_line.uos_id.id, 'account_analytic_id': False, 'taxes': i_line.invoice_line_tax_id, }) res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': price_unit, 'quantity': i_line.quantity, 'price': -1 * get_price(cr, uid, inv, company_currency, i_line, price_unit), 'account_id': cacc, 'product_id': i_line.product_id.id, 'uos_id': i_line.uos_id.id, 'account_analytic_id': False, 'taxes': i_line.invoice_line_tax_id, }) elif inv.type in ('in_invoice', 'in_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get( 'account.fiscal.position').map_account( cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get( cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get( 'invl_id', 0 ) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get( 'product.uom')._compute_price( cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: #for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get( 'stock.move') valuation_stock_move = stock_move_obj.search( cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse( cr, uid, valuation_stock_move[0], context=context).price_unit if inv.currency_id.id != company_currency: valuation_price_unit = self.pool.get( 'res.currency').compute( cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={'date': inv.date_invoice}) if valuation_price_unit != i_line.price_unit and line[ 'price_unit'] == i_line.price_unit and acc: price_diff = round( i_line.price_unit - valuation_price_unit, account_prec) line.update({ 'price': round( valuation_price_unit * line['quantity'], account_prec) }) diff_res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': price_diff, 'quantity': line['quantity'], 'price': round(price_diff * line['quantity'], account_prec), 'account_id': acc, 'product_id': line['product_id'], 'uos_id': line['uos_id'], 'account_analytic_id': line['account_analytic_id'], 'taxes': line.get('taxes', []), }) res += diff_res return res
class res_company(osv.osv): _inherit = "res.company" def _smart_cash(self, cr, uid, ids, name, args, context=None): res = {} for company in self.browse(cr, uid, ids, context=context): res[company.id] = { #SMarts Share The Percentage SMart keeps on the invoice. #SMart Order sum cash Sum of Orders in State 'progress','manual','done', line 75 #SMart Amount cash SMarts share of the order (in money) for Orders in State progress','manual','done', line 82 #SMart activity amount cash 4768.50 #SMart expense sum cash 0.00 #SMart Cash 4769.00 #SMart Order sum budget 5100.00 #SMart Amount budget 331.50 #SMart activity amount budget 4768.50 #SMart expense sum budget -1225.00 #SMart Budget 3544.00 'smart_cash': 0.0, 'smart_budget': 0.0, 'sale_order_sum_cash': 0.0, 'sale_order_sum_budget': 0.0, 'expense_sum_cash': 0.0, 'expense_sum_budget': 0.0, 'smart_amount': 0.0, 'activity_amount_cash': 0.0, 'activity_amount_budget': 0.0, # 'smart_cash_date': invoice.date_due or date.today().isoformat(), # 'smart_cash_date': date(*time.strptime(invoice.date_invoice,'%Y-%m-%d')[:3]) + timedelta(days=invoice.company_id.parent_id.prepayment_days) } # res[company.id]['smart_cash'] = 0.0 # for move in self.pool.get('account.move').browse(cr, uid, self.pool.get('account.move').search(cr,uid,[('company_id','=',company.id)],context=context), context=context): # for move in self.pool.get('account.move').browse(cr, uid, self.pool.get('account.move').search(cr,uid,[],context=context), context=context): # res[company.id]['smart_cash'] =+ move.smart_cash # res[company.id]['smart_budget'] =+ move.smart_budget #SMart Order Cash for order in self.pool.get('sale.order').browse( cr, uid, self.pool.get('sale.order').search( cr, uid, [ '&', ('company_id', '=', company.id), ('state', 'in', ('progress', 'manual', 'done')) ], context=context), context=context): # for order in company.order_cash(): # res[company.id]['smart_cash'] = res[company.id]['smart_cash'] + order.amount_total res[company.id]['smart_cash'] = res[ company.id]['smart_cash'] + order.amount_untaxed res[company.id]['sale_order_sum_cash'] += order.amount_untaxed res[company.id]['activity_amount_cash'] = res[company.id][ 'sale_order_sum_cash'] * (1 - (company.smart_share / 100)) res[company.id]['smart_amount_cash'] = res[ company.id]['sale_order_sum_cash'] * (company.smart_share / 100) #SMart Order Budget for order in self.pool.get('sale.order').browse( cr, uid, self.pool.get('sale.order').search( cr, uid, [ '&', ('company_id', '=', company.id), ('state', 'in', ('waiting_date', 'progress', 'manual', 'done')) ], context=context), context=context): # for order in company.order_budget(): # res[company.id]['smart_budget'] = res[company.id]['smart_budget'] + order.amount_total res[company.id]['smart_budget'] = res[ company.id]['smart_budget'] + order.amount_untaxed res[company. id]['sale_order_sum_budget'] += order.amount_untaxed res[company.id]['smart_amount_budget'] = res[ company.id]['sale_order_sum_budget'] * (company.smart_share / 100) res[company.id]['activity_amount_budget'] = res[company.id][ 'sale_order_sum_budget'] * (1 - (company.smart_share / 100)) #('draft', 'Draft Quotation'), = not counted #('sent', 'Quotation Sent'), = not counted #('cancel', 'Cancelled'), = not counted #('waiting_date', 'Waiting Schedule'), = counted in budget #('progress', 'Sales Order'), = counted in budget + cash #('manual', 'Sale to Invoice'), = counted in budget + cash #('shipping_except', 'Shipping Exception'), = counted in budget + cash #('invoice_except', 'Invoice Exception'), = counted in budget + cash #('done', 'Done'), = counted in budget + cash #SMart Expense Cash for expense in self.pool.get('hr.expense.expense').browse( cr, uid, self.pool.get('hr.expense.expense').search( cr, uid, [ '&', ('company_id', '=', company.id), ('state', 'in', ('done', 'paid')) ], context=context), context=context): _logger.warning("This is my expense.amount_untaxed next line") try: _logger.warning( "This is my expense.amount_untaxed %s (cash)" % (expense.amount_untaxed)) res[company.id]['smart_cash'] -= float( expense.amount_untaxed or 0.0) res[company.id]['expense_sum_cash'] -= float( expense.amount_untaxed or 0.0) except Exception, e: _logger.warning( "There are no expense.amount_untaxed %s (cash) %s" % (expense.id, e)) res[company.id]['smart_cash'] -= 666 res[company.id]['expense_sum_cash'] -= 666 #SMart Expense Budget for expense in self.pool.get('hr.expense.expense').browse( cr, uid, self.pool.get('hr.expense.expense').search( cr, uid, [ '&', ('company_id', '=', company.id), ('state', 'in', ('accepted', 'confirm', 'done', 'paid')) ], context=context), context=context): try: _logger.warning( "This is my expense.amount_untaxed %s (budget)" % (expense.amount_untaxed)) res[company.id]['smart_budget'] -= float( expense.amount_untaxed or 0.0) res[company.id]['expense_sum_budget'] -= float( expense.amount_untaxed or 0.0) except Exception, e: _logger.warning( "There are no expense.amount_untaxed %s (budget) %s" % (expense.id, e)) res[company.id]['smart_budget'] -= 666 res[company.id]['expense_sum_budget'] -= 666 # ('draft', 'New'), = not deducted in budget + cash # ('cancelled', 'Refused'), = not deducted in budget + cash # ('confirm', 'Waiting Approval'), = deducted in budget # ('accepted', 'Approved'), = deducted in budget # ('done', 'Waiting Payment'), = deducted in budget # ('paid', 'Paid'), = deducted in budget + cash #Totals res[company.id]['smart_cash'] = round( res[company.id]['smart_cash'] - res[company.id]['smart_amount_cash'], 0) res[company.id]['smart_budget'] = round( res[company.id]['smart_budget'] - res[company.id]['smart_amount_budget'], 0)
def round_base(x, base=5): from openerp.tools.float_utils import float_round as round return round(x, base)
def move_line_get(self, cr, uid, invoice_id, context=None): res = super(account_invoice_line,self).move_line_get(cr, uid, invoice_id, context=context) inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context) company_currency = inv.company_id.currency_id.id def get_price(cr, uid, inv, company_currency,i_line): cur_obj = self.pool.get('res.currency') decimal_precision = self.pool.get('decimal.precision') if inv.currency_id.id != company_currency: price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, i_line.product_id.standard_price * i_line.quantity, context={'date': inv.date_invoice}) else: price = i_line.product_id.standard_price * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, 'Account')) if inv.type in ('out_invoice','out_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': if inv.type == 'out_invoice': # debit account dacc will be the output account # first check the product, if empty check the category dacc = i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id if not dacc: dacc = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id else: # = out_refund # debit account dacc will be the input account # first check the product, if empty check the category dacc = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not dacc: dacc = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id # in both cases the credit account cacc will be the expense account # first check the product, if empty check the category cacc = i_line.product_id.property_account_expense and i_line.product_id.property_account_expense.id if not cacc: cacc = i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id if dacc and cacc: res.append({ 'type':'src', 'name': i_line.name[:64], 'price_unit':i_line.product_id.standard_price, 'quantity':i_line.quantity, 'price':get_price(cr, uid, inv, company_currency, i_line), 'account_id':dacc, 'product_id':i_line.product_id.id, 'uos_id':i_line.uos_id.id, 'account_analytic_id': False, 'taxes':i_line.invoice_line_tax_id, }) res.append({ 'type':'src', 'name': i_line.name[:64], 'price_unit':i_line.product_id.standard_price, 'quantity':i_line.quantity, 'price': -1 * get_price(cr, uid, inv, company_currency, i_line), 'account_id':cacc, 'product_id':i_line.product_id.id, 'uos_id':i_line.uos_id.id, 'account_analytic_id': False, 'taxes':i_line.invoice_line_tax_id, }) elif inv.type in ('in_invoice','in_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None if inv.type == 'in_invoice': # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id else: # = in_refund # oa will be the stock output account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get(cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id standard_price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if inv.currency_id.id != company_currency: standard_price = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, standard_price, context={'date': inv.date_invoice}) if standard_price != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: price_diff = round(i_line.price_unit - standard_price, account_prec) line.update({'price': round(standard_price * line['quantity'], account_prec)}) diff_res.append({ 'type':'src', 'name': i_line.name[:64], 'price_unit':price_diff, 'quantity':line['quantity'], 'price': round(price_diff * line['quantity'], account_prec), 'account_id':acc, 'product_id':line['product_id'], 'uos_id':line['uos_id'], 'account_analytic_id':line['account_analytic_id'], 'taxes':line.get('taxes',[]), }) res += diff_res return res
def move_line_get(self, cr, uid, invoice_id, context=None): res = super(account_invoice_line, self).move_line_get(cr, uid, invoice_id, context=context) inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context) company_currency = inv.company_id.currency_id.id def get_price(cr, uid, inv, company_currency, i_line): cur_obj = self.pool.get('res.currency') decimal_precision = self.pool.get('decimal.precision') if inv.currency_id.id != company_currency: price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, i_line.product_id.standard_price * i_line.quantity, context={'date': inv.date_invoice}) else: price = i_line.product_id.standard_price * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, 'Account')) if inv.type in ('out_invoice', 'out_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': # debit account dacc will be the output account # first check the product, if empty check the category dacc = i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id if not dacc: dacc = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id # in both cases the credit account cacc will be the expense account # first check the product, if empty check the category cacc = i_line.product_id.property_account_expense and i_line.product_id.property_account_expense.id if not cacc: cacc = i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id if dacc and cacc: res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': i_line.product_id.standard_price, 'quantity': i_line.quantity, 'price': get_price(cr, uid, inv, company_currency, i_line), 'account_id': dacc, 'product_id': i_line.product_id.id, 'uos_id': i_line.uos_id.id, 'account_analytic_id': False, 'taxes': i_line.invoice_line_tax_id, }) res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': i_line.product_id.standard_price, 'quantity': i_line.quantity, 'price': -1 * get_price(cr, uid, inv, company_currency, i_line), 'account_id': cacc, 'product_id': i_line.product_id.id, 'uos_id': i_line.uos_id.id, 'account_analytic_id': False, 'taxes': i_line.invoice_line_tax_id, }) elif inv.type in ('in_invoice', 'in_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get( 'account.fiscal.position').map_account( cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get( cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get( 'invl_id', 0 ) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id standard_price = self.pool.get( 'product.uom')._compute_price( cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if inv.currency_id.id != company_currency: standard_price = self.pool.get( 'res.currency').compute( cr, uid, company_currency, inv.currency_id.id, standard_price, context={'date': inv.date_invoice}) if standard_price != i_line.price_unit and line[ 'price_unit'] == i_line.price_unit and acc: # price with discount and without tax included price_unit = self.pool[ 'account.tax'].compute_all( cr, uid, line['taxes'], i_line.price_unit * (1 - (i_line.discount or 0.0) / 100.0), line['quantity'])['total'] price_line = round( standard_price * line['quantity'], account_prec) price_diff = round(price_unit - price_line, account_prec) line.update({'price': price_line}) diff_res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': round(price_diff / line['quantity'], account_prec), 'quantity': line['quantity'], 'price': price_diff, 'account_id': acc, 'product_id': line['product_id'], 'uos_id': line['uos_id'], 'account_analytic_id': line['account_analytic_id'], 'taxes': line.get('taxes', []), }) res += diff_res return res
def move_line_get(self, cr, uid, invoice_id, context=None): res = super(account_invoice_line,self).move_line_get(cr, uid, invoice_id, context=context) inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context) company_currency = inv.company_id.currency_id.id def get_price(cr, uid, inv, company_currency, i_line, price_unit): cur_obj = self.pool.get('res.currency') decimal_precision = self.pool.get('decimal.precision') if inv.currency_id.id != company_currency: price = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={'date': inv.date_invoice}) else: price = price_unit * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, 'Account')) if inv.type in ('out_invoice','out_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': # debit account dacc will be the output account # first check the product, if empty check the category dacc = i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id if not dacc: dacc = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id # in both cases the credit account cacc will be the expense account # first check the product, if empty check the category cacc = i_line.product_id.property_account_expense and i_line.product_id.property_account_expense.id if not cacc: cacc = i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id if dacc and cacc: price_unit = i_line.move_id and i_line.move_id.price_unit or i_line.product_id.standard_price res.append({ 'type':'src', 'name': i_line.name[:64], 'price_unit':price_unit, 'quantity':i_line.quantity, 'price':get_price(cr, uid, inv, company_currency, i_line, price_unit), 'account_id':dacc, 'product_id':i_line.product_id.id, 'uos_id':i_line.uos_id.id, 'account_analytic_id': False, 'taxes':i_line.invoice_line_tax_id, }) res.append({ 'type':'src', 'name': i_line.name[:64], 'price_unit':price_unit, 'quantity':i_line.quantity, 'price': -1 * get_price(cr, uid, inv, company_currency, i_line, price_unit), 'account_id':cacc, 'product_id':i_line.product_id.id, 'uos_id':i_line.uos_id.id, 'account_analytic_id': False, 'taxes':i_line.invoice_line_tax_id, }) elif inv.type in ('in_invoice','in_refund'): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get(cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: #for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get('stock.move') valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit if inv.currency_id.id != company_currency: valuation_price_unit = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={'date': inv.date_invoice}) if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc: # price with discount and without tax included price_unit = self.pool['account.tax'].compute_all(cr, uid, line['taxes'], i_line.price_unit * (1-(i_line.discount or 0.0)/100.0), line['quantity'])['total'] price_line = round(valuation_price_unit * line['quantity'], account_prec) price_diff = round(price_unit - price_line, account_prec) line.update({'price': price_line}) diff_res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': round(price_diff / line['quantity'], account_prec), 'quantity': line['quantity'], 'price': price_diff, 'account_id': acc, 'product_id': line['product_id'], 'uos_id': line['uos_id'], 'account_analytic_id': line['account_analytic_id'], 'taxes': line.get('taxes', []), }) res += diff_res return res
def move_line_get(self, cr, uid, invoice_id, context=None): res = super(account_invoice_line, self).move_line_get(cr, uid, invoice_id, context=context) inv = self.pool.get("account.invoice").browse(cr, uid, invoice_id, context=context) company_currency = inv.company_id.currency_id.id def get_price(cr, uid, inv, company_currency, i_line, price_unit): cur_obj = self.pool.get("res.currency") decimal_precision = self.pool.get("decimal.precision") if inv.currency_id.id != company_currency: price = cur_obj.compute( cr, uid, company_currency, inv.currency_id.id, price_unit * i_line.quantity, context={"date": inv.date_invoice}, ) else: price = price_unit * i_line.quantity return round(price, decimal_precision.precision_get(cr, uid, "Account")) if inv.type in ("out_invoice", "out_refund"): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == "real_time": # debit account dacc will be the output account # first check the product, if empty check the category dacc = ( i_line.product_id.property_stock_account_output and i_line.product_id.property_stock_account_output.id ) if not dacc: dacc = ( i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id ) # in both cases the credit account cacc will be the expense account # first check the product, if empty check the category cacc = i_line.product_id.property_account_expense and i_line.product_id.property_account_expense.id if not cacc: cacc = ( i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id ) if dacc and cacc: price_unit = i_line.move_id and i_line.move_id.price_unit or i_line.product_id.standard_price res.append( { "type": "src", "name": i_line.name[:64], "price_unit": price_unit, "quantity": i_line.quantity, "price": get_price(cr, uid, inv, company_currency, i_line, price_unit), "account_id": dacc, "product_id": i_line.product_id.id, "uos_id": i_line.uos_id.id, "account_analytic_id": False, "taxes": i_line.invoice_line_tax_id, } ) res.append( { "type": "src", "name": i_line.name[:64], "price_unit": price_unit, "quantity": i_line.quantity, "price": -1 * get_price(cr, uid, inv, company_currency, i_line, price_unit), "account_id": cacc, "product_id": i_line.product_id.id, "uos_id": i_line.uos_id.id, "account_analytic_id": False, "taxes": i_line.invoice_line_tax_id, } ) elif inv.type in ("in_invoice", "in_refund"): for i_line in inv.invoice_line: if i_line.product_id and i_line.product_id.valuation == "real_time": if i_line.product_id.type != "service": # get the price difference account at the product acc = ( i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id ) if not acc: # if not found on the product get the price difference account at the category acc = ( i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id ) a = None # oa will be the stock input account # first check the product, if empty check the category oa = ( i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id ) if not oa: oa = ( i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id ) if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get("account.fiscal.position").map_account(cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get("decimal.precision") account_prec = decimal_precision.precision_get(cr, uid, "Account") # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get("invl_id", 0) == i_line.id and a == line["account_id"]: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get("product.uom")._compute_price( cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id ) if i_line.product_id.cost_method != "standard" and i_line.purchase_line_id: # for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get("stock.move") valuation_stock_move = stock_move_obj.search( cr, uid, [("purchase_line_id", "=", i_line.purchase_line_id.id)], limit=1, context=context, ) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse( cr, uid, valuation_stock_move[0], context=context ).price_unit if inv.currency_id.id != company_currency: valuation_price_unit = self.pool.get("res.currency").compute( cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={"date": inv.date_invoice}, ) if ( valuation_price_unit != i_line.price_unit and line["price_unit"] == i_line.price_unit and acc ): price_diff = round(i_line.price_unit - valuation_price_unit, account_prec) line.update({"price": round(valuation_price_unit * line["quantity"], account_prec)}) diff_res.append( { "type": "src", "name": i_line.name[:64], "price_unit": price_diff, "quantity": line["quantity"], "price": round(price_diff * line["quantity"], account_prec), "account_id": acc, "product_id": line["product_id"], "uos_id": line["uos_id"], "account_analytic_id": line["account_analytic_id"], "taxes": line.get("taxes", []), } ) res += diff_res return res
def _onchange_invoice_amount(self): subtotal = (self.order_line_id.price_subtotal) new_val = subtotal and (self.invoice_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.invoice_percent, 6): self.invoice_percent = new_val
def _onchange_deposit_amount(self): subtotal = (self.order_id.amount_untaxed) new_val = subtotal and (self.deposit_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.deposit_percent, 6): self.deposit_percent = new_val
def get_product_cost_value(self, cr, uid, ids, block='company', context=None): ''' Utility for generate cost for product template passed ids: list of product ID block: name of field that idendify cost method (company, customer, pricelist) ''' for product in self.browse(cr, uid, ids, context=context): # Reset variable used: calc = '' error = '' warning = '' supplier_id = product.first_supplier_id.id country_id = product.first_supplier_id.country_id.id # ----------------------------------------------------------------- # Get parameter depend on block selected: # ----------------------------------------------------------------- if block == 'company': total = product.standard_price result_field = 'company_cost' base_description = _('Supplier cost') elif block == 'customer': total = product.company_cost result_field = 'customer_cost' base_description = _('Company cost') elif block == 'pricelist': total = product.customer_cost result_field = 'lst_price' base_description = _('Customer cost') else: self.write(cr, uid, product.id, { error_field: _(''' <p><font color="red">Block selection error: %s </font></p>''') % block, }, context=context) continue # Field name depend on block name: calc_field = '%s_calc' % block error_field = '%s_calc_error'% block warning_field = '%s_calc_warning' % block # Bloced error: if not total: self.write(cr, uid, product.id, { calc_field: False, error_field: _(''' <p><font color="red">Base price is empty (%s) </font></p>''') % block, warning_field: False, }, context=context) continue # ----------------------------------------------------------------- # Process all the rules: # ----------------------------------------------------------------- method = product.__getattribute__('%s_method_id' % block) transport = method.transport_id round_decimal = method.round float_mask = '%s10.%sf' % ('%', round_decimal) calc += ''' <tr> <td>0</td> <td>Base: %s</td> <td> </td> <td style="text-align:right"><b>%s</b></td> </tr>''' % ( base_description, float_mask % total, ) for rule in method.rule_ids: # Rule parameter (for readability): value = rule.value # Read rule field used: mode = rule.mode operation = rule.operation # ------------------------------------------------------------- # DISCOUNT RULE: # ------------------------------------------------------------- if operation == 'discount': base = total if not value: error += _(''' <p><font color="red"> Discount rate not found!!! </font></p>''') continue # value depend on mode: if mode == 'percentual': discount_value = total * value / 100.0 elif mode == 'fixed': discount_value = value total -= discount_value total = round(total, round_decimal) calc += ''' <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _('- Discount %s%s') % ( value, '' if mode == 'fixed' else '%', ), value if mode == 'fixed' else \ '%s x %s = %s' % ( base, value, discount_value, ), float_mask % total, ) # ------------------------------------------------------------- # DUTY RULE: # ------------------------------------------------------------- elif operation == 'duty': # ------------------------------------- # Check mandatory fields for duty calc: # ------------------------------------- if not supplier_id: error += _(''' <p><font color="red"> First supplier not found!</font> </p>''') continue # next rule if not country_id: error += _(''' <p><font color="red"> Country for first supplier not found!</font> </p>''''<p>') continue # next rule duty = product.duty_id # Check duty category presence: if not duty and not product.is_duty_set: error += _(''' <p><font color="red"> Duty category not setted on product And product is not a duty set! </font> </p>''') continue # Get duty rate depend on supplier country base = total duty_value = 0.0 if product.is_duty_set: for duty_set in product.duty_set_ids: duty_rate = self.get_duty_product_rate( cr, uid, duty_set.duty_id, country_id, context=context) duty_value += (base * duty_set.partial / 100.0) * ( duty_rate / 100.0) else: # no set duty_rate = self.get_duty_product_rate( cr, uid, duty, country_id, context=context) duty_value = base * duty_rate / 100.0 # Check duty rate value (: if not duty_value: warning += _(''' <p><font color="orange"> Duty value is zero!</font> </p>''') total += duty_value total = round(total, round_decimal) calc += ''' <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td style="text-align:right"><b>%s</b></td> </tr>''' % ( rule.sequence, _('''+ Duty %s%s<br/> <i><font color="grey">[%s-%s]</font></i> ''') % ( '(set)' if product.is_duty_set else duty_rate, '%', _('Different duty categ.') if \ product.is_duty_set \ else product.duty_id.name, product.first_supplier_id.country_id.name, ), '%s x %s = %s' % (base, duty_rate, duty_value) if \ not product.is_duty_set else duty_value, float_mask % total, ) # ------------------------------------------------------------- # EXCHANGE RULE: # ------------------------------------------------------------- elif operation == 'exchange': base = total comment = '' # Read exchange: if method.force_exchange: # method comment = _('(Met.)') exchange_rate = method.force_exchange else: supplier = product.first_supplier_id if supplier: comment = _('(Suppl.)') if supplier.cost_currency_id: exchange_rate = \ supplier.cost_currency_id.rate_silent_cost else: exchange_rate = 1.0 # EUR warning += _(''' <p><font color="orange"> No currency in supplier use 1 </font></p>''') else: exchange_rate = 0.0 if not exchange_rate: # no exchange (value 0): error += _(''' <p><font color="red"> Exchange value not found (currency and method)! </font></p>''') continue total /= exchange_rate total = round(total, round_decimal) calc += ''' <tr> <td>%s</td> <td>%s %s</td> <td>%s</td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _(': Exchange %s') % exchange_rate, comment, '%s : %s' % ( base, exchange_rate), float_mask % total, ) # ------------------------------------------------------------- # TRANSPORT RULE: # ------------------------------------------------------------- elif operation == 'transport': comment = '' # Check mandatory element for transport: if transport: comment = _('(Metod)') elif product.first_supplier_id and \ product.first_supplier_id.transport_id: comment = _('(Suppl.)') transport = product.first_supplier_id.transport_id else: error += _(''' <p><font color="red"> Setup transport in cost method %s or partner! </font></p>''') % block continue # Calculate date depend on tranport choosed transport_cost = transport.cost transport_volume = transport.volume transport_id = transport.id # Search in tranport-product relation q_x_tran = 0 for prod_tran in product.transport_ids: if prod_tran.transport_id.id == transport.id: q_x_tran = prod_tran.quantity break if q_x_tran: # Calculate with q x tran cost1 = transport_cost / q_x_tran total += cost1 total = round(total, round_decimal) calc += ''' <tr> <td>%s</td> <td>%s %s</td> <td>%s</td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _('+ Transport (sett.)'), comment, '%s / %s = %s' % ( transport_cost, q_x_tran, cost1, ), float_mask % total, ) else: # Calculated fields: volume1 = self.get_volume_single_product( cr, uid, product, context=context) # Check mandatory volume if not volume1: error += _(''' <p><font color="red"> Volume x piece not present!!! </font></p>''') continue if not transport_volume: error += _(''' <p><font color="red"> No transport total volume present!!! </font></p>''') continue pc_x_trans = transport_volume / volume1 cost1 = transport_cost / int(pc_x_trans) # cut down total += cost1 total = round(total, round_decimal) warning += _(''' <p><font color="orange"> Transport is optimistic because based on volume not on pcs x tranport in product form! </font> </p>''') calc += ''' <tr> <td>%s</td> <td>%s %s</td> <td>%s</td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _('+ Transport (calc.)<br/>' '<i><font color="orange">' '[pcs/tr. %s > %s]' '</font></i>') % ( pc_x_trans, int(pc_x_trans)), comment, '%s / %s = %s' % ( transport_cost, int(pc_x_trans), cost1, ), float_mask % total, ) # ------------------------------------------------------------- # RECHARGE RULE: # ------------------------------------------------------------- elif operation == 'recharge': base = total if not value: error += _(''' <p><font color="red"> Recharge rate not found!!! </font></p>''') continue # value depend on mode: if mode == 'percentual': recharge_value = total * value / 100.0 elif mode == 'fixed': recharge_value = value total += recharge_value total = round(total, round_decimal) calc += ''' <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _('+ Rechange %s%s') % ( value, '' if mode == 'fixed' else '%', ), value if mode == 'fixed' else \ '%s x %s = %s' % ( base, value, recharge_value, ), float_mask % total, ) # ------------------------------------------------------------- # APPROX RULE: # ------------------------------------------------------------- elif operation == 'approx': if not value: error += _(''' <p><font color="red"> Approx need to be setup (es. 0,01)! </font></p>''') continue total = (total / value) total = round(total, 0) * value # int round calc += ''' <tr> <td>%s</td> <td>%s</td> <td></td> <td style="text-align:right">%s</td> </tr>''' % ( rule.sequence, _('= Round %s') % value, float_mask % total, ) # ----------------------------------------------------------------- # Write data in product: # ----------------------------------------------------------------- self.write(cr, uid, product.id, { result_field: total, calc_field: _(''' <table> <tr> <th>Seq.</th> <th>Description</th> <th>Calculation</th> <th>Subtotal</th> </tr>%s </table>''') % calc, # embed in table error_field: error, warning_field: warning, }, context=context) return True
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None): """ Returns all information required to apply taxes (in self + their children in case of a tax goup). We consider the sequence of the parent for group of taxes. Eg. considering letters as taxes and alphabetic order as sequence : [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G] RETURN: { 'total_excluded': 0.0, # Total without taxes 'total_included': 0.0, # Total with taxes 'taxes': [{ # One dict for each tax in self and their children 'id': int, 'name': str, 'amount': float, 'sequence': int, 'account_id': int, 'refund_account_id': int, 'analytic': boolean, }] } """ if len(self) == 0: company_id = self.env.user.company_id else: company_id = self[0].company_id if not currency: currency = company_id.currency_id taxes = [] # 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 prec = currency.decimal_places if company_id.tax_calculation_rounding_method == 'round_globally': prec += 5 total_excluded = total_included = base = round(price_unit * quantity, prec) for tax in self: if tax.amount_type == 'group': ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner) total_excluded = ret['total_excluded'] base = ret['base'] total_included = ret['total_included'] tax_amount = total_included - total_excluded taxes += ret['taxes'] continue tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner) if company_id.tax_calculation_rounding_method == 'round_globally': tax_amount = round(tax_amount, prec) else: tax_amount = currency.round(tax_amount) if tax.price_include: total_excluded -= tax_amount base -= tax_amount else: total_included += tax_amount if tax.include_base_amount: base += tax_amount taxes.append({ 'id': tax.id, 'name': tax.name, 'amount': tax_amount, 'sequence': tax.sequence, 'account_id': tax.account_id.id, 'refund_account_id': tax.refund_account_id.id, 'analytic': tax.analytic, }) return { 'taxes': sorted(taxes, key=lambda k: k['sequence']), 'total_excluded': currency.round(total_excluded), 'total_included': currency.round(total_included), 'base': base, }
def _onchange_deposit_amount(self): subtotal = self.order_id.amount_untaxed new_val = subtotal and (self.deposit_amount / subtotal) * 100 or 0.0 if round(new_val, 6) != round(self.deposit_percent, 6): self.deposit_percent = new_val
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None): """ Returns all information required to apply taxes (in self + their children in case of a tax goup). We consider the sequence of the parent for group of taxes. Eg. considering letters as taxes and alphabetic order as sequence : [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G] RETURN: { 'total_excluded': 0.0, # Total without taxes 'total_included': 0.0, # Total with taxes 'taxes': [{ # One dict for each tax in self and their children 'id': int, 'name': str, 'amount': float, 'sequence': int, 'account_id': int, 'refund_account_id': int, 'analytic': boolean, }] } """ if len(self) == 0: company_id = self.env.user.company_id else: company_id = self[0].company_id if not currency: currency = company_id.currency_id taxes = [] # 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 prec = currency.decimal_places if company_id.tax_calculation_rounding_method == 'round_globally': prec += 5 total_excluded = total_included = base = round(price_unit * quantity, prec) for tax in self: if tax.amount_type == 'group': ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner) total_excluded = ret['total_excluded'] base = ret['total_excluded'] total_included = ret['total_included'] tax_amount = total_included - total_excluded taxes += ret['taxes'] continue tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner) if company_id.tax_calculation_rounding_method == 'round_globally': tax_amount = round(tax_amount, prec) else: tax_amount = currency.round(tax_amount) if tax_amount: if tax.price_include: total_excluded -= tax_amount base -= tax_amount else: total_included += tax_amount if tax.include_base_amount: base += tax_amount taxes.append({ 'id': tax.id, 'name': tax.name, 'amount': tax_amount, 'sequence': tax.sequence, 'account_id': tax.account_id.id, 'refund_account_id': tax.refund_account_id.id, 'analytic': tax.analytic, }) return { 'taxes': sorted(taxes, key=lambda k: k['sequence']), 'total_excluded': currency.round(total_excluded), 'total_included': currency.round(total_included), }
def _anglo_saxon_purchase_move_lines(self, cr, uid, i_line, res, context=None): """Return the additional move lines for purchase invoices and refunds. i_line: An account.invoice.line object. res: The move line entries produced so far by the parent move_line_get. """ inv = i_line.invoice_id company_currency = inv.company_id.currency_id.id if i_line.product_id and i_line.product_id.valuation == 'real_time': if i_line.product_id.type != 'service': # get the price difference account at the product acc = i_line.product_id.property_account_creditor_price_difference and i_line.product_id.property_account_creditor_price_difference.id if not acc: # if not found on the product get the price difference account at the category acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id a = None # oa will be the stock input account # first check the product, if empty check the category oa = i_line.product_id.property_stock_account_input and i_line.product_id.property_stock_account_input.id if not oa: oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id if oa: # get the fiscal position fpos = i_line.invoice_id.fiscal_position or False a = self.pool.get('account.fiscal.position').map_account( cr, uid, fpos, oa) diff_res = [] decimal_precision = self.pool.get('decimal.precision') account_prec = decimal_precision.precision_get( cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get( 'product.uom')._compute_price( cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id: #for average/fifo/lifo costing method, fetch real cost price from incomming moves stock_move_obj = self.pool.get('stock.move') valuation_stock_move = stock_move_obj.search( cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context) if valuation_stock_move: valuation_price_unit = stock_move_obj.browse( cr, uid, valuation_stock_move[0], context=context).price_unit if inv.currency_id.id != company_currency: valuation_price_unit = self.pool.get( 'res.currency').compute( cr, uid, company_currency, inv.currency_id.id, valuation_price_unit, context={'date': inv.date_invoice}) if valuation_price_unit != i_line.price_unit and line[ 'price_unit'] == i_line.price_unit and acc: # price with discount and without tax included price_unit = self.pool['account.tax'].compute_all( cr, uid, line['taxes'], i_line.price_unit * (1 - (i_line.discount or 0.0) / 100.0), line['quantity'])['total'] price_line = round( valuation_price_unit * line['quantity'], account_prec) price_diff = round(price_unit - price_line, account_prec) line.update({'price': price_line}) diff_res.append({ 'type': 'src', 'name': i_line.name[:64], 'price_unit': round(price_diff / line['quantity'], account_prec), 'quantity': line['quantity'], 'price': price_diff, 'account_id': acc, 'product_id': line['product_id'], 'uos_id': line['uos_id'], 'account_analytic_id': line['account_analytic_id'], 'taxes': line.get('taxes', []), }) return diff_res return []