Skip to main content

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

RouteMethod
GET /audit/transformers/:id/consumption-trendGET

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

HeaderRequiredDescription
AuthorizationYesBearer <sessionToken>

3.2 Path Parameters

ParamTypeRequiredDescription
idstringYesThe id field of the transformer document (e.g., TC-xxx)

3.3 Query Parameters

ParamTypeRequiredDefaultDescription
monthstringNoCurrent month (YYYY-MM)End month of the trend window (inclusive)
monthsintegerNo6Number 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 month ascending.
  • 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).
  • tcConsumption or installationConsumption may be null if 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 = 6startMonth = "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

ScenarioStatusError Type
Invalid month format400ValidationError (AJV)
months out of range (< 1 or > 12)400ValidationError (AJV)
Invalid/expired session401UnauthorizedError
AE accessing TC outside their section403ForbiddenError
TC not found for given id + end month404ResourceUnavailableError
AE user doc not found500DatabaseError
DB connection failure500DatabaseError

10. Performance Notes

  • DB operations: 2 reads total — 1 findOne (TC existence check) + 1 find (trend query, returns ≤12 docs)
  • AE users add 1 extra read (user lookup for section validation)
  • No index on id field currently. The query { id, month: { $gte, $lte } } will use a collection scan on id. 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.