Skip to main content

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.

note

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.