================================================================================
BrightProductsController - Summary & Response Structures
File: SonWinCommonAPI/Controllers/BrightProductsController.cs
================================================================================
--------------------------------------------------------------------------------
WHAT THE CONTROLLER DOES
--------------------------------------------------------------------------------
Exposes a single read endpoint that returns the price products / tariffs tied to
one customer + one service (metering point / EAN number) within a date range.
The data is read from the SonWin (Sonlinc) contract tables;
The query selects the contract "lines" for the requested EAN number.
--------------------------------------------------------------------------------
METHODS
--------------------------------------------------------------------------------
1) GetProducts
Route: GET bright/products
Auth: [Authorize] (controller-level)
Params:
Body: none
Returns:
What it does:
Validation that affects the result (ALL failures surface as HTTP 500:
Customer validation (AccountValidator.ValidateAccountGetOutput):
Input validation (ProductsValidator.ValidateGetProductsAsyncInput):
Output validation (ProductsValidator.ValidateGetProductsAsyncOutput):
--------------------------------------------------------------------------------
RESPONSE STRUCTURE (IEnumerable<BrightProduct>)
--------------------------------------------------------------------------------
Top level is a JSON array of BrightProduct. One element per distinct AftageNr
(EAN). Because the query filters on a single @EanNumber, in practice there is
one group, and each contract row becomes one entry in that group's Prices list.
[
{
"ValidFrom": null, // Hardcoded null (real: g.First().ValidFrom, commented out)
"ValidTo": null, // Hardcoded null (real: g.First().ValidTo, commented out)
"ServiceId": "<serviceId>", // Echo of request serviceId param (real: g.Key/AftageNr, commented out)
"Prices": [
{
"Value": 0, // Hardcoded 0 (real: r.Value, commented out; also not selected by SQL)
"Type": "kWh", // Hardcoded "kWh" (real: r.Type, commented out; not selected by SQL)
"Note": null, // Hardcoded null (real: r.Note, commented out; not selected by SQL)
"Name": "kWhPrice", // Hardcoded "kWhPrice" (real: r.Name, commented out; not selected by SQL)
"ValidFrom": "<datetime>", // Data: AFORBKONTR.FRADATO (DbProduct.ContractActiveFrom)
"ValidTo": "<datetime>", // Data: AFORBKONTR.TILDATO (DbProduct.ContractActiveTo); null = open-ended
"ValidHours": [], // Not mapped (TODO: pending DB schema)
"ValidMonth": [], // Not mapped (TODO: pending DB schema)
"ValidPart": null, // Not mapped (TODO: pending DB schema)
"ValidFraction": null, // Not mapped (TODO: pending DB schema)
"SubtractMeasurement": null// Not mapped (TODO: pending DB schema)
}
]
}
]
Notes:
- Property names above are the C# names; no [JsonPropertyName] attributes are
present, so serialization uses the configured default casing.
- Only TWO fields carry real data: Price.ValidFrom and Price.ValidTo (the
contract's FRADATO/TILDATO). Everything else is hard-coded, null, or unmapped.
- Product.ServiceId is the request input, so the output ServiceId always equals
the requested serviceId by construction.
- Grouping is by DbProduct.AftageNr (EANNR). Since the WHERE clause pins a
single @EanNumber, expect a single product group in normal use.
- The output validator rejects rows whose AftageNr differs from the requested
serviceId; given the SQL filter (kontr.EANNR = @EanNumber, AftageNr = EANNR)
this should not normally trigger.
--------------------------------------------------------------------------------
DATA SOURCE (SQL: ProductSql.GetActiveProducts)
--------------------------------------------------------------------------------
Bound parameters (BrightProductRepository.GetActiveProductsAsync):
@CompanyId = Settings.CompanyId
@CustomerId = customerId (request)
@EanNumber = serviceId (request, "edielNumber")
@StartDate = DateFrom (request)
@EndDate = DateTo (request)
Tables / joins:
FROM Sonlinc.AFORD ford (consumer)
LEFT JOIN Sonlinc.AFORBKONTR kontr (contract link)
ON ford.FIRMANR = kontr.FIRMANR AND ford.FORBNR = kontr.FORBNR
INNER JOIN Sonlinc.BAKONTRAKT bKontr (actual contracts)
ON bKontr.FIRMANR = ford.FIRMANR AND bKontr.KONTRAKT = kontr.KONTRAKT
INNER JOIN Sonlinc.AUDEBFORS fors (supply type)
ON fors.FIRMANR/INSTNR/FORBNR = ford.*
INNER JOIN Sonlinc.audeb deb (debtor; electrical only)
ON deb.* = ford.* AND deb.UDEBNR = fors.UDEBNR
(A commented-out DGF/energikilde LEFT JOIN block is left in place for future use.)
WHERE:
ford.FIRMANR = @CompanyId
AND ford.KUNDENR = @CustomerId
AND kontr.EANNR = @EanNumber
AND ISNULL(ford.STATUS2N,0) < 1 (active consumer)
AND ISNULL(fors.FORSYNINGSART,0) = 0 (electrical supply)
AND (kontr.TILDATO IS NULL OR kontr.TILDATO >= @StartDate)
AND kontr.FRADATO <= @EndDate
ORDER BY ContractName
Selected columns -> DbProduct:
ford.KUNDENR -> CustomerId (unused by mapper)
ISNULL(kontr.kontrakt,'') -> ContractName (unused by mapper)
kontr.FRADATO -> ContractActiveFrom -> Price.ValidFrom
kontr.TILDATO -> ContractActiveTo -> Price.ValidTo
ISNULL(bkontr.TYP,'') -> ContractType (unused by mapper)
ISNULL(bkontr.LINTYPE,'') -> LineType (unused by mapper)
kontr.EANNR -> AftageNr (grouping key + output validation)
DbProduct columns NOT selected by the SQL (always null/default):
Value, Type, Name, Note, PriceValidFrom, PriceValidTo
================================================================================