Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion account_credit_control/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Account Credit Control",
"version": "18.0.2.0.0",
"version": "18.0.3.0.0",
"author": "Camptocamp,"
"Odoo Community Association (OCA),"
"Okia,"
Expand Down
12 changes: 6 additions & 6 deletions account_credit_control/data/data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<field name="delay_days" eval="0" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_no_follow" />
<field name="channel">email</field>
<field name="channel_email" eval="1" />
<field name="custom_text">Manual no follow</field>
<field name="custom_mail_text">Manual no follow</field>
</record>
Expand All @@ -52,7 +52,7 @@
<field name="delay_days" eval="10" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_3_time" />
<field name="channel">email</field>
<field name="channel_email" eval="1" />
<field
name="custom_text"
>Our records indicate that we have not received the payment of the invoice mentioned below.
Expand Down Expand Up @@ -81,7 +81,7 @@ Best regards
<field name="delay_days" eval="30" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_3_time" />
<field name="channel">email</field>
<field name="channel_email" eval="1" />
<field
name="custom_text"
>Our records indicate that we have not yet received the payment of the invoice mentioned below despite our first reminder.
Expand Down Expand Up @@ -111,7 +111,7 @@ Best regards
<field name="delay_days" eval="10" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_3_time" />
<field name="channel">letter</field>
<field name="channel_letter" eval="1" />
<field name="custom_text">
Our records indicate that we still have not received the payment of the invoice mentioned below despite our two reminders.
If payment have already been sent, please disregard this notice. If not, please proceed with payment.
Expand Down Expand Up @@ -153,7 +153,7 @@ Best regards
<field name="delay_days" eval="30" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_2_time" />
<field name="channel">email</field>
<field name="channel_email" eval="1" />
<field
name="custom_text"
>Our records indicate that we have not received the payment of the invoice mentioned below.
Expand Down Expand Up @@ -182,7 +182,7 @@ Best regards
<field name="delay_days" eval="60" />
<field name="email_template_id" ref="email_template_credit_control_base" />
<field name="policy_id" ref="credit_control_2_time" />
<field name="channel">letter</field>
<field name="channel_letter" eval="1" />
<field
name="custom_text"
>Our records indicate that we still have not received the payment of the mentioned below invoice despite our reminder.
Expand Down
53 changes: 53 additions & 0 deletions account_credit_control/migrations/18.0.3.0.0/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
cr = env.cr
if openupgrade.column_exists(cr, "credit_control_line", "channel_old"):
openupgrade.map_values(
cr,
"channel_old",
"channel_letter",
[("letter", "t")],
table="credit_control_line",
)
openupgrade.map_values(
cr,
"channel_old",
"channel_email",
[("email", "t")],
table="credit_control_line",
)
openupgrade.map_values(
cr,
"channel_old",
"channel_phone",
[("phone", "t")],
table="credit_control_line",
)
if openupgrade.column_exists(cr, "credit_control_policy", "channel_old"):
openupgrade.map_values(
cr,
"channel_old",
"channel_letter",
[("letter", "t")],
table="credit_control_policy",
)
openupgrade.map_values(
cr,
"channel_old",
"channel_email",
[("email", "t")],
table="credit_control_policy",
)
openupgrade.map_values(
cr,
"channel_old",
"channel_phone",
[("phone", "t")],
table="credit_control_policy",
)
28 changes: 28 additions & 0 deletions account_credit_control/migrations/18.0.3.0.0/pre-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2025 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).


from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
# Preserve channel historic data from credit.control.line records
if openupgrade.column_exists(env.cr, "credit_control_line", "channel"):
openupgrade.copy_columns(
env.cr,
{
"credit_control_line": [
("channel", "channel_old", None),
],
},
)
if openupgrade.column_exists(env.cr, "credit_control_policy", "channel"):
openupgrade.copy_columns(
env.cr,
{
"credit_control_policy": [
("channel", "channel_old", None),
],
},
)
4 changes: 2 additions & 2 deletions account_credit_control/models/credit_control_communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def _send_communications_by_email(self):
),
)

def _mark_credit_line_as_sent(self):
def _mark_credit_line_as_sent(self, channel):
lines = self.mapped("credit_control_line_ids")
lines.write({"state": "sent"})
lines._set_sent(channel)
return lines
73 changes: 61 additions & 12 deletions account_credit_control/models/credit_control_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError

from .credit_control_policy import CHANNEL_LIST


