PMIS Sign-off
Adds a reusable PMIS document sign-off workflow on top of pmis_assessment.
The implemented hierarchy is:
pmis.signoff.workflow defines the sign-off workflow for one target model and company.
pmis.signoff.workflow.step defines ordered sign-off steps, required PMIS role and declaration text.
pmis.signoff.authority assigns role-specific workflow signers or role-independent represented presenters to a project and optional site.
pmis.signoff.case tracks one prepared document revision moving through draft, prepared, awaiting sign-offs and terminal outcomes.
pmis.signoff stores each immutable sign-off record with its signer, authenticated evidence actor, role, outcome, declaration, evidence and snapshot hashes.
pmis.signoff.adapter.registry and installed adapter models connect the generic workflow to target documents.
pmis.measurement.book supports Measurement Book financial sign-off.
pmis.situation supports temporary sale Situation certification sign-off.
The module separates durable customer signature from downstream completion. A temporary Situation is the signed document; its PDF snapshot, canonical manifest and sign-off record remain immutable even when completion fails. Situation acceptance and the company invoice policy run in an atomic completion operation. Installing pmis_situation_stock additionally requires material delivery, valuation and stock accounting to complete in that operation. An invoice is never the signed evidence. The explicit situation_sale_temporary route is the sole customer-facing Situation acceptance mechanism. Final Situations are not routed through this temporary workflow.
Table of contents
Operational concept
pmis_signoff implements document sign-off workflows for PMISuite.
It connects:
PMIS project, site and company context;
configurable sign-off workflows and ordered sign-off steps;
project/site-scoped sign-off authorities;
immutable document snapshots and canonical hashes;
authenticated and represented internal-user sign-off capture;
OCA PDF/portal approval by an assigned external Control Officer;
immutable server-observed signing IP and UTC timestamp printed beside the external signature in the signed PDF;
positive, returned and rejected outcomes;
target-document completion after all required positive sign-offs.
Portal signing uses Odoo's resolved HTTP remote address. Behind a reverse proxy, configure Odoo's proxy mode and restrict direct access to trusted proxies; browser-supplied IP values and raw forwarded headers are not used by this addon. An IP is network audit evidence, not signer identity. Non-HTTP signing has no observed IP and is explicitly labeled unavailable in the PDF. Existing immutable signed documents are not rewritten or backfilled with an invented IP.
The operator flow is:
Prepare the document for sign-off.
Send the prepared document for sign-off.
Each authorized reviewer records one sign-off at the required step. A separately authorized internal presenter may record a represented signature where the target adapter permits it.
The signature is stored durably. Positive final sign-off then attempts the target's atomic completion operation.
The case becomes completed, completion error, returned or rejected without changing the immutable signed evidence.
Sign-off records capture the signer, authenticated Odoo evidence actor, role, timestamp, timezone, declaration, selected outcome, reason or remarks and immutable document evidence.
Security scope
Sign-off cases and immutable evidence are readable only by effective project/site users: workflow signers, represented-signature presenters, target operators, and completion responsibles. Company membership and chatter follower status do not grant case access. Sign-off Managers administer configuration but receive business-case access only through the same project scope; there is no implicit auditor override.
Access consistency
access_user_ids is a materialized security projection, not a UI cache. It is rebuilt from current operational and completion responsibility plus eligible workflow signers and represented presenters. Authority resolution first filters active internal company users with the required live role group. For a case with a site, eligible exact-site assignments override project-level assignments for the same purpose and workflow role; an ineligible exact-site assignment does not suppress eligible project fallback. Cases without a site use project-level assignments. The same resolver drives authorization, pending reviewer display, wizard availability, and stored case access.
Workflow-step, authority, responsibility, completion-responsibility, user-company, user-type, active-user, and relevant group changes refresh affected cases. Refreshes lock cases in deterministic order and reconcile open completion activities so a revoked user never remains assigned. Administrators may use the private _access_integrity_report(repair=True) maintenance method on an explicitly scoped case recordset.
Sign-off Manager membership includes Valuation Manager access but grants business-case and evidence access only through the project-scoped projection. Accounting managers gain no implicit visibility; they need an explicit eligible completion path. There is no separate auditor role. Follower status never changes the projection or bypasses record rules.
Situation Operators and Measurement Operators may create/open, prepare, and send cases only for targets for which they are explicitly responsible. Cancellation additionally requires PMIS Valuation Manager membership. Signers and presenters cannot prepare, send, cancel, or retry merely because they may sign. Completion retry remains adapter-controlled and requires the configured stock/accounting permissions.
Evidence attachments inherit access from their owning case or sign-off record and remain immutable. Active workflow and presenter authorities are protected by database partial unique indexes for both project and site scopes.
Features
Sign-off cases
Adds pmis.signoff.case as a company-aware, chatter-enabled sign-off case.
Links each case to a target model, target record, document revision, PMIS project, optional site and sign-off workflow.
Uses the pmis.signoff.case sequence with SOF/%(y)s/ references.
Supports draft, prepared, awaiting sign-offs, accepted, returned, rejected, completion error, superseded and cancelled states.
Prepares deterministic canonical manifest text, content hash, immutable snapshot attachment and snapshot hash before the case can be sent.
Exposes operator-facing progress fields: current sign-off step, current role, pending reviewers, required steps and completed sign-offs.
Shows sign-off progress separately from technical/audit evidence in the form view.
Blocks direct edits to protected evidence and workflow fields. Workflow actions are required for state and evidence changes.
Treats context keys as execution hints only; context never authorizes a protected transition.
Locks completed evidence against direct mutation.
Stores completion retry count, last error and completion datetime for target completion failures.
Sign-off workflows and steps
Adds pmis.signoff.workflow for company-scoped target-model workflow configuration.
Adds pmis.signoff.workflow.step for ordered role-based sign-off steps.
Enforces unique step sequence per workflow.
Requires each step to carry a sign-off declaration and declaration version.
Validates that workflow target models are registered by the adapter registry.
Supports active/inactive workflows and steps.
Preserves sequential execution: earlier active steps must have positive sign-offs before later steps can be signed off.
Sign-off records
Adds pmis.signoff for immutable sign-off records.
Records case, company, workflow step, role, outcome, reason, signer user, signer partner, authenticated evidence actor, presenter or paper recorder, declaration, declaration version, timestamp, timezone, document revision and evidence hashes.
Supports authenticated Odoo user sign-off, in-person device signatures and uploaded-paper signatures for target adapters that allow represented signing.
Requires the represented signer, explicit actor attestation and either a captured signature or a primary signed paper document, as applicable.
Copies primary and supporting uploaded evidence into immutable attachments owned by the sign-off record; uploads must originate from the current wizard and authenticated actor.
Allows outcomes: Accepted, Accepted with Reservations, Returned for Correction and Rejected.
Requires a reason for reservations, returns and rejections.
Allows creation only through the sign-off workflow.
Denies generic RPC/ORM creation even with forged workflow context.
Blocks updates and deletion after creation.
Enforces one sign-off per case and workflow step.
Preserves immutable snapshot and manifest references for audit/support.
Adapter and evidence services
Adds pmis.signoff.adapter.registry as the target-document adapter registry.
Discovers installed adapter models through _pmis_signoff_target_model.
Provides explicit mutable adapter registration helpers used by isolated tests.
Requires adapters to provide target context, manifest payload, snapshot rendering, signable-state checks and completion behavior.
Adds pmis.signoff.canonicalizer for deterministic JSON canonicalization and SHA-256 hashing.
Normalizes datetimes, dates, floats, decimals, dictionaries, lists and bytes before hashing.
Verifies immutable attachment bytes against the stored snapshot hash before sign-off capture and completion retry.
Validates case, evidence type, company and final sign-off linkage before any elevated binary hash read.
Creates and links evidence only through private server-side helpers; generic attachment methods cannot classify, relink, mutate or delete evidence.
Measurement Book financial sign-off
Adds pmis.signoff.adapter.measurement.book for pmis.measurement.book.
Loads the default Measurement Book Financial Sign-off workflow for the main company.
Requires a submitted Measurement Book with one active draft iteration before evidence can be prepared.
Renders the Measurement Book report as the signed financial snapshot.
Renders the active Measurement Book iteration report as issued line-level evidence.
Requires the signing user to match the Measurement Book Control Officer partner for the control-officer step.
On successful completion, writes sign-off traceability fields back to the Measurement Book.
Issues the accepted iteration using the existing Measurement Book iteration issue action.
Marks the Measurement Book accepted only after all required positive sign-offs are complete.
Temporary sale Situation certification sign-off
Adds pmis.signoff.adapter.situation for submitted temporary sale pmis.situation revisions.
Requires the authenticated internal Control Officer to have matching company/project/site authority and match the Situation Control Officer.
Captures an immutable Situation report snapshot and deterministic manifest before sign-off.
Completes the Situation certification route only; any invoice preparation and posting remains an explicit, idempotent callback owned by pmis.situation.
Does not replace accepted Situation evidence with invoice evidence.
Rejects cost/internal and final Situations at the server boundary.
Configuration
Install the module with its standard dependency: pmis_assessment.
The module uses the LGPL-3 license.
Give users access through the added sign-off security groups:
PMIS Sign-off User for operational read access and sign-off wizard use.
PMIS Sign-off Officer for Control Officer sign-off work and Measurement Book iteration-line access needed by the integration.
PMIS Represented Sign-off Presenter for internal presenters who record in-person or uploaded-paper signatures on behalf of the configured signer.
PMIS Sign-off Manager for workflow, step and authority configuration.
PMIS Sign-off User implies Sales user access.
PMIS Sign-off Officer implies PMIS Sign-off User, PMIS Control Officer and PMIS Measurement Operator access.
PMIS Sign-off Manager implies PMIS Sign-off Officer and PMIS Valuation Manager access.
Sign-off cases, workflows, steps, records and authorities are company-aware and protected by multi-company record rules.
Measurement Book Financial Sign-off and Temporary Situation Certification Sign-off are loaded as noupdate data for base.main_company, each with one Control Officer step. Configure workflows for other companies as needed. The Situation workflow must use the target key situation_sale_temporary; a target model alone does not select that route.
Configure workflow-signing authorities for each project, optional site, role and authorized internal user. Configure presenter authority without a role.
Usage
Configure a sign-off workflow:
Open Bills of Quantities / Configuration / Sign-off Configuration.
Open Sign-off Workflows.
Create or edit a workflow for the target model and company.
Add ordered sign-off steps with role, declaration text and declaration version.
Keep only the applicable workflow and steps active for the company.
Assign sign-off authority:
Open Sign-off Authorities.
Select the company, PMIS project and optional PMIS site.
Select the purpose and internal user; select a role only for workflow signing.
Confirm that the user belongs to the required signer or presenter group and is allowed for the company.
Send a Measurement Book for financial sign-off:
Open a submitted pmis.measurement.book with one active draft iteration.
Use Financial Sign-off.
The module opens or creates one active sign-off case for the current document revision and workflow.
Use Prepare for Sign-off to build the immutable evidence.
Use Send for Sign-off to move the case to Awaiting Sign-offs.
Record an authenticated sign-off:
Open Sign-off / Pending Sign-offs or the sign-off case from the Measurement Book smart button.
Review the current sign-off step, pending reviewers and sign-off records.
Use Record Sign-off.
Review the declaration.
Select the outcome and enter a reason when returning, rejecting or signing off with reservations.
Use Confirm Sign-off.
Send a temporary sale Situation for certification:
Submit a temporary sale Situation with lines, a revision and an assigned Control Officer. Resolve draft variations and issue any linked Measurement Book iterations before preparing evidence.
As its responsible Situation Operator, use Certification Sign-off to open or create the case for the current revision.
Use Prepare for Sign-off, then Send for Sign-off.
Record the Control Officer's authenticated or represented sign-off. An authenticated signer needs matching role authority and must be the user of the assigned Control Officer partner.
After all active steps have positive sign-offs, completion accepts the Situation and applies its company's invoice policy. With pmis_situation_stock installed, explicit material classification and successful stock completion are also required.
Record a represented Situation signature:
Assign the internal presenter the PMIS Represented Sign-off Presenter group and a matching project/site authority whose purpose is represented_presenter.
Open the pending Situation sign-off step as that presenter. The configured Situation Control Officer remains the represented signer.
Choose In-person Device Signature and capture the signature, or choose Uploaded Paper Signature and upload the primary signed document in the wizard. Supporting uploads are optional.
Provide the required actor attestation and confirm. The wizard creates immutable copied evidence; the source upload is not retained as sign-off evidence.
An unknown original paper-signature datetime leaves both original datetime and original timezone empty. When a datetime is recorded, its valid timezone is mandatory and future datetimes are rejected; the Odoo evidence-recording datetime and actor remain separate.
Handle returned or rejected documents:
A Returned for Correction outcome moves the case to returned.
A Rejected outcome moves the case to rejected.
The case evidence remains immutable.
Correct the target document through the target document's normal correction process and create a new sign-off case for the corrected revision.
Retry completion:
If target completion fails, the valid signature remains stored while the case moves to completion_error and records an actionable error.
The atomic savepoint rolls back partial target completion effects. When an eligible responsible user can be resolved, one internal follow-up activity is created or updated. Stock delivery and valuation participate when pmis_situation_stock is installed.
Resolve the target-side cause.
An authorized internal user uses Complete Signed Situation without asking the customer to sign the unchanged revision again.
The module re-verifies target identity, company, revision, content hash and snapshot hash, records retry attribution, and closes the activity on success.
Data model notes
Sign-off workflows belong to one company and one target model.
Sign-off workflow steps inherit company from the workflow.
Sign-off cases belong to one company and one immutable target record revision.
Sign-off records belong to one case and one workflow step.
Sign-off authorities belong to one company, one PMIS project, optional PMIS site and one internal user. Workflow signers also have one role; presenters never do.
Project, site and company consistency is enforced in ORM constraints.
The selected site must belong to the selected PMIS project and company.
The target adapter supplies company, project, optional site, document revision and display name for each case.
The Measurement Book adapter stores sign-off traceability on pmis.measurement.book fields prefixed with pmis_signoff_.
Cross-company access is blocked by record rules and company consistency checks, not only by UI domains.
Tests
Test filenames identify the model under test, for example test_pmis_signoff_case.py, test_pmis_measurement_book.py and test_pmis_situation.py. Situation and Measurement Book integration variants use a suffix after the model name. Shared setup lives in common_*.py; these helper modules do not collect tests.
Run this addon with the standard PMIverse runner only:
/srv/pmiverse/_pmiconfig/scripts/test/run_pytest_addon.sh \ -a /srv/pmiverse/_pmisuite18/repos/pmiverse/operations/pmis_signoff/tests \ -d test_pmis_signoff -- -q -r a
Do not use raw pytest or odoo-bin as the standard workflow.
OCA Sign compatibility
pmis_signoff requires OCA's Odoo 18 sign_oca. Make the OCA Sign repository and its dependencies available in the Odoo addon paths.
For a Control Officer who has no active internal Odoo account:
Assign the Control Officer contact, including its email address, to the Measurement Book or temporary sale Situation.
Prepare the case and send it for sign-off as the authorized document operator.
At the pending Control Officer step, use Send Control Officer Signature. A repeated click opens the existing invitation without sending another one.
The Control Officer opens the OCA email link, reviews the prepared PDF and declaration, accepts the declaration checkbox, and signs the PDF.
The request is bound to the company, case, ordered step, assigned contact, document hashes, and declaration. A valid completed OCA signature creates an immutable oca_portal Control Officer approval and a separate signed PDF. The original PMIS snapshot is preserved. Portal users and contacts without an Odoo account can sign; active internal users use the internal authority workflow.
The sign-off identifies the assigned contact and OCA recipient, rather than inventing an authenticated internal signer or presenter. OCA's access token authorizes this particular invitation; it grants no PMIS case or target access. Unsigned invitations become unusable when their assignment, declaration, document, or workflow is stale, or their internal responsible is no longer authorized.
Internal completion runs with the requesting operator's current permissions. Measurement Book issuance requires an internal PMIS Valuation Manager when the signing Control Officer has no internal account. If delivery, valuation, accounting, or invoicing fails, the external signature and its immutable PDF remain recorded and the authorized internal responsible can retry completion. External signatures never grant internal business permissions.
An operator may cancel an unsigned invitation and send a replacement. Cancelling the invitation does not cancel the PMIS case. An ordinary OCA request linked only through its Object field does not count as PMIS approval: use the case action to create the bound Control Officer invitation.
Non-goals
This module does not implement qualified electronic signatures, automatic Situation generation, stock operations, MRP, timesheets or generic controller/API endpoints. In-person device signatures and uploaded paper documents are internal evidence records, not qualified electronic signatures.
Bug Tracker
Bugs are tracked on PMISuite Repository Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback.
Credits
Contributors
Matjaž Mozetič
Maintainers
Current maintainer:
Luxim is an independent R&D and deployment company focused on solving complex problems in the Odoo ecosystem.
Luxim is an active member of OCA (Odoo Community Association).






