Skip to content

Commit 39601a8

Browse files
committed
[IMP] stamp_sign: added dialog view and related fields on clicking stamp
Created the dialog view along with the related fields and added the Functionality for the sign and sign all buttons.
1 parent d0d79ec commit 39601a8

File tree

14 files changed

+380
-19
lines changed

14 files changed

+380
-19
lines changed

stamp_sign/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from . import models
2+
from . import controllers

stamp_sign/__manifest__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
"depends": ["sign"],
55
"category": "Sign",
66
"data": [
7-
"views/sign_template_views.xml",
87
"data/sign_data.xml",
8+
"views/sign_template_views.xml",
99
],
1010
"assets": {
11-
"sign.assets_pdf_iframe": [
12-
"stamp_sign/static/src/components/**/*",
11+
"web.assets_backend": [
12+
"stamp_sign/static/src/components/sign_request/*",
13+
"stamp_sign/static/src/dialogs/*",
14+
],
15+
"sign.assets_public_sign": [
16+
"stamp_sign/static/src/components/sign_request/*",
17+
"stamp_sign/static/src/dialogs/*",
1318
],
1419
},
1520
"installable": True,

stamp_sign/controllers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import main

stamp_sign/controllers/main.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from odoo import http
2+
from odoo.addons.sign.controllers.main import Sign
3+
4+
5+
class SignController(Sign):
6+
def get_document_qweb_context(self, sign_request_id, token, **post):
7+
data = super().get_document_qweb_context(sign_request_id, token, **post)
8+
current_request_item = data["current_request_item"]
9+
sign_item_types = data["sign_item_types"]
10+
data["logo"] = (
11+
"data:image/png;base64,%s" % http.request.env.user.company_id.logo.decode()
12+
)
13+
14+
if current_request_item:
15+
for item_type in sign_item_types:
16+
if item_type["item_type"] == "stamp":
17+
user_stamp = current_request_item._get_user_stamp()
18+
user_stamp_frame = current_request_item._get_user_stamp_frame()
19+
item_type["auto_value"] = (
20+
"data:image/png;base64,%s" % user_stamp.decode()
21+
if user_stamp
22+
else False
23+
)
24+
item_type["frame_value"] = (
25+
"data:image/png;base64,%s" % user_stamp_frame.decode()
26+
if user_stamp_frame
27+
else False
28+
)
29+
30+
return data

stamp_sign/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from . import sign_template
22
from . import res_users
3+
from . import sign_request

stamp_sign/models/res_users.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
from odoo import models, api
1+
from odoo import models, api, fields
2+
import base64
23

34

45
class ResUsers(models.Model):
56
_inherit = "res.users"
67

8+
stamp_sign = fields.Binary(string="Digital Stamp", copy=False, groups="base.group_user")
9+
stamp_sign_frame = fields.Binary(string="Digital Stamp Frame", copy=False, groups="base.group_user")
10+
711
@api.model
812
def get_current_user_company_details(self):
913
user = self.env.user
@@ -16,5 +20,10 @@ def get_current_user_company_details(self):
1620
if user.company_id and user.company_id.country_id
1721
else "",
1822
"vat": user.company_id.vat if user.company_id else "",
23+
"logo_url": False,
1924
}
25+
if user.company_id and user.company_id.logo:
26+
details["logo_url"] = "data:image/png;base64," + base64.b64encode(
27+
user.company_id.logo
28+
).decode("utf-8")
2029
return details

stamp_sign/models/sign_request.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from odoo import models
2+
3+
4+
class SignRequestItem(models.Model):
5+
_inherit = "sign.request.item"
6+
7+
def _get_user_stamp(self):
8+
self.ensure_one()
9+
sign_user = self.partner_id.user_ids[:1]
10+
if sign_user:
11+
return sign_user["stamp_sign"]
12+
return False
13+
14+
def _get_user_stamp_frame(self):
15+
self.ensure_one()
16+
sign_user = self.partner_id.user_ids[:1]
17+
if sign_user:
18+
return sign_user["stamp_sign_frame"]
19+
return False
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { patch } from "@web/core/utils/patch";
2+
import { Document } from "@sign/components/sign_request/document_signable";
3+
4+
5+
patch(Document.prototype, {
6+
getDataFromHTML() {
7+
super.getDataFromHTML()
8+
const { el: parentEl } = this.props.parent;
9+
10+
this.company = parentEl.querySelector("company_input")?.value;
11+
this.address = parentEl.querySelector("address_input")?.value;
12+
this.city = parentEl.querySelector("city_input")?.value;
13+
this.country = parentEl.querySelector("country_input")?.value;
14+
this.vat = parentEl.querySelector("vat_input")?.value;
15+
this.logo = parentEl.querySelector("logo_input")?.value;
16+
},
17+
get iframeProps() {
18+
return {
19+
...super.iframeProps,
20+
company: this.company,
21+
address: this.address,
22+
city: this.city,
23+
country: this.country,
24+
vat: this.vat,
25+
logo: this.logo,
26+
}
27+
},
28+
})

