chore: perauset customer project
This commit is contained in:
260
PLATFORM-REVIEW.md
Normal file
260
PLATFORM-REVIEW.md
Normal file
@@ -0,0 +1,260 @@
|
||||
# PerAuset Platform Review -- Daily Operations Gaps
|
||||
|
||||
**Reviewer**: Alex (Product Manager)
|
||||
**Date**: 2026-03-19
|
||||
**Scope**: Full platform review from the perspective of a daily coordinator, kitchen lead, boat coordinator, and facilitator
|
||||
**Method**: Reviewed all 66 RPC functions, 15+ frontend pages, 13 database migrations, and the role/permission system
|
||||
|
||||
---
|
||||
|
||||
## Critical (Blocks Daily Operations)
|
||||
|
||||
### 1. [Dashboard] All stats are hardcoded "--" except notifications
|
||||
The dashboard shows "Active Stays: --", "Upcoming Boats: --", "Open Tasks: --". There is no backend function to fetch dashboard summary stats. A coordinator opening the app every morning gets zero situational awareness.
|
||||
|
||||
**What to build**: A `getDashboardStats` RPC that queries active stays count, upcoming boat trips count, and open task count. Update the dashboard page to call it.
|
||||
|
||||
### 2. [Kitchen] Cannot create a meal service from the UI
|
||||
The "Create Meal" button on the kitchen page is explicitly `disabled`. The backend `createMealService` RPC exists, but the frontend form to call it is missing. A kitchen lead cannot plan any meals.
|
||||
|
||||
**What to build**: A meal creation drawer/page that calls `createMealService` with service_type, service_date, planned_headcount, and menu_notes.
|
||||
|
||||
### 3. [Kitchen] No way to see who is eating (meal headcount from stays/retreats)
|
||||
The `meal_attendance` table exists and links to stays and retreats, but there is no RPC to list meal attendance, no RPC to auto-populate attendance from active stays, and the frontend shows zero attendance data. A kitchen lead cannot know how many mouths to feed or what dietary needs exist for a given meal.
|
||||
|
||||
**What to build**: (a) `listMealAttendance` RPC filtered by meal_service_id. (b) `generateMealAttendance` RPC that auto-creates attendance records from active stays and retreat participants for a date range. (c) Frontend attendance list on each meal card showing headcount and dietary summary.
|
||||
|
||||
### 4. [Kitchen] No dietary summary per meal
|
||||
Dietary profiles exist per user, but there is no function that aggregates dietary requirements for a specific meal (e.g., "3 vegan, 2 gluten-free, 1 nut allergy"). Without this, the kitchen lead has to manually cross-reference every guest's profile.
|
||||
|
||||
**What to build**: `getMealDietarySummary` RPC that joins meal_attendance with dietary_profile and returns counts. Show this on each meal card.
|
||||
|
||||
### 5. [Retreats] People tab is always empty -- not wired to backend
|
||||
The retreat detail page hardcodes `const people: any[] = []` and `const schedule: any[] = []`. Despite `addRetreatPerson` and `addRetreatScheduleItem` RPCs existing, there is no `listRetreatPersons` or `listRetreatScheduleItems` RPC, and the "Add Person" button is `disabled`. A facilitator cannot manage retreat participants or view the schedule.
|
||||
|
||||
**What to build**: (a) `listRetreatPersons` and `listRetreatScheduleItems` RPCs. (b) Wire the retreat detail page to call them. (c) Enable the "Add Person" and "Add Schedule Item" forms calling the existing RPCs.
|
||||
|
||||
### 6. [Retreats] No `getRetreat` RPC -- detail page re-fetches all retreats
|
||||
The retreat detail page calls `listRetreats` and filters client-side by ID. This means no additional detail (persons, schedule) is loaded. There is no single-retreat fetch endpoint.
|
||||
|
||||
**What to build**: `getRetreat` RPC that returns the retreat with its persons and schedule items in one call.
|
||||
|
||||
### 7. [Stays] No "who is here right now" view
|
||||
There is no way to see currently checked-in guests. The stays list shows all stays but does not filter by "checked_in" status or date overlap with today. A coordinator doing a morning roll call has no tool for this.
|
||||
|
||||
**What to build**: Add a "Currently Checked In" filter/tab to the stays page that queries stays with status='checked_in' or where today falls within start_at/end_at. Ideally also surface this count on the dashboard.
|
||||
|
||||
### 8. [Rooms] No room availability / availability calendar
|
||||
You can see rooms and their allocations, but there is no way to check "which rooms are available from date X to date Y?" before making an allocation. This means room assignment is guesswork.
|
||||
|
||||
**What to build**: `checkRoomAvailability` RPC that accepts a date range and returns rooms with their open capacity. Frontend calendar or date-picker view on the rooms page.
|
||||
|
||||
---
|
||||
|
||||
## Important (Significantly Impacts Efficiency)
|
||||
|
||||
### 9. [Kitchen] No weekly menu planning
|
||||
Meals are individual records with no concept of a menu or weekly plan. A kitchen lead has to create each meal one at a time with no template or copy-week functionality.
|
||||
|
||||
**What to build**: `generateWeeklyMeals` RPC that bulk-creates meal_service records for breakfast/lunch/dinner across a date range. Frontend weekly calendar view for kitchen.
|
||||
|
||||
### 10. [Kitchen] No shopping list generation from menu
|
||||
There is no `meal_ingredient` or `recipe` table. The menu_notes field is free text. There is no connection between meals and inventory items. A kitchen lead cannot generate a shopping list from the planned menu.
|
||||
|
||||
**What to build**: New `meal_ingredient` table linking meal_service to inventory_item with quantity. `generateShoppingList` RPC that diffs meal ingredients against inventory.
|
||||
|
||||
### 11. [Boats] No passenger manifest view
|
||||
The trip detail page shows seat requests, but there is no consolidated manifest showing confirmed passengers with their names, cargo notes, and special requirements. The boat coordinator needs a printable list.
|
||||
|
||||
**What to build**: `getBoatManifest` RPC that returns confirmed seat requests joined with user profiles. Frontend manifest card on the trip detail page.
|
||||
|
||||
### 12. [Boats] No weather cancellation / rebooking workflow
|
||||
Cancelling a trip (`cancelBoatTrip`) does not notify affected passengers or offer rebooking. Seat requests just sit in their current state.
|
||||
|
||||
**What to build**: When a trip is cancelled, auto-create notifications for all confirmed seat request holders. Add a `rebookSeatRequest` RPC that moves a request to another trip.
|
||||
|
||||
### 13. [Tasks] No recurring task generation from templates
|
||||
Task templates have a `recurrence_cron` field, but there is no scheduler or function that creates task instances from templates based on the cron expression. Recurring tasks (daily cleaning, weekly maintenance) must be created manually every time.
|
||||
|
||||
**What to build**: A scheduled function (cron job) `generateRecurringTasks` that reads active templates with recurrence_cron and creates task instances for upcoming periods.
|
||||
|
||||
### 14. [Tasks] No task history / completion stats
|
||||
There is no way to see completed tasks over time, completion rates, or who completed the most tasks. No analytics view exists.
|
||||
|
||||
**What to build**: `getTaskStats` RPC returning completion counts by category, by user, and by time period. Frontend stats view on the tasks page.
|
||||
|
||||
### 15. [Inventory] No stocktake functionality
|
||||
You can edit item quantities one at a time, but there is no bulk stocktake flow where someone walks through the storage room updating all quantities at once.
|
||||
|
||||
**What to build**: `submitStocktake` RPC that accepts an array of {itemId, actualQuantity} and updates all in one transaction with audit trail. Frontend stocktake page with a checklist.
|
||||
|
||||
### 16. [Inventory] No consumption history
|
||||
When quantities are manually edited, the old value is lost (only the audit log captures it). There is no `inventory_transaction` table tracking additions/removals with reasons.
|
||||
|
||||
**What to build**: New `inventory_transaction` table (item_id, quantity_change, reason, user_id, created_at). `adjustInventory` RPC that creates a transaction record. Frontend history tab per item.
|
||||
|
||||
### 17. [Inventory] No automatic reorder alerts
|
||||
Items have `minimum_quantity`, and the UI shows a yellow warning icon, but there is no notification sent when stock drops below minimum. The kitchen lead has to manually check the inventory page.
|
||||
|
||||
**What to build**: Trigger (database or application-level) that creates a notification when `current_quantity` drops below `minimum_quantity`.
|
||||
|
||||
### 18. [Finance] No totals, summaries, or reports
|
||||
The finance page lists individual records but shows no totals by category, no monthly summaries, no income-vs-expense breakdown. You cannot generate a monthly report.
|
||||
|
||||
**What to build**: `getFinanceSummary` RPC returning totals by category, by record_type, and by month. Frontend summary cards at the top of the finance page.
|
||||
|
||||
### 19. [Finance] No link to retreat or project for cost tracking
|
||||
The `finance_link` table exists and the `linkFinanceRecord` RPC exists, but the frontend has no UI to link a finance record to a retreat, boat trip, stay, or inventory request. You cannot track per-retreat costs.
|
||||
|
||||
**What to build**: Add a "Link to Entity" button on finance records that opens a selector for retreat/trip/stay/item. Show linked entity badges on the finance table.
|
||||
|
||||
### 20. [Finance] No approval workflow
|
||||
`finance_record` has no `approved_by` or `approval_status` field. Anyone with `finance.manage` permission (which is missing from the roles entirely -- only admin has it via wildcard) can create records. There is no review step.
|
||||
|
||||
**What to build**: Add `approval_status` and `approved_by_user_id` to `finance_record`. Add `finance.manage` and `finance.view` permissions to relevant roles. Add approval workflow RPCs.
|
||||
|
||||
### 21. [Notifications] No way to send bulk or event-triggered notifications
|
||||
The `notification` table is write-only from the application side. There is no `createNotification` or `sendBulkNotification` RPC. Notifications are only created as side effects (if even implemented). A coordinator cannot send a message like "boat departing in 2 hours" to all passengers.
|
||||
|
||||
**What to build**: `createNotification` RPC (admin/coordinator only) that creates notifications for one or more users. `sendBulkNotification` for a group (retreat participants, today's boat passengers, all active stays).
|
||||
|
||||
### 22. [Users] No way to invite new users
|
||||
The users page shows existing users and lets admins edit roles, but there is no invite flow. New users can only join by signing in through auth.js. There is no way to pre-register someone with a role.
|
||||
|
||||
**What to build**: `inviteUser` RPC that creates a user record with email and role in 'invited' status. Send an email (or at minimum create the record so they can sign in).
|
||||
|
||||
---
|
||||
|
||||
## Nice to Have (Would Improve the Experience)
|
||||
|
||||
### 23. [Dashboard] No today's arrivals/departures widget
|
||||
The dashboard does not show who is arriving or departing today, which is critical for room turnover planning.
|
||||
|
||||
### 24. [Dashboard] No upcoming tasks widget
|
||||
The dashboard does not show the user's assigned or claimable tasks for today.
|
||||
|
||||
### 25. [Stays] No direct link from stay to room allocation
|
||||
A stay exists independently of room allocation. To see which room a guest is in, you have to go to room allocations and search by stay ID. No inline room info on the stays page.
|
||||
|
||||
### 26. [Rooms] No cleaning/turnover tracking
|
||||
There is no concept of room status (clean, dirty, in-progress) or housekeeping tasks auto-generated on checkout.
|
||||
|
||||
### 27. [Boats] Route names not human-readable
|
||||
Boat trips display "Route abc123..." (UUID truncation). Routes need a human-readable name (e.g., "Aswan to Village"). No `listBoatRoutes` function exists for the frontend.
|
||||
|
||||
### 28. [Boats] Boat names not shown
|
||||
Similar to routes -- boats are shown as UUIDs. No `listBoats` function for the frontend. Should show boat name/capacity.
|
||||
|
||||
### 29. [Retreats] No retreat-specific meal planning
|
||||
Meals can be linked to a retreat via `retreat_id` on `meal_service`, but there is no UI to plan meals for a specific retreat or view retreat meals in the retreat detail page.
|
||||
|
||||
### 30. [Retreats] No notifications to retreat participants
|
||||
Publishing a retreat does not notify registered participants. There is no mechanism to send updates to a retreat group.
|
||||
|
||||
### 31. [Tasks] Cannot assign tasks to specific roles (only users)
|
||||
`task_assignment` links to a specific user. There is no way to say "this task is for any kitchen_lead" -- you must know the person.
|
||||
|
||||
### 32. [Profile] No user preferences beyond dietary
|
||||
No notification preferences, no timezone setting, no language preference. The dietary profile is the only user preference.
|
||||
|
||||
### 33. [Kitchen] No meal feedback mechanism
|
||||
There is no way for guests to rate or comment on meals.
|
||||
|
||||
### 34. [Stays] No stay extension or modification workflow
|
||||
Once a stay is created, there is no way to extend dates or modify the stay type without cancelling and recreating.
|
||||
|
||||
### 35. [Audit Log] No filtering
|
||||
The audit log shows all entries with no ability to filter by table, user, action, or date range.
|
||||
|
||||
---
|
||||
|
||||
## Data Model Issues
|
||||
|
||||
### finance_record
|
||||
- Missing `approved_by_user_id` and `approval_status` fields
|
||||
- No `finance.manage` or `finance.view` permissions in the roles system (only admin via wildcard can access)
|
||||
|
||||
### inventory_item
|
||||
- No transaction/history table to track quantity changes over time
|
||||
- No `last_restocked_at` or `supplier` field
|
||||
|
||||
### meal_service
|
||||
- No `meal_ingredient` table linking meals to inventory items with quantities
|
||||
- `menu_notes` is free text with no structured recipe/ingredient support
|
||||
|
||||
### task_template
|
||||
- `recurrence_cron` exists but nothing reads it -- no scheduler generates instances
|
||||
|
||||
### room
|
||||
- No `cleaning_status` or `last_cleaned_at` field
|
||||
- No `floor` or `building` field for larger villages
|
||||
|
||||
### stay
|
||||
- No `room_preference` field (only `rooms.request_preference` permission exists but no schema support)
|
||||
|
||||
### boat_trip
|
||||
- No `weather_status` or `cancellation_reason` field
|
||||
- No `max_passengers` or `max_cargo_weight` field on the trip (only on boat, which is a UUID reference)
|
||||
|
||||
### notification
|
||||
- No `channel` field (in-app vs email vs SMS)
|
||||
- No `scheduled_at` field for future notifications
|
||||
|
||||
### retreat
|
||||
- No `budget` or `pricing` fields
|
||||
- No `retreat_tag` or `category` for filtering retreat types
|
||||
|
||||
### user
|
||||
- No `invited_by_user_id` or `invited_at` for tracking invitations
|
||||
- No `last_active_at` for activity monitoring
|
||||
- No `preferences` JSONB field for user settings
|
||||
|
||||
---
|
||||
|
||||
## Specific Recommendations (Priority Order)
|
||||
|
||||
### Tier 1 -- Do This Week (unblocks daily operations)
|
||||
|
||||
1. **Wire the dashboard stats**: Create `getDashboardStats` function, update dashboard page. Half-day effort.
|
||||
|
||||
2. **Enable meal creation**: Remove `disabled` from the Create Meal button, add a creation form calling `createMealService`. Half-day effort.
|
||||
|
||||
3. **Wire retreat people and schedule**: Add `listRetreatPersons` and `listRetreatScheduleItems` RPCs. Wire the retreat detail page to call them. Enable the Add Person and Add Schedule Item buttons. 1-day effort.
|
||||
|
||||
4. **Add "Currently Checked In" view**: Add a filtered tab to stays page. 2-hour effort.
|
||||
|
||||
### Tier 2 -- Do This Sprint (high-impact workflows)
|
||||
|
||||
5. **Meal attendance auto-generation**: Build the function that creates attendance records from active stays/retreats for a date. Show headcount and dietary summary per meal. 2-day effort.
|
||||
|
||||
6. **Boat manifest view**: Add a confirmed-passenger manifest to trip detail. 1-day effort.
|
||||
|
||||
7. **Room availability check**: Build the availability query and date-range picker. 1-day effort.
|
||||
|
||||
8. **Finance summary/totals**: Add summary cards to the finance page. 1-day effort.
|
||||
|
||||
9. **Recurring task generation**: Implement the cron-based task generator from templates. 1-day effort.
|
||||
|
||||
### Tier 3 -- Do Next Sprint (important but not blocking)
|
||||
|
||||
10. **Inventory transaction history and stocktake**. 2-day effort.
|
||||
11. **Low-stock notifications**. Half-day effort.
|
||||
12. **Bulk notification sending**. 1-day effort.
|
||||
13. **Finance entity linking UI**. 1-day effort.
|
||||
14. **Shopping list from menu** (requires meal_ingredient table). 3-day effort.
|
||||
15. **User invitation flow**. 1-day effort.
|
||||
16. **Boat route/boat name display** (add list functions + display). Half-day effort.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The platform has a solid data model and a comprehensive set of CRUD operations. The core tables, enum types, and permission system are well-designed. However, the gap between "data exists" and "a human can use this daily" is significant in several areas:
|
||||
|
||||
- **Kitchen module** is essentially non-functional from the UI (cannot create meals, no attendance, no dietary aggregation)
|
||||
- **Retreat detail page** is a shell (people and schedule are hardcoded empty arrays)
|
||||
- **Dashboard** provides no operational value (all stats are "--")
|
||||
- **Cross-entity workflows** are missing (menu to shopping list, stay to meal attendance, cancellation to rebooking, checkout to room cleaning)
|
||||
- **Finance** has no summaries, no approval flow, and no entity linking UI
|
||||
|
||||
The backend functions are about 70% complete. The frontend is about 50% complete relative to what the backend supports. The biggest wins come from wiring existing backend capabilities to the frontend (retreat persons, meal creation) and adding the handful of missing aggregation/summary functions that make the data actionable.
|
||||
Reference in New Issue
Block a user