...
exception message in the body.
IMPORTANT SCOPE LIMITATION:
Only ELECTRICITY supply is currently returned. The service query hard-codes
FORSYNINGSART = 0 (El), so even if an installation has water, heat, gas, etc.,
those services are not included today. (SQL for the other supply types exists
but is commented out / future work.)
Call chain:
BrightLocationsController.GetLocations
-> BrightLocationService.GetLocationByCustomerAsync (validation + mapping)
...
-
...
-
...
-
...
(SQL lives in LocationSql; sources are Sonlinc.AINSD / AFORD / AUDEBFORS /
IndividualMPoints + SWMarket.* market tables for the dates.)
--------------------------------------------------------------------------------
METHODS
--------------------------------------------------------------------------------
...
Route: GET /bright/locations
Params:
- customerId (required)
...
- limit (optional)
- (
...
- CancellationToken)
Returns:
- 200 OK -> IEnumerable<BrightLocation>
...
- 400 BadRequest (declared; see note below)
...
- 401
...
- Unauthorized
...
- 404 NotFound (declared; see note below)
What it does:
Returns Returns the list of active locations for a customer, each with its
electricity service(s).
It first validates the customer exists (commonValidator.ValidateCustomer) and validates input
(customerId required; limit, if supplied, must be 1-1000, default 100).
It then loads location headers, loads the electricity services for those
installations, attaches each service's current supply start/end dates, and
maps everything to the BrightLocation response.
Validation that affects the result (all surface as HTTP 500 with a message): -
- Missing customerId -> "Missing parameter 'CustomerId'."
...
- limit out of range (1-1000) -> "Parameter outside of allowed range..."
...
- No locations found -> "No locations found for customer {id}"
...
- A service with no start date -> "Location with missing supply start
...
- date found for meteringpointid: {id}..."
(Every returned service MUST have a supply start date or the whole call fails. The start/end dates come from the SWMarket supply-range query, which only returns the CURRENTLY active supply: FromDate <= today and ToDate and ToDate is null or in the future.)
NOTE on status codes: although 400 and 404 are declared via
ProducesResponseType, the BadRequest branch is commented out in the
controller. In practice every Every error (bad input, not found, missing dates,
DB failure) currently comes back as HTTP 500 with the message in the body.
...
installation for the customer.
[
{
...
| Code Block |
|---|
[ { "Id": |
...
<value> // Data: SonWin installation number (AINSD.INSTNR), as |
...
string "Address": |
...
<value> // Data: street + house number (AINSD.ADRESSE + AINSD.HUSNUMMER) |
...
"ZipCode": |
...
<value> // Data: postal code (AINSD.POSTNUM) |
...
"City": |
...
<value> // Data: city name (IPOST.NAVN, falling back to AINSD.STED; empty string if both null) |
...
"Properties": |
...
null // Hardcoded |
...
// (PropertyType, NumberOfResidents, Size, HouseAge, Cars[], Heating,
// HeatingSecondary, Gadgets[] are all unused today)
...
null "PriceZone": |
...
<value> // Derived: from ZipCode -> "DK1" if zip >= 6000, "DK2" if zip < 6000, |
...
null if the zip code cannot be |
...
parsed "Services": |
...
[ // Data: the electricity service(s) for this installation (empty array if none) |
...
{
...
{ "Id": |
...
<value> // Data: metering point id / EAN (IndividualMPoints.MeteringPointId, aka AftageNr) |
...
"Type": |
...
// always "consumption_trade". (Other types map to water/heating/
// cooling/tv/broadband/waste/gas_trade, but only El is queried today.)
"Status": "Active" // Hardcoded: BrightServiceStatus.Active.ToString().
// NOTE: this emits the enum NAME "Active" (capital A), NOT the
// display value "active". TODO in code: derive real status from SonWin.
"MeasurementResolution": <value> // Derived from forsyningsart: electricity => "hour"
// (broadband => "none"; other types default to "none" - TODO).
"MeasurementId": <value> // Data: metering point id (same value as Service.Id / AftageNr)
"DeliveryPointId": null // Hardcoded null: never set by the mapper
"CostResolution": null // Hardcoded null: never set by the mapper
"CostId": null // Hardcoded null: never set by the mapper
"Properties": null // Hardcoded null: BrightServiceProperties (ShowCost,
// RealtimeMeasurements) is never populated
"StartDate": <value> // Data: current supply start date (SWMarket MeteringPointRoleOccurrence.FromDate),
// as DateTimeOffset (UTC/zero offset). Required - null fails validation.
"EndDate": <value> // Data: current supply end date (SWMarket ...ToDate), as DateTimeOffset.
// OMITTED from the JSON entirely when null (JsonIgnore WhenWritingNull);
// null/absent means the supply has no scheduled end (still active).
}
],
"Longitude": null // Hardcoded null: never set by the mapper
"Latitude": null // Hardcoded null: never set by the mapper
}
...
<value> // Hardcoded "consumption_trade"
"Status": "Active" // Hardcoded: "Active"
"MeasurementResolution": <value> // Hardcoded "15min"
"MeasurementId": <value> // Data: metering point id (same value as Service.Id / AftageNr)
"DeliveryPointId": null // Hardcoded null
"CostResolution": null // Hardcoded null
"CostId": null // Hardcoded null
"Properties": null // Hardcoded null: BrightServiceProperties (ShowCost, RealtimeMeasurements) is never populated
"StartDate": <value> // Data: current supply start date (SWMarket MeteringPointRoleOccurrence.FromDate), as DateTimeOffset (UTC/zero offset). Required - null fails validation.
"EndDate": <value> // Data: current supply end date (SWMarket ...ToDate), as DateTimeOffset.
// OMITTED from the JSON entirely when null (JsonIgnore WhenWritingNull);
// null/absent means the supply has no scheduled end (still active).
}
],
"Longitude": null // Hardcoded null
"Latitude": null // Hardcoded null
}
]
|
Notes:
- Properties, Longitude and Latitude on the location are always null/absent.
...