Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][IMP] sale_automatic_workflow: add send invoice option - bp from 16.0 #3520

Open
wants to merge 1 commit into
base: 14.0
Choose a base branch
from
Open
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: 2 additions & 0 deletions sale_automatic_workflow/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ A workflow can:
* Send order confirmation mail (only when order confirmed)
* Create an invoice
* Validate the invoice
* Send the invoice via e-mail
* Confirm the picking

This module is used by Magentoerpconnect and Prestashoperpconnect.
Expand Down Expand Up @@ -91,6 +92,7 @@ Contributors
* Akim Juillerat <akim.juillerat@camptocamp.com>
* Thomas Fossoul <thomas@niboo.com>
* Phuc Tran Thanh <phuc@trobz.com>
* John Herholz <j.longneck@gmail.com>

Other credits
~~~~~~~~~~~~~
Expand Down
13 changes: 13 additions & 0 deletions sale_automatic_workflow/data/automatic_workflow_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
>[('state', '=', 'draft'), ('posted_before', '=', False)]</field>
<field name="user_id" ref="base.user_root" />
</record>
<record id="automatic_workflow_send_invoice_filter" model="ir.filters">
<field name="name">Automatic Workflow Send Invoice Filter</field>
<field name="model_id">account.move</field>
<field
name="domain"
>[('state', '=', 'posted'), ('is_move_sent', '=', False), ('move_type', '=', 'out_invoice')]</field>
<field name="user_id" ref="base.user_root" />
</record>
<record id="automatic_workflow_sale_done_filter" model="ir.filters">
<field name="name">Automatic Workflow Sale Done Filter</field>
<field name="model_id">sale.order</field>
Expand Down Expand Up @@ -66,6 +74,11 @@
name="validate_invoice_filter_id"
eval="automatic_workflow_validate_invoice_filter"
/>
<field name="send_invoice" eval="1" />
<field
name="send_invoice_filter_id"
eval="automatic_workflow_send_invoice_filter"
/>
<field name="invoice_date_is_order_date" eval="0" />
<field name="validate_picking" eval="0" />
<field name="picking_filter_id" eval="automatic_workflow_picking_filter" />
Expand Down
24 changes: 23 additions & 1 deletion sale_automatic_workflow/i18n/sale_automatic_workflow.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-31 11:29+0000\n"
"PO-Revision-Date: 2024-12-31 11:29+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -59,6 +61,11 @@ msgstr ""
msgid "Automatic Workflow Sale Done Filter"
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.filters,name:sale_automatic_workflow.automatic_workflow_send_invoice_filter
msgid "Automatic Workflow Send Invoice Filter"
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.filters,name:sale_automatic_workflow.automatic_workflow_validate_invoice_filter
msgid "Automatic Workflow Validate Invoice Filter"
Expand Down Expand Up @@ -279,6 +286,21 @@ msgid ""
"pickings..."
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.model.fields,field_description:sale_automatic_workflow.field_sale_workflow_process__send_invoice
msgid "Send Invoice"
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.model.fields,field_description:sale_automatic_workflow.field_sale_workflow_process__send_invoice_filter_id
msgid "Send Invoice Filter"
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.model.fields,field_description:sale_automatic_workflow.field_sale_workflow_process__send_invoice_filter_domain
msgid "Send Invoice Filter Domain"
msgstr ""

#. module: sale_automatic_workflow
#: model:ir.model.fields,field_description:sale_automatic_workflow.field_sale_workflow_process__send_order_confirmation_mail
msgid "Send order confirmation mail"
Expand Down Expand Up @@ -355,4 +377,4 @@ msgstr ""
#: code:addons/sale_automatic_workflow/models/sale_order.py:0
#, python-format
msgid "Workflow Warning"
msgstr ""
msgstr ""
51 changes: 51 additions & 0 deletions sale_automatic_workflow/models/automatic_workflow_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,53 @@ def _validate_invoices(self, validate_invoice_filter):
invoice.with_company(invoice.company_id), validate_invoice_filter
)

def _do_send_invoice(self, invoice, domain_filter):
"""Send an invoice by email, re-filter to ensure
it has not been sent since"""
if not self.env["account.move"].search_count(
[("id", "=", invoice.id)] + domain_filter
):
return "{} {} job bypassed".format(invoice.display_name, invoice)

