95 lines
4.1 KiB
PHP
95 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use App\Services\Auth\FinanceRoster;
|
|
use Illuminate\Support\Carbon;
|
|
use Mockery;
|
|
use Modules\EcommerceFinance\Repositories\DingWorklogMirrorRepository;
|
|
use Modules\EcommerceFinance\Services\DingWorklogPenaltyCalculator;
|
|
use Tests\TestCase;
|
|
|
|
class DingWorklogPenaltyCalculatorTest extends TestCase
|
|
{
|
|
public function test_penalties_double_for_each_person_and_accumulate(): void
|
|
{
|
|
config([
|
|
'dingtalk.worklog.penalty_start_date' => '2026-10-10',
|
|
'app.timezone' => 'Asia/Shanghai',
|
|
]);
|
|
$submitted = [];
|
|
$misses = [
|
|
'jiangling' => ['2026-10-10', '2026-10-12', '2026-10-18'],
|
|
'qiuxiang' => ['2026-10-12', '2026-10-18'],
|
|
];
|
|
foreach (['jiangling' => '江陵', 'qiuxiang' => '秋香'] as $userId => $name) {
|
|
for ($day = 10; $day <= 18; $day++) {
|
|
$date = sprintf('2026-10-%02d', $day);
|
|
if (! in_array($date, $misses[$userId], true)) {
|
|
$submitted[] = [
|
|
'creator_userid' => $userId,
|
|
'creator_name' => $name,
|
|
'statistics_date' => $date,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
$repository = Mockery::mock(DingWorklogMirrorRepository::class);
|
|
$repository->shouldReceive('earliestStatisticsDate')->once()->andReturn('2026-10-01');
|
|
$repository->shouldReceive('submittedDatesByUser')
|
|
->once()->with('2026-10-10', '2026-10-18')->andReturn($submitted);
|
|
$roster = Mockery::mock(FinanceRoster::class);
|
|
$roster->shouldReceive('cachedFinanceMembers')->once()->andReturn([
|
|
['userid' => 'jiangling', 'name' => '江陵'],
|
|
['userid' => 'qiuxiang', 'name' => '秋香'],
|
|
]);
|
|
|
|
$result = (new DingWorklogPenaltyCalculator($repository, $roster))->summary(
|
|
'2026-10-10',
|
|
'2026-10-18',
|
|
Carbon::parse('2026-10-20 10:00:00', 'Asia/Shanghai'),
|
|
);
|
|
|
|
$this->assertSame('2026-10-10', $result['start_date']);
|
|
$this->assertSame('2026-10-18', $result['end_date']);
|
|
$this->assertSame('江陵', $result['members'][0]['name']);
|
|
$this->assertSame(['2026-10-10', '2026-10-12', '2026-10-18'], $result['members'][0]['missed_dates']);
|
|
$this->assertSame(3, $result['members'][0]['missed_count']);
|
|
$this->assertSame('10 + 20 + 40', $result['members'][0]['penalty_formula']);
|
|
$this->assertSame('70', $result['members'][0]['penalty_points']);
|
|
$this->assertSame('秋香', $result['members'][1]['name']);
|
|
$this->assertSame('10 + 20', $result['members'][1]['penalty_formula']);
|
|
$this->assertSame('30', $result['members'][1]['penalty_points']);
|
|
$this->assertSame('100', $result['total_points']);
|
|
$this->assertSame('100', $result['total_points_formatted']);
|
|
}
|
|
|
|
public function test_dates_before_november_fourth_are_not_charged(): void
|
|
{
|
|
config([
|
|
'dingtalk.worklog.penalty_start_date' => '2026-11-04',
|
|
'app.timezone' => 'Asia/Shanghai',
|
|
]);
|
|
$repository = Mockery::mock(DingWorklogMirrorRepository::class);
|
|
$repository->shouldReceive('earliestStatisticsDate')->once()->andReturn('2026-10-21');
|
|
$repository->shouldReceive('submittedDatesByUser')
|
|
->once()->with('2026-11-04', '2026-11-04')->andReturn([]);
|
|
$roster = Mockery::mock(FinanceRoster::class);
|
|
$roster->shouldReceive('cachedFinanceMembers')->once()->andReturn([
|
|
['userid' => 'jiangling', 'name' => '江陵'],
|
|
]);
|
|
|
|
$result = (new DingWorklogPenaltyCalculator($repository, $roster))->summary(
|
|
'2026-10-22',
|
|
'2026-11-04',
|
|
Carbon::parse('2026-11-05 13:00:00', 'Asia/Shanghai'),
|
|
);
|
|
|
|
$this->assertSame('2026-11-04', $result['start_date']);
|
|
$this->assertSame('2026-11-04', $result['end_date']);
|
|
$this->assertSame(['2026-11-04'], $result['members'][0]['missed_dates']);
|
|
$this->assertSame('10', $result['total_points']);
|
|
}
|
|
}
|