diff --git a/pos_ticket_send_by_mail/README.rst b/pos_ticket_send_by_mail/README.rst new file mode 100644 index 0000000000..91b5b90677 --- /dev/null +++ b/pos_ticket_send_by_mail/README.rst @@ -0,0 +1,35 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================= +POS Ticket Send By Mail +======================= + +This module allow to send the mail to customer from point of sale +base on configuration. + +Credits +======= + +Authors +~~~~~~~ + +* Druidoo + +Contributors +~~~~~~~~~~~~ + +* Iván Todorovich +* Phan Hong Phuc + +Maintainers +~~~~~~~~~~~ + +.. |maintainer-ivantodorovich| image:: https://github.com/ivantodorovich.png?size=40px + :target: https://github.com/ivantodorovich + :alt: ivantodorovich + +Current maintainer: + +|maintainer-ivantodorovich| diff --git a/pos_ticket_send_by_mail/__init__.py b/pos_ticket_send_by_mail/__init__.py new file mode 100644 index 0000000000..11e0198d26 --- /dev/null +++ b/pos_ticket_send_by_mail/__init__.py @@ -0,0 +1,6 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +from . import models diff --git a/pos_ticket_send_by_mail/__manifest__.py b/pos_ticket_send_by_mail/__manifest__.py new file mode 100644 index 0000000000..7d56a3a573 --- /dev/null +++ b/pos_ticket_send_by_mail/__manifest__.py @@ -0,0 +1,31 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +{ + "name": "POS Receipt By Email", + "version": "18.0.1.0.0", + "category": "Custom", + "author": "Druidoo, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/pos", + "license": "AGPL-3", + "depends": [ + "point_of_sale", + ], + "data": [ + "views/report_paperformat.xml", + "views/view_pos_config_settings.xml", + "data/email_template_data.xml", + "data/ir_cron_data.xml", + "views/view_res_partner.xml", + "views/report_receipt.xml", + ], + "assets": { + "point_of_sale._assets_pos": [ + "pos_ticket_send_by_mail/static/src/js/*", + "pos_ticket_send_by_mail/static/src/xml/*", + ], + }, + "installable": True, +} diff --git a/pos_ticket_send_by_mail/data/email_template_data.xml b/pos_ticket_send_by_mail/data/email_template_data.xml new file mode 100644 index 0000000000..de8e41befc --- /dev/null +++ b/pos_ticket_send_by_mail/data/email_template_data.xml @@ -0,0 +1,32 @@ + + + + + Send Receipt + {{ (object.user_id.company_id.email_formatted or user.email_formatted) }} + {{ object.user_id.company_id.name }} Received {{ object.pos_reference and object.pos_reference.split(' ')[1] or '' }} + {{ object.partner_id.id }} + + + + {{ object.partner_id.lang }} + +
+

Thank you for your visit !

+

You will find your receipt attached.

+

+

Sincerely,

+

The team of the cooperative

+
+
+
+
diff --git a/pos_ticket_send_by_mail/data/ir_cron_data.xml b/pos_ticket_send_by_mail/data/ir_cron_data.xml new file mode 100644 index 0000000000..a2d1f97b71 --- /dev/null +++ b/pos_ticket_send_by_mail/data/ir_cron_data.xml @@ -0,0 +1,11 @@ + + + + Send Reciept via Email + 1 + minutes + + model._send_order_cron() + code + + diff --git a/pos_ticket_send_by_mail/i18n/fr.po b/pos_ticket_send_by_mail/i18n/fr.po new file mode 100644 index 0000000000..53ae683ecb --- /dev/null +++ b/pos_ticket_send_by_mail/i18n/fr.po @@ -0,0 +1,224 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_ticket_send_by_mail +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-11-25 08:22+0000\n" +"PO-Revision-Date: 2025-11-25 08:22+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.report,print_report_name:pos_ticket_send_by_mail.action_report_pos_receipt +msgid "'POS-Receipt-'+(object.name or '').replace('/','-')" +msgstr "'Reçu PoS-'+(object.name or '').replace('/','-')" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,help:pos_ticket_send_by_mail.field_res_partner__pos_email_receipt +#: model:ir.model.fields,help:pos_ticket_send_by_mail.field_res_users__pos_email_receipt +msgid "" +"- E-receipt: The user will only receive e-receipt \n" +"- No E-receipt: The user will not receive e-receipt" +msgstr "" +"- E-reçu : L’utilisateur recevra exclusivement un reçu électronique n\" +"- Pas d’e-reçu : L’utilisateur ne recevra pas de reçu électronique" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "" +"
\n" +" Date:" +msgstr "" +"
\n" +" Date:" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,body_html:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "" +"
\n" +"

