Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The endpoint returns a JSON array of invoice objects (no wrapper). Each object contains a nested `Info` array of supplementary key/value (or title/value) entries.

Code Block
[
  {
    "Id":          <value>,    // Composite: $"<InstNr>-<ForbnNr>-<UdebNr>-<Id>",  // Data: composite of{InstNr}-{ForbnNr}-{UdebNr}-{Id}" = AKOND.INSTNR + FORBNR + UDEBNR + REGNINGNR (REGNINGNR cast to varchar AS Id)
    "ServiceId":      -FORBNR-UDEBNR-REGNINGNR
    "ServiceId":   <value>,    // Data: AUDEBFORS.FORSYNINGSART (+AFREGNTYPE) via ForsyningsartMapper. El-only join => in practice "consumption_trade", or null (see limitations).
         "InvoiceDate": <value>,    // Data: AUDEBFORSAKOND.FORSYNINGSARTBILAGSDATO  (+ AKOND.AFREGNTYPE for KØL) via ForsyningsartMapper; null for unmapped/unknown/null supply typesDateTimeOffset, UTC offset 0) | null
    "DueDate":         "2026-01-31T00:00:00+00:00",  <value>,       // Data: AKOND.FORFDATO    (DateTimeOffset, UTC offset 0); | null if NULL
    "InvoiceDatePeriod":     "2026-01-01T00:00:00+00:00" <value>,    // Derived from StartDate/EndDate month-span: "1month"/"2month"/"3month"/"6month"/ Data: AKOND.BILAGSDATO (DateTimeOffset, UTC offset 0); null if NULL"12month" (defaults to "1month" when dates missing or other span)
    "PeriodStartDate":   <value>,    // Data:  "1month",AKOND.DATOFRA     (DateTimeOffset, UTC offset 0) | null
    "EndDate":         <value>,      // Data: derived from AKOND.DATOFRA/DATOTIL month   span (1/2/3/6/12month); defaults "1month" if either date null or span unmatchedDateTimeOffset, UTC offset 0) | null
    "StartDateRemainingAmount": <value>,// Data: running account saldo  "2026-01-01T00:00:00+00:00",     (SUM of AKOND.KR up to this line) - NOT a per-invoice remaining figure.
    "TotalAmount": <value>,    // Data: AKOND.DATOFRAKR (DateTimeOffset, UTC offset 0); null if NULLdecimal) | null
    "EndDateInvoiceStatus": <value>,  // Derived (see status   "2026-01-31T00:00:00+00:00",         // Data: AKOND.DATOTIL (DateTimeOffset, UTC offset 0); null if NULLlogic below): one of cancelled / credited / paid / overdue / unpaid non-empty BDOC.PAYLOAD exists, else "missing"
     
    "RemainingAmount": 0.00,            // Flat supplementary list; mostly DUPLICATES the structured fields above, as strings/dates.
    "Info": [                // Data: AKOND.KR (TotalAmount) - PBSI PaidAmount; null unless BOTH present
    "TotalAmount":     1953.12,
      { "Key": "invoiceNumber",   "Value": <Id> },        // Data: AKOND.REGNINGNR (string)
      { "Key": "invoiceDate",     "Value":         <InvoiceDate> },// Data: AKOND.KR
BILAGSDATO (DateTimeOffset|null)
      { "InvoiceStatusKey":   "paiddueDate",         "Value": <DueDate> },    // Data: AKOND.FORFDATO (DateTimeOffset|null)
      { "Key": "totalAmount",     "Value": <TotalAmount> },// Data: derivedAKOND.KR .ToString(see MapInvoiceStatus); one| of unpaid/paid/partly_paid/overdue/cancelled/credited only
null
      { "InvoiceTypeKey": "period",    "pdf",      "Value": <Period> },     // Derived period string
      { "Key": "remainingAmount", "Value": <Saldo> },      // Data: derivedrunning from HasPdf EXISTS check -> "pdf" or "missing" ("html" never produced)
saldo .ToString() | null
      { "Key": "status",          "InfoValue": [ <InvoiceStatus> },// Derived status string
      { "Key": "invoiceNumberdescription",     "Value": "<REGNINGNR>"<Tekst> },      // Data: AKOND.REGNINGNRTEKST
 (as Id)  NOTE: raw value, NOT the composite top-level Id
      { "Key{ "Title": "invoiceDateTekst",         "Value": "<offset>"<Tekst> },       // Data: AKOND.BILAGSDATOTEKST (DateTimeOffset)DUPLICATE orof nulldescription,
      { "Key": "dueDate",         "Value": "<offset>" },      // Data: AKOND.FORFDATO (DateTimeOffset) or null
      { "Key": "totalAmount",     "Value": "1953.12" },       // Data: AKOND.KR (.ToString(), so a STRING here// vs decimal atsent topvia level)
      { "Key": "period",Title (untranslated) not Key)
           "Value"// NOTE: "1monthocr" },key is NOT emitted (source field not yet // Data: same derivation as top-level Periodidentified - TODO)
      { "Key": "remainingAmount", "Value": "0.00" },          // Data: TotalAmount - PaidAmount (.ToString(); null unless both present)
      { "Key": "status",          "Value": "paid" },          // Data: same derivation as top-level InvoiceStatus
      { "Key": "description",     "Value": "<Tekst>" },       // Data: AKOND.TEKST
      { "Title": "Tekst",         "Value": "<Tekst>" }        // Data: AKOND.TEKST (DUPLICATE of description; uses Title (untranslated) instead of Key)
      // "ocr"  -> Not mapped (TODO: source field in SonWin not yet identified)
    ]
  }
]

Field origin detail (top-level BrightInvoice): 

]
  }
]

