getStepApprovals (stepApproval)
getStepApprovals lists every stepApproval created for one purchase order, oldest first. It's the audit view of the approval process: which units voted, in which step, with what decision and comment. Because the get projection is depth-2, you can pull the related processStep and unit snapshots alongside each vote. Every authenticated role can call it.
Package import
The tutorial source imports the framework as "lesan" โ in this repo that alias maps to the local framework source (deno.json โ ../../src/mod.ts). In your own app import from @hemedani/lesan (npm/Bun) or jsr:@hemedani/lesan (Deno). @lib and @model are the tutorial's aliases for utils/ and models/.
The validator (getStepApprovals.val.ts)โ
Takes the purchaseOrderId and returns a depth-2 projection of the stepApproval schema.
import { object, objectIdValidation } from "lesan";
import { selectStruct } from "../../../mod.ts";
import { activeRoleMixin } from "@lib";
export const getStepApprovalsValidator = () => {
return object({
set: object({
...activeRoleMixin,
purchaseOrderId: objectIdValidation,
}),
get: selectStruct("stepApproval", 2),
});
};
The implementation (getStepApprovals.fn.ts)โ
A fixed filter on the embedded "purchaseOrder._id" (converted to ObjectId), then $match โ $sort createdAt: 1. The ascending sort means the vote history reads top-down in the order the approvals were created โ step 1's approvals before step 2's.
import { type ActFn, type Document, ObjectId } from "lesan";
import { stepApproval } from "../../../mod.ts";
export const getStepApprovalsFn: ActFn = async (body) => {
const {
set: { purchaseOrderId },
get,
} = body.details;
const filters: Document = {
"purchaseOrder._id": new ObjectId(purchaseOrderId as string),
};
return await stepApproval
.aggregation({
pipeline: [
{ $match: filters },
{ $sort: { createdAt: 1 } },
] as Document[],
projection: get,
})
.toArray();
};
In the workflowโ
getStepApprovals is the read window into submitDecision's output. After submit you'll see one pending approval per unit of step 1; after votes you'll see approved/rejected statuses, decidedAt timestamps, and the decidedBy user. Compare with getPendingByUnit โ which shows only the still-open tasks for a unit, grouped by approver.
Links: overview, stepApproval model, purchaseOrder model, submit-decision, po-submit.
Run itโ
curl -X POST http://localhost:1380/lesan \
-H "Content-Type: application/json" \
-H "token: $TOKEN" \
-d '{
"model": "stepApproval",
"act": "getStepApprovals",
"details": {
"set": {
"activeRoleId": "ghost-role",
"purchaseOrderId": "<poId>"
},
"get": {
"_id": 1,
"status": 1,
"processStep": { "_id": 1, "order": 1 },
"unit": { "_id": 1, "name": 1 },
"decidedBy": { "_id": 1, "first_name": 1, "last_name": 1 }
}
}
}'
Errors & fixesโ
The fn throws nothing of its own. An invalid purchaseOrderId fails objectIdValidation; a valid id with no approvals returns [] (success). Shared auth-chain errors apply; all roles are allowed.