Thank you for your visit !

\n" +"

You will find your receipt attached.

\n" +"

\n" +"

Sincerely,

\n" +"

The team of the cooperative

\n" +"
\n" +" " +msgstr "" +"
\n" +"

Merci pour votre visite !

\n" +"

Vous trouverez votre reçu en pièce jointe.

\n" +"

\n" +"

Cordialement,

\n" +"

L’équipe de la coopérative

\n" +"
\n" +" " + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Taxes" +msgstr "Taxes" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Total" +msgstr "Total" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Amount" +msgstr "Montant" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_res_config_settings +msgid "Config Settings" +msgstr "Paramètres de configuration" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_res_partner +msgid "Contact" +msgstr "Contact" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Description" +msgstr "Description" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__no_send +msgid "Do not Send" +msgstr "Ne pas envoyer" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__1 +msgid "Do not send receipt via email" +msgstr "Ne pas envoyer le reçu par email" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__res_partner__pos_email_receipt__email_pos_receipt +msgid "E-receipt Only" +msgstr "E-reçu uniquement" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__4 +msgid "Email receipt" +msgstr "Envoyer le reçu par email" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__2 +msgid "Email receipt and print it" +msgstr "Envoyer le reçu par email et l'imprimer" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__3 +msgid "" +"Email receipt and print it unless configured on user that" +" he only receives electronically" +msgstr "" +"Envoyer le reçu par email et l'imprimer sauf si ce partenaire est configuré " +"pour recevoir uniquement le reçu électronique" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__res_partner__pos_email_receipt__no_email_pos_receipt +msgid "No E-receipt" +msgstr "Pas Reçu électronique" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_partner__pos_email_receipt +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_users__pos_email_receipt +msgid "POS Email Receipt Preference" +msgstr "Préférence d’envoi du reçu par e-mail du PoS" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Payment Mode" +msgstr "Mode de paiement" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configuration du point de vente" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_pos_order +msgid "Point of Sale Orders" +msgstr "Commandes du point de vente" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Price" +msgstr "Prix" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Quantity" +msgstr "Quantité" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.report,name:pos_ticket_send_by_mail.action_report_pos_receipt +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_pos_config__receipt_options +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_config_settings__pos_receipt_options +msgid "Receipt" +msgstr "Reçu" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.view_res_config_settings_form_pos_inherit +msgid "Receipt Options" +msgstr "Reçu" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,name:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "Send Received" +msgstr "Envoyer le reçu" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.server,name:pos_ticket_send_by_mail.ir_cron_sent_pos_ticket_ir_actions_server +msgid "Send Reciept via Email" +msgstr "Ne pas envoyer le reçu par email" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_pos_order__email_status +msgid "Send Status" +msgstr "Statut d’envoi" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__sent +msgid "Sent" +msgstr "Envoyé" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.view_res_config_settings_form_pos_inherit +msgid "" +"There are 4 ways of obtaining a receipt: 1.Do not send receipt via email " +"2.Email receipt and print it 3. Email receipt and print it unless configured" +" on user that he only receives electronically 4.Email receipt" +msgstr "" +"Il y a 4 façons d’obtenir un reçu: 1.Ne pas envoyer le reçu par e-mail " +"2.Envoyer le reçu par e-mail et l’imprimer 3.Envoyer le reçu par e-mail et " +"l’imprimer sauf si l’utilisateur est configuré pour ne recevoir que par voie" +" électronique 4. Envoyer le reçu par e-mail" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__to_send +msgid "To send" +msgstr "Envoyer" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "User:" +msgstr "Utilisateur:" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,subject:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "" +"{{ object.user_id.company_id.name }} Received {{ object.pos_reference and " +"object.pos_reference.split(' ')[1] or '' }}" +msgstr "" +"{{ object.user_id.company_id.name }} a reçu {{ object.pos_reference and " +"object.pos_reference.split(' ')[1] or '' }}" diff --git a/pos_ticket_send_by_mail/i18n/pos_ticket_send_by_mail.pot b/pos_ticket_send_by_mail/i18n/pos_ticket_send_by_mail.pot new file mode 100644 index 0000000000..12283e5bcb --- /dev/null +++ b/pos_ticket_send_by_mail/i18n/pos_ticket_send_by_mail.pot @@ -0,0 +1,204 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_ticket_send_by_mail +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-11-25 08:23+0000\n" +"PO-Revision-Date: 2025-11-25 08:23+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.report,print_report_name:pos_ticket_send_by_mail.action_report_pos_receipt +msgid "'POS-Receipt-'+(object.name or '').replace('/','-')" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,help:pos_ticket_send_by_mail.field_res_partner__pos_email_receipt +#: model:ir.model.fields,help:pos_ticket_send_by_mail.field_res_users__pos_email_receipt +msgid "" +"- E-receipt: The user will only receive e-receipt \n" +"- No E-receipt: The user will not receive e-receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "" +"
\n" +" Date:" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,body_html:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "" +"
\n" +"

