feat: backend improvements - reminder tracking, share stock status, planner notifications (#145)
- Separate stock/intake reminder tracking in DB with dedicated columns - Add shareStockStatus setting to control stock visibility on shared links - Rewrite planner notification to support both email and Shoutrrr push - Add push notification footer text for intake and stock reminders - New DB migrations: stock_reminder_tracking (0006), share_stock_status (0007) - Update backend i18n with demandCalculator section and critically low text - Add 514 passing backend tests including new coverage for all changes
This commit is contained in:
@@ -88,10 +88,10 @@ export async function runDrizzleMigrations(
|
||||
await migrate(database, { migrationsFolder });
|
||||
return { success: true };
|
||||
} catch (err: any) {
|
||||
// If the error is "duplicate column", it means the schema is already up-to-date
|
||||
// This happens when ALTER migrations in client.ts have already added the columns
|
||||
// We consider this a success with a warning, not a failure
|
||||
if (err.message?.includes("duplicate column")) {
|
||||
// If the error is about existing schema objects, the DB is already up-to-date
|
||||
// This happens when ALTER migrations in client.ts have already added the columns,
|
||||
// or when tables were created before drizzle migrations were introduced
|
||||
if (err.message?.includes("duplicate column") || err.message?.includes("already exists")) {
|
||||
return { success: true, warning: `Schema already up-to-date: ${err.message}` };
|
||||
}
|
||||
return { success: false, error: err.message };
|
||||
@@ -129,6 +129,12 @@ export async function runAlterMigrations(client: Client): Promise<{ success: boo
|
||||
`ALTER TABLE medications ADD COLUMN dose_unit text DEFAULT 'mg'`,
|
||||
// Added for intake-level takenBy: unified intakes structure
|
||||
`ALTER TABLE medications ADD COLUMN intakes_json text NOT NULL DEFAULT '[]'`,
|
||||
// Added for separate stock reminder tracking
|
||||
`ALTER TABLE user_settings ADD COLUMN last_stock_reminder_sent text`,
|
||||
`ALTER TABLE user_settings ADD COLUMN last_stock_reminder_channel text`,
|
||||
`ALTER TABLE user_settings ADD COLUMN last_stock_reminder_med_names text`,
|
||||
// Added for share stock visibility toggle
|
||||
`ALTER TABLE user_settings ADD COLUMN share_stock_status integer NOT NULL DEFAULT 1`,
|
||||
];
|
||||
|
||||
for (const sql of alterMigrations) {
|
||||
|
||||
@@ -86,12 +86,18 @@ export const userSettings = sqliteTable("user_settings", {
|
||||
language: text("language", { length: 10 }).notNull().default("en"),
|
||||
// Stock calculation mode: "automatic" (schedule-based) or "manual" (only marked doses)
|
||||
stockCalculationMode: text("stock_calculation_mode", { length: 20 }).notNull().default("automatic"),
|
||||
// Last notification tracking
|
||||
// Whether shared schedule links show stock status (Critical/Low/Normal) to intake users
|
||||
shareStockStatus: integer("share_stock_status", { mode: "boolean" }).notNull().default(true),
|
||||
// Last notification tracking (intake reminders)
|
||||
lastAutoEmailSent: text("last_auto_email_sent"),
|
||||
lastNotificationType: text("last_notification_type"),
|
||||
lastNotificationChannel: text("last_notification_channel"),
|
||||
lastReminderMedName: text("last_reminder_med_name"),
|
||||
lastReminderTakenBy: text("last_reminder_taken_by"),
|
||||
// Last stock reminder tracking (separate from intake)
|
||||
lastStockReminderSent: text("last_stock_reminder_sent"),
|
||||
lastStockReminderChannel: text("last_stock_reminder_channel"),
|
||||
lastStockReminderMedNames: text("last_stock_reminder_med_names"),
|
||||
// Timestamps
|
||||
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().default(sql`CURRENT_TIMESTAMP`),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user