Backend API (Convex)
Function list by table, KISS, args and results
Overview
- KISS architecture, realtime Convex.
- Each group (module) corresponds to 1 file in
packages/backend/convex/*
. - Input/output: write concisely; FE uses
api.<module>.<function>
from Convex codegen.
members.ts
- create: Create new member
- Args:
{ username, passwordHash, name, phone?, order?, active? }
- Returns:
member
- Note: check unique username.
- Args:
- updateProfile: Update name/phone
- Args:
{ id, name?, phone? }
- Returns:
member
- Args:
- changePassword: Change password
- Args:
{ id, passwordHash }
- Returns:
{ success }
- Args:
- toggleActive: Hide/show member
- Args:
{ id, active }
- Returns:
{ success }
- Args:
- listBrief: Brief list
- Args:
{ activeOnly? }
- Returns:
[{ _id, name, username, phone, active, order }]
- Args:
- getFull: Member details + relations
- Args:
{ id, recentLimit? }
- Returns:
{ member, assignedMarkets, recentSurveys }
- Args:
- markets: Assigned markets
- Args:
{ memberId, activeOnly? }
- Returns:
markets[]
(brief)
- Args:
- surveysInRange: Member's surveys by date
- Args:
{ memberId, fromDay, toDay }
- Returns:
surveys[]
- Args:
markets.ts
- create: Create market
- Args:
{ name, addressJson, order?, active? }
- Returns:
market
- Args:
- update: Update market
- Args:
{ id, name?, addressJson? }
- Returns:
market
- Args:
- toggleActive: Hide/show market
- Args:
{ id, active }
- Returns:
{ success }
- Args:
- reorder: Update order in bulk
- Args:
{ items: [{ id, order }] }
- Returns:
{ success }
- Args:
- listBrief: Brief list
- Args:
{ activeOnly? }
- Returns:
markets[]
(brief)
- Args:
- getFull: Market details + relations
- Args:
{ id, recentLimit? }
- Returns:
{ market, assignedMembers, recentSurveys }
- Args:
assignments.ts (assignments)
- assign: Assign member to market (idempotent)
- Args:
{ marketId, memberId }
- Returns:
assignment
- Args:
- unassign: Unassign
- Args:
{ marketId, memberId }
- Returns:
{ success }
- Args:
- listByMarket: Member list by market
- Args:
{ marketId }
- Returns:
members[]
- Args:
- listByMember: Market list by member
- Args:
{ memberId }
- Returns:
markets[]
- Args:
units.ts (units)
- listBrief: Unit list
- Args:
{ activeOnly? }
- Returns:
units[]
(sorted by order)
- Args:
- create: Create unit
- Args:
{ name, abbr?, order? }
- Returns:
unit
(unique name)
- Args:
- update: Edit unit
- Args:
{ id, name?, abbr? }
- Returns:
unit
- Args:
- toggleActive: Hide/show unit
- Args:
{ id, active }
- Returns:
{ success }
- Args:
- safeDelete: Safe delete (only if no products reference it)
- Args:
{ id }
- Returns:
{ success }
| Error if products still use it
products.ts (products)
- listBrief: Product list
- Args:
{ activeOnly? }
- Returns:
products[]
(by order)
- Args:
- listWithUnits: Product list with units
- Args:
{ activeOnly? }
- Returns:
[{ ...product, unit }]
- Args:
- create: Create product
- Args:
{ name, unitId, note?, order? }
- Returns:
product
(unique name)
- Args:
- update: Edit product
- Args:
{ id, name?, unitId?, note? }
- Returns:
product
- Args:
- toggleActive: Hide/show product
- Args:
{ id, active }
- Returns:
{ success }
- Args:
- safeDelete: Safe delete (if no surveyItems reference it)
- Args:
{ id }
- Returns:
{ success }
| Error if still referenced
- Args:
- reorder: Update order in bulk
- Args:
{ items: [{ id, order }] }
- Returns:
{ success }
- Args:
surveys.ts (survey sessions)
- createForMarket: Create survey for market + generate items
- Args:
{ marketId, memberId, surveyDay?, note?, copyFromPrevious? }
- Returns:
survey
- Note: generate item from active products by
order
; can copy prices from most recent survey of same market.
- Args:
- getFull: Get survey + items (expand product/unit)
- Args:
{ id }
- Returns:
{ survey, market, member, items[] }
- Args:
- listMineByRange: My survey list by date
- Args:
{ memberId, fromDay, toDay }
- Returns:
surveys[]
(newest first)
- Args:
- deleteCascade: Delete survey and all items
- Args:
{ id }
- Returns:
{ success }
- Args:
- lastInMarket: Most recent survey of market
- Args:
{ marketId }
- Returns:
survey | null
- Args:
- countFilled: Count rows with entered prices
- Args:
{ id }
- Returns:
{ filled, total }
- Args:
surveyItems.ts (survey lines)
- autosave: Save price/note per line (update lastUpdatedAt)
- Args:
{ id, price?, note? }
- Returns:
{ success }
- Args:
- listWithProductUnit: Item list + product/unit
- Args:
{ surveyId }
- Returns:
items[]
(expanded)
- Args:
- clearPrice: Clear price of one line
- Args:
{ id }
- Returns:
{ success }
- Args:
- bulkClear: Clear prices of multiple lines or all
- Args:
{ surveyId, productIds? }
- Returns:
{ success }
- Args:
reports.ts (snapshot reports)
- summaryByMarketRange: Live aggregation by date range (not saved)
- Args:
{ fromDay, toDay }
- Returns:
{ summaryRows, includedSurveyIds }
- Args:
- generateRange: Create immutable snapshot report
- Args:
{ fromDay, toDay, createdByAdminId }
- Returns:
report
- listBrief: Recent report list
- Args:
{ limit? }
- Returns:
[{ _id, fromDay, toDay, generatedAt }]
- Args:
- getFull: Report details
- Args:
{ id }
- Returns:
report
- Args:
FE Usage Suggestions
- /khaosat:
- Get assigned markets:
members.markets
-> "Create survey" button. - Create survey:
surveys.createForMarket
-> opensurveys.getFull
to display form. - Autosave:
surveyItems.autosave
(debounce ~300ms). - History:
surveys.listMineByRange
. - /admin:
- Catalog: units/products/markets CRUD + assignments.
- Aggregation:
reports.summaryByMarketRange
-> click "Export" =reports.generateRange
.