82 lines
3.2 KiB
TypeScript
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'),
|
|
});
|