107 lines
4.4 KiB
PHP
107 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Console;
|
|
|
|
use App\Services\Auth\FinanceRoster;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Mockery;
|
|
use Tests\TestCase;
|
|
|
|
class ImportDingAttendanceSchedulesTest extends TestCase
|
|
{
|
|
public function test_command_imports_work_and_rest_schedule_records(): void
|
|
{
|
|
config([
|
|
'database.connections.business_mirror' => [
|
|
'driver' => 'sqlite',
|
|
'database' => ':memory:',
|
|
'prefix' => '',
|
|
],
|
|
'upstream_mirrors.connection' => 'business_mirror',
|
|
'app.timezone' => 'Asia/Shanghai',
|
|
]);
|
|
DB::purge('business_mirror');
|
|
Schema::connection('business_mirror')->create('business_mirror_table_states', function (Blueprint $table): void {
|
|
$table->string('dataset_key', 191)->primary();
|
|
$table->string('source_key', 64);
|
|
$table->string('source_object', 191);
|
|
$table->string('target_table', 64);
|
|
$table->string('status', 24)->default('pending');
|
|
$table->string('run_mode', 24)->nullable();
|
|
$table->json('cursor')->nullable();
|
|
$table->json('high_watermark')->nullable();
|
|
$table->dateTime('window_started_at')->nullable();
|
|
$table->dateTime('window_ends_at')->nullable();
|
|
$table->dateTime('initial_completed_at')->nullable();
|
|
$table->dateTime('last_attempted_at')->nullable();
|
|
$table->dateTime('last_succeeded_at')->nullable();
|
|
$table->unsignedBigInteger('last_upserted_rows')->default(0);
|
|
$table->unsignedBigInteger('mirror_row_count')->default(0);
|
|
$table->string('last_error_code', 120)->nullable();
|
|
$table->timestamps();
|
|
});
|
|
(require base_path('database/migrations/2026_11_10_120000_create_ding_attendance_schedule_records.php'))->up();
|
|
|
|
$roster = Mockery::mock(FinanceRoster::class);
|
|
$roster->shouldReceive('cachedFinanceMembers')->once()->andReturn([
|
|
['userid' => '1004216768778351', 'name' => '人参'],
|
|
]);
|
|
$this->app->instance(FinanceRoster::class, $roster);
|
|
|
|
$path = tempnam(sys_get_temp_dir(), 'ding-schedule-');
|
|
file_put_contents($path, json_encode([
|
|
'success' => true,
|
|
'result' => [
|
|
[
|
|
'id' => 'schedule-work',
|
|
'userId' => '1004216768778351',
|
|
'workDate' => 1793980800000,
|
|
'groupId' => 967215034,
|
|
'classId' => 123,
|
|
'isRest' => 'N',
|
|
'checkStatus' => 'Init',
|
|
'timeChanged' => false,
|
|
],
|
|
[
|
|
'id' => 'schedule-rest',
|
|
'userId' => '1004216768778351',
|
|
'workDate' => 1794067200000,
|
|
'groupId' => 967215034,
|
|
'isRest' => 'Y',
|
|
'checkStatus' => 'Init',
|
|
'timeChanged' => false,
|
|
],
|
|
],
|
|
], JSON_UNESCAPED_UNICODE));
|
|
|
|
try {
|
|
$this->artisan('business-mirror:import-ding-attendance-schedules', [
|
|
'--file' => $path,
|
|
'--from' => '2026-11-07',
|
|
'--to' => '2026-11-08',
|
|
])->expectsOutputToContain('1 人、2 天、2 条排班')->assertSuccessful();
|
|
|
|
$rows = DB::connection('business_mirror')
|
|
->table('ding_attendance_schedule_records')
|
|
->orderBy('work_date')
|
|
->get(['user_id', 'user_name', 'work_date', 'is_rest'])
|
|
->map(static fn (object $row): array => (array) $row)
|
|
->all();
|
|
$this->assertSame([
|
|
['user_id' => '1004216768778351', 'user_name' => '人参', 'work_date' => '2026-11-07', 'is_rest' => 'N'],
|
|
['user_id' => '1004216768778351', 'user_name' => '人参', 'work_date' => '2026-11-08', 'is_rest' => 'Y'],
|
|
], $rows);
|
|
$this->assertSame(
|
|
'succeeded',
|
|
DB::connection('business_mirror')->table('business_mirror_table_states')
|
|
->where('dataset_key', 'dingtalk.attendance.finance_schedules')
|
|
->value('status'),
|
|
);
|
|
} finally {
|
|
@unlink($path);
|
|
}
|
|
}
|
|
}
|