@primocaredentgroup/listini
v0.6.0
Published
Convex component for managing dental service price lists and catalogs
Readme
@primocaredentgroup/listini
Convex component for managing dental service price lists and catalogs.
Overview
This component provides a complete system for managing:
- Service categories (3-level hierarchy)
- Dental services/procedures
- Price lists
- List rows with pricing
- Bundles/packages
Installation
npm install @primocaredentgroup/listiniSetup
1. Configure your Convex app
In your convex/convex.config.ts:
import { defineApp } from "convex/server";
import listini from "@primocaredentgroup/listini/convex.config.js";
const app = defineApp();
app.use(listini);
export default app;2. Environment Variables
Create a .env.local file:
CONVEX_DEPLOYMENT=your-deployment-urlDatabase Schema
Tables
- service_category_parents - Top-level areas (e.g., "Odontoiatria")
- service_category_groups - Sub-areas (e.g., "Chirurgia Orale")
- service_categories - Actual categories (e.g., "Conservativa")
- services - Dental procedures
- lists - Price lists
- list_rows - Price entries
- bundles - Service packages
Service Applications
Services can have different application types:
tooth- Single tootharch- Full archsextant- Sextanthemiarch- Hemiarchfull_mouth- Full mouthother- Not odontogram-related
List Types
standard- Base clinic listinsurance- Insurance pricingclinical- Internal clinical listhealthcare- Public healthcare/SSNaesthetic_medicine- Aesthetic medicine
API Functions
Service Category Parents
// Queries
ctx.runQuery(components.listini.serviceCategoryParents.getAll)
ctx.runQuery(components.listini.serviceCategoryParents.getById, { id })
// Mutations
ctx.runMutation(components.listini.serviceCategoryParents.create, { name, order })
ctx.runMutation(components.listini.serviceCategoryParents.update, { id, name, order })
ctx.runMutation(components.listini.serviceCategoryParents.remove, { id })Service Category Groups
// Queries
ctx.runQuery(components.listini.serviceCategoryGroups.getAll)
ctx.runQuery(components.listini.serviceCategoryGroups.getById, { id })
// Mutations
ctx.runMutation(components.listini.serviceCategoryGroups.create, { name, order })
ctx.runMutation(components.listini.serviceCategoryGroups.update, { id, name, order })
ctx.runMutation(components.listini.serviceCategoryGroups.remove, { id })Service Categories
// Queries
ctx.runQuery(components.listini.serviceCategories.getAll)
ctx.runQuery(components.listini.serviceCategories.getById, { id })
ctx.runQuery(components.listini.serviceCategories.getByParent, { parentId })
ctx.runQuery(components.listini.serviceCategories.getByGroup, { groupId })
// Mutations
ctx.runMutation(components.listini.serviceCategories.create, {
name,
serviceCategoryParentId,
serviceCategoryGroupId,
order
})
ctx.runMutation(components.listini.serviceCategories.update, {
id,
name,
serviceCategoryParentId,
serviceCategoryGroupId,
order
})
ctx.runMutation(components.listini.serviceCategories.remove, { id })Services
// Queries
ctx.runQuery(components.listini.services.getAll)
ctx.runQuery(components.listini.services.getById, { id })
ctx.runQuery(components.listini.services.getByCategory, { categoryId })
ctx.runQuery(components.listini.services.getActive)
// Mutations
ctx.runMutation(components.listini.services.create, {
code,
name,
categoryId,
application: "tooth" | "arch" | "sextant" | "hemiarch" | "full_mouth" | "other",
defaultDuration
})
ctx.runMutation(components.listini.services.update, {
id,
code,
name,
categoryId,
application,
defaultDuration,
isActive
})
ctx.runMutation(components.listini.services.remove, { id })Lists
// Queries
ctx.runQuery(components.listini.lists.getAll)
ctx.runQuery(components.listini.lists.getById, { id })
ctx.runQuery(components.listini.lists.getByType, { type })
ctx.runQuery(components.listini.lists.getByChannel, { channel })
ctx.runQuery(components.listini.lists.getByTypeAndChannel, { type, channel })
ctx.runQuery(components.listini.lists.getEnabled)
// Mutations
ctx.runMutation(components.listini.lists.create, {
code,
name,
type,
channel,
fallbackDiscount?: number,
employeeDiscount?: number,
maxExtraDiscount?: number,
enabled?: boolean,
isCarePlanDiscountable?: boolean,
insuranceRecipe?: boolean
})
ctx.runMutation(components.listini.lists.update, { id, ...fields })
ctx.runMutation(components.listini.lists.remove, { id })Clinic availability and the default price list are host-owned concerns. Store them in the host clinic-to-list relationship, not in this component.
List Rows
// Queries
ctx.runQuery(components.listini.listRows.getAll)
ctx.runQuery(components.listini.listRows.getById, { id })
ctx.runQuery(components.listini.listRows.getByList, { listId })
ctx.runQuery(components.listini.listRows.getByBundle, { bundleId })
ctx.runQuery(components.listini.listRows.getActiveByList, { listId })
// Mutations
ctx.runMutation(components.listini.listRows.create, {
listId,
serviceIds: string[],
name?: string,
listPrice: number,
cost?: number,
maxDiscount?: number,
fallbackDiscount?: number,
bundleId?: string,
isBundleLock?: boolean,
duration: number
})
ctx.runMutation(components.listini.listRows.update, { id, ...fields })
ctx.runMutation(components.listini.listRows.remove, { id })Bundles
// Queries
ctx.runQuery(components.listini.bundles.getAll)
ctx.runQuery(components.listini.bundles.getById, { id })
ctx.runQuery(components.listini.bundles.getActive)
// Mutations
ctx.runMutation(components.listini.bundles.create, { name })
ctx.runMutation(components.listini.bundles.update, { id, name, isActive })
ctx.runMutation(components.listini.bundles.remove, { id })Example App
Check out the example/ directory for a complete Vite + React demo application.
cd example
npm install
npm run devDevelopment
# Install dependencies
npm install
# Generate Convex code
npm run codegen
# Type check
npm run typecheckLicense
MIT
