@@ -10,6 +10,7 @@ export interface MockDataOptions {
1010 includeTimeEntries ?: boolean ;
1111 includeQuantityRecords ?: boolean ;
1212 includeIssues ?: boolean ;
13+ includeCalendar ?: boolean ;
1314}
1415
1516/**
@@ -28,6 +29,7 @@ export async function generateMockData(
2829 includeTimeEntries : true ,
2930 includeQuantityRecords : true ,
3031 includeIssues : true ,
32+ includeCalendar : true ,
3133 } ,
3234) : Promise < { success : boolean ; error ?: string } > {
3335 try {
@@ -159,6 +161,72 @@ export async function generateMockData(
159161 console . log ( "✓ Created 6 QRM cells with WIP limits" ) ;
160162 }
161163
164+ // Step 1.5: Seed Dutch holidays and factory calendar
165+ if ( options . includeCalendar ) {
166+ // Dutch holidays for 2025 and 2026
167+ // Including Christmas/New Year closure period
168+ const dutchHolidays = [
169+ // 2025 Holidays
170+ { date : '2025-01-01' , day_type : 'holiday' , name : 'Nieuwjaarsdag' , capacity_multiplier : 0 } ,
171+ { date : '2025-04-18' , day_type : 'holiday' , name : 'Goede Vrijdag' , capacity_multiplier : 0 } ,
172+ { date : '2025-04-20' , day_type : 'holiday' , name : 'Eerste Paasdag' , capacity_multiplier : 0 } ,
173+ { date : '2025-04-21' , day_type : 'holiday' , name : 'Tweede Paasdag' , capacity_multiplier : 0 } ,
174+ { date : '2025-04-26' , day_type : 'holiday' , name : 'Koningsdag' , capacity_multiplier : 0 , notes : 'Koningsdag valt op zondag, gevierd op zaterdag' } ,
175+ { date : '2025-05-05' , day_type : 'holiday' , name : 'Bevrijdingsdag' , capacity_multiplier : 0 } ,
176+ { date : '2025-05-29' , day_type : 'holiday' , name : 'Hemelvaartsdag' , capacity_multiplier : 0 } ,
177+ { date : '2025-05-30' , day_type : 'closure' , name : 'Brugdag Hemelvaart' , capacity_multiplier : 0 , notes : 'Fabriek gesloten - brugdag' } ,
178+ { date : '2025-06-08' , day_type : 'holiday' , name : 'Eerste Pinksterdag' , capacity_multiplier : 0 } ,
179+ { date : '2025-06-09' , day_type : 'holiday' , name : 'Tweede Pinksterdag' , capacity_multiplier : 0 } ,
180+ // Christmas / New Year period 2025-2026
181+ { date : '2025-12-24' , day_type : 'half_day' , name : 'Kerstavond' , capacity_multiplier : 0.5 , opening_time : '08:00' , closing_time : '12:00' , notes : 'Fabriek sluit om 12:00' } ,
182+ { date : '2025-12-25' , day_type : 'holiday' , name : 'Eerste Kerstdag' , capacity_multiplier : 0 } ,
183+ { date : '2025-12-26' , day_type : 'holiday' , name : 'Tweede Kerstdag' , capacity_multiplier : 0 } ,
184+ { date : '2025-12-29' , day_type : 'closure' , name : 'Kerstvakantie' , capacity_multiplier : 0 , notes : 'Fabriek gesloten tussen Kerst en Nieuwjaar' } ,
185+ { date : '2025-12-30' , day_type : 'closure' , name : 'Kerstvakantie' , capacity_multiplier : 0 , notes : 'Fabriek gesloten tussen Kerst en Nieuwjaar' } ,
186+ { date : '2025-12-31' , day_type : 'half_day' , name : 'Oudejaarsdag' , capacity_multiplier : 0.5 , opening_time : '08:00' , closing_time : '12:00' , notes : 'Fabriek sluit om 12:00' } ,
187+ // 2026 Holidays
188+ { date : '2026-01-01' , day_type : 'holiday' , name : 'Nieuwjaarsdag' , capacity_multiplier : 0 } ,
189+ { date : '2026-01-02' , day_type : 'closure' , name : 'Brugdag Nieuwjaar' , capacity_multiplier : 0 , notes : 'Fabriek gesloten - brugdag' } ,
190+ { date : '2026-04-03' , day_type : 'holiday' , name : 'Goede Vrijdag' , capacity_multiplier : 0 } ,
191+ { date : '2026-04-05' , day_type : 'holiday' , name : 'Eerste Paasdag' , capacity_multiplier : 0 } ,
192+ { date : '2026-04-06' , day_type : 'holiday' , name : 'Tweede Paasdag' , capacity_multiplier : 0 } ,
193+ { date : '2026-04-27' , day_type : 'holiday' , name : 'Koningsdag' , capacity_multiplier : 0 } ,
194+ { date : '2026-05-05' , day_type : 'holiday' , name : 'Bevrijdingsdag' , capacity_multiplier : 0 } ,
195+ { date : '2026-05-14' , day_type : 'holiday' , name : 'Hemelvaartsdag' , capacity_multiplier : 0 } ,
196+ { date : '2026-05-15' , day_type : 'closure' , name : 'Brugdag Hemelvaart' , capacity_multiplier : 0 , notes : 'Fabriek gesloten - brugdag' } ,
197+ { date : '2026-05-24' , day_type : 'holiday' , name : 'Eerste Pinksterdag' , capacity_multiplier : 0 } ,
198+ { date : '2026-05-25' , day_type : 'holiday' , name : 'Tweede Pinksterdag' , capacity_multiplier : 0 } ,
199+ { date : '2026-12-24' , day_type : 'half_day' , name : 'Kerstavond' , capacity_multiplier : 0.5 , opening_time : '08:00' , closing_time : '12:00' , notes : 'Fabriek sluit om 12:00' } ,
200+ { date : '2026-12-25' , day_type : 'holiday' , name : 'Eerste Kerstdag' , capacity_multiplier : 0 } ,
201+ { date : '2026-12-26' , day_type : 'holiday' , name : 'Tweede Kerstdag' , capacity_multiplier : 0 } ,
202+ { date : '2026-12-28' , day_type : 'closure' , name : 'Kerstvakantie' , capacity_multiplier : 0 , notes : 'Fabriek gesloten tussen Kerst en Nieuwjaar' } ,
203+ { date : '2026-12-29' , day_type : 'closure' , name : 'Kerstvakantie' , capacity_multiplier : 0 , notes : 'Fabriek gesloten tussen Kerst en Nieuwjaar' } ,
204+ { date : '2026-12-30' , day_type : 'closure' , name : 'Kerstvakantie' , capacity_multiplier : 0 , notes : 'Fabriek gesloten tussen Kerst en Nieuwjaar' } ,
205+ { date : '2026-12-31' , day_type : 'half_day' , name : 'Oudejaarsdag' , capacity_multiplier : 0.5 , opening_time : '08:00' , closing_time : '12:00' , notes : 'Fabriek sluit om 12:00' } ,
206+ ] ;
207+
208+ const calendarEntries = dutchHolidays . map ( holiday => ( {
209+ tenant_id : tenantId ,
210+ date : holiday . date ,
211+ day_type : holiday . day_type ,
212+ name : holiday . name ,
213+ opening_time : ( holiday as any ) . opening_time || null ,
214+ closing_time : ( holiday as any ) . closing_time || null ,
215+ capacity_multiplier : holiday . capacity_multiplier ,
216+ notes : ( holiday as any ) . notes || null ,
217+ } ) ) ;
218+
219+ const { error : calendarError } = await supabase
220+ . from ( "factory_calendar" )
221+ . upsert ( calendarEntries , { onConflict : 'tenant_id,date' } ) ;
222+
223+ if ( calendarError ) {
224+ console . warn ( "Calendar seeding warning:" , calendarError ) ;
225+ } else {
226+ console . log ( `✓ Seeded ${ calendarEntries . length } Dutch holidays and factory closures` ) ;
227+ }
228+ }
229+
162230 // Step 2: Create 6 Dutch operator profiles for shop floor use
163231 // Note: pin_hash is left NULL - operators can set PINs later via UI if needed
164232 let operatorIds : string [ ] = [ ] ;
@@ -2124,6 +2192,13 @@ export async function clearMockData(
21242192 if ( profilesErr )
21252193 console . warn ( "Demo operators deletion warning:" , profilesErr ) ;
21262194
2195+ // 17. Delete factory calendar entries (has tenant_id)
2196+ const { error : calendarErr } = await supabase
2197+ . from ( "factory_calendar" )
2198+ . delete ( )
2199+ . eq ( "tenant_id" , tenantId ) ;
2200+ if ( calendarErr ) console . warn ( "Calendar deletion warning:" , calendarErr ) ;
2201+
21272202 // Disable demo mode flag now that data is cleared
21282203 const { error : demoModeError } = await supabase . rpc ( "disable_demo_mode" , {
21292204 p_tenant_id : tenantId ,
0 commit comments