Sélectionner une révision Git
res_config_settings.py
scop_cotisation_idf.py 8,21 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 api, fields, models
class ScopCotisationsIDF(models.Model):
_name = "scop.cotisation.idf"
_description = "Cotisations 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")
piece = fields.Integer("Numéro de pièce comptable")
year = fields.Char("Année")
type = fields.Selection(
[
("inv", "Cotisation"),
("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.Monetary(
string="Reste à payer",
compute="_compute_amount_residual",
store=True,
currency_field="currency_id",
)
state = fields.Selection(
string="Etat",
selection=[
("no_invoice", "Pas de cotisation associée"),
("awaiting_payments", "En attente de paiements"),
(
"overpaid",
"La somme des paiements est supérieure au " "montant de la cotisation",
),
("paid", "La cotisation a bien été réglée !"),
],
required=False,
search="_search_state",
compute="_compute_state",
)
invoice_id = fields.Many2one(
comodel_name="scop.cotisation.idf", string="Cotisation"
)
payments_ids = fields.One2many(
comodel_name="scop.cotisation.idf",
inverse_name="invoice_id",
string="Paiements / Avoirs",
required=False,
readonly=True,
)
exoneration = fields.Boolean(
string="Exonération", compute="_compute_exoneration", store=True
)
cotiz_zero = fields.Boolean(string="Non appelée")
# ------------------------------------------------------
# Computed fields
# ------------------------------------------------------
@api.depends("payments_ids", "debit", "payments_ids.debit", "payments_ids.credit")
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
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)
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])]
@api.depends("type", "invoice_id", "payments_ids", "payments_ids.type")
def _compute_exoneration(self):
for r in self:
if r.type == "refund":
r.exoneration = True
if r.type == "inv":
exos = r.payments_ids.filtered(lambda l: l.exoneration is True)
if exos:
r.exoneration = True
# ------------------------------------------------------
# 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_cotisation_idf_form").id,
"form",
]
],
"view_mode": "form",
"res_model": "scop.cotisation.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_cotisation_idf_form").id
tree_view = self.env.ref("cgscop_invoice_idf.view_scop_cotisation_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.cotisation.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_cotisation_idf_form").id
return {
"type": "ir.actions.act_window",
"name": "Cotisation",
"views": [[form_view, "form"]],
"view_mode": "form",
"res_model": "scop.cotisation.idf",
"target": "current",
"res_id": self.invoice_id.id,
}
def action_show_partner_contribution_idf(self):
form_view = self.env.ref("cgscop_invoice_idf.view_scop_cotisation_idf_form").id
tree_view = self.env.ref("cgscop_invoice_idf.view_scop_cotisation_idf_tree").id
return {
"type": "ir.actions.act_window",
"name": "Cotisations IDF - " + self.partner_id.name,
"views": [[tree_view, "tree"], [form_view, "form"]],
"view_mode": "form",
"res_model": "scop.cotisation.idf",
"target": "current",
"domain": [("partner_id", "=", self.partner_id.id)],
}