LLD: Fetch Consumption Trend API
1. Overview
Returns a TC's tcConsumption and installationConsumption across multiple months. Used to render the TC-Installation Consumption line chart on the TC detail page.
The chart shows two lines:
- Yellow line — TC Consumption (from meter readings)
- Blue line — Installation Consumption (sum of tagged installations)
plotted across the X-axis of months (e.g., Jan through Jun).
2. Endpoint
| Route | Method |
|---|---|
GET /audit/transformers/:id/consumption-trend | GET |
Single route — user type (Admin vs AE) resolved from request.user.userType. AE users are validated against their assigned section.
3. Request
3.1 Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <sessionToken> |
3.2 Path Parameters
| Param | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The id field of the transformer document (e.g., TC-xxx) |
3.3 Query Parameters
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
month | string | No | Current month (YYYY-MM) | End month of the trend window (inclusive) |
months | integer | No | 6 | Number of months to include (1–12). Window is [month - (months-1), month] |
Example: ?month=2026-01&months=6 returns data for Aug 2025 through Jan 2026.
4. Response
4.1 Success (200)
{
"success": true,
"message": "Consumption trend fetched successfully",
"data": {
"trend": [
{
"month": "2025-09",
"tcConsumption": 2800,
"installationConsumption": 1500
},
{
"month": "2025-10",
"tcConsumption": 3010,
"installationConsumption": 1650
},
{
"month": "2025-11",
"tcConsumption": 3500,
"installationConsumption": 1900
},
{
"month": "2025-12",
"tcConsumption": 4100,
"installationConsumption": 2200
},
{
"month": "2026-01",
"tcConsumption": 3800,
"installationConsumption": 2050
},
{
"month": "2026-02",
"tcConsumption": 3200,
"installationConsumption": 1750
}
]
}
}
Notes:
- Array is sorted by
monthascending. - If a TC doesn't have a document for a particular month in the window, that month is simply absent from the array (no backfill with nulls — the frontend handles gaps).
tcConsumptionorinstallationConsumptionmay benullif the TC exists for that month but the value wasn't computed.
4.2 Not Found (404)
{
"success": false,
"message": "Transformer not found"
}
Returned when no TC document exists for the given id + month (the end month of the window).
4.3 Forbidden (403)
When AE requests trend for a TC outside their section:
{
"success": false,
"message": "TC does not belong to your assigned section"
}
5. Business Logic
5.1 Compute Month Window
endMonth = month param (or current month if not provided)
numberOfMonths = months param (or 6 if not provided)
startMonth = endMonth - (numberOfMonths - 1) months
Example: endMonth = "2026-01", numberOfMonths = 6 → startMonth = "2025-08"
5.2 Validate TC Exists
const transformer = await transformerModel
.findOne(
{ id: params.id, month: endMonth },
{ _id: 0, id: 1, "location.sectionCode": 1 }
)
.lean();
if (!transformer) {
return 404 — "Transformer not found";
}
We validate against the end month to ensure the TC exists for the currently viewed month.
5.3 AE Section Validation
Same pattern as fetchTransformerDetail:
IF userType === "AE":
1. Fetch user doc → extract user.location.sectionCode
2. Verify transformer.location.sectionCode === user.location.sectionCode
3. If mismatch → 403 Forbidden
5.4 Fetch Trend Data
const trend = await transformerModel
.find(
{
id: params.id,
month: { $gte: startMonth, $lte: endMonth },
},
{
_id: 0,
month: 1,
tcConsumption: 1,
installationConsumption: 1,
},
)
.sort({ month: 1 })
.lean();
5.5 Return Response
return {
statusCode: 200,
success: true,
message: "Consumption trend fetched successfully",
data: { trend },
};
6. Validation Schema (AJV)
6.1 Path Parameters Schema
{
type: "object",
properties: {
id: {
type: "string",
transform: ["trim"],
}
},
required: ["id"]
}
6.2 Query String Schema
{
type: "object",
properties: {
month: {
type: "string",
pattern: "^\\d{4}-(0[1-9]|1[0-2])$",
errorMessage: { pattern: "month must be in YYYY-MM format" }
},
months: {
type: "integer",
minimum: 1,
maximum: 12,
default: 6,
errorMessage: {
minimum: "months must be at least 1",
maximum: "months must be at most 12"
}
}
},
additionalProperties: false
}
6.3 Response Serialization
{
type: "object",
properties: {
trend: {
type: "array",
items: {
type: "object",
properties: {
month: { type: "string" },
tcConsumption: { type: ["number", "null"] },
installationConsumption: { type: ["number", "null"] },
},
},
},
},
}
7. Route Config
{
routeId: "fetchConsumptionTrend",
authentication: {
// No excludeFrom — requires full auth
},
authorization: {
action: "read",
resource: "audit"
}
}
8. File Structure
api/src/entities/audit/
audit.route.v1.js — Add new route entry
controller/
fetchAuditSummary.js — Existing
fetchTransformers.js — Existing
fetchTransformerDetail.js — Existing
fetchInstallations.js — Existing
auditTC.js — Existing
fetchConsumptionTrend.js — New
9. Error Handling
| Scenario | Status | Error Type |
|---|---|---|
| Invalid month format | 400 | ValidationError (AJV) |
| months out of range (< 1 or > 12) | 400 | ValidationError (AJV) |
| Invalid/expired session | 401 | UnauthorizedError |
| AE accessing TC outside their section | 403 | ForbiddenError |
TC not found for given id + end month | 404 | ResourceUnavailableError |
| AE user doc not found | 500 | DatabaseError |
| DB connection failure | 500 | DatabaseError |
10. Performance Notes
- DB operations: 2 reads total — 1
findOne(TC existence check) + 1find(trend query, returns ≤12 docs) - AE users add 1 extra read (user lookup for section validation)
- No index on
idfield currently. The query{ id, month: { $gte, $lte } }will use a collection scan onid. With ~1M docs (150K TCs × 7 months), this is acceptable for demo. For production, add an index on{ id: 1, month: 1 }. - Response size: Tiny — at most 12 objects with 3 fields each.