惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
B
Blog
阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Jina AI
Jina AI
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
L
LangChain Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
F
Fortinet All Blogs
H
Help Net Security
B
Blog RSS Feed
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
S
SegmentFault 最新的问题

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How I Built a Multi-Level Approval Process (L1, L2, L3) w...
Peter Parser · 2026-05-02 · via DEV Community

ProcessInstance, ProcessWorkItem, auto field updates, and the day I learned why escalation rules save careers.


🏢 Once upon a time in a mid-sized company…

We had a purchase request system.

It looked fine on the surface — users could submit requests, data was stored, reports existed.

But there was one massive problem:

There was no approval system.

And that created chaos.

  • Finance didn’t trust the numbers
  • Department heads didn’t know what they were approving
  • Requests were being edited after submission
  • The CFO saw critical approvals 2 weeks late

That’s when I got the task:

“Build a structured L1 → L2 → L3 approval process.
With record locking, automated emails, escalation rules, and audit-ready tracking.”

This wasn’t just a feature.
It was a system that would define how decisions move inside the company.

Here’s exactly how I built it — step by step.


🔐 1. Record Locking & Unlocking (Data Integrity First)

❌ Problem

Users were editing records even after submitting them for approval.

That meant:

  • Approvers were reviewing moving targets
  • Decisions became invalid
  • Audit trails were unreliable

✅ Solution

I implemented state-based record locking.

  • When a record is submitted → it becomes read-only
  • If rejected → it becomes editable again
  • If fully approved → it is permanently locked

🧠 Logic

if(status == "Submitted" OR "L1 Approved" OR "L2 Approved")
    isLocked = true
else
    isLocked = false

Enter fullscreen mode Exit fullscreen mode

💡 Insight

Locking isn’t just a feature — it’s what makes approvals trustworthy.


👥 2. Designing L1, L2, L3 Approval Levels

I mapped the approval hierarchy to real business roles:

Level Role Responsibility
L1 Department Head Validate request legitimacy
L2 COO Operational approval
L3 CFO Financial approval

Rules I enforced:

  • Each approver can:

    • ✅ Approve
    • ❌ Reject
    • 💬 Add comments
  • ❗ No one can modify previous decisions

  • 🔄 Rejection at any level sends the request back to the requester

💡 Insight

Approval systems are not technical flows — they are organizational trust layers.


📧 3. Automated Email Notifications (Communication Layer)

Approvals fail without visibility.

So I built a trigger-based email system tied to each stage.

📌 Email Triggers

  • On submission → notify L1
  • On L1 approval → notify L2 + requester
  • On L2 approval → notify L3
  • On final approval → notify requester + finance
  • On rejection → notify requester with reason + unlock info

📨 Example Email (L1 → L2)

Subject: L1 Approved — Pending COO Review

Hi [COO Name],

Request #[Record ID] has been approved by the Department Head.

Please review and take action before [Due Date].

Thanks,
System Automation

Enter fullscreen mode Exit fullscreen mode

💡 Insight

Emails are not notifications.
They are decision triggers.


🔄 4. Automated Field Updates (State Management)

To keep everything trackable, I designed a clear status lifecycle.

🔁 Status Flow

Draft → Submitted → L1 Approved → L2 Approved → Final Approved
                ↓           ↓            ↓
             Rejected    Rejected     Rejected
                ↓           ↓            ↓
              Unlock      Unlock       Unlock

Enter fullscreen mode Exit fullscreen mode

🧩 Fields I maintained

  • Status
  • Last_Approved_By
  • Last_Approved_Date
  • Next_Approver_Name
  • Is_Locked

Each approval step automatically updated these fields using Flows / Apex logic.

💡 Insight

If your status field is messy, your entire system becomes untraceable.


⏰ 5. Escalation Rules (The Real Game-Changer)

This is where the system went from “good” to “production-ready”.

🚨 Problem

Approvers delay.

Always.

✅ Solution: Time-based escalation

Rule 1:

  • If L1 pending > 48 hours → Reassign to L2 → Send escalation email

Rule 2:

  • If L2 pending > 24 hours → Notify CFO (view-only) → Send daily reminder to COO

🔥 Why this matters

  • Prevents bottlenecks
  • Removes dependency on manual follow-ups
  • Keeps process moving without friction

💡 Insight

Escalation rules don’t just improve systems —
they protect deadlines, teams, and accountability.


🧠 6. The Core Engine: ProcessInstance & ProcessWorkItem

This is the part that separates beginners from real Salesforce developers.

📦 ProcessInstance

Represents the entire approval process for one record.

Stores:

  • Overall status → IN_PROGRESS, APPROVED, REJECTED
  • Start time / end time
  • Current stage

🧩 ProcessWorkItem

Represents each approval step.

Stores:

  • Assigned approver
  • Step status (Pending / Approved / Rejected)
  • Due date
  • Escalation status
  • Comments

🔍 Real-world query example

Find all L2 approvals that are pending and escalated

This is critical for:

  • Dashboards
  • Reporting
  • Audits

💡 Insight

Without these objects, your system has no memory.
And without memory, there is no audit.


📊 7. Final Architecture Snapshot

User submits request
    → Lock record
    → Create ProcessInstance
    → Create ProcessWorkItem (L1)
    → Send email to L1

L1 approves
    → Update status
    → Create ProcessWorkItem (L2)
    → Notify L2

L2 approves
    → Update status
    → Create ProcessWorkItem (L3)
    → Notify L3

L3 approves
    → Final approval
    → Permanently lock record
    → Close ProcessInstance
    → Send final email

Enter fullscreen mode Exit fullscreen mode


🧪 8. What I’d Improve Next Time

No system is perfect. Here’s what I’d upgrade:

  • 🔀 Parallel approvals (e.g., L2 + Legal together)
  • 🔔 24-hour reminders (not just escalation)
  • ⚡ Store approval history as JSON for faster UI rendering
  • 📊 Build dashboards for real-time approval tracking

✅ Key Lessons from This Build

  • 🔐 Locking is non-negotiable for data integrity
  • 📧 Emails without escalation = ignored notifications
  • 🧠 ProcessInstance + ProcessWorkItem = audit backbone
  • 🧪 Always test escalations using mock overdue scenarios

🔁 Final Thought

If you’ve ever built approval systems, you already know:

L1 is fast. L2 is busy. L3 is critical.

Each level behaves differently.
Your system must respect that.


🚀 Closing

This project wasn’t just about approvals.

It was about:

  • Building trust in data
  • Creating accountability
  • Designing systems that work *without constant human follow-up

If you're building something similar or want to discuss architecture decisions, feel free to connect. Always happy to exchange ideas 🚀