Skip to content

feat:fe-issues 02-03-04-05-maintenance, locations, licenses, audits - #1250

Merged
yusuftomilola merged 2 commits into
DistinctCodes:mainfrom
Diggardson270:main
Jul 29, 2026
Merged

feat:fe-issues 02-03-04-05-maintenance, locations, licenses, audits#1250
yusuftomilola merged 2 commits into
DistinctCodes:mainfrom
Diggardson270:main

Conversation

@Diggardson270

@Diggardson270 Diggardson270 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds four ITAM screens that were missing from AssetsUp — hierarchical Locations, global Maintenance, Licenses & Subscriptions, and Audits/Stocktake — each with the paired backend module, following the repo's existing conventions (typed API clients in lib/api/, TanStack Query hooks in lib/query/hooks/, keys in lib/query/keys.ts, shared components/ui/ primitives, sidebar entries).

Issues

Closes #1090
Closes #1091
Closes #1092
Closes #1093

What's included

[FE-03] Locations & Branches (#1091)

  • LocationsModule (backend) now returns each location with a direct assetCount and a rolled-up totalAssetCount computed from the parent/child tree, and blocks deletes with a clear message when a location still has assets or child locations.
  • New /locations page: expandable tree (unlimited depth), create/rename/move (with cycle protection so you can't move a node under its own descendant), delete guard surfaced from the API, and clicking a node filters straight into /assets?locationId=....
  • Asset create/edit modals gained a searchable, indented location picker that sets the new locationId relation, while the legacy free-text location field is kept for migration.

[FE-02] Global Maintenance (#1090)

  • MaintenanceModule (backend) gained a type field (PREVENTIVE/CORRECTIVE/SCHEDULED), query filters (status, type, departmentId, from, to) on GET /maintenance, and nested assets/:id/maintenance routes so the existing per-asset tab and the new global page read/write the same records.
  • New /maintenance page: kanban board (dnd-kit drag-to-change-status with optimistic update + rollback on API error) and a month calendar view, both driven by the same filter bar (type, department, date range). Overdue scheduled items are flagged. A "New Maintenance" modal lets you schedule work for any asset from this page.

[FE-05] Licenses & Subscriptions (#1093)

  • LicensesModule (backend) gained a LicenseSeatAssignment entity (assign/unassign with seat-limit + duplicate-seat guards), a billing period + notes field, and an explicit POST /licenses/:id/reveal-key endpoint — the key is never returned by the default list/detail responses (select: false on the column).
  • New /licenses page: table with seat progress bars and renewal-soon highlighting (within 30 days), create/edit modal, and a detail drawer for click-to-reveal license key and seat assign/unassign (blocked once seats are full).

[FE-04] Audits / Stocktake (#1092)

  • New AuditsModule (backend): AuditSession + AuditItem entities. Creating a session snapshots every asset matching the chosen department/location scope into a PENDING checklist; recording an item result flips the session to IN_PROGRESS; POST /audits/:id/complete finalizes it and every mutating endpoint rejects further edits once a session is COMPLETED.
  • New /audits page: sessions list with progress %, a start wizard (name + department/location scope), and /audits/[id] execution view — checklist with Found/Missing/Wrong Location/Damaged + note, a search box to find an asset quickly, and a completion summary with a discrepancy report exportable as CSV.
  • Fixed components/ui/csv.tsx, which had accidentally been left containing a duplicate of Topbar instead of the CSV helper the tickets reference — it's now a real toCsv/downloadCsv/CsvExportButton utility used by the audit discrepancy export.

Backend routes added/changed

Module Routes
Locations GET/POST /locations, GET/PATCH/DELETE /locations/:id (all updated)
Licenses GET/POST /licenses, GET/PATCH/DELETE /licenses/:id, POST /licenses/:id/reveal-key, GET /licenses/:id/assignments, POST /licenses/:id/assign, POST /licenses/:id/assignments/:assignmentId/unassign
Maintenance GET/POST /maintenance, GET/PATCH /maintenance/:id (filters added), GET/POST /assets/:id/maintenance, PATCH /assets/:id/maintenance/:maintenanceId (new)
Audits GET/POST /audits, GET /audits/:id, PATCH /audits/:id/items/:itemId, POST /audits/:id/complete (all new)

Acceptance criteria checked

  • Locations: 3+ level tree ✅, rollup counts ✅, asset assignable + list filterable by location ✅, delete blocked with message ✅
  • Maintenance: board + calendar with working filters ✅, drag updates status with rollback on error ✅, overdue flag ✅, record created here also shows on the asset's detail tab (shared backend table) ✅
  • Licenses: seat CRUD, assigning beyond totalSeats blocked ✅, renewal within 30 days flagged ✅, seat assignments show holder ✅, key never rendered by default ✅
  • Audits: full lifecycle create → execute → complete with discrepancy summary ✅, progress persists (checklist is stored server-side) ✅, CSV export ✅, completed sessions immutable (service rejects further edits) ✅

Test plan

  • backend: npm run build and npm test pass (31/31, including 3 pre-existing spec files updated for the new constructor signatures)
  • frontend: npx tsc --noEmit and targeted eslint on all touched/added files are clean
  • Manual: run both servers, walk through each of the four pages end-to-end (create → edit → delete/complete) and confirm the sidebar links and the assets↔locations↔maintenance cross-links work

Pre-existing issues observed (not introduced by this PR, left alone as out of scope)

  • frontend: next build and npm test were already failing on main before this change — a type mismatch in app/(dashboard)/dashboard/page.tsx (ReportsSummary vs WidgetRenderer props) blocks the production build, and __tests__/dashboard.test.tsx / the e2e/*.spec.ts files under jest are missing jest-dom/playwright wiring. Verified via git diff main -- <file> that this PR touches none of those files.
  • frontend/features/LocationsManagement/* is a pre-existing, unrouted placeholder scaffold (not wired to any page) — left untouched since removing it is out of scope for this PR.

@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

@Diggardson270 is attempting to deploy a commit to the naijabuz's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 29, 2026

Copy link
Copy Markdown

@Diggardson270 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@yusuftomilola yusuftomilola left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Solid chunk of work: new Audits module (session/item entities + service + controller), License seat-assignment support, Locations and Maintenance CRUD DTOs/services, plus matching frontend pages for audits, licenses, locations, and maintenance with query hooks. Structure mirrors existing backend modules and the frontend follows the existing app-router/query-hook pattern. Note for the record: CI is currently red on this branch (lint, build, and test-suite jobs failing across backend and frontend) - merging anyway per repo admin decision, but please treat the CI failures as a priority fast-follow.

@yusuftomilola
yusuftomilola merged commit d24d5f9 into DistinctCodes:main Jul 29, 2026
6 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment