feat(api): ROT/RUT, articles, and project lifecycle on the v1 API (#904)
* feat(api): ROT/RUT + articles + dimensions on the v1 invoice surface (#895) - v1 invoice POST now routes through buildInvoiceWriteData, the same builder as the dashboard: ROT/RUT deduction lines (server-side compute, personnummer encryption), article_id + revenue_account linkage, accruals, and line_type no longer get silently dropped on the wire. - v1 invoice PATCH accepts default_dimensions so integrations can tag a draft with a project/cost centre after creation. - New PATCH/DELETE /dimensions/:id/values/:valueId: rename, archive, set end_date on project codes; delete unreferenced values (409 with an archive hint when the BFL retention trigger blocks). - New GET /articles: read-only artikelregister list (incl. housework_type) so callers can resolve article_id before composing invoice lines. - Invoice GET/POST projections now expose deduction fields and full item columns; dry-run previews never echo the encrypted personnummer. Closes #895 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(api): address review on #904 - Extract shared v1 invoice projections to lib/api/v1/invoice-columns.ts so create/detail/patch responses can't drift; PATCH now returns deduction_total + deduction_personnummer_last4 like GET/POST. - Narrow the v1 create customer fetch back to the three fields the builder reads instead of select('*'). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
31b244acf5
commit
cdac1808c9
@@ -1,16 +1,18 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`v1 spec snapshot > matches the recorded endpoint count > endpoint-count 1`] = `104`;
|
||||
exports[`v1 spec snapshot > matches the recorded endpoint count > endpoint-count 1`] = `107`;
|
||||
|
||||
exports[`v1 spec snapshot > matches the recorded endpoint key set > endpoint-keys 1`] = `
|
||||
[
|
||||
"DELETE /api/v1/companies/:companyId/customers/:id",
|
||||
"DELETE /api/v1/companies/:companyId/dimensions/:id/values/:valueId",
|
||||
"DELETE /api/v1/companies/:companyId/employees/:id",
|
||||
"DELETE /api/v1/companies/:companyId/salary-runs/:id",
|
||||
"DELETE /api/v1/companies/:companyId/suppliers/:id",
|
||||
"DELETE /api/v1/companies/:companyId/webhooks/:id",
|
||||
"GET /api/v1/companies",
|
||||
"GET /api/v1/companies/:companyId/accounts",
|
||||
"GET /api/v1/companies/:companyId/articles",
|
||||
"GET /api/v1/companies/:companyId/compliance/check",
|
||||
"GET /api/v1/companies/:companyId/customers",
|
||||
"GET /api/v1/companies/:companyId/customers/:id",
|
||||
@@ -53,6 +55,7 @@ exports[`v1 spec snapshot > matches the recorded endpoint key set > endpoint-key
|
||||
"GET /api/v1/health",
|
||||
"GET /api/v1/operations/:id",
|
||||
"PATCH /api/v1/companies/:companyId/customers/:id",
|
||||
"PATCH /api/v1/companies/:companyId/dimensions/:id/values/:valueId",
|
||||
"PATCH /api/v1/companies/:companyId/employees/:id",
|
||||
"PATCH /api/v1/companies/:companyId/invoices/:id",
|
||||
"PATCH /api/v1/companies/:companyId/salary-runs/:id",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Shared v1 invoice response projections.
|
||||
*
|
||||
* The create (POST), detail (GET), and draft-update (PATCH) endpoints all
|
||||
* return the same invoice shape; keeping the column lists in one module
|
||||
* prevents response-shape drift between them (a PATCH caller must see the
|
||||
* same fields a GET caller does). Explicit projection: excludes user_id,
|
||||
* company_id (internal scoping) and the encrypted personnummer blob
|
||||
* (deduction_personnummer_last4 is the display-safe representation).
|
||||
* Schema migrations adding columns must update these lists before the
|
||||
* field becomes visible on the public API.
|
||||
*/
|
||||
|
||||
export const INVOICE_FULL_COLUMNS =
|
||||
'id, invoice_number, customer_id, invoice_date, due_date, delivery_date, status, currency, exchange_rate, exchange_rate_date, subtotal, subtotal_sek, vat_amount, vat_amount_sek, total, total_sek, vat_treatment, vat_rate, moms_ruta, your_reference, our_reference, notes, reverse_charge_text, credited_invoice_id, document_type, converted_from_id, paid_at, paid_amount, remaining_amount, default_dimensions, deduction_total, deduction_personnummer_last4, created_at, updated_at'
|
||||
|
||||
export const INVOICE_ITEM_FULL_COLUMNS =
|
||||
'id, sort_order, line_type, description, quantity, unit, unit_price, line_total, vat_rate, vat_amount, article_id, revenue_account, deduction_type, deduction_amount, labor_hours, work_type, housing_designation, apartment_number, brf_org_number, dimensions, created_at'
|
||||
@@ -135,5 +135,10 @@ import '@/app/api/v1/companies/[companyId]/inbox-items/[id]/stamp/route'
|
||||
// Dimensions PR2: registry list + value creation (kostnadsställe/projekt).
|
||||
import '@/app/api/v1/companies/[companyId]/dimensions/route'
|
||||
import '@/app/api/v1/companies/[companyId]/dimensions/[id]/values/route'
|
||||
// #895: value lifecycle (rename/archive/end-date + delete-unreferenced).
|
||||
import '@/app/api/v1/companies/[companyId]/dimensions/[id]/values/[valueId]/route'
|
||||
|
||||
// #895: articles read (artikelregister) for invoice line linkage.
|
||||
import '@/app/api/v1/companies/[companyId]/articles/route'
|
||||
|
||||
export {}
|
||||
|
||||
Reference in New Issue
Block a user