find(1); if (!$row) throw new ApiException('请先初始化平台预警策略'); return $this->present($row->toArray()); } private function present(array $row): array { return ['alert_qty'=>(int)$row['alert_qty'],'days_per_barrel'=>(int)$row['days_per_barrel'], 'urgent_qty'=>(int)$row['urgent_qty'],'revision'=>(int)$row['revision'], 'updated_at'=>$row['updated_at'],'comparison'=>'lt','accuracy_available'=>false]; } public function save(array $input, int $actor): array { foreach (['id','threshold_qty','enterprise_id','account_id'] as $key) { if (array_key_exists($key,$input)) throw new ApiException('此入口仅保存平台统一策略,不支持企业账户阈值'); } $values=[]; foreach (['alert_qty'=>[1,10000000],'days_per_barrel'=>[1,365],'urgent_qty'=>[0,9999999],'revision'=>[1,2147483646]] as $key=>[$min,$max]) { $v=$input[$key]??null; if ((!is_int($v)&&!is_string($v)) || filter_var($v,FILTER_VALIDATE_INT)===false || (int)$v<$min || (int)$v>$max) { throw new ApiException('策略参数必须为范围内整数:'.$key); } $values[$key]=(int)$v; } if ($values['urgent_qty'] >= $values['alert_qty']) throw new ApiException('紧急预警桶数必须小于补货预警桶数'); return WaterModel::transaction(function () use ($values,$actor) { $row=WaterAlertSetting::query()->lockForUpdate()->find(1); if (!$row) throw new ApiException('请先初始化平台预警策略'); if ((int)$row->revision!==$values['revision']) throw new ApiException('策略已被其他操作员修改,请重新打开后编辑'); $before=$this->present($row->toArray()); $row->fill($values+['updated_by'=>$actor,'updated_at'=>date('Y-m-d H:i:s')]); $row->revision=$values['revision']+1; $row->save(); $after=$this->present($row->toArray()); WaterLedger::query()->insert(['kind'=>'alert_policy','created_by'=>$actor,'sku_id'=>0,'enterprise_id'=>0, 'quantity'=>0,'reference'=>'platform:alerts','note'=>'平台预警:桶数'.$before['alert_qty'].'→'.$after['alert_qty'] .';每桶天数'.$before['days_per_barrel'].'→'.$after['days_per_barrel'].';紧急桶数'.$before['urgent_qty'].'→'.$after['urgent_qty'], 'created_at'=>date('Y-m-d H:i:s')]); return $after; }); } }