# take the context from the actual action_invoice_sent method
action = invoice.action_invoice_sent()
action_context = action["context"]

# Create the email using the wizard
invoice_send_wizard = (
self.env["account.invoice.send"]
.with_context(
action_context,
mark_invoice_as_sent=True,
active_ids=[invoice.id],
force_email=True,
)
.create(
{
"is_print": False,
"composition_mode": "comment",
"model": "account.move",
"res_id": invoice.id,
}
)
)

invoice_send_wizard.onchange_is_email()
invoice_send_wizard._send_email()

return "{} {} sent invoice successfully".format(invoice.display_name, invoice)

@api.model
def _send_invoices(self, send_invoice_filter):
move_obj = self.env["account.move"]
invoices = move_obj.search(send_invoice_filter)
_logger.debug("Invoices to send: %s", invoices.ids)
for invoice in invoices:
with savepoint(self.env.cr):
self._do_send_invoice(
invoice.with_company(invoice.company_id), send_invoice_filter
)

def _do_validate_picking(self, picking, domain_filter):
"""Validate a stock.picking"""
picking.validate_picking()
Expand Down Expand Up @@ -190,6 +237,10 @@ def run_with_workflow(self, sale_workflow):
safe_eval(sale_workflow.validate_invoice_filter_id.domain)
+ workflow_domain
)
if sale_workflow.send_invoice:
self._send_invoices(
safe_eval(sale_workflow.send_invoice_filter_id.domain) + workflow_domain
)
if sale_workflow.sale_done:
self._sale_done(
safe_eval(sale_workflow.sale_done_filter_id.domain) + workflow_domain
Expand Down
12 changes: 12 additions & 0 deletions sale_automatic_workflow/models/sale_workflow_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ def _default_filter(self, xmlid):
string="Validate Invoice Filter Domain",
related="validate_invoice_filter_id.domain",
)
send_invoice = fields.Boolean()
send_invoice_filter_domain = fields.Text(
string="Send Invoice Filter Domain",
related="send_invoice_filter_id.domain",
)
validate_picking = fields.Boolean(string="Confirm and Transfer Picking")
picking_filter_domain = fields.Text(
string="Picking Filter Domain", related="picking_filter_id.domain"
Expand Down Expand Up @@ -113,6 +118,13 @@ def _default_filter(self, xmlid):
"sale_automatic_workflow." "automatic_workflow_validate_invoice_filter"
),
)
send_invoice_filter_id = fields.Many2one(
"ir.filters",
string="Send Invoice Filter",
default=lambda self: self._default_filter(
"sale_automatic_workflow." "automatic_workflow_send_invoice_filter"
),
)
sale_done_filter_id = fields.Many2one(
"ir.filters",
string="Sale Done Filter",
Expand Down
1 change: 1 addition & 0 deletions sale_automatic_workflow/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
* Akim Juillerat <akim.juillerat@camptocamp.com>
* Thomas Fossoul <thomas@niboo.com>
* Phuc Tran Thanh <phuc@trobz.com>
* John Herholz <j.longneck@gmail.com>
1 change: 1 addition & 0 deletions sale_automatic_workflow/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ A workflow can:
* Send order confirmation mail (only when order confirmed)
* Create an invoice
* Validate the invoice
* Send the invoice via e-mail
* Confirm the picking

This module is used by Magentoerpconnect and Prestashoperpconnect.
Expand Down
3 changes: 2 additions & 1 deletion sale_automatic_workflow/static/description/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
Expand Down Expand Up @@ -387,6 +386,7 @@ <h1 class="title">Sale Automatic Workflow</h1>
<li>Send order confirmation mail (only when order confirmed)</li>
<li>Create an invoice</li>
<li>Validate the invoice</li>
<li>Send the invoice via e-mail</li>
<li>Confirm the picking</li>
</ul>
</li>
Expand Down Expand Up @@ -438,6 +438,7 @@ <h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
<li>Akim Juillerat &lt;<a class="reference external" href="mailto:akim.juillerat&#64;camptocamp.com">akim.juillerat&#64;camptocamp.com</a>&gt;</li>
<li>Thomas Fossoul &lt;<a class="reference external" href="mailto:thomas&#64;niboo.com">thomas&#64;niboo.com</a>&gt;</li>
<li>Phuc Tran Thanh &lt;<a class="reference external" href="mailto:phuc&#64;trobz.com">phuc&#64;trobz.com</a>&gt;</li>
<li>John Herholz &lt;<a class="reference external" href="mailto:j.longneck&#64;gmail.com">j.longneck&#64;gmail.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
Expand Down
13 changes: 13 additions & 0 deletions sale_automatic_workflow/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ class TestCommon(SavepointCase):
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.user = cls.env["res.users"].create(
{
"name": "Sales Person",
"login": "salesperson",
"password": "salesperson",
"groups_id": [
(4, cls.env.ref("sales_team.group_sale_manager").id),
(4, cls.env.ref("account.group_account_manager").id),
],
}
)
cls.user.partner_id.email = "salesperson@example.com"


class TestAutomaticWorkflowMixin(object):
Expand Down Expand Up @@ -79,6 +91,7 @@ def create_full_automatic(self, override=None):
"validate_picking": True,
"create_invoice": True,
"validate_invoice": True,
"send_invoice": True,
"invoice_date_is_order_date": True,
}
)
Expand Down
46 changes: 46 additions & 0 deletions sale_automatic_workflow/tests/test_automatic_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from odoo import fields
from odoo.exceptions import UserError
from odoo.tests import tagged
from odoo.tools.safe_eval import safe_eval