Field origin detail (top-level BrightInvoice): 

  • Id  
  • Id              <- composite "{InstNr}-{ForbnNr}-{UdebNr}-{Id}" (Id = REGNINGNR) 
  • ServiceId       <- ForsyningsartMapper.MapToBrightServiceType(ForsyningsArt, AfregnType) 
  • DueDate         <- AKOND.FORFDATO 
  • InvoiceDate     <- AKOND.BILAGSDATO
  • Period          <- MapPeriod(DATOFRA, DATOTIL)
  • StartDate       <- AKOND.DATOFRA
  • EndDate         <- AKOND.DATOTIL
  • RemainingAmount <- AKOND.KR - PBSI PaidAmount (null unless both present)
  • TotalAmount     <- AKOND.KR
  • InvoiceStatus   <- MapInvoiceStatus(row).GetDisplayName()
  • InvoiceType     <- MapInvoiceType(row)  ("pdf" if HasPdf else "missing")
  • Info
  •            <
  • - list assembled in the mapper (see above)
  • - composite "{InstNr}-{ForbnNr}-{UdebNr}-{Id}" (Id = REGNINGNR) 
  • ServiceId       <- ForsyningsartMapper.MapToBrightServiceType(ForsyningsArt, AfregnType) 
  • DueDate         <- AKOND.FORFDATO 
  • InvoiceDate     <- AKOND.BILAGSDATO
  • Period          <- MapPeriod(DATOFRA, DATOTIL)
  • StartDate       <- AKOND.DATOFRA
  • EndDate         <- AKOND.DATOTIL
  • RemainingAmount <- AKOND.KR - PBSI PaidAmount (null unless both present)
  • TotalAmount     <- AKOND.KR
  • InvoiceStatus   <- MapInvoiceStatus(row).GetDisplayName()
  • InvoiceType     <- MapInvoiceType(row)  ("pdf" if HasPdf else "missing")
  • Info            <- list assembled in the mapper (see above)

INVOICE STATUS LOGIC (MapInvoiceStatus, first match wins):

  1. KORTSTATUS = 99 InvoiceStatus derivation (MapInvoiceStatus), in order:
  1. KORTSTATUS == 99                    -> "cancelled"
  2. TotalAmount (KR) < 0                -> "credited"
  3. SettlementDate (UDLIGNDATO) set     -> "paid"  (regardless of PaidAmount)
  4. PaidAmount >= TotalAmount           -> "paid"
  5. DueDate < today (and not fully paid)-> "overdue"
  6. PaidAmount > 0                       -> "partly_paid"
  7. otherwise                             -> "unpaidcancelled"
 (collection / reminder / deferred_* / investigation / paid_out are never returned — TODO.)

PaidAmount source: OUTER APPLY over Sonlinc.AKOND where TARIFART='PBSI' for the same INSTNR+FORBNR+UDEBNR+REGNINGNR+FIRMANR; SUM(KR*ANTAL)*-1

(PBSI rows are negative), ISNULL(...,0). Not exposed as its own response field — only feeds RemainingAmount and the status derivation.

confirmed cancelled)
  2. TotalAmount (KR) < 0                   -> "credited"   (credit note)
  3. UDLIGNDATO set OR running saldo <= 0   -> "paid"       (account square through this line; balance-forward)
  4. DueDate (FORFDATO) in the past         -> "overdue"
  5. otherwise                              -> "unpaid"
  ('partly_paid' is intentionally never produced.)

PERIOD LOGIC (MapPeriod): month span = (EndDate - StartDate) in whole months;

  • 2→"2month"
  • 3→"3month"
  • 6→"6month"
  • 12→"12month"
  • anything else (incl. missing dates or 1-month) -> "1month".

(PBSI rows are negative), ISNULL(...,0). Not exposed as its own response field — only feeds RemainingAmount and the status derivation.DbInvoice columns selected but NOT surfaced as their own response field:
  - AfregnType (AKOND.AFREGNTYPE)   used only by ServiceId (KØL -> cooling)
  - KortStatus (AKOND.KORTSTATUS)   used only by status (== 99 -> cancelled)
  - KortType   (AKOND.KORTTYPE)     selected, currently unused in mapping
  - SettlementDate (AKOND.UDLIGNDATO) used only by status
  - CollectiveBillNr (AKOND.SAMLREGNINGNR) selected; also used as a WHERE filter
  - HasPdf (EXISTS check)           used only by InvoiceType
  - PaidAmount (PBSI sum)           used by RemainingAmount + status