Skip to content
Extraits de code Groupes Projets
Valider 2fe48f13 rédigé par Benjamin - Le Filament's avatar Benjamin - Le Filament
Parcourir les fichiers

[UPD] payment order email template & schedule method of calculation

parent aee03f89
Branches
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -6,6 +6,8 @@ exclude: | ...@@ -6,6 +6,8 @@ exclude: |
^setup/|/static/description/index\.html$| ^setup/|/static/description/index\.html$|
# We don't want to mess with tool-generated files # We don't want to mess with tool-generated files
.svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|
# Maybe reactivate this when all README files include prettier ignore tags?
^README\.md$|
# Library files can have extraneous formatting (even minimized) # Library files can have extraneous formatting (even minimized)
/static/(src/)?lib/| /static/(src/)?lib/|
# Repos using Sphinx to generate docs don't need prettying # Repos using Sphinx to generate docs don't need prettying
...@@ -25,8 +27,13 @@ repos: ...@@ -25,8 +27,13 @@ repos:
entry: found forbidden files; remove them entry: found forbidden files; remove them
language: fail language: fail
files: "\\.rej$" files: "\\.rej$"
- id: en-po-files
name: en.po files cannot exist
entry: found a en.po file
language: fail
files: '[a-zA-Z0-9_]*/i18n/en\.po$'
- repo: https://github.com/oca/maintainer-tools - repo: https://github.com/oca/maintainer-tools
rev: 7d8a9f9ad73db0976fb03cbee43d953bc29b89e9 rev: ab1d7f6
hooks: hooks:
# update the NOT INSTALLABLE ADDONS section above # update the NOT INSTALLABLE ADDONS section above
- id: oca-update-pre-commit-excluded-addons - id: oca-update-pre-commit-excluded-addons
...@@ -48,10 +55,11 @@ repos: ...@@ -48,10 +55,11 @@ repos:
hooks: hooks:
- id: black - id: black
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.6.2 rev: v2.1.2
hooks: hooks:
- id: prettier - id: prettier
name: prettier (with plugin-xml) name: prettier (with plugin-xml)
exclude: ^datas/
additional_dependencies: additional_dependencies:
- "prettier@2.1.2" - "prettier@2.1.2"
- "@prettier/plugin-xml@0.12.0" - "@prettier/plugin-xml@0.12.0"
...@@ -59,7 +67,7 @@ repos: ...@@ -59,7 +67,7 @@ repos:
- --plugin=@prettier/plugin-xml - --plugin=@prettier/plugin-xml
files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$
- repo: https://github.com/pre-commit/mirrors-eslint - repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.15.0 rev: v7.8.1
hooks: hooks:
- id: eslint - id: eslint
verbose: true verbose: true
...@@ -67,7 +75,7 @@ repos: ...@@ -67,7 +75,7 @@ repos:
- --color - --color
- --fix - --fix
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0 rev: v3.2.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
# exclude autogenerated files # exclude autogenerated files
...@@ -89,37 +97,33 @@ repos: ...@@ -89,37 +97,33 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
args: ["--fix=lf"] args: ["--fix=lf"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.32.1 rev: v2.7.2
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: ["--keep-percent-format"] args: ["--keep-percent-format"]
- repo: https://github.com/PyCQA/isort - repo: https://github.com/PyCQA/isort
rev: 5.10.1 rev: 5.12.0
hooks: hooks:
- id: isort - id: isort
name: isort except __init__.py name: isort except __init__.py
args: args:
- --settings=. - --settings=.
exclude: /__init__\.py$ exclude: /__init__\.py$
- repo: https://gitlab.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: 3.9.2 rev: 3.8.3
hooks: hooks:
- id: flake8 - id: flake8
name: flake8 name: flake8
additional_dependencies: ["flake8-bugbear==20.1.4"] additional_dependencies: ["flake8-bugbear==20.1.4"]
- repo: https://github.com/PyCQA/pylint - repo: https://github.com/OCA/pylint-odoo
rev: v2.11.1 rev: 7.0.2
hooks: hooks:
- id: pylint - id: pylint_odoo
name: pylint with optional checks name: pylint with optional checks
args: args:
- --rcfile=.pylintrc - --rcfile=.pylintrc
- --exit-zero - --exit-zero
verbose: true verbose: true
additional_dependencies: &pylint_deps - id: pylint_odoo
- pylint-odoo==5.0.5
- id: pylint
name: pylint with mandatory checks
args: args:
- --rcfile=.pylintrc-mandatory - --rcfile=.pylintrc-mandatory
additional_dependencies: *pylint_deps
...@@ -4,48 +4,56 @@ ...@@ -4,48 +4,56 @@
<!-- Email d'avis de prélèvement --> <!-- Email d'avis de prélèvement -->
<record id="email_template_payment_order" model="mail.template"> <record id="email_template_payment_order" model="mail.template">
<field name="name">CG SCOP : Prélèvements</field> <field name="name">CG SCOP : Prélèvements</field>
<field <field name="model_id" ref="account_payment_order.model_account_payment_order"/>
name="model_id" <field name="email_from">"Confédération Générale des Scop et Scic" &lt;administratif.cg@scop.coop&gt;</field>
ref="account_payment_order.model_account_payment_order" <field name="reply_to">"Confédération Générale des Scop et Scic" &lt;administratif.cg@scop.coop&gt;</field>
/>
<field
name="email_from"
>"Confédération Générale des Scop et Scic" &lt;administratif.cg@scop.coop&gt;</field>
<field
name="reply_to"
>"Confédération Générale des Scop et Scic" &lt;administratif.cg@scop.coop&gt;</field>
<field name="partner_to">${object.get_recipients()}</field> <field name="partner_to">${object.get_recipients()}</field>
<field name="subject">CG SCOP : Avis de prélèvement</field> <field name="subject">CG SCOP : Avis de prélèvement</field>
<field name="body_html" type="html"> <field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;"> <div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;"> <p style="margin: 0px; padding: 0px; font-size: 13px;">
<p>${object.get_email_values().get("partner_id").member_number} - ${object.get_email_values().get("partner_id").name}</p>
<p>&#160;</p>
<p>Chère Coopératrice, Cher Coopérateur,</p> <p>Chère Coopératrice, Cher Coopérateur,</p>
<p>&#160;</p> <p>&#160;</p>
<p <p>&#160;</p>
>Vous avez choisi de régler vos cotisations à la Confédération générale des Scop et des Scic par prélèvement bancaire.</p> <p>
<p Vous avez choisi de régler vos cotisations à la Confédération générale des Scop et des Scic par prélèvement bancaire.
>Nous vous informons que nous allons procéder le ${object.get_email_values().get("date").strftime('%d/%m/%Y')} à un prélèvement sur votre compte ${object.get_email_values().get("bank")} de ${format_amount(object.get_email_values().get("total"), object.company_currency_id)}</p> </p>
<p>
Nous vous informons que nous avons procédé ce jour à un ordre de prélèvement qui sera présenté au débit de votre compte le ${object.get_email_values().get("date").strftime('%d/%m/%Y')}.
</p>
<p>&#160;</p>
<p>
Le mandat de prélèvement enregistré pour votre coopérative est le suivant : ${object.get_email_values().get("bank")}
</p>
<p>&#160;</p>
<p>
Ce courriel vous est envoyé à titre informatif, l’ordre de prélèvement ne peut plus être arrêté en banque, sauf par vos soins en prenant contact avec votre établissement bancaire.
</p>
<p>Dans ce cas, nous vous remercions de bien vouloir nous en informer.</p>
<p>&#160;</p>
<p>
En cas de difficulté économique, nous vous invitons également à vous rapprocher de votre délégation régionale.
</p>
<p>&#160;</p> <p>&#160;</p>
<p> <p>
Ce prélèvement correspond au paiement des cotisations : Ce prélèvement correspond au paiement des cotisations :
<ul> <ul>
% for line in object.get_email_values().get("deadline"): % for line in object.get_email_values().get("deadline"):
% set quarter = "er" if line.get("cotiz_quarter") == "1" else "ème" % set quarter = "er" if line.get("quarter") == "1" else "ème"
<li> <li>
${line.get("cotiz_quarter")}${quarter} Trimestre ${line.get("year")} : ${format_amount(line.get("amount_total_signed"), object.company_currency_id)} ${line.get("quarter")}${quarter} Trimestre ${line.get("year")} : ${format_amount(line.get("amount"), object.company_currency_id)}
</li> </li>
% endfor % endfor
</ul> </ul>
</p> </p>
<p>&#160;</p> <p>&#160;</p>
<p
>Nous vous rappelons que les bordereaux de cotisations sont désormais mis à disposition dans <a
href="https://extranet.scop.coop/"
>votre espace extranet</a> et ne sont plus transmis par courrier.</p>
<p> <p>
Pour toute question relative à vos cotisations appelées par la CGSCOP, notre équipe est à votre disposition par téléphone au 01 44 85 47 00 ou par courriel à <a Nous vous rappelons que les bordereaux de cotisations sont mis à disposition dans <a href="https://extranet.scop.coop/">votre espace extranet</a> et ne sont plus transmis par courrier.
href="mailto:administratif.cg@scop.coop" </p>
>administratif.cg@scop.coop</a>. <p>
Pour toute question relative à vos cotisations appelées par la CGSCOP, notre équipe est à votre disposition par téléphone au 01 44 85 47 00 ou par courriel à <a href="mailto:administratif.cg@scop.coop">administratif.cg@scop.coop</a>.
</p> </p>
<p>&#160;</p> <p>&#160;</p>
<p <p
......
...@@ -49,10 +49,12 @@ class AccountBankingMandate(models.Model): ...@@ -49,10 +49,12 @@ class AccountBankingMandate(models.Model):
Affecte le mandat courant pur la facture passée en paramètre Affecte le mandat courant pur la facture passée en paramètre
:param invoice : objet account.move :param invoice : objet account.move
""" """
payment_mode = self.env["account.payment.mode"].search([ payment_mode = self.env["account.payment.mode"].search(
[
("payment_method_id.code", "=", "sepa_direct_debit"), ("payment_method_id.code", "=", "sepa_direct_debit"),
("company_id", "=", self.env.company.id) ("company_id", "=", self.env.company.id),
]) ]
)
if not payment_mode: if not payment_mode:
raise UserError(_("Aucun mode de prélèvement SEPA configuré.")) raise UserError(_("Aucun mode de prélèvement SEPA configuré."))
...@@ -70,9 +72,10 @@ class AccountBankingMandate(models.Model): ...@@ -70,9 +72,10 @@ class AccountBankingMandate(models.Model):
Supprime le mandat courant pur la facture passée en paramètre Supprime le mandat courant pur la facture passée en paramètre
:param invoice : objet account.move :param invoice : objet account.move
""" """
payment_mode = self.env["account.payment.mode"].search([ payment_mode = self.env["account.payment.mode"].search(
("name", "ilike", "Virement"), ("company_id", "=", self.env.company.id) [("name", "ilike", "Virement"), ("company_id", "=", self.env.company.id)],
], limit=1) limit=1,
)
for invoice in invoice_ids: for invoice in invoice_ids:
invoice.update( invoice.update(
{ {
......
# Copyright 2020 Le Filament # Copyright 2020 Le Filament
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from itertools import groupby
from odoo import _, fields, models from odoo import _, fields, models
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
...@@ -33,8 +35,11 @@ class AccountPaymentOrder(models.Model): ...@@ -33,8 +35,11 @@ class AccountPaymentOrder(models.Model):
def _compute_bank_line_amount(self): def _compute_bank_line_amount(self):
for po in self: for po in self:
po.bank_line_amount = sum(po.payment_ids.filtered( po.bank_line_amount = sum(
lambda p: not p.reversed_entry_id).mapped("amount_total_signed")) po.payment_ids.filtered(lambda p: not p.reversed_entry_id).mapped(
"amount_total_signed"
)
)
def _compute_attachment_ids(self): def _compute_attachment_ids(self):
Attachment = self.env["ir.attachment"] Attachment = self.env["ir.attachment"]
...@@ -124,11 +129,7 @@ class AccountPaymentOrder(models.Model): ...@@ -124,11 +129,7 @@ class AccountPaymentOrder(models.Model):
try: try:
template = self.env.ref("cgscop_cotisation.email_template_payment_order") template = self.env.ref("cgscop_cotisation.email_template_payment_order")
except Exception: except Exception:
raise UserError( raise UserError(_("Aucun modèle d'e-mail n'a été trouvé."))
_(
"Aucun modèle d'e-mail n'a été trouvé."
)
)
# Get partners # Get partners
partner_ids = self.payment_line_ids.mapped("partner_id") partner_ids = self.payment_line_ids.mapped("partner_id")
for partner in partner_ids: for partner in partner_ids:
...@@ -178,20 +179,32 @@ class AccountPaymentOrder(models.Model): ...@@ -178,20 +179,32 @@ class AccountPaymentOrder(models.Model):
partner_line_ids = self.payment_line_ids.filtered( partner_line_ids = self.payment_line_ids.filtered(
lambda l: l.partner_id == partner_id lambda l: l.partner_id == partner_id
) )
invoice_ids = partner_line_ids.mapped("move_line_id.move_id").filtered(
"is_contribution" quarter_detail = []
quarter_agg = []
for line in partner_line_ids:
invoice_id = line.move_line_id.move_id
quarter_detail.append(
("%s-%s" % (invoice_id.year, invoice_id.cotiz_quarter), line.amount_currency)
) )
quarter_detail.sort(key=lambda x: x[0])
for quarter, values in groupby(quarter_detail, key=lambda x: x[0]):
amount = 0
for val in values:
amount += val[1]
quarter_agg.append({
"year": quarter[0:4],
"quarter": quarter[-1],
"amount": amount,
})
return { return {
"partner_id": partner_id,
"total": sum(partner_line_ids.mapped("amount_currency")), "total": sum(partner_line_ids.mapped("amount_currency")),
"date": partner_line_ids.mapped("date")[0], "date": partner_line_ids.mapped("date")[0],
"bank": partner_line_ids.mapped("partner_bank_id.acc_number")[0], "bank": partner_line_ids.mapped("partner_bank_id.acc_number")[0],
"deadline": invoice_ids.read_group( "deadline": quarter_agg,
domain=[("id", "in", invoice_ids.ids)],
fields=["year", "cotiz_quarter", "amount_total_signed"],
groupby=["year", "cotiz_quarter"],
orderby="year,cotiz_quarter",
lazy=False,
),
} }
def get_recipients(self): def get_recipients(self):
......
...@@ -137,10 +137,27 @@ ...@@ -137,10 +137,27 @@
<h1><field name="name" /></h1> <h1><field name="name" /></h1>
<group> <group>
<group> <group>
<field name="datas" filename="name" attrs="{'invisible':[('type','=','url')]}" string="Télécharger le fichier"/> <field
<field name="name" invisible="1" attrs="{'invisible':[('type','=','url')]}" class="oe_inline oe_right"/> name="datas"
<field name="url" widget="url" attrs="{'invisible':[('type','=','binary')]}"/> filename="name"
<field name="mimetype" groups="base.group_no_one"/> attrs="{'invisible':[('type','=','url')]}"
string="Télécharger le fichier"
/>
<field
name="name"
invisible="1"
attrs="{'invisible':[('type','=','url')]}"
class="oe_inline oe_right"
/>
<field
name="url"
widget="url"
attrs="{'invisible':[('type','=','binary')]}"
/>
<field
name="mimetype"
groups="base.group_no_one"
/>
<field name="type" /> <field name="type" />
</group> </group>
<group> <group>
......
...@@ -20,10 +20,12 @@ class ScopDecesWizard(models.TransientModel): ...@@ -20,10 +20,12 @@ class ScopDecesWizard(models.TransientModel):
if mandate_ids: if mandate_ids:
for mandate in mandate_ids: for mandate in mandate_ids:
mandate.update({"state": "expired"}) mandate.update({"state": "expired"})
invoice_ids = self.env["account.move"].search([ invoice_ids = self.env["account.move"].search(
[
("mandate_id", "=", mandate.id), ("mandate_id", "=", mandate.id),
("move_type", "in", ("out_invoice", "out_refund")), ("move_type", "in", ("out_invoice", "out_refund")),
("state", "in", ("draft", "posted")), ("state", "in", ("draft", "posted")),
("payment_state", "in", ("draft", "not_paid", "partial")), ("payment_state", "in", ("draft", "not_paid", "partial")),
]) ]
)
mandate._remove_invoice_mandate(invoice_ids) mandate._remove_invoice_mandate(invoice_ids)
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter