172 lines
6.7 KiB
PHP
172 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Modules\EcommerceFinance\Repositories\DingWorklogMirrorRepository;
|
|
use Tests\TestCase;
|
|
|
|
class DingWorklogMirrorRepositoryTest extends TestCase
|
|
{
|
|
private DingWorklogMirrorRepository $repository;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
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_04_230000_create_ding_worklog_reports.php'))->up();
|
|
|
|
$this->repository = app(DingWorklogMirrorRepository::class);
|
|
}
|
|
|
|
public function test_submissions_before_noon_belong_to_the_previous_statistics_day(): void
|
|
{
|
|
$this->assertSame(
|
|
'2026-11-03',
|
|
DingWorklogMirrorRepository::statisticsDate('2026-11-04 10:26:00')->toDateString(),
|
|
);
|
|
$this->assertSame(
|
|
'2026-11-04',
|
|
DingWorklogMirrorRepository::statisticsDate('2026-11-05 11:59:59')->toDateString(),
|
|
);
|
|
$this->assertSame(
|
|
'2026-11-03',
|
|
DingWorklogMirrorRepository::statisticsDate(
|
|
Carbon::parse('2026-11-04 10:26:00', 'Asia/Shanghai')->getTimestampMs(),
|
|
)->toDateString(),
|
|
);
|
|
}
|
|
|
|
public function test_noon_is_the_cutoff_for_the_next_statistics_day(): void
|
|
{
|
|
$this->assertSame(
|
|
'2026-11-05',
|
|
DingWorklogMirrorRepository::statisticsDate('2026-11-05 12:00:00')->toDateString(),
|
|
);
|
|
}
|
|
|
|
public function test_daily_summary_and_details_use_the_saved_statistics_date(): void
|
|
{
|
|
Carbon::setTestNow(Carbon::parse('2026-11-05 15:00:00', 'Asia/Shanghai'));
|
|
|
|
try {
|
|
$now = now();
|
|
$this->repository->upsertReports([
|
|
[
|
|
'report_id' => 'report-a',
|
|
'template_name' => '财务日报',
|
|
'creator_userid' => 'user-a',
|
|
'creator_name' => '秋香',
|
|
'submitted_at' => '2026-11-04 10:26:00',
|
|
'statistics_date' => '2026-11-03',
|
|
'remark' => null,
|
|
'raw_payload' => '{}',
|
|
'synced_at' => $now,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
],
|
|
[
|
|
'report_id' => 'report-b',
|
|
'template_name' => '财务日报',
|
|
'creator_userid' => 'user-b',
|
|
'creator_name' => '李斯',
|
|
'submitted_at' => '2026-11-04 11:20:00',
|
|
'statistics_date' => '2026-11-03',
|
|
'remark' => null,
|
|
'raw_payload' => '{}',
|
|
'synced_at' => $now,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
],
|
|
[
|
|
'report_id' => 'report-c',
|
|
'template_name' => '财务日报',
|
|
'creator_userid' => 'user-a',
|
|
'creator_name' => '秋香',
|
|
'submitted_at' => '2026-11-05 12:00:00',
|
|
'statistics_date' => '2026-11-05',
|
|
'remark' => null,
|
|
'raw_payload' => '{}',
|
|
'synced_at' => $now,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
],
|
|
]);
|
|
$this->repository->recordSuccess(
|
|
3,
|
|
'财务日报',
|
|
Carbon::parse('2026-10-01 00:00:00', 'Asia/Shanghai'),
|
|
$now,
|
|
);
|
|
|
|
$summary = $this->repository->dailySummary('2026-11-03', '2026-11-05');
|
|
$this->assertSame([
|
|
[
|
|
'statistics_date' => '2026-11-05',
|
|
'submission_count' => 1,
|
|
'submitter_count' => 1,
|
|
'first_submitted_at' => '2026-11-05 12:00:00',
|
|
'last_submitted_at' => '2026-11-05 12:00:00',
|
|
],
|
|
[
|
|
'statistics_date' => '2026-11-03',
|
|
'submission_count' => 2,
|
|
'submitter_count' => 2,
|
|
'first_submitted_at' => '2026-11-04 10:26:00',
|
|
'last_submitted_at' => '2026-11-04 11:20:00',
|
|
],
|
|
], $summary);
|
|
|
|
$details = $this->repository->submissionsForDate('2026-11-03');
|
|
$this->assertSame(['report-b', 'report-a'], array_column($details, 'report_id'));
|
|
$this->assertSame('succeeded', $this->repository->state()['status']);
|
|
$this->assertSame(3, (int) $this->repository->state()['mirror_row_count']);
|
|
} finally {
|
|
Carbon::setTestNow();
|
|
}
|
|
}
|
|
|
|
public function test_permission_failure_is_exposed_to_the_page(): void
|
|
{
|
|
$this->repository->recordFailure('dingtalk_worklog_permission_required');
|
|
|
|
$state = $this->repository->state();
|
|
$this->assertSame('failed', $state['status']);
|
|
$this->assertSame('dingtalk_worklog_permission_required', $state['last_error_code']);
|
|
$this->assertTrue(DingWorklogMirrorRepository::isPermissionError($state['last_error_code']));
|
|
}
|
|
}
|