diff --git a/app/Console/Commands/TaskLedgerGenerateCommand.php b/app/Console/Commands/TaskLedgerGenerateCommand.php
new file mode 100644
index 0000000..8b16678
--- /dev/null
+++ b/app/Console/Commands/TaskLedgerGenerateCommand.php
@@ -0,0 +1,92 @@
+argument('date');
+
+ $this->generateTasks(
+ $date ? Carbon::parse($date) : today()
+ );
+ }
+
+ protected function generateTasks(Carbon $datetime): void
+ {
+ /** @var \App\Models\PlanLedger */
+ $planable = DB::transaction(function () use ($datetime) {
+ $date = $datetime->format('Y-m-d');
+
+ if (! is_null($planable = PlanLedger::where('date', $date)->first())) {
+ return $planable;
+ }
+
+ /** @var \App\Models\PlanLedger */
+ $planable = PlanLedger::create(['date' => $date]);
+
+ $plan = $planable->plan()->create([
+ 'name' => "{$date} 总账录入",
+ 'plan_status' => PlanStatus::Published,
+ ]);
+
+ return $planable->setRelation('plan', $plan);
+ });
+
+ Store::lazyById()->each(function (Store $store) use ($planable) {
+ DB::transaction(function () use ($store, $planable) {
+ $taskable = TaskLedger::firstOrNew([
+ 'store_id' => $store->id,
+ 'date' => $planable->date->format('Y-m-d'),
+ ]);
+
+ if ($taskable->exists) {
+ return;
+ }
+
+ $taskable->save();
+
+ $ledger = Ledger::where('store_id', $store->id)
+ ->where('date', $planable->date->format('Y-m-d'))
+ ->first();
+
+ $taskable->task()->create([
+ 'plan_id' => $planable->plan->id,
+ 'name' => '总账录入',
+ 'start_at' => $planable->date->copy()->startOfDay(),
+ 'end_at' => $planable->date->copy()->endOfDay(),
+ 'task_status' => $ledger ? TaskStatus::Success : TaskStatus::Pending,
+ 'completed_at' => $ledger?->created_at,
+ ]);
+ });
+ });
+ }
+}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index e6b9960..5c2613a 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -12,7 +12,7 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule): void
{
- // $schedule->command('inspire')->hourly();
+ $schedule->command(Commands\TaskLedgerGenerateCommand::class)->dailyAt('01:00');
}
/**
diff --git a/app/Enums/TaskStatus.php b/app/Enums/TaskStatus.php
new file mode 100644
index 0000000..79b8399
--- /dev/null
+++ b/app/Enums/TaskStatus.php
@@ -0,0 +1,39 @@
+value];
+ }
+
+ public static function options(): array
+ {
+ return [
+ self::Pending->value => '待完成',
+ self::Processing->value => '进行中',
+ self::Success->value => '已完成',
+ self::Failed->value => '未完成',
+ self::Revoked->value => '已撤销',
+ ];
+ }
+
+ public static function labelMap(): array
+ {
+ return [
+ self::Pending->value => ''.self::Pending->text().'',
+ self::Processing->value => ''.self::Processing->text().'',
+ self::Success->value => ''.self::Success->text().'',
+ self::Failed->value => ''.self::Failed->text().'',
+ self::Revoked->value => ''.self::Revoked->text().'',
+ ];
+ }
+}
diff --git a/app/Models/Task.php b/app/Models/Task.php
new file mode 100644
index 0000000..54307cd
--- /dev/null
+++ b/app/Models/Task.php
@@ -0,0 +1,40 @@
+ TaskStatus::Pending,
+ ];
+
+ protected $casts = [
+ 'start_at' => 'datetime',
+ 'end_at' => 'datetime',
+ 'task_status' => TaskStatus::class,
+ 'completed_at' => 'datetime',
+ ];
+
+ protected $fillable = [
+ 'plan_id',
+ 'taskable_type',
+ 'taskable_id',
+ 'name',
+ 'start_at',
+ 'end_at',
+ 'task_status',
+ 'completed_at',
+ ];
+
+ public function taskable(): MorphTo
+ {
+ return $this->morphTo();
+ }
+}
diff --git a/app/Models/TaskLedger.php b/app/Models/TaskLedger.php
new file mode 100644
index 0000000..d0aeaf1
--- /dev/null
+++ b/app/Models/TaskLedger.php
@@ -0,0 +1,32 @@
+ 'date',
+ ];
+
+ protected $fillable = [
+ 'store_id',
+ 'date',
+ ];
+
+ public function task(): MorphOne
+ {
+ return $this->morphOne(Task::class, 'taskable');
+ }
+
+ public function store(): BelongsTo
+ {
+ return $this->belongsTo(Store::class);
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index e3bfef3..c9fc7c3 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -45,6 +45,7 @@ class AppServiceProvider extends ServiceProvider
\App\Models\PlanPerformance::class,
\App\Models\Reimbursement::class,
\App\Models\StoreMasterCommission::class,
+ \App\Models\TaskLedger::class,
\App\Models\EmployeePromotion::class,
\App\Models\Agreement::class,
])->mapWithKeys(fn ($model) => [(new $model)->getTable() => $model])->all()
diff --git a/database/migrations/2024_04_08_223111_create_plans_table.php b/database/migrations/2024_04_08_223111_create_plans_table.php
index ac02e8a..18f17c3 100644
--- a/database/migrations/2024_04_08_223111_create_plans_table.php
+++ b/database/migrations/2024_04_08_223111_create_plans_table.php
@@ -13,10 +13,13 @@ return new class extends Migration
{
Schema::create('plans', function (Blueprint $table) {
$table->id();
+ $table->string('planable_type');
+ $table->unsignedBigInteger('planable_id');
$table->string('name')->comment('名称');
- $table->morphs('planable');
$table->tinyInteger('plan_status')->comment('状态');
$table->timestamps();
+
+ $table->unique(['planable_type', 'planable_id'], 'planable_type');
});
}
diff --git a/database/migrations/2024_04_15_075647_create_tasks_table.php b/database/migrations/2024_04_15_075647_create_tasks_table.php
new file mode 100644
index 0000000..8f552d0
--- /dev/null
+++ b/database/migrations/2024_04_15_075647_create_tasks_table.php
@@ -0,0 +1,37 @@
+id();
+ $table->string('taskable_type');
+ $table->unsignedBigInteger('taskable_id');
+ $table->foreignId('plan_id')->comment('任务计划');
+ $table->string('name')->comment('任务名称');
+ $table->dateTime('start_at')->nullable()->comment('开始时间');
+ $table->dateTime('end_at')->nullable()->comment('结束时间');
+ $table->tinyInteger('task_status')->comment('任务状态');
+ $table->dateTime('completed_at')->nullable()->comment('完成时间');
+ $table->timestamps();
+
+ $table->unique(['taskable_type', 'taskable_id'], 'taskable_type');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('tasks');
+ }
+};
diff --git a/database/migrations/2024_04_15_081617_create_task_ledgers_table.php b/database/migrations/2024_04_15_081617_create_task_ledgers_table.php
new file mode 100644
index 0000000..07b128e
--- /dev/null
+++ b/database/migrations/2024_04_15_081617_create_task_ledgers_table.php
@@ -0,0 +1,29 @@
+id();
+ $table->foreignId('store_id')->comment('门店ID');
+ $table->date('date')->comment('日期');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('task_ledgers');
+ }
+};