MyKindlebox/mykindlebox/server/db/schema.ts

82 lines
3.2 KiB
TypeScript

import { sql } from 'drizzle-orm';
import { sqliteTable, text, integer, real, check } from 'drizzle-orm/sqlite-core';
export const rabbits = sqliteTable(
'rabbits',
{
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
farm: text('farm'),
sex: text('sex').notNull().default('unknown'),
dob: text('dob'),
weightLbs: real('weight_lbs'),
earNumber: text('ear_number'),
location: text('location'),
status: text('status').notNull().default('active'),
colorName: text('color_name'),
photoPath: text('photo_path'),
registrationNumber: text('registration_number'),
gcNumber: text('gc_number'),
sireId: integer('sire_id').references((): any => rabbits.id),
damId: integer('dam_id').references((): any => rabbits.id),
// Genetics loci
locusA: text('locus_a'),
locusB: text('locus_b'),
locusC: text('locus_c'),
locusD: text('locus_d'),
locusE: text('locus_e'),
locusEn: text('locus_en'),
locusV: text('locus_v'),
// Chain-authority freeform ancestor text (see memory-bank/architecture.md)
// Generation 1 (parents)
sireNameText: text('sire_name_text'),
damNameText: text('dam_name_text'),
// Generation 2 (grandparents)
paternalGrandsireNameText: text('paternal_grandsire_name_text'),
paternalGranddamNameText: text('paternal_granddam_name_text'),
maternalGrandsireNameText: text('maternal_grandsire_name_text'),
maternalGranddamNameText: text('maternal_granddam_name_text'),
// Generation 3 (great-grandparents)
ppGrandsireNameText: text('pp_grandsire_name_text'),
ppGranddamNameText: text('pp_granddam_name_text'),
pmGrandsireNameText: text('pm_grandsire_name_text'),
pmGranddamNameText: text('pm_granddam_name_text'),
mpGrandsireNameText: text('mp_grandsire_name_text'),
mpGranddamNameText: text('mp_granddam_name_text'),
mmGrandsireNameText: text('mm_grandsire_name_text'),
mmGranddamNameText: text('mm_granddam_name_text'),
createdAt: text('created_at').notNull().default(sql`(current_timestamp)`),
updatedAt: text('updated_at').notNull().default(sql`(current_timestamp)`),
},
(table) => [
check('sex_check', sql`${table.sex} in ('buck', 'doe', 'unknown')`),
check(
'status_check',
sql`${table.status} in ('active', 'for_sale', 'on_hold', 'sold', 'deceased', 'other')`
),
]
);
export const litters = sqliteTable('litters', {
id: integer('id').primaryKey({ autoIncrement: true }),
sireId: integer('sire_id').references(() => rabbits.id),
damId: integer('dam_id').references(() => rabbits.id),
// A litter record spans the breeding→kindle lifecycle: `breedDate` is set when
// the pairing is recorded; `kindleDate` (nullable until the doe kindles) and
// `kitCount` are filled in later. At least one of the two dates is required —
// enforced in routes/litters.ts, not by the schema.
breedDate: text('breed_date'),
kindleDate: text('kindle_date'),
kitCount: integer('kit_count'),
notes: text('notes'),
createdAt: text('created_at').notNull().default(sql`(current_timestamp)`),
});
export const settings = sqliteTable('settings', {
key: text('key').primaryKey(),
value: text('value'),
});