Add music store seed preset and repair data reset script
- music-store-seed.ts: 52 templates covering strings, brass, woodwinds, guitar, plus music-specific tickets and a school band batch - reset-repairs.ts: clears all repair data for switching between presets - New scripts: bun run db:seed-music, bun run db:seed-reset-repairs
This commit is contained in:
172
packages/backend/src/db/seeds/music-store-seed.ts
Normal file
172
packages/backend/src/db/seeds/music-store-seed.ts
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* Music store seed — populates the dev database with music-store-specific data.
|
||||||
|
* Run: bun run src/db/seeds/music-store-seed.ts
|
||||||
|
*
|
||||||
|
* Prerequisites: dev-seed must have been run first (company, accounts, RBAC already exist).
|
||||||
|
* This adds music-specific repair templates, tickets, and batch data.
|
||||||
|
*/
|
||||||
|
import postgres from 'postgres'
|
||||||
|
|
||||||
|
const DB_URL = process.env.DATABASE_URL ?? 'postgresql://lunarfront:lunarfront@localhost:5432/lunarfront'
|
||||||
|
const COMPANY_ID = 'a0000000-0000-0000-0000-000000000001'
|
||||||
|
|
||||||
|
const sql = postgres(DB_URL)
|
||||||
|
|
||||||
|
async function seed() {
|
||||||
|
console.log('Seeding music store data...')
|
||||||
|
|
||||||
|
// Verify company exists (dev-seed must run first)
|
||||||
|
const [company] = await sql`SELECT id FROM company WHERE id = ${COMPANY_ID}`
|
||||||
|
if (!company) {
|
||||||
|
console.error('Company not found — run dev-seed first: bun run db:seed-dev')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update company name to music store
|
||||||
|
await sql`UPDATE company SET name = 'Harmony Music Shop' WHERE id = ${COMPANY_ID}`
|
||||||
|
console.log(' Updated company name: Harmony Music Shop')
|
||||||
|
|
||||||
|
// --- Music Repair Service Templates ---
|
||||||
|
const templates = [
|
||||||
|
// Strings — Violin
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Violin', size: '4/4', itemType: 'flat_rate', price: '65.00', cost: '15.00' },
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Violin', size: '3/4', itemType: 'flat_rate', price: '55.00', cost: '12.00' },
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Violin', size: '1/2', itemType: 'flat_rate', price: '50.00', cost: '10.00' },
|
||||||
|
{ name: 'Bridge Setup', itemCategory: 'Violin', size: '4/4', itemType: 'flat_rate', price: '40.00', cost: '10.00' },
|
||||||
|
{ name: 'Bridge Replacement', itemCategory: 'Violin', size: '4/4', itemType: 'flat_rate', price: '75.00', cost: '25.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Violin', size: '4/4', itemType: 'flat_rate', price: '35.00', cost: '12.00' },
|
||||||
|
{ name: 'Peg Fitting', itemCategory: 'Violin', size: null, itemType: 'labor', price: '30.00', cost: null },
|
||||||
|
{ name: 'Soundpost Adjustment', itemCategory: 'Violin', size: null, itemType: 'labor', price: '25.00', cost: null },
|
||||||
|
{ name: 'Seam Repair', itemCategory: 'Violin', size: null, itemType: 'labor', price: '45.00', cost: null },
|
||||||
|
|
||||||
|
// Strings — Viola
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Viola', size: null, itemType: 'flat_rate', price: '65.00', cost: '15.00' },
|
||||||
|
{ name: 'Bridge Setup', itemCategory: 'Viola', size: null, itemType: 'flat_rate', price: '45.00', cost: '12.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Viola', size: null, itemType: 'flat_rate', price: '40.00', cost: '15.00' },
|
||||||
|
|
||||||
|
// Strings — Cello
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Cello', size: null, itemType: 'flat_rate', price: '80.00', cost: '20.00' },
|
||||||
|
{ name: 'Bridge Setup', itemCategory: 'Cello', size: null, itemType: 'flat_rate', price: '55.00', cost: '15.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Cello', size: null, itemType: 'flat_rate', price: '50.00', cost: '20.00' },
|
||||||
|
{ name: 'Endpin Repair', itemCategory: 'Cello', size: null, itemType: 'labor', price: '35.00', cost: null },
|
||||||
|
|
||||||
|
// Strings — Bass
|
||||||
|
{ name: 'Bow Rehair', itemCategory: 'Bass', size: null, itemType: 'flat_rate', price: '90.00', cost: '25.00' },
|
||||||
|
{ name: 'Bridge Setup', itemCategory: 'Bass', size: null, itemType: 'flat_rate', price: '65.00', cost: '20.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Bass', size: null, itemType: 'flat_rate', price: '60.00', cost: '25.00' },
|
||||||
|
|
||||||
|
// Guitar
|
||||||
|
{ name: 'String Change', itemCategory: 'Guitar', size: 'Acoustic', itemType: 'flat_rate', price: '25.00', cost: '8.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Guitar', size: 'Electric', itemType: 'flat_rate', price: '25.00', cost: '7.00' },
|
||||||
|
{ name: 'String Change', itemCategory: 'Guitar', size: 'Classical', itemType: 'flat_rate', price: '25.00', cost: '10.00' },
|
||||||
|
{ name: 'Full Setup', itemCategory: 'Guitar', size: 'Acoustic', itemType: 'flat_rate', price: '65.00', cost: '5.00' },
|
||||||
|
{ name: 'Full Setup', itemCategory: 'Guitar', size: 'Electric', itemType: 'flat_rate', price: '65.00', cost: '5.00' },
|
||||||
|
{ name: 'Fret Level & Crown', itemCategory: 'Guitar', size: null, itemType: 'labor', price: '150.00', cost: null },
|
||||||
|
{ name: 'Pickup Installation', itemCategory: 'Guitar', size: null, itemType: 'labor', price: '45.00', cost: null },
|
||||||
|
{ name: 'Nut Replacement', itemCategory: 'Guitar', size: null, itemType: 'flat_rate', price: '35.00', cost: '8.00' },
|
||||||
|
{ name: 'Tuning Machine Replacement', itemCategory: 'Guitar', size: null, itemType: 'flat_rate', price: '40.00', cost: '15.00' },
|
||||||
|
|
||||||
|
// Brass
|
||||||
|
{ name: 'Valve Overhaul', itemCategory: 'Trumpet', size: null, itemType: 'labor', price: '85.00', cost: null },
|
||||||
|
{ name: 'Chemical Cleaning', itemCategory: 'Trumpet', size: null, itemType: 'flat_rate', price: '55.00', cost: '10.00' },
|
||||||
|
{ name: 'Dent Removal', itemCategory: 'Trumpet', size: null, itemType: 'labor', price: '50.00', cost: null },
|
||||||
|
{ name: 'Slide Repair', itemCategory: 'Trombone', size: null, itemType: 'labor', price: '75.00', cost: null },
|
||||||
|
{ name: 'Chemical Cleaning', itemCategory: 'Trombone', size: null, itemType: 'flat_rate', price: '65.00', cost: '12.00' },
|
||||||
|
{ name: 'Dent Removal', itemCategory: 'Trombone', size: null, itemType: 'labor', price: '60.00', cost: null },
|
||||||
|
{ name: 'Valve Overhaul', itemCategory: 'French Horn', size: null, itemType: 'labor', price: '120.00', cost: null },
|
||||||
|
{ name: 'Chemical Cleaning', itemCategory: 'French Horn', size: null, itemType: 'flat_rate', price: '75.00', cost: '15.00' },
|
||||||
|
{ name: 'Valve Overhaul', itemCategory: 'Tuba', size: null, itemType: 'labor', price: '150.00', cost: null },
|
||||||
|
|
||||||
|
// Woodwinds
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Clarinet', size: null, itemType: 'flat_rate', price: '120.00', cost: '30.00' },
|
||||||
|
{ name: 'Cork Replacement', itemCategory: 'Clarinet', size: null, itemType: 'flat_rate', price: '45.00', cost: '5.00' },
|
||||||
|
{ name: 'Key Adjustment', itemCategory: 'Clarinet', size: null, itemType: 'labor', price: '35.00', cost: null },
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Flute', size: null, itemType: 'flat_rate', price: '110.00', cost: '25.00' },
|
||||||
|
{ name: 'Headjoint Cork', itemCategory: 'Flute', size: null, itemType: 'flat_rate', price: '30.00', cost: '5.00' },
|
||||||
|
{ name: 'Key Adjustment', itemCategory: 'Flute', size: null, itemType: 'labor', price: '35.00', cost: null },
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Saxophone', size: 'Alto', itemType: 'flat_rate', price: '150.00', cost: '40.00' },
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Saxophone', size: 'Tenor', itemType: 'flat_rate', price: '175.00', cost: '50.00' },
|
||||||
|
{ name: 'Cork & Felt Replacement', itemCategory: 'Saxophone', size: null, itemType: 'flat_rate', price: '65.00', cost: '10.00' },
|
||||||
|
{ name: 'Neck Cork', itemCategory: 'Saxophone', size: null, itemType: 'flat_rate', price: '20.00', cost: '3.00' },
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Oboe', size: null, itemType: 'flat_rate', price: '200.00', cost: '60.00' },
|
||||||
|
{ name: 'Reed Adjustment', itemCategory: 'Oboe', size: null, itemType: 'labor', price: '15.00', cost: null },
|
||||||
|
{ name: 'Pad Replacement', itemCategory: 'Bassoon', size: null, itemType: 'flat_rate', price: '250.00', cost: '80.00' },
|
||||||
|
|
||||||
|
// General
|
||||||
|
{ name: 'General Cleaning', itemCategory: null, size: null, itemType: 'flat_rate', price: '30.00', cost: '5.00' },
|
||||||
|
{ name: 'Diagnostic Evaluation', itemCategory: null, size: null, itemType: 'flat_rate', price: '25.00', cost: null },
|
||||||
|
]
|
||||||
|
|
||||||
|
// Deactivate generic templates first
|
||||||
|
await sql`UPDATE repair_service_template SET is_active = false`
|
||||||
|
console.log(' Deactivated generic templates')
|
||||||
|
|
||||||
|
for (const t of templates) {
|
||||||
|
const existing = await sql`SELECT id FROM repair_service_template WHERE name = ${t.name} AND COALESCE(item_category, '') = ${t.itemCategory ?? ''} AND COALESCE(size, '') = ${t.size ?? ''}`
|
||||||
|
if (existing.length > 0) continue
|
||||||
|
await sql`INSERT INTO repair_service_template (name, item_category, size, item_type, default_price, default_cost, is_active) VALUES (${t.name}, ${t.itemCategory}, ${t.size}, ${t.itemType}, ${t.price}, ${t.cost}, true)`
|
||||||
|
console.log(` Template: ${t.name} — ${t.itemCategory ?? 'General'} ${t.size ?? ''}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Music Repair Tickets ---
|
||||||
|
// First clear any generic tickets
|
||||||
|
await sql`DELETE FROM repair_ticket WHERE id NOT IN (SELECT DISTINCT repair_ticket_id FROM repair_note)`
|
||||||
|
|
||||||
|
const acctRows = await sql`SELECT id, name FROM account`
|
||||||
|
const acctIds: Record<string, string> = {}
|
||||||
|
for (const a of acctRows) acctIds[a.name] = a.id
|
||||||
|
|
||||||
|
const tickets = [
|
||||||
|
{ customer: 'Mike Thompson', item: 'Fender Stratocaster', serial: 'US22-045891', problem: 'Fret buzz on 3rd and 5th fret, needs full setup', condition: 'good', status: 'in_progress', estimate: '65.00' },
|
||||||
|
{ customer: 'Emily Chen', item: 'Yamaha YTR-2330 Trumpet', serial: 'YTR-78432', problem: 'Stuck 2nd valve, sluggish action on all valves', condition: 'fair', status: 'pending_approval', estimate: '85.00' },
|
||||||
|
{ customer: 'David Smith', item: 'German Workshop Violin 4/4', serial: null, problem: 'Bow needs rehair, bridge slightly warped', condition: 'fair', status: 'ready', estimate: '105.00' },
|
||||||
|
{ customer: 'Carlos Garcia', item: 'Martin D-28 Acoustic Guitar', serial: 'M2284563', problem: 'Broken tuning peg, needs replacement', condition: 'good', status: 'new', estimate: null },
|
||||||
|
{ customer: 'Lisa Johnson', item: 'Yamaha YCL-255 Clarinet', serial: null, problem: 'Several pads worn, keys sticking', condition: 'poor', status: 'diagnosing', estimate: null },
|
||||||
|
{ customer: 'Walk-In Customer', item: 'Gemeinhardt 2SP Flute', serial: null, problem: 'Squeaks on high notes, headjoint cork may need replacing', condition: 'fair', status: 'intake', estimate: null },
|
||||||
|
{ customer: 'Smith Family', item: 'Suzuki Student Violin 1/2', serial: null, problem: 'Pegs slipping, bridge leaning forward', condition: 'fair', status: 'new', estimate: null },
|
||||||
|
{ customer: 'Johnson Family', item: 'Selmer AS500 Alto Saxophone', serial: 'AS-99231', problem: 'Neck cork loose, low notes not speaking', condition: 'good', status: 'in_progress', estimate: '85.00' },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const t of tickets) {
|
||||||
|
const existing = await sql`SELECT id FROM repair_ticket WHERE customer_name = ${t.customer} AND problem_description = ${t.problem}`
|
||||||
|
if (existing.length > 0) continue
|
||||||
|
const num = String(Math.floor(100000 + Math.random() * 900000))
|
||||||
|
const acctId = acctIds[t.customer] ?? null
|
||||||
|
await sql`INSERT INTO repair_ticket (ticket_number, customer_name, account_id, item_description, serial_number, problem_description, condition_in, status, estimated_cost) VALUES (${num}, ${t.customer}, ${acctId}, ${t.item}, ${t.serial}, ${t.problem}, ${t.condition}, ${t.status}, ${t.estimate})`
|
||||||
|
console.log(` Ticket: ${t.customer} — ${t.item} [${t.status}]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- School Band Batch ---
|
||||||
|
const batchExists = await sql`SELECT id FROM repair_batch WHERE contact_name = 'Mr. Williams'`
|
||||||
|
if (batchExists.length === 0) {
|
||||||
|
const schoolId = acctIds['Lincoln High School']
|
||||||
|
if (schoolId) {
|
||||||
|
const batchNum = String(Math.floor(100000 + Math.random() * 900000))
|
||||||
|
const [batch] = await sql`INSERT INTO repair_batch (batch_number, account_id, contact_name, contact_phone, contact_email, item_count, notes, status) VALUES (${batchNum}, ${schoolId}, 'Mr. Williams', '555-0210', 'williams@lincoln.edu', 6, 'Annual band instrument checkup — 6 instruments for fall semester', 'intake') RETURNING id`
|
||||||
|
|
||||||
|
const batchTickets = [
|
||||||
|
{ item: 'Student Flute — Gemeinhardt 2SP', problem: 'Pads worn, headjoint cork needs check', condition: 'fair' },
|
||||||
|
{ item: 'Student Clarinet — Yamaha YCL-255', problem: 'Keys sticking, barrel cork dried out', condition: 'fair' },
|
||||||
|
{ item: 'Student Clarinet — Buffet B12', problem: 'Barrel crack, needs assessment', condition: 'poor' },
|
||||||
|
{ item: 'Student Trumpet — Bach TR300', problem: 'Valve alignment off, general cleaning needed', condition: 'good' },
|
||||||
|
{ item: 'Student Trombone — Yamaha YSL-354', problem: 'Slide dent near bell, sluggish movement', condition: 'fair' },
|
||||||
|
{ item: 'Student Alto Sax — Selmer AS500', problem: 'Neck cork loose, octave key sticky', condition: 'fair' },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const bt of batchTickets) {
|
||||||
|
const num = String(Math.floor(100000 + Math.random() * 900000))
|
||||||
|
await sql`INSERT INTO repair_ticket (ticket_number, customer_name, account_id, repair_batch_id, item_description, problem_description, condition_in, status) VALUES (${num}, 'Lincoln High School', ${schoolId}, ${batch.id}, ${bt.item}, ${bt.problem}, ${bt.condition}, 'new')`
|
||||||
|
console.log(` Batch ticket: ${bt.item}`)
|
||||||
|
}
|
||||||
|
console.log(' Batch: Lincoln High School — 6 instruments')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\nMusic store seed complete!')
|
||||||
|
await sql.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
seed().catch((err) => {
|
||||||
|
console.error('Seed failed:', err)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
37
packages/backend/src/db/seeds/reset-repairs.ts
Normal file
37
packages/backend/src/db/seeds/reset-repairs.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Reset repair data — clears all repair tickets, batches, templates, notes, and line items.
|
||||||
|
* Run: bun run db:seed-reset-repairs
|
||||||
|
*
|
||||||
|
* Use this before switching between seed presets (e.g. generic → music store).
|
||||||
|
*/
|
||||||
|
import postgres from 'postgres'
|
||||||
|
|
||||||
|
const DB_URL = process.env.DATABASE_URL ?? 'postgresql://lunarfront:lunarfront@localhost:5432/lunarfront'
|
||||||
|
const sql = postgres(DB_URL)
|
||||||
|
|
||||||
|
async function reset() {
|
||||||
|
console.log('Resetting repair data...')
|
||||||
|
|
||||||
|
const notes = await sql`DELETE FROM repair_note RETURNING id`
|
||||||
|
console.log(` Deleted ${notes.length} notes`)
|
||||||
|
|
||||||
|
const lineItems = await sql`DELETE FROM repair_line_item RETURNING id`
|
||||||
|
console.log(` Deleted ${lineItems.length} line items`)
|
||||||
|
|
||||||
|
const tickets = await sql`DELETE FROM repair_ticket RETURNING id`
|
||||||
|
console.log(` Deleted ${tickets.length} tickets`)
|
||||||
|
|
||||||
|
const batches = await sql`DELETE FROM repair_batch RETURNING id`
|
||||||
|
console.log(` Deleted ${batches.length} batches`)
|
||||||
|
|
||||||
|
const templates = await sql`DELETE FROM repair_service_template RETURNING id`
|
||||||
|
console.log(` Deleted ${templates.length} templates`)
|
||||||
|
|
||||||
|
console.log('\nRepair data cleared. Run a seed to repopulate.')
|
||||||
|
await sql.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
reset().catch((err) => {
|
||||||
|
console.error('Reset failed:', err)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user