Beispiel #1
0
 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)
Beispiel #4
0
 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
Beispiel #5
0
    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
Beispiel #6
0
 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_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
Beispiel #9
0
 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
Beispiel #10
0
 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 _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
Beispiel #14
0
 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())
Beispiel #15
0
 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()
Beispiel #16
0
 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)
Beispiel #17
0
    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
Beispiel #18
0
    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)
Beispiel #20
0
 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'))
Beispiel #21
0
 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'))
Beispiel #22
0
 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 _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
Beispiel #24
0
 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
Beispiel #27
0
 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)
Beispiel #29
0
    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)
Beispiel #30
0
    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
Beispiel #31
0
 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
Beispiel #32
0
    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
Beispiel #33
0
 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
Beispiel #35
0
    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)
Beispiel #36
0
 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
Beispiel #38
0
    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)
Beispiel #41
0
 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
Beispiel #44
0
    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 []
Beispiel #45
0
    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
Beispiel #46
0
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)
Beispiel #47
0
def round_base(x, base=5):
        from openerp.tools.float_utils import float_round as round
        return round(x, base)
Beispiel #48
0
    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
Beispiel #49
0
    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
Beispiel #51
0
    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_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_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
Beispiel #55
0
    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>&nbsp;</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
Beispiel #56
0
    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
Beispiel #58
0
    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),
        }
Beispiel #59
0
    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 []