Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 32eac9b370d6670063068869d6d8e6f2d2e2ef28
  • 14.0 par défaut
  • 13.0
  • 12.0 protégée
4 résultats

scop_invoice_idf.py

Blame
  • scop_invoice_idf.py 7,56 Kio
    # © 2021 Le Filament (<http://www.le-filament.com>)
    # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
    
    from odoo import models, fields, api
    
    
    class ScopInvoiceIDF(models.Model):
        _name = "scop.invoice.idf"
        _description = "Paiements IDF"
    
        # ------------------------------------------------------
        # Fields declaration
        # ------------------------------------------------------
        name = fields.Char('Libellé')
        company_id = fields.Many2one(
            comodel_name='res.company',
            string='Société',
        )
        partner_id = fields.Many2one(
            comodel_name='res.partner',
            string='Adhérent',
            required=True,
            domain=[('is_company', '=', True)])
        journal = fields.Char('Journal')
        writing_date = fields.Date('Date écriture')
        acc_doc = fields.Char('Numéro de pièce comptable')
        year = fields.Char('Année')
        type = fields.Selection([
            ('inv', 'Facture'),
            ('refund', 'Avoir'),
            ('reject', 'Rejet'),
            ('pay', 'Paiement')],
            string='Type', required=True)
        lettrage = fields.Char('Référence de lettrage')
        currency_id = fields.Many2one(
            comodel_name='res.currency',
            string='Monnaie',
            related='company_id.currency_id')
        debit = fields.Monetary(string='Débit', currency_field='currency_id')
        credit = fields.Monetary(string='Crédit', currency_field='currency_id')
        amount_residual = fields.Float(
            string='Reste à payer',
            compute='_compute_amount_residual',
            store=True, currency_field='currency_id'
        )
        state = fields.Selection(
            string='Etat',
            selection=[('no_invoice', 'Pas de facture associée'),
                       ('awaiting_payments', 'En attente de paiements'),
                       ('overpaid', 'La somme des paiements est supérieure au '
                                    'montant de la facture'),
                       ('paid', 'La facture a bien été réglée !')],
            required=False,
            search='_search_state',
            compute='_compute_state')
    
        invoice_id = fields.Many2one(
            comodel_name='scop.invoice.idf',
            string='Facture',
        )
        payments_ids = fields.One2many(
            comodel_name='scop.invoice.idf',
            inverse_name='invoice_id',
            string='Paiements / Avoirs',
            required=False, readonly=True)
    
        # ------------------------------------------------------
        # Computed fields
        # ------------------------------------------------------
        @api.depends('payments_ids', 'debit',
                     'payments_ids.debit', 'payments_ids.debit')
        @api.multi
        def _compute_amount_residual(self):
            for r in self:
                if r.type == 'inv':
                    if r.payments_ids:
                        amount_paid = sum(
                            r.payments_ids.mapped('credit'))
                        r.amount_residual = r.debit - amount_paid
                    else:
                        r.amount_residual = r.debit
    
        @api.multi
        def _compute_state(self):
            """
            A line can be in different states :
            - No invoice related to a payment / refund
            - Too many payments related to one invoice
            - Some payments are missing
            - The invoice has been paid
            """
            def which_state(amount_residual):
                if amount_residual > 0:
                    return 'awaiting_payments'
                elif amount_residual < 0:
                    return 'overpaid'
                else:
                    return 'paid'
    
            for r in self:
                if r.type != 'inv':
                    if not r.invoice_id:
                        r.state = 'no_invoice'
                    else:
                        r.state = which_state(r.invoice_id.amount_residual)
                else:
                    r.state = which_state(r.amount_residual)
    
        @api.multi
        def _search_state(self, operator, value):
            recs = None
            if operator == '=':
                recs = self.search([]).filtered(lambda x: x.state == value)
            elif operator == 'in':
                recs = self.search([]).filtered(lambda x: x.state in value)
            elif operator == '!=':
                recs = self.search([]).filtered(lambda x: x.state != value)
            elif operator == 'not in':
                recs = self.search([]).filtered(lambda x: x.state not in value)
            if recs:
                return [('id', 'in', [x.id for x in recs])]
    
        # ------------------------------------------------------
        # Actions
        # ------------------------------------------------------
        def reconcile(self):
            """
            Link payments and invoices if same letter for a given year
            :return:
            """
            years = set(self.mapped('year'))
            partners = self.mapped('partner_id')
            for year in years:
                for partner in partners:
                    invoice_lines = self.search([
                        ['year', '=', year],
                        ['partner_id', '=', partner.id],
                        ['type', '=', 'inv']])
                    letters = set(invoice_lines.mapped('lettrage'))
                    lines_to_lettre = self.search([
                        ['year', '=', year],
                        ['partner_id', '=', partner.id],
                        ['type', '!=', 'inv']])
                    for line in lines_to_lettre:
                        if line.lettrage in letters:
                            line.invoice_id = invoice_lines.filtered(
                                lambda l: l.lettrage == line.lettrage)[0]
    
        def action_open_payment(self):
            return {
                'type': 'ir.actions.act_window',
                'name': 'Paiement / Avoir',
                'views': [
                    [self.env.ref(
                        'cgscop_invoice_idf.view_scop_invoice_idf_form').id,
                     "form"]
                ],
                'view_mode': 'form',
                'res_model': 'scop.invoice.idf',
                'target': 'current',
                'res_id': self.id
            }
    
        def action_free_payment(self):
            self.invoice_id = None
    
        def action_show_payments(self):
            form_view = self.env.ref(
                        'cgscop_invoice_idf.view_scop_invoice_idf_form').id
            tree_view = self.env.ref(
                'cgscop_invoice_idf.view_scop_invoice_idf_tree').id
            return {
                'type': 'ir.actions.act_window',
                'name': 'Paiement / Avoir',
                'views': [
                    [tree_view, "tree"], [form_view, "form"]
                ],
                'view_mode': 'form',
                'res_model': 'scop.invoice.idf',
                'target': 'current',
                'domain': [('id', 'in', self.payments_ids.ids)]
            }
    
        def action_show_invoice(self):
            form_view = self.env.ref(
                        'cgscop_invoice_idf.view_scop_invoice_idf_form').id
            return {
                'type': 'ir.actions.act_window',
                'name': 'Facture',
                'views': [
                    [form_view, "form"]
                ],
                'view_mode': 'form',
                'res_model': 'scop.invoice.idf',
                'target': 'current',
                'res_id': self.invoice_id.id
            }
    
        def action_show_partner_invoice_idf(self):
            form_view = self.env.ref(
                        'cgscop_invoice_idf.view_scop_invoice_idf_form').id
            tree_view = self.env.ref(
                'cgscop_invoice_idf.view_scop_invoice_idf_tree').id
            return {
                'type': 'ir.actions.act_window',
                'name': 'Factures IDF - ' + self.partner_id.name,
                'views': [
                    [tree_view, "tree"], [form_view, "form"]
                ],
                'view_mode': 'form',
                'res_model': 'scop.invoice.idf',
                'target': 'current',
                'domain': [('partner_id', '=', self.partner_id.id)]
            }