Add lessons module, rate cycles, EC2 deploy scripts, and help content
- Lessons module: lesson types, instructors, schedule slots, enrollments, sessions (list + week grid view), lesson plans, grading scales, templates - Rate cycles: replace monthly_rate with billing_interval + billing_unit on enrollments; add weekly/monthly/quarterly rate presets to lesson types and schedule slots with auto-fill on enrollment form - Member detail page: tabbed layout for details, identity documents, enrollments - Sessions week view: custom 7-column grid replacing react-big-calendar - Music store seed: instructors, lesson types, slots, enrollments, sessions, grading scale, lesson plan template - Scrollbar styling: themed to match sidebar/app palette - deploy/: EC2 setup and redeploy scripts, nginx config, systemd service - Help: add Lessons category (overview, types, instructors, slots, enrollments, sessions, plans/grading); collapsible sidebar with independent scroll; remove POS/accounting references from docs
This commit is contained in:
@@ -17,6 +17,7 @@ import { accounts, members } from './accounts.js'
|
||||
// --- Enums ---
|
||||
|
||||
export const lessonFormatEnum = pgEnum('lesson_format', ['private', 'group'])
|
||||
export const billingUnitEnum = pgEnum('billing_unit', ['day', 'week', 'month', 'quarter', 'year'])
|
||||
|
||||
// --- Tables ---
|
||||
|
||||
@@ -37,7 +38,9 @@ export const lessonTypes = pgTable('lesson_type', {
|
||||
instrument: varchar('instrument', { length: 100 }),
|
||||
durationMinutes: integer('duration_minutes').notNull(),
|
||||
lessonFormat: lessonFormatEnum('lesson_format').notNull().default('private'),
|
||||
baseRateMonthly: varchar('base_rate_monthly', { length: 20 }),
|
||||
rateWeekly: numeric('rate_weekly', { precision: 10, scale: 2 }),
|
||||
rateMonthly: numeric('rate_monthly', { precision: 10, scale: 2 }),
|
||||
rateQuarterly: numeric('rate_quarterly', { precision: 10, scale: 2 }),
|
||||
isActive: boolean('is_active').notNull().default(true),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
@@ -55,6 +58,9 @@ export const scheduleSlots = pgTable('schedule_slot', {
|
||||
startTime: time('start_time').notNull(),
|
||||
room: varchar('room', { length: 100 }),
|
||||
maxStudents: integer('max_students').notNull().default(1),
|
||||
rateWeekly: numeric('rate_weekly', { precision: 10, scale: 2 }),
|
||||
rateMonthly: numeric('rate_monthly', { precision: 10, scale: 2 }),
|
||||
rateQuarterly: numeric('rate_quarterly', { precision: 10, scale: 2 }),
|
||||
isActive: boolean('is_active').notNull().default(true),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
@@ -84,7 +90,9 @@ export const enrollments = pgTable('enrollment', {
|
||||
status: enrollmentStatusEnum('status').notNull().default('active'),
|
||||
startDate: date('start_date').notNull(),
|
||||
endDate: date('end_date'),
|
||||
monthlyRate: numeric('monthly_rate', { precision: 10, scale: 2 }),
|
||||
rate: numeric('rate', { precision: 10, scale: 2 }),
|
||||
billingInterval: integer('billing_interval'),
|
||||
billingUnit: billingUnitEnum('billing_unit'),
|
||||
makeupCredits: integer('makeup_credits').notNull().default(0),
|
||||
notes: text('notes'),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
|
||||
Reference in New Issue
Block a user