200 lines
8.3 KiB
PHP
200 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Console;
|
|
|
|
use App\Services\Auth\FinanceRoster;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Mockery;
|
|
use Modules\EcommerceFinance\Services\DingTalkWorklogClient;
|
|
use Tests\TestCase;
|
|
|
|
class SyncDingWorklogsTest extends TestCase
|
|
{
|
|
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',
|
|
'dingtalk.worklog.enabled' => true,
|
|
'dingtalk.worklog.template_name' => '财务日报',
|
|
'dingtalk.worklog.template_names' => ['财务日报'],
|
|
'dingtalk.worklog.finance_only_templates' => ['空白日志'],
|
|
'dingtalk.worklog.lookback_days' => 35,
|
|
]);
|
|
DB::purge('business_mirror');
|
|
Cache::flush();
|
|
|
|
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();
|
|
}
|
|
|
|
public function test_command_stores_reports_under_the_correct_statistics_date(): void
|
|
{
|
|
Carbon::setTestNow(Carbon::parse('2026-11-05 13:00:00', 'Asia/Shanghai'));
|
|
|
|
try {
|
|
$client = Mockery::mock(DingTalkWorklogClient::class);
|
|
$client->shouldReceive('isConfigured')->once()->andReturnTrue();
|
|
$client->shouldReceive('listReports')->once()->andReturn([
|
|
'pages' => 1,
|
|
'reports' => [
|
|
[
|
|
'report_id' => 'before-noon',
|
|
'creator_id' => 'user-a',
|
|
'creator_name' => '秋香',
|
|
'template_name' => '财务日报',
|
|
'create_time' => '2026-11-04 10:26:00',
|
|
],
|
|
[
|
|
'report_id' => 'last-minute',
|
|
'creator_id' => 'user-b',
|
|
'creator_name' => '李斯',
|
|
'template_name' => '财务日报',
|
|
'create_time' => '2026-11-05 11:59:59',
|
|
],
|
|
[
|
|
'report_id' => 'noon',
|
|
'creator_id' => 'user-c',
|
|
'creator_name' => '晨曦',
|
|
'template_name' => '财务日报',
|
|
'create_time' => '2026-11-05 12:00:00',
|
|
],
|
|
],
|
|
]);
|
|
$this->app->instance(DingTalkWorklogClient::class, $client);
|
|
|
|
$this->artisan('business-mirror:sync-ding-worklogs')
|
|
->expectsOutputToContain('写入/更新 3 条')
|
|
->assertSuccessful();
|
|
|
|
$rows = DB::connection('business_mirror')
|
|
->table('ding_worklog_reports')
|
|
->orderBy('report_id')
|
|
->get(['report_id', 'creator_userid', 'statistics_date'])
|
|
->map(static fn (object $row): array => (array) $row)
|
|
->all();
|
|
|
|
$this->assertSame([
|
|
[
|
|
'report_id' => 'before-noon',
|
|
'creator_userid' => 'user-a',
|
|
'statistics_date' => '2026-11-03',
|
|
],
|
|
[
|
|
'report_id' => 'last-minute',
|
|
'creator_userid' => 'user-b',
|
|
'statistics_date' => '2026-11-04',
|
|
],
|
|
[
|
|
'report_id' => 'noon',
|
|
'creator_userid' => 'user-c',
|
|
'statistics_date' => '2026-11-05',
|
|
],
|
|
], $rows);
|
|
} finally {
|
|
Carbon::setTestNow();
|
|
}
|
|
}
|
|
|
|
public function test_blank_logs_are_included_only_for_finance_members(): void
|
|
{
|
|
Carbon::setTestNow(Carbon::parse('2026-11-05 13:00:00', 'Asia/Shanghai'));
|
|
config(['dingtalk.worklog.template_names' => ['财务日报', '空白日志']]);
|
|
|
|
try {
|
|
$client = Mockery::mock(DingTalkWorklogClient::class);
|
|
$client->shouldReceive('isConfigured')->once()->andReturnTrue();
|
|
$client->shouldReceive('listReports')
|
|
->once()
|
|
->withArgs(static fn ($from, $to, string $template): bool => $template === '财务日报')
|
|
->andReturn([
|
|
'pages' => 1,
|
|
'reports' => [[
|
|
'report_id' => 'finance-daily',
|
|
'creator_id' => 'user-finance-daily',
|
|
'creator_name' => '秋香',
|
|
'template_name' => '财务日报',
|
|
'create_time' => '2026-11-04 22:14:16',
|
|
]],
|
|
]);
|
|
$client->shouldReceive('listReports')
|
|
->once()
|
|
->withArgs(static fn ($from, $to, string $template): bool => $template === '空白日志')
|
|
->andReturn([
|
|
'pages' => 1,
|
|
'reports' => [
|
|
[
|
|
'report_id' => 'finance-blank-log',
|
|
'creator_id' => 'user-renshen',
|
|
'creator_name' => '人参',
|
|
'template_name' => '空白日志',
|
|
'create_time' => '2026-11-04 23:00:00',
|
|
],
|
|
[
|
|
'report_id' => 'other-department-blank-log',
|
|
'creator_id' => 'user-other',
|
|
'creator_name' => '其他人',
|
|
'template_name' => '空白日志',
|
|
'create_time' => '2026-11-04 23:10:00',
|
|
],
|
|
],
|
|
]);
|
|
$this->app->instance(DingTalkWorklogClient::class, $client);
|
|
|
|
$roster = Mockery::mock(FinanceRoster::class);
|
|
$roster->shouldReceive('findEligible')->once()->with('user-renshen')
|
|
->andReturn(['restricted' => false]);
|
|
$roster->shouldReceive('findEligible')->once()->with('user-other')
|
|
->andReturn(['restricted' => true]);
|
|
$this->app->instance(FinanceRoster::class, $roster);
|
|
|
|
$this->artisan('business-mirror:sync-ding-worklogs')
|
|
->expectsOutputToContain('写入/更新 2 条')
|
|
->assertSuccessful();
|
|
|
|
$this->assertSame(
|
|
['finance-blank-log', 'finance-daily'],
|
|
DB::connection('business_mirror')->table('ding_worklog_reports')
|
|
->orderBy('report_id')->pluck('report_id')->all(),
|
|
);
|
|
$this->assertSame(
|
|
'财务日报 / 空白日志',
|
|
DB::connection('business_mirror')->table('business_mirror_table_states')
|
|
->where('dataset_key', 'dingtalk.worklog.finance_daily_reports')
|
|
->value('source_object'),
|
|
);
|
|
} finally {
|
|
Carbon::setTestNow();
|
|
}
|
|
}
|
|
}
|