from .common import TestAutomaticWorkflowMixin, TestCommon

Expand Down Expand Up @@ -234,3 +235,48 @@ def test_create_payment_with_invoice_currency_id(self):
)
self.assertTrue(payment_id)
self.assertEqual(invoice.currency_id.id, payment_id.currency_id.id)

def test_automatic_invoice_send_mail(self):
workflow = self.create_full_automatic()
workflow.send_invoice = False
sale = self.create_sale_order(workflow)
sale.user_id = self.user.id
sale._onchange_workflow_process_id()
self.run_job()
invoice = sale.invoice_ids
invoice.message_subscribe(partner_ids=[invoice.partner_id.id])
invoice.company_id.invoice_is_email = True
previous_message_ids = invoice.message_ids
workflow.send_invoice = True
sale._onchange_workflow_process_id()
self.run_job()

new_messages = self.env["mail.message"].search(
[
("id", "in", invoice.message_ids.ids),
("id", "not in", previous_message_ids.ids),
]
)

self.assertTrue(
new_messages.filtered(
lambda x: x.subtype_id == self.env.ref("mail.mt_comment")
)
)

def test_job_bypassing(self):
"""We can only test send_invoice for now as it is the only option
to actually implement this."""
workflow = self.create_full_automatic()
workflow_job = self.env["automatic.workflow.job"]
sale = self.create_sale_order(workflow)
sale._onchange_workflow_process_id()
send_invoice_filter = safe_eval(workflow.send_invoice_filter_id.domain)

# Trigger everything, then check if send invoice jobs is bypassed
self.run_job()

invoice = sale.invoice_ids
res_send_invoice = workflow_job._do_send_invoice(invoice, send_invoice_filter)

self.assertIn("job bypassed", res_send_invoice)
29 changes: 29 additions & 0 deletions sale_automatic_workflow/views/sale_workflow_process_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,35 @@
/>
</div>
</div>
<field name="send_invoice" />
<label
for="send_invoice_filter_id"
attrs="{'required':[('send_invoice','=',True)],
'invisible':[('send_invoice','!=',True)]}"
/>
<div
attrs="{'required':[('send_invoice','=',True)],
'invisible':[('send_invoice','!=',True)]}"
>
<field
name="send_invoice_filter_domain"
widget="domain"
attrs="{'invisible': [('send_invoice_filter_id', '=', False)]}"
options="{'model': 'account.move'}"
/>
<div class="oe_edit_only oe_inline">
Set selection based on a search filter:

<field
name="send_invoice_filter_id"
domain="[('model_id', '=', 'account.move')]"
class="oe_inline"
context="{'default_model_id': 'account.move', 'default_active': False, 'active_test': False}"
can_create="true"
can_write="true"
/>
</div>
</div>
<field name="register_payment" />
<label
for="payment_filter_id"
Expand Down
Loading