stamp_sign/static/src/components/sign_request/sign_items.xml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<templates xml:space="preserve">
3-
<t t-name="sign.stampItem" t-extend="sign.signItem">
4-
<t t-jquery="t[t-if='readonly']" t-append="true">
5-
<t t-if="type == 'stamp'" t-call="sign.stampSignItem"/>
6-
</t>
3+
<t t-name="stamp_sign.signItem" t-inherit="sign.signItem" t-inherit-mode="extension">
4+
<xpath expr="//t[@t-if='readonly']" position="inside">
5+
<t t-if="type == 'stamp'" t-call="stamp_sign.stampSignItem"/>
6+
</xpath>
77

8-
<t t-jquery="t[t-if='!readonly']" t-append="true">
9-
<button t-if="type == 'stamp'" t-att-title="role" t-attf-class="{{classes}} o_sign_sign_item text-center" style="color:#757575;" t-att-style="style" t-att-data-stamp="value">
8+
<xpath expr="//t[@t-if='!readonly']" position="inside">
9+
<button t-if="type == 'stamp'" t-att-title="role"
10+
t-attf-class="{{classes}} o_sign_sign_item text-center" style="color:red;"
11+
t-att-style="style" t-att-data-signature="value">
1012
<span class="o_sign_helper"/>
13+
<img t-if="frame_value" t-att-src="frame_value" alt="Frame" />
1114
<img t-if="value" t-att-src="value" alt="Stamp"/>
1215
<t t-if="!value">
13-
<span class="o_placeholder ps-0">
16+
<span class="o_placeholder ps-0 fs-6">
1417
<t t-esc="placeholder"/>
1518
</span>
1619
</t>
1720
</button>
18-
</t>
21+
</xpath>
1922
</t>
2023

21-
<div t-name="sign.stampSignItem" t-att-title="role" t-attf-class="{{classes}} o_sign_sign_item" t-att-data-id="id" t-att-style="style" t-att-data-stamp="value">
24+
<div t-name="stamp_sign.stampSignItem" t-att-title="role" t-attf-class="{{classes}} o_sign_sign_item check-this" t-att-data-id="id" t-att-style="style" >
2225
<div class="sign_item_body">
2326
<span t-if="value" class="o_sign_helper"/>
27+
<img t-if="frame_value" t-att-src="frame_value" alt="Frame" class="o_sign_frame" />
2428
<img t-if="value" t-att-src="value" alt="Stamp"/>
2529
<t t-if="!value">
26-
<span class="o_placeholder ps-0">
30+
<span class="o_placeholder ps-0 d-flex justify-content-center align-items-center"
31+
style="font-size:20px">
2732
<t t-esc="placeholder"/>
2833
</span>
2934
</t>
Lines changed: 142 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,159 @@
1-
/** @odoo-module **/
2-
1+
import { user } from "@web/core/user";
2+
import { _t } from "@web/core/l10n/translation";
3+
import { StampDialog } from "../../dialogs/stamp_add_dialog";
34
import { patch } from "@web/core/utils/patch";
45
import { SignablePDFIframe } from "@sign/components/sign_request/signable_PDF_iframe";
6+
import { SignNameAndSignatureDialog } from "@sign/dialogs/dialogs"
57

