PricelistFileStatusEnum::class, 'processing_current_step_percentage' => 'integer', 'available_date' => 'date', 'workflow_steps' => 'array', 'file_meta' => 'array', ]; protected static function booted() { static::creating(function ($pricelistFile) { if (empty($pricelistFile->workflow_steps)) { $pricelistFile->workflow_steps = \App\Enums\PricelistWorkflowStep::defaultSteps(); } }); } public function supplier(): BelongsTo { return $this->belongsTo(Supplier::class); } public function priceList(): BelongsTo { return $this->belongsTo(PriceList::class); } public function lines(): HasMany { return $this->hasMany(PricelistFileLine::class); } /** * Egy workflow lépés aktuális státusza a `workflow_steps` tömbből * ('pending' / 'inprogress' / 'completed' / 'failed'), vagy null, ha a lépés * nem szerepel a rekordban (régi fájloknál előfordulhat). */ public function stepStatus(PricelistWorkflowStep $step): ?string { foreach ($this->workflow_steps ?? [] as $workflowStep) { if (($workflowStep['name'] ?? null) === $step->value) { return $workflowStep['status'] ?? null; } } return null; } /** * Van-e a fájlban blokkoló (hibás) sor. Ez a jóváhagyás egyik feltétele: * hibás sorral nem indítható végrehajtás. */ public function hasErrorLines(): bool { return $this->lines() ->where('status', PricelistFileLineStatusEnum::error->value) ->exists(); } /** * Jóváhagyható-e a fájl. Egyetlen igazságforrás: ezt nézi a felületi gomb * láthatósága ÉS a végrehajtási job is induláskor - a felület 5 mp-enként * pollozik, így a gomb megjelenítése és a kattintás között változhat az állapot. */ public function canBeApproved(): bool { return $this->status === PricelistFileStatusEnum::waiting_for_approval && $this->stepStatus(PricelistWorkflowStep::Validation) === 'completed' && ! $this->hasErrorLines(); } /** * Elindult-e már a végrehajtás. Ha igen, a fájl újratöltése (Edit -> a teljes * lánc újraindítása) TILOS: addigra már létrejöhettek termékek és árak, egy * nulláról induló újrafuttatás duplikálna. Helyette a Folytatás vagy a * Visszavonás akció használható. */ public function hasExecutionStarted(): bool { return ! in_array($this->stepStatus(PricelistWorkflowStep::Execution), ['pending', null], true); } /** * Soronkénti státuszok darabszáma (státusz => darab), a jóváhagyás előtti * összegző modalhoz. */ public function lineStatusCounts(): array { return $this->lines() ->selectRaw('status, COUNT(*) as total') ->groupBy('status') ->pluck('total', 'status') ->all(); } }