'array', 'is_active' => 'boolean', 'is_incremental' => 'boolean', 'use_life_table' => 'boolean', 'run_in_parallel' => 'boolean', 'batch_size' => 'integer', 'truncate_before_migration' => 'boolean', 'create_indexes_after' => 'boolean', 'python_script_args' => 'array', 'last_run_at' => 'datetime', 'last_successful_migration_at' => 'datetime', 'next_run_at' => 'datetime', ]; protected static function newFactory(): MigrationScheduleFactory { return MigrationScheduleFactory::new(); } public function sourceDatabase(): BelongsTo { return $this->belongsTo(SourceDatabase::class); } public function targetDatabase(): BelongsTo { return $this->belongsTo(TargetDatabase::class); } public function migrationRuns(): HasMany { return $this->hasMany(MigrationRun::class, 'schedule_id'); } public function scheduledTables(): BelongsToMany { return $this->belongsToMany(Table::class, 'migration_schedule_tables') ->withPivot('order') ->orderByPivot('order'); } public function getNextRunAttribute(): ?string { if (!$this->is_active || !$this->cron_expression) { return null; } $cron = new \Cron\CronExpression($this->cron_expression); $nextRun = $cron->getNextRunDate(new \DateTime(), 0, true); return $nextRun->setTimezone(new \DateTimeZone($this->timezone))->format('Y-m-d H:i:s'); } }