<?php
set_exception_handler(static function(Throwable $e){if(isset($GLOBALS['save']))($GLOBALS['save'])('preflight-error.json',['class'=>get_class($e),'message'=>$e->getMessage(),'native'=>Read7Gate::$native,'denied'=>Read7Gate::$denied]);fwrite(STDERR,'Read7 readonly path stopped; private original retained'.PHP_EOL);exit(1);});require __DIR__.'/common.php';Read7Gate::$phase='preflight';Read7Gate::$journal=fopen(__DIR__.'/private/preflight-native.jsonl','xb');chmod(__DIR__.'/private/preflight-native.jsonl',0600);
$tables=Read7Gate::TABLES;$in=implode(',',array_fill(0,count($tables),'?'));$cols=$lane==='B'?$q('SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('.$in.') ORDER BY TABLE_NAME,ORDINAL_POSITION',$tables):$q('SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME IN ('.$in.') ORDER BY TABLE_NAME,COLUMN_ID',array_map('strtoupper',$tables));$schema=[];foreach($cols as $c)$schema[strtolower($c['table_name'])][]=$c;$identity=$q($lane==='B'?'SELECT DATABASE() AS db':"SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS db FROM DUAL");if($identity[0]['db']!==$cfg['database'])throw new RuntimeException('Actual exact primary identity');
$actor=$q('SELECT * FROM ydy_user WHERE id=?',[$lane==='B'?97260:2791]);if(count($actor)!==1||$actor[0]['type']!==0)throw new RuntimeException('Original type0 actor');$previous=json_decode(file_get_contents(__DIR__.'/private/original-actor.json'),true);if($actor!==$previous)throw new RuntimeException('Original actor full row drift');
$configs=$q('SELECT config_key,config_value FROM ydy_config WHERE status=? AND config_key IN (?,?,?,?) ORDER BY id',[1,'consume_subsidy_audit_mode','ossDisjunctor','ossHost','businessIdentify']);$ossPresence=$q('SELECT config_key,COUNT(*) AS cnt FROM ydy_config WHERE status=? AND config_key IN (?,?,?,?,?,?,?) GROUP BY config_key',[1,'ossDisjunctor','ossAccessKeyId','ossAccessKeySecret','ossEndpoint','ossBucket','ossHost','businessIdentify']);
$batch=[];$details=[];if(isset($schema['ydy_consume_subsidy_batch'],$schema['ydy_consume_subsidy_detail'])){$batch=$q('SELECT * FROM ydy_consume_subsidy_batch b WHERE b.store_id=? AND b.is_delete=? AND EXISTS (SELECT 1 FROM ydy_consume_subsidy_detail d WHERE d.batch_id=b.id AND d.store_id=? AND d.is_delete=?) ORDER BY b.id DESC LIMIT 1',[10001,0,10001,0]);if($batch)$details=$q('SELECT * FROM ydy_consume_subsidy_detail WHERE batch_id=? AND store_id=? AND is_delete=? ORDER BY staff_name ASC,consume_date ASC,meal_times ASC',[(int)$batch[0]['id'],10001,0]);}
$candidates=[];$selection=null;$menuRows=[];$dishRows=[];$staffRows=[];$relations=[];$departments=[];
if(isset($schema['ydy_date_menu'],$schema['ydy_dishes'],$schema['ydy_staff'],$schema['ydy_staff_department'],$schema['ydy_department'])){$candidates=$q('SELECT a.menu_date,a.meal_times,a.staff_uuid,sd.department_uuid FROM ydy_date_menu a JOIN ydy_staff s ON s.uuid=a.staff_uuid JOIN ydy_staff_department sd ON sd.staff_uuid=s.uuid JOIN ydy_department dep ON dep.uuid=sd.department_uuid JOIN ydy_dishes d ON d.uuid=a.dishes_uuid WHERE a.meal_type<? AND a.meal_times IN (?,?,?) AND s.is_show=? AND dep.is_show=? AND d.is_del=? AND d.status=? AND d.category>=? AND d.category<=? AND d.unit>=? AND d.unit<=? AND NOT EXISTS (SELECT 1 FROM ydy_department child WHERE child.puuid=dep.uuid AND child.is_show=?) ORDER BY a.id DESC LIMIT 20',[3,1,2,3,1,1,1,1,1,7,1,14,1]);$seen=[];foreach($candidates as $c){$date=$c['menu_date'];if(!is_string($date)||!preg_match('/^\d{4}-\d{2}-\d{2}(?: 00:00:00(?:\.0+)?)?$/D',$date))continue;$date=substr($date,0,10);$key=$date.'|'.$c['meal_times'].'|'.$c['department_uuid'];if(isset($seen[$key]))continue;$seen[$key]=true;if(count($seen)>5)break;$count=$q('SELECT COUNT(DISTINCT a.staff_uuid) AS cnt FROM ydy_date_menu a JOIN ydy_staff_department sd ON sd.staff_uuid=a.staff_uuid WHERE sd.department_uuid=? AND a.menu_date=? AND a.meal_times=? AND a.meal_type<?',[$c['department_uuid'],$date,(int)$c['meal_times'],3]);if((int)$count[0]['cnt']!==1)continue;$selection=['menu_date'=>$date,'meal_times'=>(int)$c['meal_times'],'staff_uuid'=>$c['staff_uuid'],'department_uuid'=>$c['department_uuid']];break;}if($selection){$menuRows=$q('SELECT * FROM ydy_date_menu WHERE staff_uuid=? AND menu_date=? AND meal_times=? AND meal_type<? ORDER BY id',[$selection['staff_uuid'],$selection['menu_date'],$selection['meal_times'],3]);$ids=array_values(array_unique(array_column($menuRows,'dishes_uuid')));if($ids)$dishRows=$q('SELECT * FROM ydy_dishes WHERE uuid IN ('.implode(',',array_fill(0,count($ids),'?')).') ORDER BY id',$ids);$staffRows=$q('SELECT * FROM ydy_staff WHERE uuid=?',[$selection['staff_uuid']]);$relations=$q('SELECT * FROM ydy_staff_department WHERE staff_uuid=? ORDER BY id',[$selection['staff_uuid']]);$departments=$q('SELECT name,uuid,puuid FROM ydy_department WHERE is_show=?',[1]);}}
$walletDepartments=$q('SELECT uuid,name FROM ydy_department ORDER BY name ASC');$ties=[];$names=[];foreach($walletDepartments as $r){$n=$r['name'];$names[$n]=($names[$n]??0)+1;}foreach($names as $n=>$count)if($count>1)$ties[]=hash('sha256',(string)$n);
$out=['schema'=>$schema,'identity'=>$identity,'actor'=>$actor,'configs'=>$configs,'oss_presence'=>$ossPresence,'batch'=>$batch,'details'=>$details,'print_selection'=>$selection,'menu_rows'=>$menuRows,'dish_rows'=>$dishRows,'staff_rows'=>$staffRows,'relations'=>$relations,'departments'=>$departments,'wallet_departments'=>$walletDepartments,'wallet_name_tie_hashes'=>$ties,'observer'=>$GLOBALS['READ7_OBSERVER'],'native'=>Read7Gate::$native,'denied'=>Read7Gate::$denied,'fresh_readonly'=>Read7Gate::$reads,'HTTP'=>0,'Auth'=>0,'DML'=>0,'DDL'=>0];$save('preflight.json',$out);echo json_encode(['lane'=>$lane,'schema_tables'=>count($schema),'batch_rows'=>count($batch),'detail_rows'=>count($details),'print_selection_nonempty'=>$selection!==null,'menus'=>count($menuRows),'dishes'=>count($dishRows),'wallet_departments'=>count($walletDepartments),'name_ties'=>count($ties),'fresh_readonly'=>Read7Gate::$reads,'DML'=>0,'HTTP'=>0]),PHP_EOL;