class CreditControlLine(models.Model):
"""A credit control line describes an amount due by a customer
Expand Down Expand Up @@ -62,11 +60,15 @@ class CreditControlLine(models.Model):
"Draft and ignored lines will be "
"generated again on the next run.",
)
channel = fields.Selection(
selection=CHANNEL_LIST,
required=True,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We lose this required, I guess we should add a check to make sure that at least one channel field is True.

readonly=False,
)

channel_email = fields.Boolean(string="By e-mail")
channel_letter = fields.Boolean(string="By post")
channel_phone = fields.Boolean(string="By phone")

email_sent = fields.Boolean()
letter_sent = fields.Boolean()
phone_sent = fields.Boolean()

invoice_id = fields.Many2one(comodel_name="account.move", readonly=True)
partner_id = fields.Many2one(
comodel_name="res.partner",
Expand Down Expand Up @@ -163,18 +165,21 @@ def _prepare_from_move_line(
self, move_line, level, controlling_date, open_amount, default_lines_vals
):
"""Create credit control line"""
channel = level.channel
channel_email = level.channel_email
channel_letter = level.channel_letter
partner = move_line.partner_id
# Fallback to letter
if channel == "email" and partner and not partner.email:
channel = "letter"
# Fallback to letter on missing email address
if channel_email and partner and not partner.email:
channel_email = False
channel_letter = True
data = default_lines_vals.copy()
data.update(
{
"date": controlling_date,
"date_due": move_line.date_maturity,
"state": "draft",
"channel": channel,
"channel_email": channel_email,
"channel_letter": channel_letter,
"invoice_id": (move_line.move_id.id if move_line.move_id else False),
"partner_id": partner.id,
"amount_due": (
Expand Down Expand Up @@ -273,6 +278,50 @@ def create_or_update_from_mv_lines(

return new_lines

def run_channel_letter(self):
if not self:
return
wiz = self.env["credit.control.printer"].create({"line_ids": self.ids})
wiz.print_lines()

def run_channel_email(self):
if not self:
return
comm_obj = self.env["credit.control.communication"]
comms = comm_obj._generate_comm_from_credit_lines(self)
comms._generate_emails()

def run_channel_action(self):
lines = self.filtered(lambda rec: rec.state == "to_be_sent")
letter_lines = lines.filtered("channel_letter")
letter_lines.run_channel_letter()

email_lines = lines.filtered("channel_email")
email_lines.run_channel_email()

def _channel_list(self):
return ["email", "letter", "phone"]

def _update_state_on_sent(self):
for rec in self:
sent = True
for chan in self._channel_list():
to_be_sent = rec[f"channel_{chan}"]
sent_ok = rec[f"{chan}_sent"]
if to_be_sent and not sent_ok:
sent = False
break
if sent:
rec.state = "sent"

def _set_sent(self, channel):
"""Check all selected channels are done"""
channels = self._channel_list()
assert channel in channels
if channel:
self.write({f"{channel}_sent": True})
self._update_state_on_sent()

def unlink(self):
for line in self:
if line.state != "draft":
Expand Down
6 changes: 3 additions & 3 deletions account_credit_control/models/credit_control_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from odoo.exceptions import UserError, ValidationError
from odoo.osv import expression

CHANNEL_LIST = [("letter", "Letter"), ("email", "Email"), ("phone", "Phone")]


class CreditControlPolicy(models.Model):
"""Define a policy of reminder"""
Expand Down Expand Up @@ -320,7 +318,9 @@ class CreditControlPolicyLevel(models.Model):
domain=[("model", "=", "credit.control.communication")],
required=True,
)
channel = fields.Selection(selection=CHANNEL_LIST, required=True)
channel_email = fields.Boolean(string="By e-mail")
channel_letter = fields.Boolean(string="By post")
channel_phone = fields.Boolean(string="By phone")
custom_text = fields.Text(string="Custom Message", required=True, translate=True)
mail_show_invoice_detail = fields.Boolean(string="Show Invoice Details in mail")
custom_mail_text = fields.Html(
Expand Down
16 changes: 2 additions & 14 deletions account_credit_control/models/credit_control_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def generate_credit_lines(self):
"""
try:
self.env.cr.execute(
"SELECT id FROM credit_control_run" " LIMIT 1 FOR UPDATE NOWAIT"
"SELECT id FROM credit_control_run LIMIT 1 FOR UPDATE NOWAIT"
)
except Exception as err:
# In case of exception openerp will do a rollback
Expand Down Expand Up @@ -200,16 +200,4 @@ def set_to_ready_lines(self):
self.hide_change_state_button = True

def run_channel_action(self):
self.ensure_one()
lines = self.line_ids.filtered(lambda x: x.state == "to_be_sent")
letter_lines = lines.filtered(lambda x: x.channel == "letter")
email_lines = lines.filtered(lambda x: x.channel == "email")
if email_lines:
comm_obj = self.env["credit.control.communication"]
comms = comm_obj._generate_comm_from_credit_lines(email_lines)
comms._generate_emails()
if letter_lines:
wiz = self.env["credit.control.printer"].create(
{"line_ids": letter_lines.ids}
)
return wiz.print_lines
self.mapped("line_ids").run_channel_action()
6 changes: 4 additions & 2 deletions account_credit_control/models/mail_mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ def _update_control_line_status(self):
lines = self.env["credit.control.line"].search(
[("communication_id", "=", msg.res_id), ("state", "=", "queued")]
)
new_state = "sent" if mail.state == "sent" else "email_error"
lines.write({"state": new_state})
if mail.state == "sent":
lines._set_sent("email")
else:
lines.write({"state": "email_error"})

def _postprocess_sent_message(
self, success_pids, failure_reason=False, failure_type=None
Expand Down
Loading
Loading