[IMP] account_peppol: improve move states and filters
Structure `peppol_move_state` according to the following logic: 1. Ready to Send / Invoices confirmed addressed to partners that are Peppol valid and not in one of the other statuses. Default behavior upon posting such an invoice. 2. Queued / In case of asynchronous sending only, the instruction to send has been given via the Send & Print but the cron wasn't run yet. It is still possible to cancel the sending. 3. Pending Reception / Too late to cancel, synchronous or asynchronous sending makes it now impossible to cancel the sending 4. Canceled / Once asked explicitly by the user. It's instant. 5. Done / Upon confirmation or delivery received from the AP 6. Error / Upon confirmation of a notification of error received from the AP Add an action on sale journals to open invoices that are ready to be sent via Peppol - Peppol ready filter in Customer Invoices view - Rename `PEPPOL state` to `Peppol status` for consistency - Pre-fill valid phone numbers in `account_peppol_phone_number` field - Fix async sending in demo mode closes odoo/odoo#139615 Signed-off-by: Laurent Smet (las) <las@odoo.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import _, fields, models
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
@@ -22,3 +22,14 @@ class AccountJournal(models.Model):
|
||||
('company_id', 'in', self.company_id.ids),
|
||||
])
|
||||
edi_users._peppol_get_message_status()
|
||||
|
||||
def action_peppol_ready_moves(self):
|
||||
return {
|
||||
'name': _("Peppol Ready invoices"),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'list',
|
||||
'res_model': 'account.move',
|
||||
'context': {
|
||||
'search_default_peppol_ready': 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,16 @@ class AccountMove(models.Model):
|
||||
peppol_message_uuid = fields.Char(string='PEPPOL message ID')
|
||||
peppol_move_state = fields.Selection(
|
||||
selection=[
|
||||
('to_send', 'To Send'),
|
||||
('processing', 'Processing'),
|
||||
('ready', 'Ready to send'),
|
||||
('to_send', 'Queued'),
|
||||
('processing', 'Pending Reception'),
|
||||
('canceled', 'Canceled'),
|
||||
('done', 'Done'),
|
||||
('error', 'Error'),
|
||||
],
|
||||
compute='_compute_peppol_move_state', store=True,
|
||||
string='PEPPOL status',
|
||||
copy=False,
|
||||
readonly=True,
|
||||
)
|
||||
peppol_is_demo_uuid = fields.Boolean(compute="_compute_peppol_is_demo_uuid")
|
||||
|
||||
@@ -29,8 +30,22 @@ class AccountMove(models.Model):
|
||||
if any(move.peppol_move_state in {'processing', 'done'} for move in self):
|
||||
raise UserError(_("Cannot cancel an entry that has already been sent to PEPPOL"))
|
||||
self.peppol_move_state = 'canceled'
|
||||
self.send_and_print_values = False
|
||||
|
||||
@api.depends('peppol_message_uuid')
|
||||
def _compute_peppol_is_demo_uuid(self):
|
||||
for move in self:
|
||||
move.peppol_is_demo_uuid = (move.peppol_message_uuid or '').startswith('demo_')
|
||||
|
||||
@api.depends('state')
|
||||
def _compute_peppol_move_state(self):
|
||||
for move in self:
|
||||
if all([
|
||||
move.company_id.account_peppol_proxy_state == 'active',
|
||||
move.partner_id.account_peppol_is_endpoint_valid,
|
||||
move.state == 'posted',
|
||||
not move.peppol_move_state,
|
||||
]):
|
||||
move.peppol_move_state = 'ready'
|
||||
else:
|
||||
move.peppol_move_state = move.peppol_move_state
|
||||
|
||||
@@ -43,6 +43,7 @@ class ResCompany(models.Model):
|
||||
account_peppol_migration_key = fields.Char(string="Migration Key")
|
||||
account_peppol_phone_number = fields.Char(
|
||||
string='Phone number (for validation)',
|
||||
compute='_compute_account_peppol_phone_number', store=True, readonly=False,
|
||||
help='You will receive a verification code to this phone number',
|
||||
)
|
||||
account_peppol_proxy_state = fields.Selection(
|
||||
@@ -72,7 +73,7 @@ class ResCompany(models.Model):
|
||||
# HELPER METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _sanitize_peppol_phone_number(self):
|
||||
def _sanitize_peppol_phone_number(self, phone_number=None):
|
||||
self.ensure_one()
|
||||
|
||||
error_message = _(
|
||||
@@ -83,7 +84,10 @@ class ResCompany(models.Model):
|
||||
if not phonenumbers:
|
||||
raise ValidationError(error_message)
|
||||
|
||||
phone_number = self.account_peppol_phone_number
|
||||
phone_number = phone_number or self.account_peppol_phone_number
|
||||
if not phone_number:
|
||||
return
|
||||
|
||||
if not phone_number.startswith('+'):
|
||||
phone_number = f'+{phone_number}'
|
||||
|
||||
@@ -164,6 +168,17 @@ class ResCompany(models.Model):
|
||||
if not company.account_peppol_contact_email:
|
||||
company.account_peppol_contact_email = company.email
|
||||
|
||||
@api.depends('phone')
|
||||
def _compute_account_peppol_phone_number(self):
|
||||
for company in self:
|
||||
if not company.account_peppol_phone_number:
|
||||
try:
|
||||
# precompute only if it's a valid phone number
|
||||
company._sanitize_peppol_phone_number(company.phone)
|
||||
company.account_peppol_phone_number = company.phone
|
||||
except ValidationError:
|
||||
continue
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# LOW-LEVEL METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@@ -58,7 +58,7 @@ def _mock_make_request(func, self, *args, **kwargs):
|
||||
return {
|
||||
'messages': [{
|
||||
'message_uuid': 'demo_%s' % uuid.uuid4(),
|
||||
} for i in args[1]],
|
||||
} for i in args[1]['documents']],
|
||||
}
|
||||
|
||||
endpoint = args[0].split('/')[-1]
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
<div class="w-100">
|
||||
<a type="object" name="peppol_get_message_status" groups="account.group_account_invoice">Fetch Peppol invoice status</a>
|
||||
</div>
|
||||
<div class="w-100">
|
||||
<a type="object" name="action_peppol_ready_moves" groups="account.group_account_invoice">Peppol ready invoices</a>
|
||||
</div>
|
||||
</t>
|
||||
<t t-elif="journal_type == 'purchase'">
|
||||
<t t-if="record.is_peppol_journal.raw_value">
|
||||
|
||||
@@ -72,7 +72,12 @@
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//search/group/filter[@name='status']" position="after">
|
||||
<filter string="PEPPOL state" name="peppol_move_state" context="{'group_by': 'peppol_move_state'}"/>
|
||||
<filter string="Peppol status" name="peppol_move_state" context="{'group_by': 'peppol_move_state'}"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@name='to_check']" position='after'>
|
||||
<separator/>
|
||||
<filter name="peppol_ready" string="Peppol Ready" domain="[('state', '=', 'posted'), ('peppol_move_state', '=', 'ready')]"/>
|
||||
<separator/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -107,6 +107,10 @@ class AccountMoveSend(models.TransientModel):
|
||||
|
||||
if all([self.checkbox_send_peppol, self.enable_peppol, self.enable_ubl_cii_xml, not self.checkbox_ubl_cii_xml]):
|
||||
self.checkbox_ubl_cii_xml = True
|
||||
if self.checkbox_send_peppol and self.enable_peppol:
|
||||
for move in self.move_ids:
|
||||
if not move.peppol_move_state or move.peppol_move_state == 'ready':
|
||||
move.peppol_move_state = 'to_send'
|
||||
|
||||
return super().action_send_and_print(force_synchronous=force_synchronous, allow_fallback_pdf=allow_fallback_pdf, **kwargs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user