6-
patch(SignablePDFIframe.prototype, {
78

9+
patch(SignablePDFIframe.prototype, {
810
enableCustom(signItem) {
911
super.enableCustom(signItem);
1012

1113
const signItemElement = signItem.el;
1214
const signItemData = signItem.data;
1315
const signItemType = this.signItemTypesById[signItemData.type_id];
14-
const { item_type: type } = signItemType;
1516

16-
if (type === "stamp") {
17+
if (signItemType.item_type === 'stamp') {
1718
signItemElement.addEventListener("click", (e) => {
1819
this.handleSignatureDialogClick(e.currentTarget, signItemType);
1920
});
2021
}
2122
},
23+
24+
openSignatureDialog(signatureItem, type) {
25+
if (this.dialogOpen) {
26+
return;
27+
}
28+
29+
this.dialogOpen = true;
30+
31+
const dataRequired = this.stampDetailsInDialog(signatureItem, type);
32+
33+
this.closeFn = this.dialog.add(
34+
type.item_type === "stamp" ? StampDialog : SignNameAndSignatureDialog,
35+
dataRequired,
36+
{
37+
onClose: () => {
38+
this.dialogOpen = false;
39+
},
40+
}
41+
);
42+
},
43+
44+
stampDetailsInDialog(signatureItem, type) {
45+
const signature = {
46+
name: this.props.signerName,
47+
company: this.props.company,
48+
address: this.props.address,
49+
city: this.props.city,
50+
country: this.props.country,
51+
vat: this.props.vat,
52+
logo: this.props.logo,
53+
}
54+
55+
const frame = {};
56+
const { height, width } = signatureItem.getBoundingClientRect();
57+
const signFrame = signatureItem.querySelector(".o_sign_frame");
58+
const signatureImage = signatureItem?.dataset?.signature;
59+
const signMode = type.auto_value ? "draw" : "auto"
60+
if (signMode == "draw" && signatureImage) {
61+
signature.signatureImage = signatureImage;
62+
}
63+
64+
return {
65+
frame,
66+
signature,
67+
signatureType: type.item_type,
68+
displaySignatureRatio: width / height,
69+
activeFrame: Boolean(signFrame) || !type.auto_value,
70+
mode: signMode,
71+
defaultFrame: type.frame_value || "",
72+
hash: this.frameHash,
73+
signatureImage,
74+
onConfirm: async () => {
75+
if (!signature.isSignatureEmpty && signature.signatureChanged) {
76+
const signatureName = signature.name;
77+
this.signerName = signatureName;
78+
await frame.updateFrame();
79+
const frameData = frame.getFrameImageSrc();
80+
const signatureSrc = signature.getSignatureImage();
81+
type.auto_value = frameData;
82+
type.frame_value = frameData;
83+
if (user.userId) {
84+
await this.updateUserSignature(type);
85+
}
86+
this.fillItemWithSignature(signatureItem, signatureSrc, {
87+
frame: frameData,
88+
hash: this.frameHash,
89+
});
90+
} else if (signature.signatureChanged) {
91+
delete signatureItem.dataset.signature;
92+
delete signatureItem.dataset.frame;
93+
signatureItem.replaceChildren();
94+
const signHelperspan = document.createElement("span");
95+
signHelperspan.classList.add("o_sign_helper");
96+
signatureItem.append(signHelperspan);
97+
if (type.placeholder) {
98+
const placeholderSpan = document.createElement("span");
99+
placeholderSpan.classList.add("o_placeholder");
100+
placeholderSpan.innerText = type.placeholder;
101+
signatureItem.append(placeholderSpan)
102+
}
103+
}
104+
this.closeDialog();
105+
this.handleInput();
106+
},
107+
onConfirmAll: async () => {
108+
const signatureName = signature.name;
109+
this.signerName = signatureName;
110+
await frame.updateFrame();
111+
const frameData = frame.getFrameImageSrc();
112+
const signatureSrc = signature.getSignatureImage();
113+
type.auto_value = signatureSrc;
114+
type.frame_value = frameData;
115+
if (user.userId) {
116+
await this.updateUserSignature(type);
117+
}
118+
for (const page in this.signItems) {
119+
await Promise.all(
120+
Object.values(this.signItems[page]).reduce((promishList, signItem) => {
121+
if (
122+
signItem.data.responsible === this.currentRole &&
123+
signItem.data.type_id === type.id
124+
) {
125+
promishList.push(
126+
Promise.all([
127+
this.adjustSignatureSize(signatureSrc, signItem.el),
128+
this.adjustSignatureSize(frameData, signItem.el),
129+
]).then(([data, frameData]) => {
130+
this.fillItemWithSignature(signItem.el, data, {
131+
frame: frameData,
132+
hash: this.frameHash,
133+
});
134+
})
135+
);
136+
}
137+
return promishList;
138+
}, [])
139+
);
140+
}
141+
this.closeDialog();
142+
this.handleInput();
143+
},
144+
onCancel: () => {
145+
this.closeDialog();
146+
},
147+
};
148+
},
149+
150+
getSignatureValueFromElement(item) {
151+
if (item.data.type === "stamp") {
152+
return item.el.dataset.signature;
153+
}
154+
else {
155+
return super.getSignatureValueFromElement(item);
156+
}
157+
},
158+
22159
});

0 commit comments

Comments
 (0)