Merge branch 'dev' of https://github.com/Oloodi/krow-workforce into feature/session-persistence-new
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
> **Status: LEGACY / ARCHIVED REFERENCE**
|
||||
> This document is based on a historical export from the Base44 platform.
|
||||
> It is maintained in this repository solely for reference purposes during the rebuild and is **not** to be considered the definitive or active API specification for the production system.
|
||||
> The actual data schemas and operations are now defined directly within `backend/dataconnect/`.
|
||||
> The historical V1 Data Connect schemas and operations now live in `legacy/dataconnect-v1/`.
|
||||
> The active V2 backend source of truth is the unified/backend service stack under `backend/command-api`, `backend/query-api`, `backend/core-api`, and `backend/unified-api`.
|
||||
|
||||
**Original Version:** 3.0
|
||||
**Original Date:** 2025-11-20
|
||||
@@ -1423,4 +1424,4 @@ firebase functions:config:set \
|
||||
|
||||
---
|
||||
|
||||
© 2025 KROW Workforce / Oloodi Technologies Inc. All rights reserved.
|
||||
© 2025 KROW Workforce / Oloodi Technologies Inc. All rights reserved.
|
||||
|
||||
@@ -926,7 +926,7 @@ Via modular `profile_sections/` architecture:
|
||||
| Legacy Client Mobile | `_legacy/apps/krow_client_context.md` | Flutter (context doc) |
|
||||
| Legacy Worker (Legacy Staff) Mobile | `_legacy/apps/krow_staff_context.md` | Flutter (context doc) |
|
||||
| Legacy Backend | `_legacy/apps/php_backend_context.md` | PHP/Laravel |
|
||||
| New Backend | `backend/dataconnect/` | Firebase Data Connect |
|
||||
| Legacy V1 Data Connect Backend | `legacy/dataconnect-v1/` | Firebase Data Connect |
|
||||
|
||||
---
|
||||
|
||||
@@ -974,7 +974,7 @@ For each feature in Sprint 3:
|
||||
|
||||
2. **Write Schema Incrementally**
|
||||
```gql
|
||||
# backend/dataconnect/schema/event.gql
|
||||
# legacy/dataconnect-v1/schema/event.gql
|
||||
type Event @table {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
name: String!
|
||||
@@ -989,7 +989,7 @@ For each feature in Sprint 3:
|
||||
|
||||
3. **Define Queries/Mutations**
|
||||
```gql
|
||||
# backend/dataconnect/queries/events.gql
|
||||
# legacy/dataconnect-v1/queries/events.gql
|
||||
query ListEvents($status: EventStatus) @auth(level: USER) {
|
||||
events(where: { status: { eq: $status } }) {
|
||||
id, name, status, date
|
||||
@@ -1308,7 +1308,7 @@ Business (1) ──┬── (1) BusinessSetting
|
||||
| Legacy Client context | `_legacy/apps/krow_client_context.md` |
|
||||
| Legacy Staff context | `_legacy/apps/krow_staff_context.md` |
|
||||
| Architecture diagrams | `internal/launchpad/assets/diagrams/` |
|
||||
| Data Connect schemas | `backend/dataconnect/` |
|
||||
| Data Connect schemas | `legacy/dataconnect-v1/` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@ What was validated live against the deployed stack:
|
||||
- staff auth bootstrap
|
||||
- client dashboard, billing, coverage, hubs, vendors, managers, team members, orders, and reports
|
||||
- client coverage incident feed for geofence and override review
|
||||
- client blocked-staff review and invited shift-manager creation
|
||||
- client hub, order, coverage review, device token, and late-worker cancellation flows
|
||||
- client swap-request review, dispatch-team management, and dispatch-candidate ranking
|
||||
- client invoice approve and dispute
|
||||
- staff dashboard, availability, payments, shifts, profile sections, documents, certificates, attire, bank accounts, benefits, and time card
|
||||
- staff availability, profile, tax form, bank account, shift apply, shift accept, push token registration, clock-in, clock-out, location stream upload, and swap request
|
||||
- staff benefit history read model
|
||||
- staff availability, profile, tax form, bank account, shift apply, shift accept, push token registration, clock-in, clock-out, location stream upload, swap request, and completed-shift submission
|
||||
- direct file upload helpers and verification job creation through the unified host
|
||||
- client and staff sign-out
|
||||
|
||||
@@ -107,6 +110,20 @@ Important operational rules:
|
||||
- background location streams are stored as raw batch payloads in the private v2 bucket and summarized in SQL for query speed
|
||||
- incident review lives on `GET /client/coverage/incidents`
|
||||
- confirmed late-worker recovery is exposed on `POST /client/coverage/late-workers/:assignmentId/cancel`
|
||||
- client swap review is exposed on:
|
||||
- `GET /client/coverage/swap-requests`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
- dispatch-team management is exposed on:
|
||||
- `GET /client/coverage/dispatch-teams`
|
||||
- `GET /client/coverage/dispatch-candidates`
|
||||
- `POST /client/coverage/dispatch-teams/memberships`
|
||||
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
|
||||
- dispatch ranking order is:
|
||||
1. `CORE`
|
||||
2. `CERTIFIED_LOCATION`
|
||||
3. `MARKETPLACE`
|
||||
- expired swap requests are auto-cancelled by the notification worker and emit manager plus staff alerts
|
||||
- queued alerts are written to `notification_outbox`, dispatched by the private Cloud Run worker service `krow-notification-worker-v2`, and recorded in `notification_deliveries`
|
||||
|
||||
## 5) Route model
|
||||
@@ -143,6 +160,9 @@ Those routes still exist for backend/internal compatibility, but mobile/frontend
|
||||
|
||||
- [Authentication](./authentication.md)
|
||||
- [Unified API](./unified-api.md)
|
||||
- [Mobile Coding Agent Spec](./mobile-coding-agent-spec.md)
|
||||
- [Mobile Frontend Implementation Spec](./mobile-frontend-implementation-spec.md)
|
||||
- [Staff Shifts](./staff-shifts.md)
|
||||
- [Core API](./core-api.md)
|
||||
- [Command API](./command-api.md)
|
||||
- [Query API](./query-api.md)
|
||||
|
||||
388
docs/BACKEND/API_GUIDES/V2/mobile-coding-agent-spec.md
Normal file
388
docs/BACKEND/API_GUIDES/V2/mobile-coding-agent-spec.md
Normal file
@@ -0,0 +1,388 @@
|
||||
# Mobile Coding Agent Spec
|
||||
|
||||
This document is the frontend handoff spec for an AI coding agent working on the mobile applications against the v2 backend.
|
||||
|
||||
Use this as the primary implementation brief.
|
||||
|
||||
Base URL:
|
||||
|
||||
- `https://krow-api-v2-933560802882.us-central1.run.app`
|
||||
|
||||
Supporting docs:
|
||||
|
||||
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/authentication.md`
|
||||
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/unified-api.md`
|
||||
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/mobile-frontend-implementation-spec.md`
|
||||
- `/Users/wiel/Development/krow-workforce/docs/BACKEND/API_GUIDES/V2/staff-shifts.md`
|
||||
|
||||
## 1) Non-negotiable rules
|
||||
|
||||
- Use the unified base URL only.
|
||||
- Do not call `/query/*`, `/commands/*`, or `/core/*` directly from frontend.
|
||||
- Send `Authorization: Bearer <firebase-id-token>` on protected routes.
|
||||
- Send `Idempotency-Key` on every write route.
|
||||
- Treat `order`, `shift`, `shiftRole`, and `assignment` as different objects.
|
||||
- For staff shift applications, `roleId` must come from the response of `GET /staff/shifts/open`.
|
||||
|
||||
## 2) What is implemented now
|
||||
|
||||
Safe to build against now:
|
||||
|
||||
- client auth/session
|
||||
- client dashboard, billing, coverage, hubs, vendors, managers, team members, orders, reports
|
||||
- client coverage reviews, worker rating, block/unblock, late-worker cancellation
|
||||
- client swap review and dispatch-team management
|
||||
- staff auth/session
|
||||
- staff dashboard, availability, payments, shifts, profile, tax forms, bank accounts, benefits, documents, attire, certificates
|
||||
- staff clock-in, clock-out, location streaming, swap request, completed-shift submission
|
||||
- upload, signed URL, verification, and rapid-order processing
|
||||
|
||||
Not part of this implementation spec:
|
||||
|
||||
- backend `/auth/refresh`
|
||||
- SMS or email notification fallback
|
||||
- AI-driven report insights
|
||||
- AI-driven personalized shift matching
|
||||
- full NFC attestation enforcement
|
||||
- chat backend
|
||||
|
||||
## 3) Auth implementation
|
||||
|
||||
### Client app
|
||||
|
||||
Use:
|
||||
|
||||
- `POST /auth/client/sign-in`
|
||||
- `POST /auth/client/sign-up`
|
||||
- `GET /auth/session`
|
||||
- `POST /auth/client/sign-out`
|
||||
|
||||
Do not build a separate refresh route.
|
||||
|
||||
Token refresh remains on the Firebase client SDK side.
|
||||
|
||||
### Staff app
|
||||
|
||||
Use:
|
||||
|
||||
- `POST /auth/staff/phone/start`
|
||||
- `POST /auth/staff/phone/verify`
|
||||
- `GET /auth/session`
|
||||
- `POST /auth/staff/sign-out`
|
||||
|
||||
Important:
|
||||
|
||||
- `POST /auth/staff/phone/start` can return `mode = CLIENT_FIREBASE_SDK`
|
||||
- when that happens, the app must complete Firebase phone verification on-device
|
||||
- after that, the app must call `POST /auth/staff/phone/verify` with the Firebase `idToken`
|
||||
|
||||
Do not assume staff auth is a fully backend-managed OTP flow.
|
||||
|
||||
## 4) Core data model assumptions
|
||||
|
||||
- `order`: client-facing staffing request
|
||||
- `shift`: a scheduled work instance under an order
|
||||
- `shiftRole`: a role slot inside a shift
|
||||
- `application`: worker applies to a `shiftRole`
|
||||
- `assignment`: worker is actually attached to a shift
|
||||
|
||||
Rules:
|
||||
|
||||
- `GET /staff/shifts/open` returns opportunities, not assignments
|
||||
- `GET /staff/shifts/assigned` returns active assigned shifts
|
||||
- `GET /client/orders/view` is the timeline/read model for client
|
||||
- `POST /client/orders/:orderId/edit` and `POST /client/orders/:orderId/cancel` apply to future shifts only
|
||||
|
||||
## 5) Client app screen mapping
|
||||
|
||||
### Home
|
||||
|
||||
- `GET /client/session`
|
||||
- `GET /client/dashboard`
|
||||
- `GET /client/reorders`
|
||||
|
||||
### Billing
|
||||
|
||||
- `GET /client/billing/accounts`
|
||||
- `GET /client/billing/invoices/pending`
|
||||
- `GET /client/billing/invoices/history`
|
||||
- `GET /client/billing/current-bill`
|
||||
- `GET /client/billing/savings`
|
||||
- `GET /client/billing/spend-breakdown`
|
||||
- `POST /client/billing/invoices/:invoiceId/approve`
|
||||
- `POST /client/billing/invoices/:invoiceId/dispute`
|
||||
|
||||
### Coverage
|
||||
|
||||
- `GET /client/coverage?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/stats?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/core-team?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/incidents?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD`
|
||||
- `GET /client/coverage/blocked-staff`
|
||||
- `GET /client/coverage/swap-requests?status=OPEN`
|
||||
- `GET /client/coverage/dispatch-teams`
|
||||
- `GET /client/coverage/dispatch-candidates?shiftId=uuid&roleId=uuid`
|
||||
- `POST /client/coverage/reviews`
|
||||
- `POST /client/coverage/late-workers/:assignmentId/cancel`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
- `POST /client/coverage/dispatch-teams/memberships`
|
||||
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
|
||||
|
||||
Coverage review payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"assignmentId": "uuid",
|
||||
"rating": 4,
|
||||
"comment": "Strong performance on the shift",
|
||||
"markAsBlocked": false
|
||||
}
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- worker rating happens through `POST /client/coverage/reviews`
|
||||
- the same endpoint also supports `markAsFavorite` to add or remove a worker from business favorites
|
||||
- blocking a worker is done through the same endpoint using `markAsBlocked`
|
||||
- dispatch ranking order is:
|
||||
1. `CORE`
|
||||
2. `CERTIFIED_LOCATION`
|
||||
3. `MARKETPLACE`
|
||||
|
||||
Swap management flow:
|
||||
|
||||
1. worker requests swap
|
||||
2. backend moves original assignment to `SWAP_REQUESTED`
|
||||
3. replacement workers see the shift in `GET /staff/shifts/open`
|
||||
4. client/ops reads `GET /client/coverage/swap-requests`
|
||||
5. client/ops reads `GET /client/coverage/dispatch-candidates`
|
||||
6. client/ops resolves or cancels the swap request
|
||||
7. if unresolved and expired, backend auto-cancels it
|
||||
|
||||
### Orders
|
||||
|
||||
- `GET /client/orders/view`
|
||||
- `GET /client/orders/:orderId/reorder-preview`
|
||||
- `POST /client/orders/one-time`
|
||||
- `POST /client/orders/recurring`
|
||||
- `POST /client/orders/permanent`
|
||||
- `POST /client/orders/:orderId/edit`
|
||||
- `POST /client/orders/:orderId/cancel`
|
||||
- `POST /rapid-orders/process`
|
||||
|
||||
Rules:
|
||||
|
||||
- use `POST /rapid-orders/process` for the single-call rapid-order flow
|
||||
- recent orders should expect total price and hourly rate fields
|
||||
- order edit and cancel only affect future shifts
|
||||
|
||||
### Hubs and managers
|
||||
|
||||
- `GET /client/hubs`
|
||||
- `GET /client/cost-centers`
|
||||
- `GET /client/hubs/:hubId/managers`
|
||||
- `GET /client/team-members`
|
||||
- `POST /client/shift-managers`
|
||||
- `POST /client/hubs`
|
||||
- `PUT /client/hubs/:hubId`
|
||||
- `DELETE /client/hubs/:hubId`
|
||||
- `POST /client/hubs/:hubId/assign-nfc`
|
||||
- `POST /client/hubs/:hubId/managers`
|
||||
|
||||
Rules:
|
||||
|
||||
- `POST /client/shift-managers` creates an invited manager identity
|
||||
- if `hubId` is present, backend links the manager to that hub too
|
||||
|
||||
### Reports
|
||||
|
||||
- `GET /client/reports/summary?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/daily-ops?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/spend?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/coverage?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/forecast?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/performance?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/no-show?date=YYYY-MM-DD`
|
||||
|
||||
Important:
|
||||
|
||||
- these are operational reports
|
||||
- this is not the same as the separate AI insights research issue
|
||||
|
||||
## 6) Staff app screen mapping
|
||||
|
||||
### Home
|
||||
|
||||
- `GET /staff/session`
|
||||
- `GET /staff/dashboard`
|
||||
- `GET /staff/profile-completion`
|
||||
|
||||
### Availability
|
||||
|
||||
- `GET /staff/availability`
|
||||
- `PUT /staff/availability`
|
||||
- `POST /staff/availability/quick-set`
|
||||
|
||||
### Find shifts
|
||||
|
||||
- `GET /staff/shifts/open`
|
||||
- `POST /staff/shifts/:shiftId/apply`
|
||||
|
||||
Rule:
|
||||
|
||||
- use `roleId` from the open-shifts response
|
||||
|
||||
### My shifts
|
||||
|
||||
- `GET /staff/shifts/pending`
|
||||
- `GET /staff/shifts/assigned`
|
||||
- `GET /staff/shifts/cancelled`
|
||||
- `GET /staff/shifts/completed`
|
||||
- `GET /staff/shifts/:shiftId`
|
||||
- `POST /staff/shifts/:shiftId/accept`
|
||||
- `POST /staff/shifts/:shiftId/decline`
|
||||
- `POST /staff/shifts/:shiftId/request-swap`
|
||||
- `POST /staff/shifts/:shiftId/submit-for-approval`
|
||||
|
||||
Staff shift detail and list rules:
|
||||
|
||||
- assigned shifts include `clientName`, `hourlyRate`, `totalRate`, `startTime`, `endTime`
|
||||
- shift detail includes `clientName`, `latitude`, `longitude`, `hourlyRate`, `totalRate`
|
||||
- completed shifts include `date`, `clientName`, `startTime`, `endTime`, `hourlyRate`, `totalRate`
|
||||
|
||||
### Clock in / clock out
|
||||
|
||||
- `GET /staff/clock-in/shifts/today`
|
||||
- `GET /staff/clock-in/status`
|
||||
- `POST /staff/clock-in`
|
||||
- `POST /staff/clock-out`
|
||||
- `POST /staff/location-streams`
|
||||
|
||||
Clock-in payload rules:
|
||||
|
||||
- if using NFC, send `nfcTagId`
|
||||
- if using geo, send `latitude`, `longitude`, `accuracyMeters`
|
||||
- send `overrideReason` only when geo override is allowed
|
||||
- send `proofNonce` and `proofTimestamp` on attendance writes
|
||||
- send `attestationProvider` and `attestationToken` only if the device has them
|
||||
|
||||
Clock-in read rules:
|
||||
|
||||
`GET /staff/clock-in/shifts/today` returns fields including:
|
||||
|
||||
- `clientName`
|
||||
- `hourlyRate`
|
||||
- `totalRate`
|
||||
- `latitude`
|
||||
- `longitude`
|
||||
- `clockInMode`
|
||||
- `allowClockInOverride`
|
||||
- `geofenceRadiusMeters`
|
||||
- `nfcTagId`
|
||||
|
||||
Policy values:
|
||||
|
||||
- `NFC_REQUIRED`
|
||||
- `GEO_REQUIRED`
|
||||
- `EITHER`
|
||||
|
||||
### Payments
|
||||
|
||||
- `GET /staff/payments/summary`
|
||||
- `GET /staff/payments/history`
|
||||
- `GET /staff/payments/chart`
|
||||
|
||||
### Profile
|
||||
|
||||
- `GET /staff/profile/sections`
|
||||
- `GET /staff/profile/personal-info`
|
||||
- `GET /staff/profile/industries`
|
||||
- `GET /staff/profile/skills`
|
||||
- `GET /staff/profile/documents`
|
||||
- `GET /staff/profile/attire`
|
||||
- `GET /staff/profile/tax-forms`
|
||||
- `GET /staff/profile/emergency-contacts`
|
||||
- `GET /staff/profile/certificates`
|
||||
- `GET /staff/profile/bank-accounts`
|
||||
- `GET /staff/profile/benefits`
|
||||
- `GET /staff/profile/benefits/history`
|
||||
- `GET /staff/profile/time-card`
|
||||
- `GET /staff/profile/privacy`
|
||||
- `PUT /staff/profile/personal-info`
|
||||
- `PUT /staff/profile/experience`
|
||||
- `PUT /staff/profile/locations`
|
||||
- `POST /staff/profile/emergency-contacts`
|
||||
- `PUT /staff/profile/emergency-contacts/:contactId`
|
||||
- `PUT /staff/profile/tax-forms/:formType`
|
||||
- `POST /staff/profile/tax-forms/:formType/submit`
|
||||
- `POST /staff/profile/bank-accounts`
|
||||
- `PUT /staff/profile/privacy`
|
||||
|
||||
Profile data rules:
|
||||
|
||||
- `GET /staff/profile/documents` returns documents only
|
||||
- `GET /staff/profile/attire` returns attire only
|
||||
- `GET /staff/profile/tax-forms` returns tax forms only
|
||||
- `GET /staff/profile/certificates` returns certificates only
|
||||
- benefit summary and benefit history are separate endpoints
|
||||
|
||||
### FAQ
|
||||
|
||||
- `GET /staff/faqs`
|
||||
- `GET /staff/faqs/search?q=...`
|
||||
|
||||
## 7) Upload flows
|
||||
|
||||
### General upload pattern
|
||||
|
||||
For documents, attire, and certificates:
|
||||
|
||||
1. `POST /upload-file`
|
||||
2. `POST /create-signed-url`
|
||||
3. upload bytes to storage
|
||||
4. `POST /verifications`
|
||||
5. finalize using the appropriate staff route
|
||||
|
||||
Staff upload routes:
|
||||
|
||||
- `POST /staff/profile/photo`
|
||||
- `POST /staff/profile/documents/:documentId/upload`
|
||||
- `PUT /staff/profile/documents/:documentId/upload`
|
||||
- `POST /staff/profile/attire/:documentId/upload`
|
||||
- `PUT /staff/profile/attire/:documentId/upload`
|
||||
- `POST /staff/profile/certificates`
|
||||
- `DELETE /staff/profile/certificates/:certificateId`
|
||||
|
||||
Rules:
|
||||
|
||||
- backend treats verification-linked file state as the source of truth
|
||||
- frontend may still send `fileUri` or `photoUrl`, but verification linkage wins
|
||||
|
||||
## 8) What the coding agent should not assume
|
||||
|
||||
- do not invent a backend refresh route
|
||||
- do not assume swap is staff-only; there is now a client/ops review side
|
||||
- do not assume documents and attire share the same read endpoint
|
||||
- do not assume backend direct CRUD on internal services
|
||||
- do not assume AI reports, SMS fallback, or full NFC attestation are available
|
||||
|
||||
## 9) Suggested implementation order for the coding agent
|
||||
|
||||
1. auth/session flows
|
||||
2. client home + orders + coverage
|
||||
3. staff home + shifts + clock-in
|
||||
4. profile sections and upload flows
|
||||
5. reports and billing polish
|
||||
6. swap review and dispatch-team management
|
||||
|
||||
## 10) Definition of done for frontend integration
|
||||
|
||||
Frontend implementation is aligned when:
|
||||
|
||||
- every screen calls the unified v2 routes only
|
||||
- every write sends an `Idempotency-Key`
|
||||
- staff shift apply uses `roleId` from open shifts
|
||||
- clock-in respects `clockInMode`
|
||||
- swap request uses the staff endpoint and swap review uses the client coverage endpoints
|
||||
- documents, attire, certificates, and tax forms use their correct route families
|
||||
@@ -0,0 +1,305 @@
|
||||
# Mobile Frontend Implementation Spec
|
||||
|
||||
This is the shortest path for frontend to implement the v2 mobile clients against the unified backend.
|
||||
|
||||
Base URL:
|
||||
|
||||
- `https://krow-api-v2-933560802882.us-central1.run.app`
|
||||
|
||||
Use this doc together with:
|
||||
|
||||
- [Authentication](./authentication.md)
|
||||
- [Unified API](./unified-api.md)
|
||||
- [Staff Shifts](./staff-shifts.md)
|
||||
|
||||
## 1) Global rules
|
||||
|
||||
- Use unified routes only.
|
||||
- Send `Authorization: Bearer <firebase-id-token>` on protected routes.
|
||||
- Send `Idempotency-Key` on all write routes.
|
||||
- Do not call `/query/*`, `/commands/*`, or `/core/*` directly from frontend.
|
||||
|
||||
## 2) Core model frontend should assume
|
||||
|
||||
- `order` is the client-facing request for staffing.
|
||||
- `shift` is the concrete scheduled unit of work under an order.
|
||||
- `shiftRole` is the role slot inside a shift that staff apply to.
|
||||
- `assignment` is the worker-to-shift record once a worker is attached.
|
||||
|
||||
Important consequences:
|
||||
|
||||
- `GET /staff/shifts/open` returns open shift-role opportunities.
|
||||
- `POST /staff/shifts/:shiftId/apply` must send the `roleId` from that response.
|
||||
- `GET /client/orders/view` is the timeline/read model for the client app.
|
||||
- `POST /client/orders/:orderId/edit` and `POST /client/orders/:orderId/cancel` only affect future shifts.
|
||||
|
||||
## 3) Auth implementation
|
||||
|
||||
### Client app
|
||||
|
||||
- sign in with `POST /auth/client/sign-in`
|
||||
- sign up with `POST /auth/client/sign-up`
|
||||
- hydrate session with `GET /auth/session`
|
||||
- sign out with `POST /auth/client/sign-out`
|
||||
|
||||
### Staff app
|
||||
|
||||
- start phone auth with `POST /auth/staff/phone/start`
|
||||
- complete phone auth with `POST /auth/staff/phone/verify`
|
||||
- hydrate session with `GET /auth/session`
|
||||
- sign out with `POST /auth/staff/sign-out`
|
||||
|
||||
Token refresh:
|
||||
|
||||
- keep using Firebase client SDK refresh behavior
|
||||
- there is no backend `/auth/refresh` route
|
||||
|
||||
## 4) Client app screen mapping
|
||||
|
||||
### Home / dashboard
|
||||
|
||||
- `GET /client/session`
|
||||
- `GET /client/dashboard`
|
||||
- `GET /client/reorders`
|
||||
|
||||
### Billing / payments
|
||||
|
||||
- `GET /client/billing/accounts`
|
||||
- `GET /client/billing/invoices/pending`
|
||||
- `GET /client/billing/invoices/history`
|
||||
- `GET /client/billing/current-bill`
|
||||
- `GET /client/billing/savings`
|
||||
- `GET /client/billing/spend-breakdown`
|
||||
- `POST /client/billing/invoices/:invoiceId/approve`
|
||||
- `POST /client/billing/invoices/:invoiceId/dispute`
|
||||
|
||||
### Coverage
|
||||
|
||||
- `GET /client/coverage?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/stats?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/core-team?date=YYYY-MM-DD`
|
||||
- `GET /client/coverage/incidents?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD`
|
||||
- `GET /client/coverage/blocked-staff`
|
||||
- `GET /client/coverage/swap-requests?status=OPEN`
|
||||
- `GET /client/coverage/dispatch-teams`
|
||||
- `GET /client/coverage/dispatch-candidates?shiftId=uuid&roleId=uuid`
|
||||
- `POST /client/coverage/reviews`
|
||||
- `POST /client/coverage/late-workers/:assignmentId/cancel`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
- `POST /client/coverage/dispatch-teams/memberships`
|
||||
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
|
||||
|
||||
Use `POST /client/coverage/reviews` when the business is rating a worker after coverage review.
|
||||
|
||||
Payload may include:
|
||||
|
||||
```json
|
||||
{
|
||||
"staffId": "uuid",
|
||||
"assignmentId": "uuid",
|
||||
"rating": 4,
|
||||
"feedback": "Strong performance on the shift",
|
||||
"markAsFavorite": true,
|
||||
"markAsBlocked": false
|
||||
}
|
||||
```
|
||||
|
||||
If `markAsFavorite` is `true`, backend adds that worker to the business favorites list. If `markAsFavorite` is `false`, backend removes them from that list. If `markAsBlocked` is `true`, backend blocks that worker for that business and rejects future apply or assign attempts until a later review sets `markAsBlocked: false`.
|
||||
|
||||
Swap-management rule:
|
||||
|
||||
- use `GET /client/coverage/swap-requests` as the client review feed
|
||||
- use `GET /client/coverage/dispatch-candidates` for the ranked replacement list
|
||||
- use `POST /client/coverage/swap-requests/:swapRequestId/resolve` when ops selects a replacement
|
||||
- use `POST /client/coverage/swap-requests/:swapRequestId/cancel` when ops wants to close the swap request without replacement
|
||||
|
||||
Dispatch-priority rule:
|
||||
|
||||
1. `CORE`
|
||||
2. `CERTIFIED_LOCATION`
|
||||
3. `MARKETPLACE`
|
||||
|
||||
### Orders
|
||||
|
||||
- `GET /client/orders/view`
|
||||
- `GET /client/orders/:orderId/reorder-preview`
|
||||
- `POST /client/orders/one-time`
|
||||
- `POST /client/orders/recurring`
|
||||
- `POST /client/orders/permanent`
|
||||
- `POST /client/orders/:orderId/edit`
|
||||
- `POST /client/orders/:orderId/cancel`
|
||||
|
||||
Rapid-order flow:
|
||||
|
||||
- use `POST /rapid-orders/process` for the single-call transcribe-and-parse flow
|
||||
|
||||
### Hubs and managers
|
||||
|
||||
- `GET /client/hubs`
|
||||
- `GET /client/cost-centers`
|
||||
- `GET /client/hubs/:hubId/managers`
|
||||
- `GET /client/team-members`
|
||||
- `POST /client/shift-managers`
|
||||
- `POST /client/hubs`
|
||||
- `PUT /client/hubs/:hubId`
|
||||
- `DELETE /client/hubs/:hubId`
|
||||
- `POST /client/hubs/:hubId/assign-nfc`
|
||||
- `POST /client/hubs/:hubId/managers`
|
||||
|
||||
`POST /client/shift-managers` is the fastest path to create an invited manager identity for a business. If `hubId` is provided, backend also links that manager to the hub.
|
||||
|
||||
### Reports
|
||||
|
||||
- `GET /client/reports/summary?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/daily-ops?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/spend?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/coverage?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/forecast?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/performance?date=YYYY-MM-DD`
|
||||
- `GET /client/reports/no-show?date=YYYY-MM-DD`
|
||||
|
||||
## 5) Staff app screen mapping
|
||||
|
||||
### Home / dashboard
|
||||
|
||||
- `GET /staff/session`
|
||||
- `GET /staff/dashboard`
|
||||
- `GET /staff/profile-completion`
|
||||
|
||||
### Availability
|
||||
|
||||
- `GET /staff/availability`
|
||||
- `PUT /staff/availability`
|
||||
- `POST /staff/availability/quick-set`
|
||||
|
||||
### Find shifts
|
||||
|
||||
- `GET /staff/shifts/open`
|
||||
- `POST /staff/shifts/:shiftId/apply`
|
||||
|
||||
Rule:
|
||||
|
||||
- send the `roleId` from the open-shifts response
|
||||
- this is the concrete `shift_roles.id`
|
||||
|
||||
### My shifts
|
||||
|
||||
- `GET /staff/shifts/pending`
|
||||
- `GET /staff/shifts/assigned`
|
||||
- `GET /staff/shifts/cancelled`
|
||||
- `GET /staff/shifts/completed`
|
||||
- `GET /staff/shifts/:shiftId`
|
||||
- `POST /staff/shifts/:shiftId/accept`
|
||||
- `POST /staff/shifts/:shiftId/decline`
|
||||
- `POST /staff/shifts/:shiftId/request-swap`
|
||||
- `POST /staff/shifts/:shiftId/submit-for-approval`
|
||||
|
||||
Current swap behavior:
|
||||
|
||||
- backend records the swap request
|
||||
- assignment moves to `SWAP_REQUESTED`
|
||||
- shift becomes visible in the replacement pool
|
||||
- client/ops can review and resolve swap requests through the coverage endpoints
|
||||
- if the swap request expires without coverage, backend auto-cancels it and alerts both the manager path and the original worker
|
||||
|
||||
### Clock in / clock out
|
||||
|
||||
- `GET /staff/clock-in/shifts/today`
|
||||
- `GET /staff/clock-in/status`
|
||||
- `POST /staff/clock-in`
|
||||
- `POST /staff/clock-out`
|
||||
- `POST /staff/location-streams`
|
||||
|
||||
Frontend should respect:
|
||||
|
||||
- `clockInMode`
|
||||
- `allowClockInOverride`
|
||||
- `latitude`
|
||||
- `longitude`
|
||||
- `geofenceRadiusMeters`
|
||||
- `nfcTagId`
|
||||
|
||||
Clock-in proof rules:
|
||||
|
||||
- use `nfcTagId` for NFC clocking
|
||||
- use `latitude`, `longitude`, and `accuracyMeters` for geolocation clocking
|
||||
- send `overrideReason` only when a geofence override is allowed
|
||||
- send `proofNonce` and `proofTimestamp` on attendance writes
|
||||
|
||||
### Payments
|
||||
|
||||
- `GET /staff/payments/summary`
|
||||
- `GET /staff/payments/history`
|
||||
- `GET /staff/payments/chart`
|
||||
|
||||
### Profile
|
||||
|
||||
- `GET /staff/profile/sections`
|
||||
- `GET /staff/profile/personal-info`
|
||||
- `GET /staff/profile/industries`
|
||||
- `GET /staff/profile/skills`
|
||||
- `GET /staff/profile/documents`
|
||||
- `GET /staff/profile/attire`
|
||||
- `GET /staff/profile/tax-forms`
|
||||
- `GET /staff/profile/emergency-contacts`
|
||||
- `GET /staff/profile/certificates`
|
||||
- `GET /staff/profile/bank-accounts`
|
||||
- `GET /staff/profile/benefits`
|
||||
- `GET /staff/profile/benefits/history`
|
||||
- `GET /staff/profile/time-card`
|
||||
- `GET /staff/profile/privacy`
|
||||
- `PUT /staff/profile/personal-info`
|
||||
- `PUT /staff/profile/experience`
|
||||
- `PUT /staff/profile/locations`
|
||||
- `POST /staff/profile/emergency-contacts`
|
||||
- `PUT /staff/profile/emergency-contacts/:contactId`
|
||||
- `PUT /staff/profile/tax-forms/:formType`
|
||||
- `POST /staff/profile/tax-forms/:formType/submit`
|
||||
- `POST /staff/profile/bank-accounts`
|
||||
- `PUT /staff/profile/privacy`
|
||||
|
||||
Document model rule:
|
||||
|
||||
- `GET /staff/profile/documents` returns only documents
|
||||
- `GET /staff/profile/attire` returns attire items
|
||||
- `GET /staff/profile/tax-forms` returns tax-form rows
|
||||
- `GET /staff/profile/certificates` returns certificates
|
||||
|
||||
### FAQ
|
||||
|
||||
- `GET /staff/faqs`
|
||||
- `GET /staff/faqs/search?q=...`
|
||||
|
||||
## 6) Upload implementation
|
||||
|
||||
For documents, attire, and certificates:
|
||||
|
||||
1. `POST /upload-file`
|
||||
2. `POST /create-signed-url`
|
||||
3. upload file bytes to storage with the signed URL
|
||||
4. `POST /verifications`
|
||||
5. finalize with:
|
||||
- `PUT /staff/profile/documents/:documentId/upload`
|
||||
- `PUT /staff/profile/attire/:documentId/upload`
|
||||
- `POST /staff/profile/certificates`
|
||||
|
||||
Use the verification-linked file as the source of truth.
|
||||
|
||||
## 7) What frontend should not assume
|
||||
|
||||
- do not assume order edit mutates past shifts
|
||||
- do not assume swap resolution is complete beyond the request step
|
||||
- do not assume raw `/query/*` or `/commands/*` routes are stable for app integration
|
||||
- do not assume blocked workers can still apply to future shifts for that business
|
||||
|
||||
## 8) Demo reset
|
||||
|
||||
To reset dev demo data:
|
||||
|
||||
```bash
|
||||
source ~/.nvm/nvm.sh
|
||||
nvm use 23.5.0
|
||||
cd backend/command-api
|
||||
npm run seed:v2-demo
|
||||
```
|
||||
183
docs/BACKEND/API_GUIDES/V2/staff-shifts.md
Normal file
183
docs/BACKEND/API_GUIDES/V2/staff-shifts.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# Staff Shifts V2
|
||||
|
||||
This document is the frontend handoff for the `staff/shifts/*` routes on the unified v2 API.
|
||||
|
||||
Base URL:
|
||||
|
||||
- `https://krow-api-v2-933560802882.us-central1.run.app`
|
||||
|
||||
## Read routes
|
||||
|
||||
- `GET /staff/shifts/assigned`
|
||||
- `GET /staff/shifts/open`
|
||||
- `GET /staff/shifts/pending`
|
||||
- `GET /staff/shifts/cancelled`
|
||||
- `GET /staff/shifts/completed`
|
||||
- `GET /staff/shifts/:shiftId`
|
||||
|
||||
## Write routes
|
||||
|
||||
- `POST /staff/shifts/:shiftId/apply`
|
||||
- `POST /staff/shifts/:shiftId/accept`
|
||||
- `POST /staff/shifts/:shiftId/decline`
|
||||
- `POST /staff/shifts/:shiftId/request-swap`
|
||||
- `POST /staff/shifts/:shiftId/submit-for-approval`
|
||||
|
||||
All write routes require:
|
||||
|
||||
- `Authorization: Bearer <firebase-id-token>`
|
||||
- `Idempotency-Key: <unique-per-action>`
|
||||
|
||||
## Shift lifecycle
|
||||
|
||||
### Find shifts
|
||||
|
||||
`GET /staff/shifts/open`
|
||||
|
||||
- use this for the worker marketplace feed
|
||||
- the worker applies to a concrete shift role
|
||||
- send the `roleId` returned by the open-shifts response
|
||||
- `roleId` here means `shift_roles.id`, not the role catalog id
|
||||
|
||||
Apply request example:
|
||||
|
||||
```json
|
||||
{
|
||||
"roleId": "uuid",
|
||||
"instantBook": false
|
||||
}
|
||||
```
|
||||
|
||||
### Pending shifts
|
||||
|
||||
`GET /staff/shifts/pending`
|
||||
|
||||
- use `POST /staff/shifts/:shiftId/accept` to accept
|
||||
- use `POST /staff/shifts/:shiftId/decline` to decline
|
||||
|
||||
### Assigned shifts
|
||||
|
||||
`GET /staff/shifts/assigned`
|
||||
|
||||
Each item now includes:
|
||||
|
||||
- `clientName`
|
||||
- `hourlyRate`
|
||||
- `totalRate`
|
||||
- `startTime`
|
||||
- `endTime`
|
||||
|
||||
### Shift detail
|
||||
|
||||
`GET /staff/shifts/:shiftId`
|
||||
|
||||
Each detail response now includes:
|
||||
|
||||
- `clientName`
|
||||
- `latitude`
|
||||
- `longitude`
|
||||
- `hourlyRate`
|
||||
- `totalRate`
|
||||
|
||||
Use this as the source of truth for the shift detail screen.
|
||||
|
||||
### Request swap
|
||||
|
||||
`POST /staff/shifts/:shiftId/request-swap`
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"reason": "Need coverage for a family emergency"
|
||||
}
|
||||
```
|
||||
|
||||
Current backend behavior:
|
||||
|
||||
- marks the assignment as `SWAP_REQUESTED`
|
||||
- stores the reason
|
||||
- emits `SHIFT_SWAP_REQUESTED`
|
||||
- exposes the shift in the replacement pool
|
||||
- starts the swap-expiry window used by backend auto-cancellation
|
||||
|
||||
Manager/ops review happens through:
|
||||
|
||||
- `GET /client/coverage/swap-requests`
|
||||
- `GET /client/coverage/dispatch-candidates`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
|
||||
If the swap request expires without coverage, backend auto-cancels it and alerts the manager path plus the original worker.
|
||||
|
||||
### Submit completed shift for approval
|
||||
|
||||
`POST /staff/shifts/:shiftId/submit-for-approval`
|
||||
|
||||
Use this after the worker has clocked out.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"note": "Worked full shift and all tasks were completed"
|
||||
}
|
||||
```
|
||||
|
||||
Current backend behavior:
|
||||
|
||||
- only allows shifts in `CHECKED_OUT` or `COMPLETED`
|
||||
- creates or updates the assignment timesheet
|
||||
- sets the timesheet to `SUBMITTED` unless it is already `APPROVED` or `PAID`
|
||||
- emits `TIMESHEET_SUBMITTED_FOR_APPROVAL`
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"assignmentId": "uuid",
|
||||
"shiftId": "uuid",
|
||||
"timesheetId": "uuid",
|
||||
"status": "SUBMITTED",
|
||||
"submitted": true
|
||||
}
|
||||
```
|
||||
|
||||
## Completed shifts
|
||||
|
||||
`GET /staff/shifts/completed`
|
||||
|
||||
Each item now includes:
|
||||
|
||||
- `date`
|
||||
- `clientName`
|
||||
- `startTime`
|
||||
- `endTime`
|
||||
- `hourlyRate`
|
||||
- `totalRate`
|
||||
- `timesheetStatus`
|
||||
- `paymentStatus`
|
||||
|
||||
## Clock-in support fields
|
||||
|
||||
`GET /staff/clock-in/shifts/today`
|
||||
|
||||
Each item now includes:
|
||||
|
||||
- `clientName`
|
||||
- `hourlyRate`
|
||||
- `totalRate`
|
||||
- `latitude`
|
||||
- `longitude`
|
||||
- `clockInMode`
|
||||
- `allowClockInOverride`
|
||||
|
||||
## Frontend rule
|
||||
|
||||
Use the unified routes only.
|
||||
|
||||
Do not build new mobile work on:
|
||||
|
||||
- `/query/*`
|
||||
- `/commands/*`
|
||||
- `/core/*`
|
||||
@@ -44,6 +44,10 @@ Full auth behavior, including staff phone flow and refresh rules, is documented
|
||||
- `GET /client/coverage/stats`
|
||||
- `GET /client/coverage/core-team`
|
||||
- `GET /client/coverage/incidents`
|
||||
- `GET /client/coverage/blocked-staff`
|
||||
- `GET /client/coverage/swap-requests`
|
||||
- `GET /client/coverage/dispatch-teams`
|
||||
- `GET /client/coverage/dispatch-candidates`
|
||||
- `GET /client/hubs`
|
||||
- `GET /client/cost-centers`
|
||||
- `GET /client/vendors`
|
||||
@@ -69,6 +73,7 @@ Full auth behavior, including staff phone flow and refresh rules, is documented
|
||||
- `POST /client/orders/permanent`
|
||||
- `POST /client/orders/:orderId/edit`
|
||||
- `POST /client/orders/:orderId/cancel`
|
||||
- `POST /client/shift-managers`
|
||||
- `POST /client/hubs`
|
||||
- `PUT /client/hubs/:hubId`
|
||||
- `DELETE /client/hubs/:hubId`
|
||||
@@ -78,6 +83,79 @@ Full auth behavior, including staff phone flow and refresh rules, is documented
|
||||
- `POST /client/billing/invoices/:invoiceId/dispute`
|
||||
- `POST /client/coverage/reviews`
|
||||
- `POST /client/coverage/late-workers/:assignmentId/cancel`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
- `POST /client/coverage/dispatch-teams/memberships`
|
||||
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
|
||||
|
||||
Coverage-review request payload may also send:
|
||||
|
||||
```json
|
||||
{
|
||||
"staffId": "uuid",
|
||||
"assignmentId": "uuid",
|
||||
"rating": 2,
|
||||
"feedback": "Worker left the shift early without approval",
|
||||
"markAsFavorite": false,
|
||||
"issueFlags": ["LEFT_EARLY"],
|
||||
"markAsBlocked": true
|
||||
}
|
||||
```
|
||||
|
||||
If `markAsFavorite` is `true`, backend adds that worker to the business favorites list. If `markAsFavorite` is `false`, backend removes them from that list. If `markAsBlocked` is `true`, backend adds that staff member to the business-level blocked list and future apply or assign attempts are rejected until a later review sends `markAsBlocked: false`.
|
||||
|
||||
Swap-review routes:
|
||||
|
||||
- `GET /client/coverage/swap-requests?status=OPEN`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/resolve`
|
||||
- `POST /client/coverage/swap-requests/:swapRequestId/cancel`
|
||||
|
||||
Resolve example:
|
||||
|
||||
```json
|
||||
{
|
||||
"applicationId": "uuid",
|
||||
"note": "Dispatch selected the strongest replacement candidate"
|
||||
}
|
||||
```
|
||||
|
||||
Dispatch-team routes:
|
||||
|
||||
- `GET /client/coverage/dispatch-teams`
|
||||
- `GET /client/coverage/dispatch-candidates?shiftId=uuid&roleId=uuid`
|
||||
- `POST /client/coverage/dispatch-teams/memberships`
|
||||
- `DELETE /client/coverage/dispatch-teams/memberships/:membershipId`
|
||||
|
||||
Dispatch-team membership example:
|
||||
|
||||
```json
|
||||
{
|
||||
"staffId": "uuid",
|
||||
"hubId": "uuid",
|
||||
"teamType": "CORE",
|
||||
"notes": "Preferred lead barista for this location"
|
||||
}
|
||||
```
|
||||
|
||||
Dispatch priority order is:
|
||||
|
||||
1. `CORE`
|
||||
2. `CERTIFIED_LOCATION`
|
||||
3. `MARKETPLACE`
|
||||
|
||||
Shift-manager creation example:
|
||||
|
||||
```json
|
||||
{
|
||||
"firstName": "Nora",
|
||||
"lastName": "Lead",
|
||||
"email": "nora.lead@example.com",
|
||||
"phone": "+15550001234",
|
||||
"hubId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
The manager is created as an invited business membership. If `hubId` is present, backend also links the manager to that hub.
|
||||
|
||||
## 3) Staff routes
|
||||
|
||||
@@ -109,6 +187,7 @@ Full auth behavior, including staff phone flow and refresh rules, is documented
|
||||
- `GET /staff/profile/certificates`
|
||||
- `GET /staff/profile/bank-accounts`
|
||||
- `GET /staff/profile/benefits`
|
||||
- `GET /staff/profile/benefits/history`
|
||||
- `GET /staff/profile/time-card`
|
||||
- `GET /staff/profile/privacy`
|
||||
- `GET /staff/faqs`
|
||||
@@ -153,6 +232,7 @@ Example `GET /staff/clock-in/shifts/today` item:
|
||||
- `POST /staff/shifts/:shiftId/accept`
|
||||
- `POST /staff/shifts/:shiftId/decline`
|
||||
- `POST /staff/shifts/:shiftId/request-swap`
|
||||
- `POST /staff/shifts/:shiftId/submit-for-approval`
|
||||
- `PUT /staff/profile/personal-info`
|
||||
- `PUT /staff/profile/experience`
|
||||
- `PUT /staff/profile/locations`
|
||||
@@ -174,6 +254,7 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
- `POST /invoke-llm`
|
||||
- `POST /rapid-orders/transcribe`
|
||||
- `POST /rapid-orders/parse`
|
||||
- `POST /rapid-orders/process`
|
||||
- `POST /verifications`
|
||||
- `GET /verifications/:verificationId`
|
||||
- `POST /verifications/:verificationId/review`
|
||||
@@ -183,7 +264,9 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
|
||||
- `POST /staff/profile/photo`
|
||||
- `POST /staff/profile/documents/:documentId/upload`
|
||||
- `PUT /staff/profile/documents/:documentId/upload`
|
||||
- `POST /staff/profile/attire/:documentId/upload`
|
||||
- `PUT /staff/profile/attire/:documentId/upload`
|
||||
- `POST /staff/profile/certificates`
|
||||
- `DELETE /staff/profile/certificates/:certificateId`
|
||||
|
||||
@@ -191,7 +274,22 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
|
||||
- `roleId` on `POST /staff/shifts/:shiftId/apply` is the concrete `shift_roles.id` for that shift, not the catalog role definition id.
|
||||
- `accountType` on `POST /staff/profile/bank-accounts` accepts either lowercase or uppercase and is normalized by the backend.
|
||||
- Document routes now return only document rows. They do not mix in attire items anymore.
|
||||
- Tax-form data should come from `GET /staff/profile/tax-forms`, not `GET /staff/profile/documents`.
|
||||
- Staff benefit activity should come from `GET /staff/profile/benefits/history`; the summary card should keep using `GET /staff/profile/benefits`.
|
||||
- File upload routes return a storage path plus a signed URL. Frontend uploads the file directly to storage using that URL.
|
||||
- The frontend upload contract for documents, attire, and certificates is:
|
||||
1. `POST /upload-file`
|
||||
2. `POST /create-signed-url`
|
||||
3. `POST /verifications`
|
||||
4. finalize with:
|
||||
- `PUT /staff/profile/documents/:documentId/upload`
|
||||
- `PUT /staff/profile/attire/:documentId/upload`
|
||||
- `POST /staff/profile/certificates`
|
||||
- Finalization requires `verificationId`. Frontend may still send `fileUri` or `photoUrl`, but the backend treats the verification-linked file as the source of truth.
|
||||
- `POST /rapid-orders/process` is the single-call route for "transcribe + parse".
|
||||
- `POST /client/orders/:orderId/edit` builds a replacement order from future shifts only.
|
||||
- `POST /client/orders/:orderId/cancel` cancels future shifts only on the mobile surface and leaves historical shifts intact.
|
||||
- Verification upload and review routes are live and were validated through document, attire, and certificate flows. Do not rely on long-lived verification history durability until the dedicated persistence slice is landed in `core-api-v2`.
|
||||
- Attendance policy is explicit. Reads now expose `clockInMode` and `allowClockInOverride`.
|
||||
- `clockInMode` values are:
|
||||
@@ -206,7 +304,11 @@ These are exposed as direct unified aliases even though they are backed by `core
|
||||
- send `overrideReason` only when the worker is bypassing a geofence failure and the shift/hub allows overrides
|
||||
- `POST /staff/location-streams` is for the background tracking loop after a worker is already clocked in.
|
||||
- `GET /client/coverage/incidents` is the review feed for geofence breaches, missing-location batches, and clock-in overrides.
|
||||
- `GET /client/coverage/blocked-staff` is the review feed for workers currently blocked by that business.
|
||||
- `POST /client/coverage/late-workers/:assignmentId/cancel` is the client-side recovery action when lateness is confirmed by incident evidence or elapsed grace time.
|
||||
- `GET /client/coverage/swap-requests` is the manager/ops review feed for swap requests, candidate applications, and status.
|
||||
- `GET /client/coverage/dispatch-candidates` returns ranked candidates with the dispatch-team priority already applied.
|
||||
- swap auto-cancellation is backend-driven. If a swap request expires without a replacement, backend cancels the original assignment, marks the swap request `AUTO_CANCELLED`, and alerts both the manager path and the original worker.
|
||||
- Raw location stream payloads are stored in the private v2 bucket; SQL only stores the summary and incident index.
|
||||
- Push delivery is backed by:
|
||||
- SQL token registry in `device_push_tokens`
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Data Connect Connectors Pattern
|
||||
|
||||
> [!WARNING]
|
||||
> This document describes the legacy V1 Data Connect connector pattern.
|
||||
> For current backend work, use the V2 unified API docs under `docs/BACKEND/API_GUIDES/V2/`.
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the **Data Connect Connectors** pattern implemented in the KROW mobile app. This pattern centralizes all backend query logic by mirroring backend connector structure in the mobile data layer.
|
||||
@@ -45,9 +49,9 @@ apps/mobile/packages/data_connect/lib/src/connectors/
|
||||
└── ...
|
||||
```
|
||||
|
||||
**Maps to backend structure:**
|
||||
**Maps to legacy backend structure:**
|
||||
```
|
||||
backend/dataconnect/connector/
|
||||
legacy/dataconnect-v1/connector/
|
||||
├── staff/
|
||||
├── order/
|
||||
├── user/
|
||||
@@ -260,7 +264,7 @@ When backend adds new connector (e.g., `order`):
|
||||
- `staff_main` - Guards bottom nav items requiring profile completion
|
||||
|
||||
**Backend Queries Used**:
|
||||
- `backend/dataconnect/connector/staff/queries/profile_completion.gql`
|
||||
- `legacy/dataconnect-v1/connector/staff/queries/profile_completion.gql`
|
||||
|
||||
### Shifts Connector
|
||||
|
||||
@@ -271,15 +275,15 @@ When backend adds new connector (e.g., `order`):
|
||||
- `applyForShifts()` - Handles shift application with error tracking
|
||||
|
||||
**Backend Queries Used**:
|
||||
- `backend/dataconnect/connector/shifts/queries/list_shift_roles_by_vendor.gql`
|
||||
- `backend/dataconnect/connector/shifts/mutations/apply_for_shifts.gql`
|
||||
- `legacy/dataconnect-v1/connector/shifts/queries/list_shift_roles_by_vendor.gql`
|
||||
- `legacy/dataconnect-v1/connector/shifts/mutations/apply_for_shifts.gql`
|
||||
|
||||
## Future Expansion
|
||||
|
||||
As the app grows, additional connectors will be added:
|
||||
- `order_connector_repository` (queries from `backend/dataconnect/connector/order/`)
|
||||
- `user_connector_repository` (queries from `backend/dataconnect/connector/user/`)
|
||||
- `emergency_contact_connector_repository` (queries from `backend/dataconnect/connector/emergencyContact/`)
|
||||
- `order_connector_repository` (queries from `legacy/dataconnect-v1/connector/order/`)
|
||||
- `user_connector_repository` (queries from `legacy/dataconnect-v1/connector/user/`)
|
||||
- `emergency_contact_connector_repository` (queries from `legacy/dataconnect-v1/connector/emergencyContact/`)
|
||||
- etc.
|
||||
|
||||
Each following the same Clean Architecture pattern implemented for Staff Connector.
|
||||
|
||||
Reference in New Issue
Block a user