task-h.4
This commit is contained in:
530
plans/task-h.3.md
Normal file
530
plans/task-h.3.md
Normal file
@@ -0,0 +1,530 @@
|
||||
# Task H.3: Approval Signature Strategy
|
||||
|
||||
## Goal
|
||||
|
||||
ทำให้ PDF ใบเสนอราคาสามารถแสดงข้อมูลผู้จัดทำ ผู้อนุมัติ และผู้มีอำนาจอนุมัติได้อย่างถูกต้อง
|
||||
|
||||
รองรับทั้ง:
|
||||
|
||||
```txt
|
||||
Preview PDF
|
||||
Approved PDF
|
||||
Approved Snapshot
|
||||
Document Artifact
|
||||
```
|
||||
|
||||
โดยข้อมูลลายเซ็นต้องมาจาก Approval Workflow จริง ไม่ใช่ค่าคงที่ใน Template
|
||||
|
||||
---
|
||||
|
||||
# Background
|
||||
|
||||
Task H.2 เพิ่ม:
|
||||
|
||||
```txt
|
||||
Dynamic Topic Engine
|
||||
PDFME Runtime Mapping
|
||||
Template Mapping Resolver
|
||||
```
|
||||
|
||||
Task H.1 เพิ่ม:
|
||||
|
||||
```txt
|
||||
Approved Snapshot
|
||||
Artifact Storage
|
||||
```
|
||||
|
||||
Task H.3 จะเติมส่วนที่ยังขาด:
|
||||
|
||||
```txt
|
||||
Prepared By
|
||||
Approved By
|
||||
Authorized By
|
||||
Position
|
||||
Approval Timeline Resolution
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Current Problem
|
||||
|
||||
Template ปัจจุบันมี placeholder เช่น:
|
||||
|
||||
```txt
|
||||
app1
|
||||
app1_position
|
||||
|
||||
app2
|
||||
app2_position
|
||||
|
||||
app3
|
||||
app3_position
|
||||
```
|
||||
|
||||
แต่ยังไม่มี strategy กลางสำหรับดึงข้อมูลจริงจาก:
|
||||
|
||||
```txt
|
||||
quotation
|
||||
approval workflow
|
||||
approval actions
|
||||
membership
|
||||
business role
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.1 Signature Data Contract
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
src/features/crm/quotations/document/signature.types.ts
|
||||
```
|
||||
|
||||
Define:
|
||||
|
||||
```ts
|
||||
type SignatureBlock = {
|
||||
preparedBy: {
|
||||
name: string;
|
||||
position: string;
|
||||
};
|
||||
|
||||
approvedBy: {
|
||||
name: string;
|
||||
position: string;
|
||||
};
|
||||
|
||||
authorizedBy: {
|
||||
name: string;
|
||||
position: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.2 Position Resolution Strategy
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
src/features/crm/quotations/document/signature-position.ts
|
||||
```
|
||||
|
||||
Resolve position from:
|
||||
|
||||
```txt
|
||||
membership.businessRole
|
||||
```
|
||||
|
||||
Recommended mapping:
|
||||
|
||||
```txt
|
||||
sales
|
||||
→ Sales Engineer
|
||||
|
||||
sales_support
|
||||
→ Sales Support
|
||||
|
||||
sales_manager
|
||||
→ Sales Manager
|
||||
|
||||
department_manager
|
||||
→ Department Manager
|
||||
|
||||
top_manager
|
||||
→ General Manager
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Do NOT hardcode display strings inside PDF generator.
|
||||
|
||||
Source from:
|
||||
|
||||
```txt
|
||||
crm_job_title
|
||||
```
|
||||
|
||||
master option when available.
|
||||
|
||||
Fallback:
|
||||
|
||||
```txt
|
||||
businessRole label
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.3 Prepared By Resolution
|
||||
|
||||
Prepared By source:
|
||||
|
||||
Priority:
|
||||
|
||||
```txt
|
||||
quotation.salesmanId
|
||||
```
|
||||
|
||||
Fallback:
|
||||
|
||||
```txt
|
||||
quotation.createdBy
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```txt
|
||||
preparedBy.name
|
||||
preparedBy.position
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Must resolve display name.
|
||||
|
||||
Never use raw user id.
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.4 Approved By Resolution
|
||||
|
||||
Resolve from approval workflow history.
|
||||
|
||||
Source:
|
||||
|
||||
```txt
|
||||
crm_approval_actions
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Find latest approved action from:
|
||||
|
||||
```txt
|
||||
sales_manager
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```txt
|
||||
department_manager
|
||||
```
|
||||
|
||||
depending on workflow configuration.
|
||||
|
||||
Output:
|
||||
|
||||
```txt
|
||||
approvedBy.name
|
||||
approvedBy.position
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.5 Authorized By Resolution
|
||||
|
||||
Resolve from final approval step.
|
||||
|
||||
Source:
|
||||
|
||||
```txt
|
||||
crm_approval_actions
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Find final approved action.
|
||||
|
||||
Expected role:
|
||||
|
||||
```txt
|
||||
top_manager
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```txt
|
||||
authorizedBy.name
|
||||
authorizedBy.position
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.6 Signature Resolver
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
src/features/crm/quotations/document/server/signature-resolver.ts
|
||||
```
|
||||
|
||||
Expose:
|
||||
|
||||
```ts
|
||||
resolveQuotationSignatures(
|
||||
quotationId,
|
||||
organizationId
|
||||
)
|
||||
```
|
||||
|
||||
Returns:
|
||||
|
||||
```ts
|
||||
SignatureBlock
|
||||
```
|
||||
|
||||
Responsibilities:
|
||||
|
||||
```txt
|
||||
load quotation
|
||||
load approval history
|
||||
resolve users
|
||||
resolve positions
|
||||
build final signature object
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.7 PDF Mapping Integration
|
||||
|
||||
Update:
|
||||
|
||||
```txt
|
||||
src/features/crm/quotations/document/server/service.ts
|
||||
```
|
||||
|
||||
Inject:
|
||||
|
||||
```txt
|
||||
signatures.preparedBy.name
|
||||
signatures.preparedBy.position
|
||||
|
||||
signatures.approvedBy.name
|
||||
signatures.approvedBy.position
|
||||
|
||||
signatures.authorizedBy.name
|
||||
signatures.authorizedBy.position
|
||||
```
|
||||
|
||||
Into:
|
||||
|
||||
```txt
|
||||
documentData
|
||||
templateInput
|
||||
approvedSnapshot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.8 PDFME Placeholder Mapping
|
||||
|
||||
Update seed mappings.
|
||||
|
||||
Expected:
|
||||
|
||||
```txt
|
||||
app1
|
||||
→ signatures.preparedBy.name
|
||||
|
||||
app1_position
|
||||
→ signatures.preparedBy.position
|
||||
|
||||
app2
|
||||
→ signatures.approvedBy.name
|
||||
|
||||
app2_position
|
||||
→ signatures.approvedBy.position
|
||||
|
||||
app3
|
||||
→ signatures.authorizedBy.name
|
||||
|
||||
app3_position
|
||||
→ signatures.authorizedBy.position
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Idempotent seed.
|
||||
|
||||
Update existing mappings if incorrect.
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.9 Approved Snapshot Integration
|
||||
|
||||
Update:
|
||||
|
||||
```txt
|
||||
prepareApprovedQuotationSnapshot()
|
||||
```
|
||||
|
||||
Snapshot must store:
|
||||
|
||||
```txt
|
||||
resolved signatures
|
||||
```
|
||||
|
||||
Purpose:
|
||||
|
||||
Future PDF regeneration must preserve:
|
||||
|
||||
```txt
|
||||
who approved
|
||||
who authorized
|
||||
```
|
||||
|
||||
even if users later change.
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.10 Preview Behavior
|
||||
|
||||
Preview PDF:
|
||||
|
||||
```txt
|
||||
resolve live signatures
|
||||
```
|
||||
|
||||
Approved PDF:
|
||||
|
||||
```txt
|
||||
prefer approved snapshot signatures
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
Approved artifact must remain immutable.
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.11 UI Visibility
|
||||
|
||||
Update quotation detail.
|
||||
|
||||
Add section:
|
||||
|
||||
```txt
|
||||
Approval Signatures
|
||||
```
|
||||
|
||||
Display:
|
||||
|
||||
```txt
|
||||
Prepared By
|
||||
Approved By
|
||||
Authorized By
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```txt
|
||||
name
|
||||
position
|
||||
approval timestamp
|
||||
```
|
||||
|
||||
if available.
|
||||
|
||||
---
|
||||
|
||||
# Scope H3.12 Verification
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
scripts/verify-task-h3.js
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
```txt
|
||||
preparedBy exists
|
||||
approvedBy exists
|
||||
authorizedBy exists
|
||||
|
||||
app1 mapped
|
||||
app2 mapped
|
||||
app3 mapped
|
||||
|
||||
snapshot contains signatures
|
||||
|
||||
approved PDF contains names
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# ADR
|
||||
|
||||
Create:
|
||||
|
||||
```txt
|
||||
docs/adr/0012-approval-signature-strategy.md
|
||||
```
|
||||
|
||||
Freeze:
|
||||
|
||||
```txt
|
||||
Prepared By rule
|
||||
Approved By rule
|
||||
Authorized By rule
|
||||
Position resolution rule
|
||||
Snapshot immutability rule
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Explicit Non-Scope
|
||||
|
||||
Do NOT implement:
|
||||
|
||||
```txt
|
||||
Digital signature
|
||||
Image signature
|
||||
Certificate signature
|
||||
PKI
|
||||
e-Signature
|
||||
QR verification
|
||||
Stamp image upload
|
||||
```
|
||||
|
||||
Only text-based approval identity.
|
||||
|
||||
---
|
||||
|
||||
# Output
|
||||
|
||||
1. Files Added
|
||||
2. Files Modified
|
||||
3. Signature Resolution Strategy
|
||||
4. Position Resolution Strategy
|
||||
5. PDF Mapping Changes
|
||||
6. Snapshot Changes
|
||||
7. Verification Result
|
||||
8. ADR Added
|
||||
9. Remaining Risks
|
||||
|
||||
---
|
||||
|
||||
# Definition of Done
|
||||
|
||||
✔ Prepared By resolves correctly
|
||||
|
||||
✔ Approved By resolves correctly
|
||||
|
||||
✔ Authorized By resolves correctly
|
||||
|
||||
✔ Position resolves correctly
|
||||
|
||||
✔ PDF Preview displays signatures
|
||||
|
||||
✔ Approved PDF displays signatures
|
||||
|
||||
✔ Approved Snapshot stores signatures
|
||||
|
||||
✔ app1/app2/app3 mappings work
|
||||
|
||||
✔ Artifact remains immutable
|
||||
|
||||
✔ ADR created
|
||||
Reference in New Issue
Block a user