You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							251 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							251 lines
						
					
					
						
							12 KiB
						
					
					
				
								# -*- coding: utf-8 -*-
							 | 
						|
								##############################################################################
							 | 
						|
								#
							 | 
						|
								#    Cybrosys Technologies Pvt. Ltd.
							 | 
						|
								#    Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
							 | 
						|
								#    Author: Treesa Maria Jude(<https://www.cybrosys.com>)
							 | 
						|
								#    you can modify it under the terms of the GNU LESSER
							 | 
						|
								#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
							 | 
						|
								#
							 | 
						|
								#    It is forbidden to publish, distribute, sublicense, or sell copies
							 | 
						|
								#    of the Software or modified copies of the Software.
							 | 
						|
								#
							 | 
						|
								#    This program is distributed in the hope that it will be useful,
							 | 
						|
								#    but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						|
								#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						|
								#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
							 | 
						|
								#
							 | 
						|
								#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
							 | 
						|
								#    GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
							 | 
						|
								#    If not, see <https://www.gnu.org/licenses/>.
							 | 
						|
								#
							 | 
						|
								##############################################################################
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								from odoo.tools import float_is_zero
							 | 
						|
								from odoo.exceptions import UserError
							 | 
						|
								from odoo import fields, models, api, _
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class RoundOffSetting(models.TransientModel):
							 | 
						|
								    _inherit = 'account.config.settings'
							 | 
						|
								
							 | 
						|
								    round_off = fields.Boolean(string='Allow rounding of invoice amount', help="Allow rounding of invoice amount")
							 | 
						|
								    round_off_account = fields.Many2one('account.account', string='Round Off Account')
							 | 
						|
								
							 | 
						|
								    @api.multi
							 | 
						|
								    def set_round_off(self):
							 | 
						|
								        ir_values_obj = self.env['ir.values']
							 | 
						|
								        ir_values_obj.sudo().set_default('account.config.settings', "round_off", self.round_off)
							 | 
						|
								        ir_values_obj.sudo().set_default('account.config.settings', "round_off_account", self.round_off_account.id)
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class AccountRoundOff(models.Model):
							 | 
						|
								    _inherit = 'account.invoice'
							 | 
						|
								
							 | 
						|
								    round_off_value = fields.Float(compute='_compute_amount', string='Round off amount')
							 | 
						|
								    rounded_total = fields.Float(compute='_compute_amount', string='Rounded Total')
							 | 
						|
								    round_active = fields.Boolean(compute='get_round_active')
							 | 
						|
								
							 | 
						|
								    def get_round_active(self):
							 | 
						|
								        ir_values = self.env['ir.values']
							 | 
						|
								        for i in self:
							 | 
						|
								            i.round_active = ir_values.get_default('account.config.settings', 'round_off')
							 | 
						|
								
							 | 
						|
								    @api.one
							 | 
						|
								    @api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id',
							 | 
						|
								                 'date_invoice', 'type')
							 | 
						|
								    def _compute_amount(self):
							 | 
						|
								        self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line_ids)
							 | 
						|
								        self.amount_tax = sum(line.amount for line in self.tax_line_ids)
							 | 
						|
								        self.rounded_total = round(self.amount_untaxed + self.amount_tax)
							 | 
						|
								        self.amount_total = self.amount_untaxed + self.amount_tax
							 | 
						|
								        self.round_off_value = self.rounded_total - (self.amount_untaxed + self.amount_tax)
							 | 
						|
								        amount_total_company_signed = self.amount_total
							 | 
						|
								        amount_untaxed_signed = self.amount_untaxed
							 | 
						|
								        if self.currency_id and self.company_id and self.currency_id != self.company_id.currency_id:
							 | 
						|
								            currency_id = self.currency_id.with_context(date=self.date_invoice)
							 | 
						|
								            amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id)
							 | 
						|
								            amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id)
							 | 
						|
								        sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
							 | 
						|
								        self.amount_total_company_signed = amount_total_company_signed * sign
							 | 
						|
								        self.amount_total_signed = self.amount_total * sign
							 | 
						|
								        self.amount_untaxed_signed = amount_untaxed_signed * sign
							 | 
						|
								
							 | 
						|
								    @api.one
							 | 
						|
								    @api.depends(
							 | 
						|
								        'state', 'currency_id', 'invoice_line_ids.price_subtotal',
							 | 
						|
								        'move_id.line_ids.amount_residual',
							 | 
						|
								        'move_id.line_ids.currency_id')
							 | 
						|
								    def _compute_residual(self):
							 | 
						|
								        residual = 0.0
							 | 
						|
								        residual_company_signed = 0.0
							 | 
						|
								        sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
							 | 
						|
								        for line in self.sudo().move_id.line_ids:
							 | 
						|
								            if line.account_id.internal_type in ('receivable', 'payable'):
							 | 
						|
								                residual_company_signed += line.amount_residual
							 | 
						|
								                if line.currency_id == self.currency_id:
							 | 
						|
								                    residual += line.amount_residual_currency if line.currency_id else line.amount_residual
							 | 
						|
								                else:
							 | 
						|
								                    from_currency = (line.currency_id and line.currency_id.with_context(
							 | 
						|
								                        date=line.date)) or line.company_id.currency_id.with_context(date=line.date)
							 | 
						|
								                    residual += from_currency.compute(line.amount_residual, self.currency_id)
							 | 
						|
								        self.residual_company_signed = abs(residual_company_signed) * sign
							 | 
						|
								        self.residual_signed = abs(residual) * sign
							 | 
						|
								        if self.round_active is True and self.type == 'out_invoice':
							 | 
						|
								            self.residual = round(abs(residual))
							 | 
						|
								        else:
							 | 
						|
								            self.residual = abs(residual)
							 | 
						|
								        digits_rounding_precision = self.currency_id.rounding
							 | 
						|
								        if float_is_zero(self.residual, precision_rounding=digits_rounding_precision):
							 | 
						|
								            self.reconciled = True
							 | 
						|
								        else:
							 | 
						|
								            self.reconciled = False
							 | 
						|
								
							 | 
						|
								    @api.multi
							 | 
						|
								    def action_move_create(self):
							 | 
						|
								        """ Creates invoice related analytics and financial move lines """
							 | 
						|
								        account_move = self.env['account.move']
							 | 
						|
								
							 | 
						|
								        for inv in self:
							 | 
						|
								
							 | 
						|
								            if not inv.journal_id.sequence_id:
							 | 
						|
								                raise UserError(_('Please define sequence on the journal related to this invoice.'))
							 | 
						|
								            if not inv.invoice_line_ids:
							 | 
						|
								                raise UserError(_('Please create some invoice lines.'))
							 | 
						|
								            if inv.move_id:
							 | 
						|
								                continue
							 | 
						|
								
							 | 
						|
								            ctx = dict(self._context, lang=inv.partner_id.lang)
							 | 
						|
								
							 | 
						|
								            if not inv.date_invoice:
							 | 
						|
								                inv.with_context(ctx).write({'date_invoice': fields.Date.context_today(self)})
							 | 
						|
								            date_invoice = inv.date_invoice
							 | 
						|
								            company_currency = inv.company_id.currency_id
							 | 
						|
								
							 | 
						|
								            # create move lines (one per invoice line + eventual taxes and analytic lines)
							 | 
						|
								            iml = inv.invoice_line_move_line_get()
							 | 
						|
								            iml += inv.tax_line_move_line_get()
							 | 
						|
								
							 | 
						|
								            diff_currency = inv.currency_id != company_currency
							 | 
						|
								            # create one move line for the total and possibly adjust the other lines amount
							 | 
						|
								            total, total_currency, iml = inv.with_context(ctx).compute_invoice_totals(company_currency, iml)
							 | 
						|
								
							 | 
						|
								            name = inv.name or '/'
							 | 
						|
								            if inv.payment_term_id:
							 | 
						|
								                totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=company_currency.id).compute(
							 | 
						|
								                    total, date_invoice)[0]
							 | 
						|
								                res_amount_currency = total_currency
							 | 
						|
								                ctx['date'] = date_invoice
							 | 
						|
								                for i, t in enumerate(totlines):
							 | 
						|
								                    if inv.currency_id != company_currency:
							 | 
						|
								                        amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id)
							 | 
						|
								                    else:
							 | 
						|
								                        amount_currency = False
							 | 
						|
								
							 | 
						|
								                    # last line: add the diff
							 | 
						|
								                    res_amount_currency -= amount_currency or 0
							 | 
						|
								                    if i + 1 == len(totlines):
							 | 
						|
								                        amount_currency += res_amount_currency
							 | 
						|
								                    if self.round_active is True and self.type == 'out_invoice':
							 | 
						|
								                        iml.append({
							 | 
						|
								                            'type': 'dest',
							 | 
						|
								                            'name': name,
							 | 
						|
								                            'price': t[1]+self.round_off_value,
							 | 
						|
								                            'account_id': inv.account_id.id,
							 | 
						|
								                            'date_maturity': t[0],
							 | 
						|
								                            'amount_currency': diff_currency and amount_currency,
							 | 
						|
								                            'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                            'invoice_id': inv.id
							 | 
						|
								                        })
							 | 
						|
								                        ir_values = self.env['ir.values']
							 | 
						|
								                        acc_id = ir_values.get_default('account.config.settings', 'round_off_account')
							 | 
						|
								                        iml.append({
							 | 
						|
								                            'type': 'dest',
							 | 
						|
								                            'name': "Round off",
							 | 
						|
								                            'price': -self.round_off_value,
							 | 
						|
								                            'account_id': acc_id,
							 | 
						|
								                            'date_maturity': t[0],
							 | 
						|
								                            'amount_currency': diff_currency and amount_currency,
							 | 
						|
								                            'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                            'invoice_id': inv.id
							 | 
						|
								                        })
							 | 
						|
								                    else:
							 | 
						|
								
							 | 
						|
								                        iml.append({
							 | 
						|
								                            'type': 'dest',
							 | 
						|
								                            'name': name,
							 | 
						|
								                            'price': t[1],
							 | 
						|
								                            'account_id': inv.account_id.id,
							 | 
						|
								                            'date_maturity': t[0],
							 | 
						|
								                            'amount_currency': diff_currency and amount_currency,
							 | 
						|
								                            'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                            'invoice_id': inv.id
							 | 
						|
								                        })
							 | 
						|
								
							 | 
						|
								            else:
							 | 
						|
								                if self.round_active is True and self.type == 'out_invoice':
							 | 
						|
								                    iml.append({
							 | 
						|
								                        'type': 'dest',
							 | 
						|
								                        'name': name,
							 | 
						|
								                        'price': total + self.round_off_value,
							 | 
						|
								                        'account_id': inv.account_id.id,
							 | 
						|
								                        'date_maturity': inv.date_due,
							 | 
						|
								                        'amount_currency': diff_currency and total_currency,
							 | 
						|
								                        'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                        'invoice_id': inv.id
							 | 
						|
								                    })
							 | 
						|
								                    ir_values = self.env['ir.values']
							 | 
						|
								                    acc_id = ir_values.get_default('account.config.settings', 'round_off_account')
							 | 
						|
								                    iml.append({
							 | 
						|
								                        'type': 'dest',
							 | 
						|
								                        'name': "Round off",
							 | 
						|
								                        'price': -self.round_off_value,
							 | 
						|
								                        'account_id': acc_id,
							 | 
						|
								                        'date_maturity': inv.date_due,
							 | 
						|
								                        'amount_currency': diff_currency and total_currency,
							 | 
						|
								                        'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                        'invoice_id': inv.id
							 | 
						|
								                    })
							 | 
						|
								                else:
							 | 
						|
								                    iml.append({
							 | 
						|
								                        'type': 'dest',
							 | 
						|
								                        'name': name,
							 | 
						|
								                        'price': total,
							 | 
						|
								                        'account_id': inv.account_id.id,
							 | 
						|
								                        'date_maturity': inv.date_due,
							 | 
						|
								                        'amount_currency': diff_currency and total_currency,
							 | 
						|
								                        'currency_id': diff_currency and inv.currency_id.id,
							 | 
						|
								                        'invoice_id': inv.id
							 | 
						|
								                    })
							 | 
						|
								            part = self.env['res.partner']._find_accounting_partner(inv.partner_id)
							 | 
						|
								            line = [(0, 0, self.line_get_convert(l, part.id)) for l in iml]
							 | 
						|
								            line = inv.group_lines(iml, line)
							 | 
						|
								
							 | 
						|
								            journal = inv.journal_id.with_context(ctx)
							 | 
						|
								            line = inv.finalize_invoice_move_lines(line)
							 | 
						|
								
							 | 
						|
								            date = inv.date or date_invoice
							 | 
						|
								            move_vals = {
							 | 
						|
								                'ref': inv.reference,
							 | 
						|
								                'line_ids': line,
							 | 
						|
								                'journal_id': journal.id,
							 | 
						|
								                'date': date,
							 | 
						|
								                'narration': inv.comment,
							 | 
						|
								            }
							 | 
						|
								            ctx['company_id'] = inv.company_id.id
							 | 
						|
								            ctx['invoice'] = inv
							 | 
						|
								            ctx_nolang = ctx.copy()
							 | 
						|
								            ctx_nolang.pop('lang', None)
							 | 
						|
								            move = account_move.with_context(ctx_nolang).create(move_vals)
							 | 
						|
								            # Pass invoice in context in method post: used if you want to get the same
							 | 
						|
								            # account move reference when creating the same invoice after a cancelled one:
							 | 
						|
								            move.post()
							 | 
						|
								            # make the invoice point to that move
							 | 
						|
								            vals = {
							 | 
						|
								                'move_id': move.id,
							 | 
						|
								                'date': date,
							 | 
						|
								                'move_name': move.name,
							 | 
						|
								            }
							 | 
						|
								            inv.with_context(ctx).write(vals)
							 | 
						|
								        return True
							 | 
						|
								
							 |