This is a standalone build scope for the Baskit picker app, compiled from the wider Baskit scope so the picker app can be built on its own while staying compatible with the shared backend. It gathers everything picker-facing in one place: the screens and flows, what the app must do, the APIs it uses, the changes the backend needs, and the database to stand up. Where it references sections, those point to the Baskit Phase 1 Build Scope.
The picker app is used by the person who physically collects an order in-store. Baskit routes each order’s per-store leg to a picker, who claims it, picks it against a deadline and a prepaid-card spend target, resolves anything out of stock, bags it, and hands it to the driver.
The picker app runs on six screens. The five core screens are shown below in flow order — earnings is a tab reached from the feed. Each designed screen is annotated with what it must do; the states are summarized in the table beneath.
| Screen | Purpose | Primary actions |
|---|---|---|
| Job feed | See available, active, and today’s jobs, including same-store batches with any bonus. | Go on duty · open a job · refresh |
| Job detail | Review the store, items, pack-by deadline, and payout before committing. | Accept · decline |
| Active pick | Work items grouped by aisle against the deadline and the prepaid-card spend target. | Mark picked · can’t find · next aisle |
| Substitute | Resolve an out-of-stock item, honouring the customer’s preference. | Choose substitute · ask customer · refund-skip |
| Ready for handoff | Group items into bags (cold, fresh, bakery) and release the order. | Show handoff code · mark handed off |
| Earnings | Track today and the week, with a history of jobs and payouts. | View breakdown · history |
| ID | Requirement | Priority |
|---|---|---|
| PK-01 | Sign in as a picker and go on or off duty; only approved pickers see jobs. | Must |
| PK-02 | See a job feed of available, active, and today’s jobs with store, distance, item count, pack-by time, and payout. | Must |
| PK-03 | See same-store jobs grouped as a batch with any batch bonus. | Should |
| PK-04 | Accept or decline a job; on accept it moves to the active pick and leaves other pickers’ feeds. | Must |
| PK-05 | Work an active pick with items grouped by aisle, showing progress and the pack-by countdown. | Must |
| PK-06 | See the prepaid-card spend target for the store and record the actual amount spent, with a receipt. | Must |
| PK-07 | Mark each item picked, or flag ‘can’t find’ to substitute or refund. | Must |
| PK-08 | Substitute from suggested alternatives honouring the customer preference, ask the customer, or refund-skip. | Must |
| PK-09 | Complete the pick, group items into bags (cold, fresh, bakery), and reach the handoff screen. | Must |
| PK-10 | Release the order to the driver against the handoff code. | Must |
| PK-11 | See earnings for today and the week, with a history of jobs and payouts. | Should |
| PK-12 | Receive push notifications for new nearby jobs and approaching pack-by deadlines. | Should |
| PK-13 | Keep an active pick usable through brief offline periods and sync on reconnect. | Should |
The picker app authenticates as a picker and calls the picker endpoints under /api/v1/picker, plus shared auth and device registration. Two of these go beyond the picker set in the main scope and are new backend work: setting on-duty status with location, and recording actual card spend with a receipt (both marked in the next section).
| Method | Endpoint | What the client uses it for |
|---|---|---|
| POST | /api/v1/auth/login | Sign in as a picker; receive a JWT with the picker role |
| PATCH | /api/v1/picker/status | Go on or off duty and push current location |
| GET | /api/v1/picker/jobs | Job feed: available, active, today |
| POST | /api/v1/picker/jobs/{id}:accept | Claim a job |
| POST | /api/v1/picker/jobs/{id}:decline | Pass a job |
| GET | /api/v1/picker/jobs/{id} | Job detail: items by aisle, spend target, deadline |
| POST | /api/v1/picker/jobs/{id}/items/{itemId}:pick | Mark an item picked |
| POST | /api/v1/picker/jobs/{id}/items/{itemId}:substitute | Record a substitution |
| POST | /api/v1/picker/jobs/{id}/items/{itemId}:refund | Refund and skip an item |
| POST | /api/v1/picker/jobs/{id}:spend | Record actual card spend and upload the receipt |
| POST | /api/v1/picker/jobs/{id}:handoff | Release the order against the handoff code |
| GET | /api/v1/picker/earnings | Earnings summary and history |
| POST | /api/v1/devices | Register the push token |
The picker app needs the backend to treat each store leg of an order as a dispatchable job and to carry the picking lifecycle, the prepaid-card spend, the handoff, and earnings. The table lists each change and whether it is new work or an adjustment to something already scoped.
| Area | What changes | Type |
|---|---|---|
| Roles & auth | Add the picker role and an approval plus on-duty state; issue picker-scoped JWTs so only approved, on-duty pickers receive jobs. | Adjust |
| Job dispatch | Turn each order’s per-store leg into a claimable job with status, pack-by, payout, and optional same-store batching; claim-lock so two pickers cannot take the same job. | New |
| On-duty & location | Endpoint to set on or off duty and push location, used to rank nearby jobs in the feed. | New |
| Prepaid card & spend | Assign a prepaid card to a job with a spend target, and capture the actual spend and receipt at the till. | New |
| Picking state | Per-item state machine (pending to picked, substituted, or refunded) driven by events from the app. | New |
| Substitutions | Store proposed substitutes, the customer-preference flag, and the decision (auto or customer). | New |
| Handoff | Generate and verify handoff codes and record bag grouping and the driver. | New |
| Earnings & payout | Record base, tip, and batch bonus per job and expose earnings summaries. | New |
| Reconciliation tie-in | Feed the captured spend and receipt into the existing reconciliation against the customer charge. | Adjust |
| Notifications | Push new-job and pack-by deadline alerts to picker devices. | New |
The picker slice centres on order_stores — one row per store leg, which is the job. Around it sit the picker, the items and their substitutions, the prepaid card and captured spend, the handoff, and earnings. This is a focused view of the full model in the scope.
The accompanying file baskit_picker_schema.sql stands the picker database up. It creates 7 enums and 15 tables: the picker-specific tables (pickers, picker_shifts, picker_devices, prepaid_cards, job_batches, order_stores, job_cards, order_items, substitutions, handoffs, picker_earnings) plus a minimal form of the shared tables they depend on (accounts, retailers_stores, products, orders) so it runs on its own.
Create a fresh database and apply the schema:
createdb baskit_picker psql baskit_picker -f baskit_picker_schema.sql