diff --git a/pos_esign_request/README.rst b/pos_esign_request/README.rst
index d5837bb..8ac1e10 100644
--- a/pos_esign_request/README.rst
+++ b/pos_esign_request/README.rst
@@ -53,7 +53,8 @@ You need two devices: one for POS, another one for taking signs
- Open E-Sign Kiosk on the second device
- Open menu ``[[ Point of Sale ]] >> Dashboard``
- - Click ``E-Sign`` on the same POS as opened on the first device
+ - Click three dots on the same POS as opened on the first device
+ - Click ``E-Sign``
- On the first device click ``Customer`` button
@@ -70,6 +71,13 @@ You need two devices: one for POS, another one for taking signs
- On the first device for the customer in the **E-Sign** column ✔ sign
appears
+Known issues / Roadmap
+======================
+
+Current implementation technically depends on ``pos_self_order`` module.
+Meanwhile no functional feature are used, only technical feature of self
+order screen.
+
Bug Tracker
===========
diff --git a/pos_esign_request/__manifest__.py b/pos_esign_request/__manifest__.py
index adcf4de..da756f1 100644
--- a/pos_esign_request/__manifest__.py
+++ b/pos_esign_request/__manifest__.py
@@ -10,16 +10,24 @@
"website": "https://github.com/it-projects-llc/pos-addons",
"license": "LGPL-3",
"depends": [
- "pos_longpolling",
+ "pos_self_order",
],
+ "assets": {
+ "pos_self_order.assets": [
+ "pos_esign_request/static/src/app/**/*",
+ "web/static/lib/jquery/jquery.js",
+ "web/static/src/core/signature/name_and_signature.scss",
+ "web/static/src/core/signature/name_and_signature.xml",
+ "web/static/src/core/signature/name_and_signature.js",
+ ],
+ "point_of_sale._assets_pos": [
+ "pos_esign_request/static/src/overrides/**/*",
+ ],
+ },
"data": [
- "views/assets.xml",
- "views/pos_config_view.xml",
"views/partner_views.xml",
+ "views/pos_config_views.xml",
+ "views/res_config_settings_views.xml",
],
"demo": [],
- "qweb": [
- "static/src/xml/pos_esign.xml",
- "static/src/xml/est_templates.xml",
- ],
}
diff --git a/pos_esign_request/controllers/main.py b/pos_esign_request/controllers/main.py
index 4cb9051..13eecb2 100644
--- a/pos_esign_request/controllers/main.py
+++ b/pos_esign_request/controllers/main.py
@@ -1,32 +1,29 @@
-import json
+from werkzeug.exceptions import Unauthorized
from odoo import http
-from odoo.http import request
+from odoo.http import request, route
class PosESignExtension(http.Controller):
- @http.route("/pos_longpolling/sign_request", type="json", auth="user")
- def sign_request(self, vals):
- channel_name = "pos.sign_request.to_est"
- config_id = request.env["pos.config"].browse(vals.get("config_id", False))
- if (
- request.env["ir.config_parameter"]
+ def _verify_pos_config(self, access_token):
+ pos_config_sudo = (
+ request.env["pos.config"]
.sudo()
- .get_param("pos_longpolling.allow_public")
- ):
- config_id = config_id.sudo()
-
- config_id.send_to_esign_tab(channel_name, config_id.id, json.dumps(vals))
+ .search([("access_token", "=", access_token)], limit=1)
+ )
+ if not pos_config_sudo or not pos_config_sudo.has_active_session:
+ raise Unauthorized("Invalid access token")
+ return pos_config_sudo
- @http.route("/pos_longpolling/submit_sign", type="json", auth="user")
- def submit_kiosk_sign(self, vals):
- config_id = request.env["pos.config"].browse(vals.get("config_id", 0))
+ @route("/pos_esign_request/sign_response", type="json", auth="public")
+ def submit_kiosk_sign(self, access_token, vals):
+ config = self._verify_pos_config(access_token)
res = self.update_partner_sign(vals)
- if res and config_id:
- channel_name = "pos.sign_request"
- config_id._send_to_channel_by_id(
- config_id._cr.dbname, config_id.id, channel_name, json.dumps(res)
+ if res and config.current_session_id:
+ session = config.current_session_id
+ request.env["bus.bus"]._sendone(
+ session._get_bus_channel_name(), "ESIGN_RESPONSE", res
)
return True
@@ -37,9 +34,11 @@ def update_partner_sign(self, vals):
if not (partner_id and sign):
return False
- partner_id = request.env["res.partner"].browse(int(partner_id))
- ir_attachment = request.env["ir.attachment"]
- attachment = ir_attachment.create(
+ Partners = request.env["res.partner"].sudo()
+ partner_id = Partners.browse(int(partner_id))
+
+ Attachments = request.env["ir.attachment"].sudo()
+ attachment = Attachments.create(
{
"type": "binary",
"name": partner_id.name + "E-Sign",
diff --git a/pos_esign_request/models/__init__.py b/pos_esign_request/models/__init__.py
index 0650744..6f23194 100644
--- a/pos_esign_request/models/__init__.py
+++ b/pos_esign_request/models/__init__.py
@@ -1 +1,4 @@
-from . import models
+from . import pos_config
+from . import pos_session
+from . import res_config_settings
+from . import res_partner
diff --git a/pos_esign_request/models/models.py b/pos_esign_request/models/models.py
deleted file mode 100644
index 2793910..0000000
--- a/pos_esign_request/models/models.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import logging
-
-from odoo import _, api, fields, models
-from odoo.exceptions import UserError
-
-_logger = logging.getLogger(__name__)
-
-
-class PosConfig(models.Model):
- _inherit = "pos.config"
-
- ask_for_sign = fields.Boolean(string="Ask To Sign", default=False)
- mandatory_ask_for_sign = fields.Boolean(
- string="Mandatory Ask To Sign", default=False
- )
- terms_to_sign = fields.Char(string="Terms & Conditions")
-
- @api.depends("ask_for_sign")
- @api.onchange("ask_for_sign")
- def _onchange_ask_for_sign(self):
- if not self.ask_for_sign:
- self.mandatory_ask_for_sign = False
-
- @api.model
- def send_to_esign_tab(self, channel_name, sub_channel, data):
- notifications = self.send_data_by_poll(channel_name, sub_channel, data)
- _logger.debug("EST notifications for %s: %s", self.ids, notifications)
- return
-
- @api.model
- def send_data_by_poll(self, channel_name, sub_channel, data):
- channel = '["%s","%s","%s"]' % (self._cr.dbname, channel_name, sub_channel)
- notifications = [[channel, data]]
- self.env["bus.bus"].sendmany(notifications)
- return notifications
-
- def open_esign_kiosk(self):
- if self.company_id not in self.env.companies:
- raise UserError(
- _("Current user is not activated on company %s") % self.company_id.name
- )
- return {
- "name": "E-Sign Kiosk",
- "type": "ir.actions.client",
- "tag": "est_kiosk_mode",
- "target": "fullscreen",
- "context": {
- "config_id": self.id,
- "terms_to_sign": self.terms_to_sign,
- "pos_name": self.name,
- "company_name": self.company_id.name,
- },
- }
-
-
-class ResPartner(models.Model):
- """Partners"""
-
- _inherit = "res.partner"
-
- sign_attachment_id = fields.Many2one("ir.attachment", "E-Sign")
diff --git a/pos_esign_request/models/pos_config.py b/pos_esign_request/models/pos_config.py
new file mode 100644
index 0000000..21402a5
--- /dev/null
+++ b/pos_esign_request/models/pos_config.py
@@ -0,0 +1,45 @@
+from odoo import api, fields, models
+
+
+class PosConfig(models.Model):
+ _inherit = "pos.config"
+
+ ask_for_sign = fields.Boolean(string="Ask To Sign", default=False)
+ mandatory_ask_for_sign = fields.Boolean(
+ string="Mandatory Ask To Sign", default=False
+ )
+ terms_to_sign = fields.Char(string="Terms & Conditions (ESign)")
+
+ def _get_esign_route(self):
+ self.ensure_one()
+ base_route = f"/pos-self/{self.id}/esign_kiosk"
+ return f"{base_route}?access_token={self.access_token}"
+
+ def preview_esign_app(self):
+ self.ensure_one()
+ return {
+ "type": "ir.actions.act_url",
+ "url": self._get_esign_route(),
+ "target": "new",
+ }
+
+ @api.depends("ask_for_sign")
+ @api.onchange("ask_for_sign")
+ def _onchange_ask_for_sign(self):
+ if not self.ask_for_sign:
+ self.mandatory_ask_for_sign = False
+
+ def sign_request(self, **kw):
+ for config in self:
+ if config.current_session_id and config.access_token:
+ self.env["bus.bus"]._sendone(
+ f"pos_config-{config.access_token}", "ESIGN_REQUEST", kw
+ )
+
+ def _get_self_ordering_data(self):
+ res = super()._get_self_ordering_data()
+ res["config"].update(
+ name=self.name,
+ terms_to_sign=self.terms_to_sign,
+ )
+ return res
diff --git a/pos_esign_request/models/pos_session.py b/pos_esign_request/models/pos_session.py
new file mode 100644
index 0000000..5698338
--- /dev/null
+++ b/pos_esign_request/models/pos_session.py
@@ -0,0 +1,10 @@
+from odoo import models
+
+
+class PosSession(models.Model):
+ _inherit = "pos.session"
+
+ def _loader_params_res_partner(self):
+ res = super()._loader_params_res_partner()
+ res["search_params"]["fields"].append("sign_attachment_id")
+ return res
diff --git a/pos_esign_request/models/res_config_settings.py b/pos_esign_request/models/res_config_settings.py
new file mode 100644
index 0000000..2e23c95
--- /dev/null
+++ b/pos_esign_request/models/res_config_settings.py
@@ -0,0 +1,22 @@
+from odoo import api, fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = "res.config.settings"
+
+ pos_ask_for_sign = fields.Boolean(
+ related="pos_config_id.ask_for_sign", readonly=False
+ )
+ pos_mandatory_ask_for_sign = fields.Boolean(
+ related="pos_config_id.mandatory_ask_for_sign", readonly=False
+ )
+ pos_terms_to_sign = fields.Char(
+ related="pos_config_id.terms_to_sign", readonly=False
+ )
+
+ @api.onchange("pos_ask_for_sign", "pos_self_ordering_mode")
+ def _onchange_ask_for_sign(self):
+ if self.pos_ask_for_sign:
+ self.pos_self_ordering_mode = "mobile"
+ else:
+ self.pos_mandatory_ask_for_sign = False
diff --git a/pos_esign_request/models/res_partner.py b/pos_esign_request/models/res_partner.py
new file mode 100644
index 0000000..41f1aad
--- /dev/null
+++ b/pos_esign_request/models/res_partner.py
@@ -0,0 +1,7 @@
+from odoo import fields, models
+
+
+class Partner(models.Model):
+ _inherit = "res.partner"
+
+ sign_attachment_id = fields.Many2one("ir.attachment", "E-Sign")
diff --git a/pos_esign_request/readme/ROADMAP.md b/pos_esign_request/readme/ROADMAP.md
new file mode 100644
index 0000000..77d1ffc
--- /dev/null
+++ b/pos_esign_request/readme/ROADMAP.md
@@ -0,0 +1,2 @@
+Current implementation technically depends on `pos_self_order` module.
+Meanwhile no functional feature are used, only technical feature of self order screen.
diff --git a/pos_esign_request/readme/USAGE.md b/pos_esign_request/readme/USAGE.md
index e36eb52..6a0410a 100644
--- a/pos_esign_request/readme/USAGE.md
+++ b/pos_esign_request/readme/USAGE.md
@@ -4,7 +4,8 @@ You need two devices: one for POS, another one for taking signs
* Open E-Sign Kiosk on the second device
* Open menu `[[ Point of Sale ]] >> Dashboard`
- * Click `E-Sign` on the same POS as opened on the first device
+ * Click three dots on the same POS as opened on the first device
+ * Click `E-Sign`
* On the first device click `Customer` button
* Select a Customer
diff --git a/pos_esign_request/static/description/index.html b/pos_esign_request/static/description/index.html
index 1227909..42b5c79 100644
--- a/pos_esign_request/static/description/index.html
+++ b/pos_esign_request/static/description/index.html
@@ -376,11 +376,12 @@
POS E-Sign Request
Configuration
Usage
-Bug Tracker
-Credits
@@ -406,7 +407,8 @@
Open a POS on a first device
Open E-Sign Kiosk on the second device
Open menu [[ Point of Sale ]] >> Dashboard
-Click E-Sign on the same POS as opened on the first device
+Click three dots on the same POS as opened on the first device
+Click E-Sign
On the first device click Customer button
@@ -419,8 +421,14 @@
appears
+
+
+
Current implementation technically depends on pos_self_order module.
+Meanwhile no functional feature are used, only technical feature of self
+order screen.
+
-
+
Bugs are tracked on GitHub Issues .
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
@@ -428,15 +436,15 @@
Do not contact contributors directly about support or help with technical issues.
-
+
-
+
This module is part of the it-projects-llc/pos-addons project on GitHub.
You are welcome to contribute.
diff --git a/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.js b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.js
new file mode 100644
index 0000000..6df7c0d
--- /dev/null
+++ b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.js
@@ -0,0 +1,61 @@
+/** @odoo-module */
+
+import {Component, markup, useState} from "@odoo/owl";
+import {NameAndSignature} from "@web/core/signature/name_and_signature";
+import {useSelfOrder} from "@pos_self_order/app/self_order_service";
+import {useService} from "@web/core/utils/hooks";
+
+export class ESignKioskPage extends Component {
+ static template = "pos_esign_request.ESignKioskPage";
+ static components = {NameAndSignature};
+
+ setup() {
+ this.selfOrder = useSelfOrder();
+ this.router = useService("router");
+ this.rpc = useService("rpc");
+ this.selfOrder.esignRequest = {
+ showingTerms: false,
+ isSubmitting: false,
+ signature: {},
+ };
+ this.state = useState(this.selfOrder.esignRequest);
+ }
+
+ showTerms() {
+ this.state.showingTerms = true;
+ }
+
+ hideTerms() {
+ this.state.showingTerms = false;
+ }
+
+ get terms() {
+ return markup(this.selfOrder.config.terms_to_sign);
+ }
+
+ async onClickSubmit() {
+ this.state.isSubmitting = true;
+
+ try {
+ const vals = this.prepareSignValues();
+ await this.rpc("/pos_esign_request/sign_response", {
+ access_token: this.selfOrder.access_token,
+ vals: vals,
+ });
+ this.state.partner_id = null;
+ } finally {
+ this.state.isSubmitting = false;
+ }
+ }
+
+ onClickReject() {
+ this.state.partner_id = null;
+ }
+
+ prepareSignValues() {
+ return {
+ partner_id: this.state.partner_id,
+ sign: this.state.signature.getSignatureImage()[1],
+ };
+ }
+}
diff --git a/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.scss b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.scss
new file mode 100644
index 0000000..f1a1dcb
--- /dev/null
+++ b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.scss
@@ -0,0 +1,41 @@
+.est_kiosk_mode {
+ width: 100%;
+ text-align: center;
+ position: relative;
+ background-color: #fff;
+ padding: 2em;
+
+ h1 {
+ margin: 0 0 2rem 0;
+ }
+
+ .message_demo_barcodes {
+ font-size: 0.9em;
+ margin: 0;
+ }
+
+ p {
+ margin: 1rem 0;
+ }
+
+ img {
+ overflow: hidden; // prevent margins colapsing with h1
+ width: 200px;
+ }
+
+ > button {
+ font-size: 1.2em;
+ margin-bottom: 2rem;
+ width: 100%;
+ }
+
+ > button:last-child {
+ margin-bottom: 0;
+ }
+
+ .o_web_sign_draw_button,
+ .o_web_sign_load_button,
+ .o_web_sign_auto_button {
+ display: none;
+ }
+}
diff --git a/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.xml b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.xml
new file mode 100644
index 0000000..0473458
--- /dev/null
+++ b/pos_esign_request/static/src/app/pages/esign_kiosk_page/esign_kiosk_page.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
Terms and Conditions
+
+
+
+
+
+
E-Sign Kiosk
+
Related to
+
+
+ Welcome
+ !
+
+ Draw your signature
+
+
+
+ Waiting for a sign request
+
+
+
+
+ Show Terms and Conditions
+ Hide Terms and Conditions
+
+
+ Submit Sign
+
+ Reject
+
+
+
diff --git a/pos_esign_request/static/src/app/self_order_bus_service.js b/pos_esign_request/static/src/app/self_order_bus_service.js
new file mode 100644
index 0000000..7805d70
--- /dev/null
+++ b/pos_esign_request/static/src/app/self_order_bus_service.js
@@ -0,0 +1,18 @@
+/** @odoo-module */
+
+import {SelfOrderBus} from "@pos_self_order/app/self_order_bus_service";
+import {patch} from "@web/core/utils/patch";
+
+patch(SelfOrderBus.prototype, {
+ dispatch(message) {
+ super.dispatch(...arguments);
+
+ if (message.type === "ESIGN_REQUEST") {
+ this.ws_esignRequest(message.payload);
+ }
+ },
+ ws_esignRequest(payload) {
+ this.selfOrder.esignRequest.signature.name = payload.partner_name;
+ this.selfOrder.esignRequest.partner_id = payload.partner_id;
+ },
+});
diff --git a/pos_esign_request/static/src/app/self_order_index.js b/pos_esign_request/static/src/app/self_order_index.js
new file mode 100644
index 0000000..395528f
--- /dev/null
+++ b/pos_esign_request/static/src/app/self_order_index.js
@@ -0,0 +1,12 @@
+/** @odoo-module */
+
+import selfOrder from "@pos_self_order/app/self_order_index";
+import {ESignKioskPage} from "@pos_esign_request/app/pages/esign_kiosk_page/esign_kiosk_page";
+import {patch} from "@web/core/utils/patch";
+
+// I don't know why import { selfOrderIndex} } does not work
+const selfOrderIndex = selfOrder.selfOrderIndex;
+
+patch(selfOrderIndex, {
+ components: {...selfOrderIndex.components, ESignKioskPage},
+});
diff --git a/pos_esign_request/static/src/app/self_order_index.xml b/pos_esign_request/static/src/app/self_order_index.xml
new file mode 100644
index 0000000..c8afa4d
--- /dev/null
+++ b/pos_esign_request/static/src/app/self_order_index.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pos_esign_request/static/src/css/esign.css b/pos_esign_request/static/src/css/esign.css
deleted file mode 100644
index b60065d..0000000
--- a/pos_esign_request/static/src/css/esign.css
+++ /dev/null
@@ -1,48 +0,0 @@
-.est_kiosk_mode_container {
- background: url("../../../../web_enterprise/static/src/img/application-switcher-bg.jpg")
- no-repeat center center fixed;
- background-size: cover;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-
-.est_kiosk_mode {
- width: 100%;
- text-align: center;
- position: relative;
- background-color: #fff;
- padding: 2em;
-
- h1 {
- margin: 0 0 2rem 0;
- }
-
- .message_demo_barcodes {
- font-size: 0.9em;
- margin: 0;
- }
-
- p {
- text-align: left;
- margin: 3rem 0;
- }
-
- > button {
- font-size: 1.2em;
- margin-bottom: 2rem;
- width: 100%;
- }
-
- > button:last-child {
- margin-bottom: 0;
- }
-}
-
-.est_kiosk_mode img {
- overflow: hidden; // prevent margins colapsing with h1
- margin-top: 3rem;
- width: 200px;
-}
diff --git a/pos_esign_request/static/src/css/pos_esign.css b/pos_esign_request/static/src/css/pos_esign.css
deleted file mode 100644
index 7ad21c5..0000000
--- a/pos_esign_request/static/src/css/pos_esign.css
+++ /dev/null
@@ -1,52 +0,0 @@
-.est_kiosk_mode_container {
- background: url("../../../../web_enterprise/static/src/img/application-switcher-bg.jpg")
- no-repeat center center fixed;
- background-size: cover;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-
-.est_kiosk_mode {
- width: 100%;
- text-align: center;
- position: relative;
- background-color: #fff;
- padding: 2em;
-
- h1 {
- margin: 0 0 2rem 0;
- }
-
- .message_demo_barcodes {
- font-size: 0.9em;
- margin: 0;
- }
-
- p {
- text-align: left;
- margin: 3rem 0;
- }
-
- > button {
- font-size: 1.2em;
- margin-bottom: 2rem;
- width: 100%;
- }
-
- > button:last-child {
- margin-bottom: 0;
- }
-}
-
-.est_kiosk_mode img {
- overflow: hidden; // prevent margins colapsing with h1
- margin-top: 3rem;
- width: 200px;
-}
-
-.button.esign {
- left: 120px;
-}
diff --git a/pos_esign_request/static/src/js/ClientListScreen.js b/pos_esign_request/static/src/js/ClientListScreen.js
deleted file mode 100644
index 8973235..0000000
--- a/pos_esign_request/static/src/js/ClientListScreen.js
+++ /dev/null
@@ -1,23 +0,0 @@
-odoo.define("pos_esign_request.ClientListScreen", function (require) {
- "use strict";
-
- var ClientListScreen = require("point_of_sale.ClientListScreen");
- const Registries = require("point_of_sale.Registries");
-
- const POSESignRequestClientListScreen = (x) =>
- class extends x {
- mounted() {
- super.mounted.apply(this, arguments);
- this.env.pos.on("changed:partner_esign", this.render, this);
- }
-
- willUnmount() {
- super.willUnmount.apply(this, arguments);
- this.env.pos.off("changed:partner_esign", null, this);
- }
- };
-
- Registries.Component.extend(ClientListScreen, POSESignRequestClientListScreen);
-
- return ClientListScreen;
-});
diff --git a/pos_esign_request/static/src/js/PaymentScreen.js b/pos_esign_request/static/src/js/PaymentScreen.js
deleted file mode 100644
index ab44a4f..0000000
--- a/pos_esign_request/static/src/js/PaymentScreen.js
+++ /dev/null
@@ -1,41 +0,0 @@
-odoo.define("pos_esign_request.PaymentScreen", function (require) {
- "use strict";
-
- const PaymentScreen = require("point_of_sale.PaymentScreen");
- const Registries = require("point_of_sale.Registries");
-
- const POSESignRequestPaymentScreen = (x) =>
- class extends x {
- get canCustomerValidatePayment() {
- const client = this.currentOrder.get_client();
- // Customer is not set
- if (!client) return true;
-
- // Does not need to ask for sign
- if (!this.env.pos.config.ask_for_sign) return true;
-
- // Customer did sign
- if (client.sign_attachment_id) return true;
-
- // Sign is not mandatory
- if (!this.env.pos.config.mandatory_ask_for_sign) return true;
-
- // Customer did not sign and it is mandatory
- return false;
- }
-
- mounted() {
- super.mounted.apply(this, arguments);
- this.env.pos.on("changed:partner_esign", this.render, this);
- }
-
- willUnmount() {
- super.willUnmount.apply(this, arguments);
- this.env.pos.off("changed:partner_esign", null, this);
- }
- };
-
- Registries.Component.extend(PaymentScreen, POSESignRequestPaymentScreen);
-
- return POSESignRequestPaymentScreen;
-});
diff --git a/pos_esign_request/static/src/js/esign_mode.js b/pos_esign_request/static/src/js/esign_mode.js
deleted file mode 100644
index 858109b..0000000
--- a/pos_esign_request/static/src/js/esign_mode.js
+++ /dev/null
@@ -1,278 +0,0 @@
-odoo.define("pos_esign_request.esign_mode", function (require) {
- "use strict";
-
- var core = require("web.core");
- var rpc = require("web.rpc");
- var Widget = require("web.Widget");
- var Session = require("web.session");
- var local_storage = require("web.local_storage");
- var AbstractAction = require("web.AbstractAction");
-
- var QWeb = core.qweb;
- var _t = core._t;
-
- var AcceptModalKiosk = Widget.extend({
- events: {
- "click #sign_clean": "clearSignature",
- },
- initSignature: function (ev) {
- var signature = this.kiosk.$el.find("#signature");
- signature.empty().jSignature({
- "decor-color": "#D1D0CE",
- color: "#000",
- "background-color": "#fff",
- });
- this.empty_sign = signature.jSignature("getData", "image");
- },
- clearSignature: function (ev) {
- $("#signature").jSignature("reset");
- },
- submitForm: function (ev) {
- var self = this;
- var $confirm_btn = $("button#submit_sign");
- ev.preventDefault();
- var values = this.compose_vals();
- var is_empty = values.signature
- ? this.empty_sign[1] === values.signature[1]
- : false;
- $("#drawsign")
- .toggleClass("panel-danger", is_empty)
- .toggleClass("panel-default", !is_empty);
- if (is_empty) {
- setTimeout(function () {
- $confirm_btn.removeAttr("data-loading-text").button("reset");
- });
- return false;
- }
-
- $confirm_btn.prepend('
');
- $confirm_btn.attr("disabled", true);
- Session.rpc("/pos_longpolling/submit_sign", {
- vals: values,
- }).then(function (result) {
- self.kiosk.close_sign_form();
- });
- return false;
- },
-
- compose_vals: function () {
- var $drawsign = $("#drawsign");
- var signature = $drawsign.find("#signature").jSignature("getData", "image");
- return {
- partner_id: this.kiosk.partner.partner_id,
- sign: signature ? JSON.stringify(signature[1]) : false,
- config_id: this.kiosk.action.context.config_id,
- };
- },
- });
-
- var KioskMode = AbstractAction.extend({
- init: function (parent, action) {
- this._super(parent, action);
- this.parent = parent;
- this.action = action;
- this.session = Session;
- var context = this.action.context;
-
- if (context.config_id) {
- this.save_locally("config_id", context.config_id);
- this.save_locally("terms_to_sign", context.terms_to_sign);
- this.save_locally("pos_name", context.pos_name);
- } else {
- context.config_id = this.get_from_storage("config_id");
- context.pos_name = this.get_from_storage("pos_name");
- context.terms_to_sign = this.get_from_storage("terms_to_sign");
- }
- },
-
- save_locally: function (key, value) {
- local_storage.setItem("est." + key, JSON.stringify(value));
- },
-
- get_from_storage: function (key) {
- return JSON.parse(local_storage.getItem("est." + key));
- },
-
- update_bus: function () {
- var self = this;
- this.bus = this.searchModelConfig.env.services.bus_service;
- this.bus.stopPolling();
- var channel_name = "pos.sign_request.to_est";
- this.esign_channel_name = this.get_full_channel_name(
- channel_name,
- String(this.action.context.config_id) + ""
- );
- this.bus.addChannel(this.esign_channel_name);
- this.force_start_polling();
- this.bus.onNotification(this.bus, function (data) {
- var check = false;
- try {
- check =
- data &&
- data.length &&
- JSON.parse(data[0][0])[1] === channel_name;
- } catch (error) {
- check = false;
- }
- if (check) {
- self.on_est_sign_updates(data);
- }
- });
- },
-
- force_start_polling: function () {
- this.bus.startPolling();
- if (!this.bus._isActive) {
- this.bus._poll();
- this.bus.stop = false;
- }
- },
-
- get_full_channel_name: function (channel_name, sub_channel) {
- return JSON.stringify([Session.db, channel_name, sub_channel]);
- },
-
- on_est_sign_updates: function (message) {
- var self = this;
- var options = JSON.parse(message[0][1]);
- if (!options.partner_id) {
- return;
- }
- this.set_partner(options);
- this.render_client_data();
- },
-
- set_partner: function (options) {
- this.partner = options;
- },
-
- render_client_data: function () {
- var self = this;
- var sign_panel = $("#drawsign");
-
- this.$el
- .find(".greeting_message")
- .text("Welcome " + this.partner.partner_name + "!");
- sign_panel.show();
- this.sign_widget.initSignature();
- },
-
- start: function () {
- var self = this;
- this.company_name = this.action.company_name;
- this.company_image_url = this.session.url("/web/image", {
- model: "res.company",
- id: this.session.company_id,
- field: "logo",
- });
-
- this.$el.html(QWeb.render("ESTKioskMode", {widget: self}));
- this.toggle_full_screen();
- this.start_sign_widget();
- // TODO: remove it
- $(".o_hr_attendance_button_partners").on("click", function (e) {
- this.sign_widget.initSignature(e);
- });
- var terms_container = this.$el.find(".terms_container");
- terms_container.find(".terms_text").hide();
- terms_container
- .find(".fold_terms")
- .hide()
- .on("click", function (e) {
- terms_container.find(".fold_terms").hide();
- terms_container.find(".terms_text").hide();
- terms_container.find(".unfold_terms").show();
- });
-
- terms_container.find(".unfold_terms").on("click", function (e) {
- terms_container.find(".fold_terms").show();
- terms_container.find(".terms_text").show();
- terms_container.find(".unfold_terms").hide();
- });
- this.update_bus();
- return this._super.apply(this, arguments);
- },
-
- toggle_full_screen: function () {
- if (!document.webkitIsFullScreen) {
- var el = document.documentElement;
- var requestMethod =
- el.requestFullScreen ||
- el.webkitRequestFullScreen ||
- el.mozRequestFullScreen ||
- el.msRequestFullScreen;
- if (requestMethod) {
- // Native full screen.
- requestMethod.call(el);
- } else if (typeof window.ActiveXObject !== "undefined") {
- // Older IE.
- var wscript = new ActiveXObject("WScript.Shell");
- if (wscript !== null) {
- wscript.SendKeys("{F11}");
- }
- }
-
- // Event_toggleFullScreen.toggleFullScreen(document.documentElement);
- // anyway hide navbar from others
- $("nav").hide();
- }
- },
-
- start_sign_widget: function () {
- var self = this;
-
- this.sign_widget = new AcceptModalKiosk();
- this.sign_widget.setElement($("#modalaccept"));
- this.sign_widget.start();
- this.sign_widget.kiosk = this;
-
- this.$el.find("#sign_clean").on("click", function (e) {
- self.sign_widget.clearSignature(e);
- });
-
- this.$el.find("#submit_sign").on("click", function (e) {
- self.sign_widget.submitForm(e);
- });
-
- this.$el.find("#reject_sign").on("click", function (e) {
- self.close_sign_form();
- });
- },
-
- close_sign_form: function () {
- var $confirm_btn = this.$el.find("button#submit_sign");
- var $drawsign = $("#drawsign");
-
- this.$el.find(".greeting_message").text("Waiting for a sign request");
- $drawsign.hide();
- $("#signature").empty();
- $confirm_btn.find("i.fa.fa-spinner.fa-spin").remove();
- $confirm_btn.attr("disabled", false);
- this.partner = false;
- },
-
- on_barcode_scanned: function (barcode) {
- var self = this;
- var hr_employee = new Model("res.partner");
- hr_employee.call("attendance_scan", [barcode]).then(function (result) {
- if (result.action) {
- self.do_action(result.action);
- } else if (result.warning) {
- self.do_warn(result.warning);
- }
- });
- },
-
- destroy: function () {
- clearInterval(this.clock_start);
- this._super.apply(this, arguments);
- },
- });
-
- core.action_registry.add("est_kiosk_mode", KioskMode);
-
- return {
- KioskMode: KioskMode,
- AcceptModalKiosk: AcceptModalKiosk,
- };
-});
diff --git a/pos_esign_request/static/src/js/pos_esign.js b/pos_esign_request/static/src/js/pos_esign.js
deleted file mode 100644
index a6b137e..0000000
--- a/pos_esign_request/static/src/js/pos_esign.js
+++ /dev/null
@@ -1,73 +0,0 @@
-odoo.define("pos_esign_request.esign_request", function (require) {
- "use strict";
-
- var Session = require("web.session");
- var models = require("point_of_sale.models");
-
- const PosComponent = require("point_of_sale.PosComponent");
- const Registries = require("point_of_sale.Registries");
- const {posbus} = require("point_of_sale.utils");
-
- models.load_fields("res.partner", ["sign_attachment_id"]);
-
- var PosModelSuper = models.PosModel;
- models.PosModel = models.PosModel.extend({
- initialize: function () {
- var self = this;
- PosModelSuper.prototype.initialize.apply(this, arguments);
-
- this.ready.then(function () {
- if (!self.config.ask_for_sign) {
- return;
- }
- var channel_name = "pos.sign_request";
- var callback = self.updates_from_sign_kiosk;
- var bus = self.get_bus();
- bus.add_channel_callback(channel_name, self.esign_callback, self);
- bus.start();
- });
- },
-
- esign_callback: function (res) {
- if (!res) {
- return;
- }
- res = JSON.parse(res);
-
- var partner = this.db.get_partner_by_id(res.partner_id);
- if (partner) {
- partner.sign_attachment_id = res.attachment_id;
- this.trigger("changed:partner_esign", res);
- }
- },
-
- esign_request: function (vals) {
- Session.rpc("/pos_longpolling/sign_request", {
- vals: vals,
- });
- },
- });
-
- class ButtonEsign extends PosComponent {
- async onClickAttButton() {
- var partner = this.props.partner;
- if (!partner) {
- return;
- }
- this.env.pos.waiting_for_esign_partner = partner;
- this.env.pos.trigger("changed:partner_esign");
- Session.rpc("/pos_longpolling/sign_request", {
- vals: {
- partner_id: partner.id,
- partner_name: partner.name,
- config_id: this.env.pos.config.id,
- },
- });
- }
- }
- ButtonEsign.template = "ESignButton";
-
- Registries.Component.add(ButtonEsign);
-
- return ButtonEsign;
-});
diff --git a/pos_esign_request/static/src/overrides/models/pos_bus.js b/pos_esign_request/static/src/overrides/models/pos_bus.js
new file mode 100644
index 0000000..ee72129
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/models/pos_bus.js
@@ -0,0 +1,29 @@
+/** @odoo-module */
+
+import {PosBus} from "@point_of_sale/app/bus/pos_bus_service";
+import {patch} from "@web/core/utils/patch";
+
+patch(PosBus.prototype, {
+ // Override
+ dispatch(message) {
+ super.dispatch(...arguments);
+
+ const payload = message.payload;
+ if (message.type === "ESIGN_RESPONSE" && payload?.partner_id) {
+ const partner = this.pos.db.get_partner_by_id(payload.partner_id);
+ if (partner) {
+ if (
+ this.pos.waiting_for_esign_partner &&
+ this.pos.waiting_for_esign_partner.id === partner.id
+ ) {
+ this.pos.waiting_for_esign_partner = null;
+ }
+
+ partner.sign_attachment_id = payload.attachment_id;
+
+ // Updates screen in general
+ window.dispatchEvent(new Event("resize"));
+ }
+ }
+ },
+});
diff --git a/pos_esign_request/static/src/overrides/models/pos_store.js b/pos_esign_request/static/src/overrides/models/pos_store.js
new file mode 100644
index 0000000..1b0104f
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/models/pos_store.js
@@ -0,0 +1,14 @@
+/** @odoo-module */
+
+import {PosStore} from "@point_of_sale/app/store/pos_store";
+import {patch} from "@web/core/utils/patch";
+
+patch(PosStore.prototype, {
+ async requestSign(partner) {
+ this.waiting_for_esign_partner = partner;
+ await this.orm.call("pos.config", "sign_request", [this.config.id], {
+ partner_id: partner.id,
+ partner_name: partner.name,
+ });
+ },
+});
diff --git a/pos_esign_request/static/src/overrides/partner_list/partner_line/partner_line.xml b/pos_esign_request/static/src/overrides/partner_list/partner_line/partner_line.xml
new file mode 100644
index 0000000..865aa48
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/partner_list/partner_line/partner_line.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ Waiting...
+
+
+ E-Sign
+
+
+
+
+
+
diff --git a/pos_esign_request/static/src/overrides/partner_list/partner_list.xml b/pos_esign_request/static/src/overrides/partner_list/partner_list.xml
new file mode 100644
index 0000000..cbdda03
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/partner_list/partner_list.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ E-Sign
+
+
+ !partner.sign_attachment_id and pos.waiting_for_esign_partner == partner
+ () => pos.requestSign(partner)
+
+
+
diff --git a/pos_esign_request/static/src/overrides/payment_screen/payment_screen.js b/pos_esign_request/static/src/overrides/payment_screen/payment_screen.js
new file mode 100644
index 0000000..9c66b08
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/payment_screen/payment_screen.js
@@ -0,0 +1,35 @@
+/** @odoo-module */
+
+import {ErrorPopup} from "@point_of_sale/app/errors/popups/error_popup";
+import {PaymentScreen} from "@point_of_sale/app/screens/payment_screen/payment_screen";
+import {_t} from "@web/core/l10n/translation";
+import {patch} from "@web/core/utils/patch";
+
+patch(PaymentScreen.prototype, {
+ async validateOrder() {
+ const partner = this.currentOrder.get_partner();
+
+ do {
+ // Customer is not set
+ if (!partner) break;
+
+ // Does not need to ask for sign
+ if (!this.pos.config.ask_for_sign) break;
+
+ // Customer did sign
+ if (partner.sign_attachment_id) break;
+
+ // Sign is not mandatory
+ if (!this.pos.config.mandatory_ask_for_sign) break;
+
+ // Customer did not sign and it is mandatory
+ this.popup.add(ErrorPopup, {
+ title: _t("Error"),
+ body: _t("Customer hasn't signed yet."),
+ });
+ return false;
+ } while (false); // eslint-disable-line no-constant-condition
+
+ return await super.validateOrder(...arguments);
+ },
+});
diff --git a/pos_esign_request/static/src/overrides/payment_screen/payment_screen.xml b/pos_esign_request/static/src/overrides/payment_screen/payment_screen.xml
new file mode 100644
index 0000000..531f7db
--- /dev/null
+++ b/pos_esign_request/static/src/overrides/payment_screen/payment_screen.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ E-Sign
+
+
+
+
diff --git a/pos_esign_request/static/src/xml/est_templates.xml b/pos_esign_request/static/src/xml/est_templates.xml
deleted file mode 100644
index 1a0d65a..0000000
--- a/pos_esign_request/static/src/xml/est_templates.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
E-Sign Kiosk
-
Related to
-
-
-
Waiting for a sign request
-
-
Click to unfold the Terms and Conditions
-
Terms and Conditions
-
-
Click to fold Terms and Conditions
-
-
-
-
-
-
Draw your signature
-
-
-
Submit Sign
-
Reject
-
-
-
-
-
-
-
-
- Start New Session
- Create
-
-
-
diff --git a/pos_esign_request/static/src/xml/pos_esign.xml b/pos_esign_request/static/src/xml/pos_esign.xml
deleted file mode 100644
index ce5a413..0000000
--- a/pos_esign_request/static/src/xml/pos_esign.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
- E-Sign
-
-
-
-
-
-
-
-
-
- canCustomerValidatePayment
-
-
-
-
-
- E-Sign
-
-
-
-
-
-
-
-
-
-
-
-
- Waiting...
-
-
-
-
-
-
diff --git a/pos_esign_request/views/assets.xml b/pos_esign_request/views/assets.xml
deleted file mode 100644
index fb56cbd..0000000
--- a/pos_esign_request/views/assets.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/pos_esign_request/views/pos_config_view.xml b/pos_esign_request/views/pos_config_view.xml
deleted file mode 100644
index 112e8df..0000000
--- a/pos_esign_request/views/pos_config_view.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
- pos.config.form
- pos.config
-
-
-
-
-
-
-
-
-
-
-
- pos.config.kanban.view
- pos.config
-
-
-
-
-
-
- E-Sign
-
-
-
-
-
diff --git a/pos_esign_request/views/pos_config_views.xml b/pos_esign_request/views/pos_config_views.xml
new file mode 100644
index 0000000..93496fc
--- /dev/null
+++ b/pos_esign_request/views/pos_config_views.xml
@@ -0,0 +1,27 @@
+
+
+
+ pos.config.view.kanban.pos.esign
+ pos.config
+
+
+
+
+
+
+
+
+
+
diff --git a/pos_esign_request/views/res_config_settings_views.xml b/pos_esign_request/views/res_config_settings_views.xml
new file mode 100644
index 0000000..5ca651f
--- /dev/null
+++ b/pos_esign_request/views/res_config_settings_views.xml
@@ -0,0 +1,32 @@
+
+
+
+