Thank you for your visit !

\n" +"

You will find your receipt attached.

\n" +"

\n" +"

Sincerely,

\n" +"

The team of the cooperative

\n" +"
\n" +" " +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Taxes" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Total" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Amount" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_res_partner +msgid "Contact" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Description" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__no_send +msgid "Do not Send" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__1 +msgid "Do not send receipt via email" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__res_partner__pos_email_receipt__email_pos_receipt +msgid "E-receipt Only" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__4 +msgid "Email receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__2 +msgid "Email receipt and print it" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_config__receipt_options__3 +msgid "" +"Email receipt and print it unless configured on user that" +" he only receives electronically" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__res_partner__pos_email_receipt__no_email_pos_receipt +msgid "No E-receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_partner__pos_email_receipt +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_users__pos_email_receipt +msgid "POS Email Receipt Preference" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Payment Mode" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model,name:pos_ticket_send_by_mail.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Price" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "Quantity" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.report,name:pos_ticket_send_by_mail.action_report_pos_receipt +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_pos_config__receipt_options +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_res_config_settings__pos_receipt_options +msgid "Receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.view_res_config_settings_form_pos_inherit +msgid "Receipt Options" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,name:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "Send Receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.actions.server,name:pos_ticket_send_by_mail.ir_cron_sent_pos_ticket_ir_actions_server +msgid "Send Reciept via Email" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields,field_description:pos_ticket_send_by_mail.field_pos_order__email_status +msgid "Send Status" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__sent +msgid "Sent" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.view_res_config_settings_form_pos_inherit +msgid "" +"There are 4 ways of obtaining a receipt: 1.Do not send receipt via email " +"2.Email receipt and print it 3. Email receipt and print it unless configured" +" on user that he only receives electronically 4.Email receipt" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:ir.model.fields.selection,name:pos_ticket_send_by_mail.selection__pos_order__email_status__to_send +msgid "To send" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model_terms:ir.ui.view,arch_db:pos_ticket_send_by_mail.report_receipt_document +msgid "User:" +msgstr "" + +#. module: pos_ticket_send_by_mail +#: model:mail.template,subject:pos_ticket_send_by_mail.email_send_pos_receipt +msgid "" +"{{ object.user_id.company_id.name }} Received {{ object.pos_reference and " +"object.pos_reference.split(' ')[1] or '' }}" +msgstr "" \ No newline at end of file diff --git a/pos_ticket_send_by_mail/models/__init__.py b/pos_ticket_send_by_mail/models/__init__.py new file mode 100644 index 0000000000..d93ea62153 --- /dev/null +++ b/pos_ticket_send_by_mail/models/__init__.py @@ -0,0 +1,9 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +from . import res_partner +from . import pos_order +from . import pos_config +from . import res_config_settings diff --git a/pos_ticket_send_by_mail/models/pos_config.py b/pos_ticket_send_by_mail/models/pos_config.py new file mode 100644 index 0000000000..16a64f4ff0 --- /dev/null +++ b/pos_ticket_send_by_mail/models/pos_config.py @@ -0,0 +1,19 @@ +from odoo import fields, models + + +class PosConfig(models.Model): + _inherit = "pos.config" + + receipt_options = fields.Selection( + [ + ("1", "Do not send receipt via email"), + ("2", "Email receipt and print it"), + ( + "3", + "Email receipt and print it unless configured on user that \ + he only receives electronically", + ), + ("4", "Email receipt"), + ], + string="Receipt", + ) diff --git a/pos_ticket_send_by_mail/models/pos_order.py b/pos_ticket_send_by_mail/models/pos_order.py new file mode 100644 index 0000000000..12c258695e --- /dev/null +++ b/pos_ticket_send_by_mail/models/pos_order.py @@ -0,0 +1,66 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +import logging + +import odoo +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class PosOrder(models.Model): + _inherit = "pos.order" + + email_status = fields.Selection( + [("no_send", "Do not Send"), ("to_send", "To send"), ("sent", "Sent")], + default="no_send", + copy=False, + string="Send Status", + ) + + @api.model + def _send_order_cron(self): + _logger.info("------------------------------------------------------") + mail_template = self.env.ref( + "pos_ticket_send_by_mail.email_send_pos_receipt", + raise_if_not_found=False, + ) + if not mail_template.exists(): + _logger.warning("No mail template found for sending ticket") + return + _logger.info("Start to send ticket") + for order in self.search([("email_status", "=", "to_send")]): + mail_template.send_mail(order.id, force_send=True) + order.email_status = "sent" + # Make sure we commit the change to not send ticket twice + if not odoo.tools.config["test_enable"]: + self.env.cr.commit() # pylint: disable=E8102 + + def action_pos_order_paid(self): + # Send e-receipt for the partner. + # It depends on value of the field `receipt_option` + # that we config in pos.config.settings + # receipt_option = 1: Don't send e-receipt + # receipt_option = 2 or 3: Send e-receipt + res = super().action_pos_order_paid() + self._set_order_to_send() + return res + + def _set_order_to_send(self): + receipt_options = self.config_id.receipt_options + receipt_options = receipt_options and int(receipt_options) or False + for order in self: + if ( + receipt_options in [2, 3, 4] + and order.partner_id.email + and order.partner_id.pos_email_receipt != "no_email_pos_receipt" + ): + order.email_status = "to_send" + + def _get_statments(self): + self.ensure_one() + acc_move_lines = self.account_move.line_ids + return acc_move_lines.mapped("statement_id") diff --git a/pos_ticket_send_by_mail/models/res_config_settings.py b/pos_ticket_send_by_mail/models/res_config_settings.py new file mode 100644 index 0000000000..d9a80c9f07 --- /dev/null +++ b/pos_ticket_send_by_mail/models/res_config_settings.py @@ -0,0 +1,16 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + pos_receipt_options = fields.Selection( + string="Receipt", + related="pos_config_id.receipt_options", + readonly=False, + ) diff --git a/pos_ticket_send_by_mail/models/res_partner.py b/pos_ticket_send_by_mail/models/res_partner.py new file mode 100644 index 0000000000..ba80084797 --- /dev/null +++ b/pos_ticket_send_by_mail/models/res_partner.py @@ -0,0 +1,26 @@ +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +from odoo import api, fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + pos_email_receipt = fields.Selection( + [ + ("email_pos_receipt", "E-receipt Only"), + ("no_email_pos_receipt", "No E-receipt"), + ], + string="POS Email Receipt Preference", + help="- E-receipt: The user will only receive e-receipt \n" + "- No E-receipt: The user will not receive e-receipt", + ) + + @api.model + def _load_pos_data_fields(self, config_id): + fields = super()._load_pos_data_fields(config_id) + fields.append("pos_email_receipt") + return fields diff --git a/pos_ticket_send_by_mail/pyproject.toml b/pos_ticket_send_by_mail/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/pos_ticket_send_by_mail/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/pos_ticket_send_by_mail/readme/CONTRIBUTORS.md b/pos_ticket_send_by_mail/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..aaff50bdac --- /dev/null +++ b/pos_ticket_send_by_mail/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Trobz](https://www.trobz.com): + - Phan Hong Phuc diff --git a/pos_ticket_send_by_mail/static/description/icon.png b/pos_ticket_send_by_mail/static/description/icon.png new file mode 100644 index 0000000000..fd60220fbe Binary files /dev/null and b/pos_ticket_send_by_mail/static/description/icon.png differ diff --git a/pos_ticket_send_by_mail/static/src/js/receipt_screen_widget.esm.js b/pos_ticket_send_by_mail/static/src/js/receipt_screen_widget.esm.js new file mode 100644 index 0000000000..b94d7d7e35 --- /dev/null +++ b/pos_ticket_send_by_mail/static/src/js/receipt_screen_widget.esm.js @@ -0,0 +1,29 @@ +/* + +# Copyright (C) 2016-Today: La Louve () +# Copyright (C) 2019-Today: Druidoo () +# @author: La Louve +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html + +*/ + +import {ReceiptScreen} from "@point_of_sale/app/screens/receipt_screen/receipt_screen"; +import {patch} from "@web/core/utils/patch"; + +patch(ReceiptScreen.prototype, { + get showSendReceiptOption() { + const receipt_options = this.pos.config + ? this.pos.config.receipt_options + : false; + const client = this.currentOrder.partner_id; + const email_pos_receipt = client ? client.pos_email_receipt : false; + if ( + receipt_options && + receipt_options === "3" && + email_pos_receipt == "email_pos_receipt" + ) { + return false; + } + return true; + }, +}); diff --git a/pos_ticket_send_by_mail/static/src/xml/receipt_screen.xml b/pos_ticket_send_by_mail/static/src/xml/receipt_screen.xml new file mode 100644 index 0000000000..2ff31cfdde --- /dev/null +++ b/pos_ticket_send_by_mail/static/src/xml/receipt_screen.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/pos_ticket_send_by_mail/tests/__init__.py b/pos_ticket_send_by_mail/tests/__init__.py new file mode 100644 index 0000000000..7361e0bb80 --- /dev/null +++ b/pos_ticket_send_by_mail/tests/__init__.py @@ -0,0 +1 @@ +from . import test_pos_ticket_mail diff --git a/pos_ticket_send_by_mail/tests/test_pos_ticket_mail.py b/pos_ticket_send_by_mail/tests/test_pos_ticket_mail.py new file mode 100644 index 0000000000..d7d71b73f5 --- /dev/null +++ b/pos_ticket_send_by_mail/tests/test_pos_ticket_mail.py @@ -0,0 +1,404 @@ +from odoo import fields +from odoo.tests.common import TransactionCase + + +class PosTicketMailTest(TransactionCase): + def setUp(self): + super().setUp() + + self.ir_config_parameter = self.env["ir.config_parameter"].sudo() + self.PosOrder = self.env["pos.order"] + self.partner1 = self.env.ref("base.res_partner_1") + self.posconfig = self.env["pos.config"] + self.pos_sale_journal = self.env["account.journal"].search( + [("type", "=", "cash")], + limit=1, + ) + self.cash_payment_method = self.env["pos.payment.method"].create( + { + "name": "Cash", + "journal_id": self.pos_sale_journal.id, + "company_id": self.env.company.id, + } + ) + + self.pos_config = self.posconfig.search( + [("name", "=", "test_pos_email")], limit=1 + ) + if not self.pos_config: + self.pos_config = self.posconfig.create( + { + "name": "test_pos_email", + } + ) + self.pos_config.journal_id = self.pos_sale_journal.id + self.pos_config.payment_method_ids = [(4, self.cash_payment_method.id)] + self.res_users = self.env["res.users"] + self.pos_user = self.res_users.search( + [("login", "=", "pos_test_email")], limit=1 + ) + if not self.pos_user: + self.pos_user = self.res_users.create( + { + "name": "pos_test_email", + "login": "pos_test_email", + "email": "pos_test_email@mail.com", + } + ) + self.pos_session = self.env["pos.session"] + self.PosSession = self.pos_session.search( + [("user_id", "=", self.pos_user.id)], limit=1 + ) + if not self.PosSession: + self.PosSession = self.env["pos.session"].create( + { + "user_id": self.pos_user.id, + "config_id": self.pos_config.id, + } + ) + self.led_lamp = self.env.ref("point_of_sale.led_lamp") + self.whiteboard_pen = self.env.ref("point_of_sale.whiteboard_pen") + self.newspaper_rack = self.env.ref("point_of_sale.newspaper_rack") + self.partner_3 = self.env.ref("base.res_partner_3") + + def test_01_pos_config_no_mail_sent(self): + """ + POS config do not send email + """ + + def compute_tax(product, price, qty=1, taxes=None): + if not taxes: + taxes = product.taxes_id.filtered( + lambda t: t.company_id.id == self.env.user.id + ) + currency = self.pos_config.pricelist_id.currency_id + res = taxes.compute_all(price, currency, qty, product=product) + untax = res["total_excluded"] + return untax, sum(tax.get("amount", 0.0) for tax in res["taxes"]) + + self.ir_config_parameter.set_param("point_of_sale.receipt_options", "1") + open_session = self.PosSession.search( + [ + ("state", "!=", "closed"), + ("config_id", "=", self.pos_config.id), + ("rescue", "=", False), + ] + ) + if open_session: + current_session = open_session + else: + self.pos_config.open_existing_session_cb() + current_session = self.pos_config.current_session_id + pricelist_id = False + if self.pos_config.available_pricelist_ids: + pricelist_id = self.pos_config.available_pricelist_ids[0].id + untax, atax = compute_tax(self.led_lamp, 0.9) + carrot_order = { + "access_token": False, + "amount_paid": untax + atax, + "amount_return": 0, + "amount_tax": atax, + "amount_total": untax + atax, + "date_order": fields.Datetime.to_string(fields.Datetime.now()), + "fiscal_position_id": False, + "pricelist_id": pricelist_id, + "lines": [ + [ + 0, + 0, + { + "discount": 0, + "id": 42, + "pack_lot_ids": [], + "price_unit": 0.9, + "product_id": self.led_lamp.id, + "price_subtotal": 0.9, + "price_subtotal_incl": 1.04, + "qty": 1, + "tax_ids": [(6, 0, self.led_lamp.taxes_id.ids)], + }, + ] + ], + "payment_ids": [ + [ + 0, + 0, + { + "amount": untax + atax, + "name": fields.Datetime.now(), + "payment_method_id": self.cash_payment_method.id, + }, + ] + ], + "name": "Order 00042-003-0014", + "partner_id": False, + "session_id": current_session.id, + "sequence_number": 2, + "uuid": "00042-003-0014", + "user_id": self.env.uid, + "to_invoice": False, + } + untax, atax = compute_tax(self.whiteboard_pen, 1.2) + pos_order_id = self.PosOrder.sync_from_ui([carrot_order])["pos.order"][0]["id"] + self.PosOrder01 = self.PosOrder.browse(pos_order_id) + self.PosOrder01.action_pos_order_paid() + current_session.action_pos_session_closing_control() + + def test_02_pos_config_mail_sent_print_no_partner(self): + """ + POS config Email receipt and print it + No Partner + """ + + def compute_tax(product, price, qty=1, taxes=None): + if not taxes: + taxes = product.taxes_id.filtered( + lambda t: t.company_id.id == self.env.user.id + ) + currency = self.pos_config.pricelist_id.currency_id + res = taxes.compute_all(price, currency, qty, product=product) + untax = res["total_excluded"] + return untax, sum(tax.get("amount", 0.0) for tax in res["taxes"]) + + self.ir_config_parameter.set_param("point_of_sale.receipt_options", "2") + open_session = self.PosSession.search( + [ + ("state", "!=", "closed"), + ("config_id", "=", self.pos_config.id), + ("rescue", "=", False), + ] + ) + if open_session: + current_session = open_session + else: + self.pos_config.open_existing_session_cb() + current_session = self.pos_config.current_session_id + pricelist_id = False + if self.pos_config.available_pricelist_ids: + pricelist_id = self.pos_config.available_pricelist_ids[0].id + untax, atax = compute_tax(self.led_lamp, 0.9) + carrot_order = { + "access_token": False, + "amount_paid": untax + atax, + "amount_return": 0, + "amount_tax": atax, + "amount_total": untax + atax, + "date_order": fields.Datetime.to_string(fields.Datetime.now()), + "fiscal_position_id": False, + "pricelist_id": pricelist_id, + "lines": [ + [ + 0, + 0, + { + "discount": 0, + "id": 43, + "pack_lot_ids": [], + "price_unit": 0.9, + "product_id": self.led_lamp.id, + "price_subtotal": 0.9, + "price_subtotal_incl": 1.04, + "qty": 1, + "tax_ids": [(6, 0, self.led_lamp.taxes_id.ids)], + }, + ] + ], + "payment_ids": [ + [ + 0, + 0, + { + "amount": untax + atax, + "name": fields.Datetime.now(), + "payment_method_id": self.cash_payment_method.id, + }, + ] + ], + "name": "Order 00042-003-0024", + "partner_id": False, + "session_id": current_session.id, + "sequence_number": 3, + "uuid": "00042-003-0028", + "user_id": self.env.uid, + "id": "00042-003-0028", + "to_invoice": False, + } + untax, atax = compute_tax(self.whiteboard_pen, 1.2) + pos_order_id = self.PosOrder.sync_from_ui([carrot_order])["pos.order"][0]["id"] + self.PosOrder02 = self.PosOrder.browse(pos_order_id) + self.PosOrder02.action_pos_order_paid() + self.PosOrder02._send_order_cron() + current_session.action_pos_session_closing_control() + + def test_03_pos_config_mail_sent_print_partner(self): + """ + POS config Email receipt and print it + Set Partner + """ + + def compute_tax(product, price, qty=1, taxes=None): + if not taxes: + taxes = product.taxes_id.filtered( + lambda t: t.company_id.id == self.env.user.id + ) + currency = self.pos_config.pricelist_id.currency_id + res = taxes.compute_all(price, currency, qty, product=product) + untax = res["total_excluded"] + return untax, sum(tax.get("amount", 0.0) for tax in res["taxes"]) + + self.ir_config_parameter.set_param("point_of_sale.receipt_options", "2") + open_session = self.PosSession.search( + [ + ("state", "!=", "closed"), + ("config_id", "=", self.pos_config.id), + ("rescue", "=", False), + ] + ) + if open_session: + current_session = open_session + else: + self.pos_config.open_existing_session_cb() + current_session = self.pos_config.current_session_id + pricelist_id = False + if self.pos_config.available_pricelist_ids: + pricelist_id = self.pos_config.available_pricelist_ids[0].id + untax, atax = compute_tax(self.led_lamp, 0.9) + carrot_order = { + "access_token": False, + "amount_paid": untax + atax, + "amount_return": 0, + "amount_tax": atax, + "amount_total": untax + atax, + "date_order": fields.Datetime.to_string(fields.Datetime.now()), + "fiscal_position_id": False, + "pricelist_id": pricelist_id, + "lines": [ + [ + 0, + 0, + { + "discount": 0, + "id": 44, + "pack_lot_ids": [], + "price_unit": 0.9, + "product_id": self.led_lamp.id, + "price_subtotal": 0.9, + "price_subtotal_incl": 1.04, + "qty": 1, + "tax_ids": [(6, 0, self.led_lamp.taxes_id.ids)], + }, + ] + ], + "payment_ids": [ + [ + 0, + 0, + { + "amount": untax + atax, + "name": fields.Datetime.now(), + "payment_method_id": self.cash_payment_method.id, + }, + ] + ], + "name": "Order 00042-003-0044", + "partner_id": self.partner1.id, + "session_id": current_session.id, + "sequence_number": 4, + "uuid": "00042-003-0129", + "user_id": self.env.uid, + "id": "00042-003-0129", + "to_invoice": False, + } + untax, atax = compute_tax(self.whiteboard_pen, 1.2) + pos_order_id = self.PosOrder.sync_from_ui([carrot_order])["pos.order"][0]["id"] + self.PosOrder03 = self.PosOrder.browse(pos_order_id) + self.PosOrder03.action_pos_order_paid() + self.PosOrder03._send_order_cron() + current_session.action_pos_session_closing_control() + + def test_04_pos_config_mail_print_partner_e_ticket(self): + """ + POS config Email receipt and print it + Set Partner and also e-receipt + """ + + def compute_tax(product, price, qty=1, taxes=None): + if not taxes: + taxes = product.taxes_id.filtered( + lambda t: t.company_id.id == self.env.user.id + ) + currency = self.pos_config.pricelist_id.currency_id + res = taxes.compute_all(price, currency, qty, product=product) + untax = res["total_excluded"] + return untax, sum(tax.get("amount", 0.0) for tax in res["taxes"]) + + self.ir_config_parameter.set_param("point_of_sale.receipt_options", "2") + self.partner_3.pos_email_receipt = "email_pos_receipt" + open_session = self.PosSession.search( + [ + ("state", "!=", "closed"), + ("config_id", "=", self.pos_config.id), + ("rescue", "=", False), + ] + ) + if open_session: + current_session = open_session + else: + self.pos_config.open_existing_session_cb() + current_session = self.pos_config.current_session_id + pricelist_id = False + if self.pos_config.available_pricelist_ids: + pricelist_id = self.pos_config.available_pricelist_ids[0].id + untax, atax = compute_tax(self.led_lamp, 0.9) + carrot_order = { + "access_token": False, + "amount_paid": untax + atax, + "amount_return": 0, + "amount_tax": atax, + "amount_total": untax + atax, + "date_order": fields.Datetime.to_string(fields.Datetime.now()), + "fiscal_position_id": False, + "pricelist_id": pricelist_id, + "lines": [ + [ + 0, + 0, + { + "discount": 0, + "id": 45, + "pack_lot_ids": [], + "price_unit": 0.9, + "product_id": self.led_lamp.id, + "price_subtotal": 0.9, + "price_subtotal_incl": 1.04, + "qty": 1, + "tax_ids": [(6, 0, self.led_lamp.taxes_id.ids)], + }, + ] + ], + "payment_ids": [ + [ + 0, + 0, + { + "amount": untax + atax, + "name": fields.Datetime.now(), + "payment_method_id": self.cash_payment_method.id, + }, + ] + ], + "name": "Order 00042-003-0051", + "partner_id": self.partner_3.id, + "session_id": current_session.id, + "sequence_number": 4, + "uuid": "00042-003-0151", + "user_id": self.env.uid, + "id": "00042-003-0151", + "to_invoice": False, + } + untax, atax = compute_tax(self.whiteboard_pen, 1.2) + pos_order_id = self.PosOrder.sync_from_ui([carrot_order])["pos.order"][0]["id"] + self.PosOrder04 = self.PosOrder.browse(pos_order_id) + self.PosOrder04.action_pos_order_paid() + self.PosOrder._send_order_cron() + current_session.action_pos_session_closing_control() diff --git a/pos_ticket_send_by_mail/views/report_paperformat.xml b/pos_ticket_send_by_mail/views/report_paperformat.xml new file mode 100644 index 0000000000..48a4bdc058 --- /dev/null +++ b/pos_ticket_send_by_mail/views/report_paperformat.xml @@ -0,0 +1,18 @@ + + + + Point Of Sale Receipt + + custom + 150 + 60 + Portrait + 3 + 3 + 3 + 3 + + 3 + 130 + + diff --git a/pos_ticket_send_by_mail/views/report_receipt.xml b/pos_ticket_send_by_mail/views/report_receipt.xml new file mode 100644 index 0000000000..1e8a8bf640 --- /dev/null +++ b/pos_ticket_send_by_mail/views/report_receipt.xml @@ -0,0 +1,120 @@ + + + + + + diff --git a/pos_ticket_send_by_mail/views/view_pos_config_settings.xml b/pos_ticket_send_by_mail/views/view_pos_config_settings.xml new file mode 100644 index 0000000000..4e224f6a94 --- /dev/null +++ b/pos_ticket_send_by_mail/views/view_pos_config_settings.xml @@ -0,0 +1,37 @@ + + + + res.config.settings.view.form.inherit.pos_ticket_send_by_mail + + res.config.settings + + + + + + + + + + + + + + Receipt + pos.order + qweb-pdf + pos_ticket_send_by_mail.report_receipt + pos_ticket_send_by_mail.report_receipt + + 'POS-Receipt-'+(object.name or '').replace('/','-') + + diff --git a/pos_ticket_send_by_mail/views/view_res_partner.xml b/pos_ticket_send_by_mail/views/view_res_partner.xml new file mode 100644 index 0000000000..e012f88232 --- /dev/null +++ b/pos_ticket_send_by_mail/views/view_res_partner.xml @@ -0,0 +1,13 @@ + + + + view_partner_form_inherit + res.partner + + + + + + + +