Equipment CRUD Workflow¶
GaveKort MultiTenant - Wallet Items Management¶
Equipment in this system refers to Wallet Items (Giftcards, Range Tokens, Greenfee Tickets).
graph TD
Start([Admin/Staff Initiates]) --> CheckAuth{Check<br/>Authorization}
CheckAuth -->|Not Authorized| Error1["❌ Permission Denied<br/>HTTP 403"]
CheckAuth -->|Authorized| ChooseOp{Select<br/>Operation}
%% CREATE/ISSUE PATH
ChooseOp -->|Issue New| Issue["📝 Issue Equipment<br/>- Form: Product + User + ClaimCode"]
Issue --> Validate1["✓ Validate Input<br/>- productId exists?<br/>- idempotencyKey unique?"]
Validate1 -->|Invalid| Error2["❌ Validation Error<br/>Return 400"]
Validate1 -->|Valid| Lock["🔒 Acquire Idempotency Lock<br/>idempotency_keys collection"]
Lock --> CreateWallet["📦 Create Wallet Item<br/>- walletItemId (UUID)<br/>- userId, type, value<br/>- status: ACTIVE<br/>- issuedBy, issuedAt"]
CreateWallet --> CreateLedger1["📋 Create Ledger Transaction<br/>- type: ISSUE<br/>- amount: product.value<br/>- reference: walletItemId"]
CreateLedger1 --> UpdateProjection1["📊 Update Wallet Projection<br/>Recalculate user balance"]
UpdateProjection1 --> CompleteIdempotency1["✅ Mark Idempotency Complete<br/>Store response result"]
CompleteIdempotency1 --> Response1["✓ Return walletItemId<br/>+ ledgerTxId"]
%% EDIT PATH
ChooseOp -->|Edit Item| Edit["✏️ Edit Equipment<br/>- Lookup by walletItemId<br/>- Allow: value, expiresAt, claimCode"]
Edit --> CheckStatus["⚠️ Check Item Status<br/>- ACTIVE? OK<br/>- REDEEMED/EXPIRED? Blocked"]
CheckStatus -->|Invalid Status| Error3["❌ Cannot Edit<br/>Item Already Used"]
CheckStatus -->|Valid| Validate2["✓ Validate Changes<br/>- Prevent reducing value<br/>below used amount"]
Validate2 -->|Invalid| Error4["❌ Invalid Change<br/>Used amount exceeded"]
Validate2 -->|Valid| UpdateWallet["♻️ Update Wallet Item<br/>- Modify fields<br/>- Set updatedAt"]
UpdateWallet --> CreateLedger2["📋 Create Ledger Transaction<br/>- type: ADJUST/MODIFY<br/>- Record what changed<br/>- Audit trail"]
CreateLedger2 --> UpdateProjection2["📊 Update Wallet Projection<br/>Recalculate if value changed"]
UpdateProjection2 --> Response2["✓ Return Updated Item"]
%% DELETE/REVOKE PATH
ChooseOp -->|Delete/Revoke| Delete["🗑️ Delete Equipment<br/>- Lookup by walletItemId<br/>- Request reason"]
Delete --> CheckStatus2["⚠️ Check Item Status<br/>- ACTIVE? OK<br/>- REDEEMED/EXPIRED? Already Gone"]
CheckStatus2 -->|Invalid| Error5["❌ Cannot Delete<br/>Item Already Used"]
CheckStatus2 -->|Valid| Confirm["🔍 Require Confirmation<br/>- Admin confirms deletion<br/>- Reason recorded"]
Confirm --> SetStatus["⛔ Mark as BLOCKED<br/>status: BLOCKED<br/>Soft delete for audit trail"]
SetStatus --> CreateLedger3["📋 Create Ledger Transaction<br/>- type: BLOCK<br/>- reason: [admin reason]<br/>- refund: if partially used"]
CreateLedger3 --> UpdateProjection3["📊 Update Wallet Projection<br/>Remove from active balance"]
UpdateProjection3 --> AuditLog["📝 Add Admin Audit Log<br/>- Action: DELETE_EQUIPMENT<br/>- Admin ID, timestamp, reason"]
AuditLog --> Response3["✓ Deletion Confirmed<br/>Item marked as BLOCKED"]
%% SUCCESS PATHS
Response1 --> Success["✅ OPERATION COMPLETE"]
Response2 --> Success
Response3 --> Success
Error1 --> Fail["❌ OPERATION FAILED"]
Error2 --> Fail
Error3 --> Fail
Error4 --> Fail
Error5 --> Fail
style Start fill:#e1f5ff
style Success fill:#c8e6c9
style Fail fill:#ffcdd2
style Lock fill:#fff3e0
style CreateWallet fill:#f3e5f5
style CreateLedger1 fill:#f3e5f5
style CreateLedger2 fill:#f3e5f5
style CreateLedger3 fill:#f3e5f5
style UpdateProjection1 fill:#e0f2f1
style UpdateProjection2 fill:#e0f2f1
style UpdateProjection3 fill:#e0f2f1
Process Details¶
CREATE (ISSUE)¶
- Initiator: Admin/Staff user
- Entry Point:
issueGiftCard()callable function - Data Created:
wallet_items/{walletItemId}- Equipment recordledger_transactions/{txId}- ISSUE transactionwallet_projections/{userId}- Balance updated- Idempotency: Full protection via idempotencyKey
- Audit: Tracked in ledger (issuedBy, issuedAt)
EDIT (MODIFY)¶
- Allowed Changes: value, expiresAt, claimCode (if not yet claimed)
- Status Restrictions: Only ACTIVE items can be edited
- Validation: Cannot reduce value below usedAmount
- Ledger: Creates ADJUST transaction for changes
- Audit: updatedAt timestamp and ledger entry
DELETE (BLOCK/REVOKE)¶
- Method: Soft delete (status → BLOCKED)
- Reason: Maintains audit trail
- Restrictions: Can only block ACTIVE items
- Refund Logic: If partially used, creates REFUND transaction
- Audit Log: Full admin action logged in admin_audit_log
- Timestamp: Immutable deletion record
Data Integrity Rules¶
- ✅ Cannot edit REDEEMED or EXPIRED items
- ✅ Cannot reduce value below usedAmount
- ✅ Every operation creates ledger entry
- ✅ Idempotency prevents duplicate operations
- ✅ Projections auto-recalculated after each change