Skip to content

Commit b9120e9

Browse files
committed
[ADD] stamp_sign: add company stamp field
This commit introduces the stamp_sign module, which adds a new Stamp field type to the core Sign application. before: The Sign application only supported standard text signatures and initials. There was no built-in way to apply a company-style stamp with structured information like an address and logo. after: A new Stamp type is available in the Sign editor. Users can drag a stamp field onto the document. During the signing process, clicking the field opens a dialog to input company details (name, address, VAT, logo). This information is rendered into a stamp image and applied to the document. The final signed PDF includes stamp. impact: This extends the sign module with a new stamp type, improving its utility for official business documents that require a formal company stamp.
1 parent fbf9ee9 commit b9120e9

17 files changed

+947
-0
lines changed

stamp_sign/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from . import models
4+
from . import controllers

stamp_sign/__manifest__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
{
4+
"name": "Stamp Sign",
5+
"version": "1.0",
6+
"depends": ["sign"],
7+
"category": "Sign",
8+
"author": "arkp",
9+
"data": [
10+
"data/sign_data.xml",
11+
"views/sign_request_templates.xml",
12+
],
13+
"assets": {
14+
"web.assets_backend": [
15+
"stamp_sign/static/src/components/sign_request/*",
16+
"stamp_sign/static/src/dialogs/*",
17+
],
18+
"sign.assets_public_sign": [
19+
"stamp_sign/static/src/components/sign_request/*",
20+
"stamp_sign/static/src/dialogs/*",
21+
],
22+
},
23+
"installable": True,
24+
"application": True,
25+
"license": "LGPL-3",
26+
}

stamp_sign/controllers/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from . import main

stamp_sign/controllers/main.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from odoo import http
4+
from odoo.addons.sign.controllers.main import Sign # type: ignore
5+
6+
7+
class Sign(Sign):
8+
def get_document_qweb_context(self, sign_request_id, token, **post):
9+
data = super().get_document_qweb_context(sign_request_id, token, **post)
10+
current_request_item = data["current_request_item"]
11+
sign_item_types = data["sign_item_types"]
12+
company_logo = http.request.env.user.company_id.logo
13+
if company_logo:
14+
data["logo"] = "data:image/png;base64,%s" % company_logo.decode()
15+
else:
16+
data["logo"] = False
17+
18+
if current_request_item:
19+
user_stamp = current_request_item._get_user_signature_asset("stamp_sign_stamp")
20+
user_stamp_frame = current_request_item._get_user_signature_asset("stamp_sign_stamp_frame")
21+
22+
encoded_user_stamp = (
23+
"data:image/png;base64,%s" % user_stamp.decode()
24+
if user_stamp
25+
else False
26+
)
27+
encoded_user_stamp_frame = (
28+
"data:image/png;base64,%s" % user_stamp_frame.decode()
29+
if user_stamp_frame
30+
else False
31+
)
32+
stamp_item_type = next(
33+
(
34+
item_type
35+
for item_type in sign_item_types
36+
if item_type["item_type"] == "stamp"
37+
),
38+
None,
39+
)
40+
if stamp_item_type:
41+
stamp_item_type["auto_value"] = encoded_user_stamp
42+
stamp_item_type["frame_value"] = encoded_user_stamp_frame
43+
44+
return data
45+
46+
@http.route(["/sign/update_user_signature"], type="json", auth="user")
47+
def update_signature(
48+
self, sign_request_id, role, signature_type=None, datas=None, frame_datas=None
49+
):
50+
user = http.request.env.user
51+
if not user or signature_type not in [
52+
"sign_signature",
53+
"sign_initials",
54+
"stamp_sign_stamp",
55+
]:
56+
return False
57+
58+
sign_request_item_sudo = (
59+
http.request.env["sign.request.item"]
60+
.sudo()
61+
.search(
62+
[("sign_request_id", "=", sign_request_id), ("role_id", "=", role)],
63+
limit=1,
64+
)
65+
)
66+
67+
allowed = sign_request_item_sudo.partner_id.id == user.partner_id.id
68+
if not allowed:
69+
return False
70+
if datas:
71+
user[signature_type] = datas[datas.find(",") + 1 :]
72+
else:
73+
# If no data, clear the field in the database
74+
user[signature_type] = False
75+
76+
# Do the same check for the frame data
77+
if frame_datas:
78+
user[signature_type + "_frame"] = frame_datas[frame_datas.find(",") + 1 :]
79+
else:
80+
# If no frame data, clear the frame field in the database
81+
user[signature_type + "_frame"] = False
82+
# --- End of Corrected Block ---
83+
84+
return True

stamp_sign/data/sign_data.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<odoo>
3+
<record model="sign.item.type" id="stamp_item_type">
4+
<field name="name">Stamp</field>
5+
<field name="item_type">stamp</field>
6+
<field name="tip">stamp</field>
7+
<field name="placeholder">Stamp</field>
8+
<field name="default_width" type="float">0.300</field>
9+
<field name="default_height" type="float">0.10</field>
10+
<field name="icon">fa-legal</field>
11+
</record>
12+
</odoo>

stamp_sign/models/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from . import sign_template
4+
from . import res_users
5+
from . import sign_request

stamp_sign/models/res_users.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Part of Odoo. See LICENSE file for full copyright and licensing details.
2+
3+
from odoo import models, fields
4+
5+
SIGN_USER_FIELDS = ["stamp_sign_stamp","stamp_sign_stamp_frame"]
6+
7+
8+
class ResUsers(models.Model):
9+
_inherit = "res.users"
10+
11+
@property
12+
def SELF_READABLE_FIELDS(self):
13+
return super().SELF_READABLE_FIELDS + SIGN_USER_FIELDS
14+
15+
@property
16+
def SELF_WRITEABLE_FIELDS(self):
17+
return super().SELF_WRITEABLE_FIELDS + SIGN_USER_FIELDS
18+
19+
stamp_sign_stamp = fields.Binary(
20+
string="Company Stamp", copy=False, groups="base.group_user"
21+
)
22+
stamp_sign_stamp_frame = fields.Binary(
23+
string="Company Stamp Frame", copy=False, groups="base.group_user"
24+
)

0 commit comments

Comments
 (0)