Skip to content

August 21, 2026 — Backend

Release date: Friday, August 21, 2026

Summary

This week makes tender packages match how procurement actually picks risk: add and remove coverage lines, drop many buildings in one request, and include fire and security answers reinsurers need. Insurance year planning is locked to one year ahead so the API cannot skip years or open a second renewal draft. The old initiate-portfolio HTTP step is gone.

Shipped

  • Tender by coverage line: Draft tenders accept coverageLineIds (preferred) so only those lines are seeded. buildingIds remains a shortcut that still seeds all shouldRenew: true lines for the year. Adding a line for a building already on the tender merges into that working copy.
  • Bulk remove from tenders: Remove many working-copy buildings in one request, or remove selected coverage lines (drops the building when no lines remain). Both are all-or-nothing.
  • Fire and security on snapshots: Working copies and snapshots now copy access control, alarm, extinguishing, and guard answers from building baselines (not the workbook).
  • Coverage list lifecycle filters: GET /api/v1/insurance-years/:year/coverage-lines can filter expired vs upcoming vs on-risk today (isExpired / isUpcoming).
  • One year ahead only: POST /api/v1/insurance-years accepts only the next year (ACTIVE + 1, or newest + 1 if none is active) and rejects a second projected draft.
  • Initiate-portfolio removed: That HTTP endpoint is gone. Portfolio copy stays an internal renewal-service method.

Engineering (commit recap)

Backend — week of August 17 – August 23, 2026

Window: after 2026-08-14, before 2026-08-22 (--no-merges). The August 14 tender EML / should-renew seed commit is already in the August 14 notes.

Summary

Five non-merge commits landed on August 17 and 19. Tender work added coverage-line selection, bulk building and coverage removal, and fire/security baseline flags on seed JSON. Insurance-year work dropped the public initiate-portfolio route, added coverage-list lifecycle query flags, and enforced next-year-only create with a single projected draft.

Themes

  • Tender selection by coverage line: POST /api/v1/tenders/:id/buildings takes coverageLineIds or buildingIds (at least one; coverage ids win). Lines must belong to the tender insurance year. Seed copies fire/security baselines onto the working copy. POST /api/v1/tenders/:id/coverages/remove takes sourceCoverageLineIds (the ids stored on coverageSummary).
  • Tender bulk building remove: POST /api/v1/tenders/:id/buildings/remove with buildingRowIds (TenderBuilding.id) so the UI Massehandlinger Fjern action is one request. Draft only; missing ids → 404 and no deletes.
  • Tender fire/security snapshot: Seed util copies fire-alarm, transmission, extinguishing, access-control, and guard flags from building baselines into TenderBuilding.data (and snapshots on approve). Last week’s notes said these were omitted; they are now included.
  • Coverage list lifecycle: Shared Prisma filters (isExpired / isUpcoming, UTC date-only, same rules as BMS expiry/upcoming) on the year coverage-lines list so the tender picker can show active vs expired vs future starts.
  • Insurance year create contract: POST /api/v1/insurance-years returns 400 if year is not exactly the next allowed year, and 409 if a PROJECTED year already exists. Clients cannot skip years or plan more than one year ahead.
  • Initiate-portfolio HTTP gone: Controller, DTO, OpenAPI, and http/api.http examples removed. Internal renewal copy remains for in-process use.

Notable fixes or risks (if any)

  • Client break: Stop calling initiate-portfolio. Create the next year with POST /api/v1/insurance-years (year + copyFromYear) only.
  • Tender add body: Sending both id lists uses coverageLineIds and ignores buildingIds. Empty both lists fails validation.
  • Tender remove: Bulk coverage and building removes are all-or-nothing (404 if any id is missing). Removing the last line on a working-copy building deletes that building row.
  • Coverage list filters: Combine isExpired=false and isUpcoming=false for on-risk today. Omit both flags to keep the unfiltered list.