#feature: some update
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Services\ConfigService;
|
||||
use App\Services\DingTalkService;
|
||||
use App\Services\ErpRequestReportService;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use InvalidArgumentException;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ErpRequestReportServiceTest extends TestCase
|
||||
{
|
||||
public function test_it_defaults_to_the_previous_calendar_day(): void
|
||||
{
|
||||
CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-08-02 16:30:00', 'UTC'));
|
||||
|
||||
try {
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$connection = Mockery::mock(Connection::class);
|
||||
$query = Mockery::mock(Builder::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
$database->shouldReceive('connection')->once()->with('agentslave')->andReturn($connection);
|
||||
$connection->shouldReceive('table')->once()->with('request_records')->andReturn($query);
|
||||
$query->shouldReceive('selectRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('leftJoin')->once()->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '>=', '2026-08-02 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '<', '2026-08-03 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.request_uri', 'like', '/openapi/erp/%')->andReturnSelf();
|
||||
$query->shouldReceive('groupByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->twice()->andReturnSelf();
|
||||
$query->shouldReceive('orderByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('get')->once()->andReturn(collect());
|
||||
$dingTalkService->shouldReceive('sendTextToToken')
|
||||
->once()
|
||||
->with('report-token', "2026-08-02 ERP OpenAPI 请求统计\n无请求记录")
|
||||
->andReturnTrue();
|
||||
|
||||
$result = (new ErpRequestReportService($database, $dingTalkService, $configService))->sendReport();
|
||||
|
||||
$this->assertSame('2026-08-02', $result['date']);
|
||||
$this->assertSame('2026-08-02 00:00:00', $result['from']);
|
||||
$this->assertSame('2026-08-02 23:59:59', $result['to']);
|
||||
} finally {
|
||||
CarbonImmutable::setTestNow();
|
||||
}
|
||||
}
|
||||
|
||||
public function test_it_sends_the_previous_days_erp_requests_grouped_by_company_and_uri(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$connection = Mockery::mock(Connection::class);
|
||||
$query = Mockery::mock(Builder::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
|
||||
$database->shouldReceive('connection')->once()->with('agentslave')->andReturn($connection);
|
||||
$connection->shouldReceive('table')->once()->with('request_records')->andReturn($query);
|
||||
$query->shouldReceive('selectRaw')->once()->with("agents.name as agent_name, agents.code as agent_code, SUBSTRING_INDEX(request_records.request_uri, '?', 1) as request_uri, COUNT(*) as request_count")->andReturnSelf();
|
||||
$query->shouldReceive('leftJoin')->once()->with('agents', 'agents.id', '=', 'request_records.user_id')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '>=', '2026-08-02 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '<', '2026-08-03 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.request_uri', 'like', '/openapi/erp/%')->andReturnSelf();
|
||||
$query->shouldReceive('groupByRaw')->once()->with("agents.id, agents.name, agents.code, SUBSTRING_INDEX(request_records.request_uri, '?', 1)")->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->once()->with('agents.name')->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->once()->with('agents.code')->andReturnSelf();
|
||||
$query->shouldReceive('orderByRaw')->once()->with("SUBSTRING_INDEX(request_records.request_uri, '?', 1)")->andReturnSelf();
|
||||
$query->shouldReceive('get')->once()->andReturn(collect([
|
||||
(object) [
|
||||
'agent_name' => '广州医路精密医疗器械有限公司',
|
||||
'agent_code' => 'G201704010003',
|
||||
'request_uri' => '/openapi/erp/deliveries',
|
||||
'request_count' => 2,
|
||||
],
|
||||
(object) [
|
||||
'agent_name' => '广州医路精密医疗器械有限公司',
|
||||
'agent_code' => 'G201704010003',
|
||||
'request_uri' => '/openapi/erp/orders?access_token=secret',
|
||||
'request_count' => 3,
|
||||
],
|
||||
]));
|
||||
|
||||
$dingTalkService->shouldReceive('sendTextToToken')
|
||||
->once()
|
||||
->with('report-token', "2026-08-02 ERP OpenAPI 请求统计\n\n广州医路精密医疗器械有限公司 G201704010003\n/openapi/erp/deliveries 2次\n/openapi/erp/orders 3次")
|
||||
->andReturnTrue();
|
||||
|
||||
$result = (new ErpRequestReportService($database, $dingTalkService, $configService))
|
||||
->sendReport('2026-08-02');
|
||||
|
||||
$this->assertSame('2026-08-02', $result['date']);
|
||||
$this->assertSame(5, $result['request_count']);
|
||||
$this->assertSame(1, $result['company_count']);
|
||||
}
|
||||
|
||||
public function test_it_supports_inclusive_date_ranges(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$connection = Mockery::mock(Connection::class);
|
||||
$query = Mockery::mock(Builder::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
$database->shouldReceive('connection')->once()->with('agentslave')->andReturn($connection);
|
||||
$connection->shouldReceive('table')->once()->with('request_records')->andReturn($query);
|
||||
$query->shouldReceive('selectRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('leftJoin')->once()->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '>=', '2026-08-01 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '<', '2026-08-08 00:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.request_uri', 'like', '/openapi/erp/%')->andReturnSelf();
|
||||
$query->shouldReceive('groupByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->twice()->andReturnSelf();
|
||||
$query->shouldReceive('orderByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('get')->once()->andReturn(collect());
|
||||
$dingTalkService->shouldReceive('sendTextToToken')
|
||||
->once()
|
||||
->with('report-token', "2026-08-01 ~ 2026-08-07 ERP OpenAPI 请求统计\n无请求记录")
|
||||
->andReturnTrue();
|
||||
|
||||
$result = (new ErpRequestReportService($database, $dingTalkService, $configService))
|
||||
->sendReport(null, '2026-08-01', '2026-08-07');
|
||||
|
||||
$this->assertSame('2026-08-01 ~ 2026-08-07', $result['date']);
|
||||
$this->assertSame('2026-08-01 00:00:00', $result['from']);
|
||||
$this->assertSame('2026-08-07 23:59:59', $result['to']);
|
||||
}
|
||||
|
||||
public function test_it_supports_inclusive_datetime_ranges(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$connection = Mockery::mock(Connection::class);
|
||||
$query = Mockery::mock(Builder::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
$database->shouldReceive('connection')->once()->with('agentslave')->andReturn($connection);
|
||||
$connection->shouldReceive('table')->once()->with('request_records')->andReturn($query);
|
||||
$query->shouldReceive('selectRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('leftJoin')->once()->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '>=', '2026-08-02 08:00:00')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.created', '<', '2026-08-02 18:00:01')->andReturnSelf();
|
||||
$query->shouldReceive('where')->once()->with('request_records.request_uri', 'like', '/openapi/erp/%')->andReturnSelf();
|
||||
$query->shouldReceive('groupByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->twice()->andReturnSelf();
|
||||
$query->shouldReceive('orderByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('get')->once()->andReturn(collect());
|
||||
$dingTalkService->shouldReceive('sendTextToToken')
|
||||
->once()
|
||||
->with('report-token', "2026-08-02 08:00:00 ~ 2026-08-02 18:00:00 ERP OpenAPI 请求统计\n无请求记录")
|
||||
->andReturnTrue();
|
||||
|
||||
$result = (new ErpRequestReportService($database, $dingTalkService, $configService))
|
||||
->sendReport(null, '2026-08-02 08:00:00', '2026-08-02 18:00:00');
|
||||
|
||||
$this->assertSame('2026-08-02 08:00:00 ~ 2026-08-02 18:00:00', $result['date']);
|
||||
}
|
||||
|
||||
public function test_it_rejects_date_mixed_with_from_to(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
$database->shouldNotReceive('connection');
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('--date 不能与 --from/--to 同时使用');
|
||||
|
||||
(new ErpRequestReportService($database, $dingTalkService, $configService))
|
||||
->sendReport('2026-08-02', '2026-08-01', '2026-08-07');
|
||||
}
|
||||
|
||||
public function test_it_requires_a_configured_dingtalk_token_before_querying(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn(null);
|
||||
$database->shouldNotReceive('connection');
|
||||
$dingTalkService->shouldNotReceive('sendTextToToken');
|
||||
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('未配置 ERP 请求日报的钉钉机器人 Token');
|
||||
|
||||
(new ErpRequestReportService($database, $dingTalkService, $configService))
|
||||
->sendReport('2026-08-02');
|
||||
}
|
||||
|
||||
public function test_it_splits_large_reports_into_safe_dingtalk_messages(): void
|
||||
{
|
||||
$database = Mockery::mock(DatabaseManager::class);
|
||||
$connection = Mockery::mock(Connection::class);
|
||||
$query = Mockery::mock(Builder::class);
|
||||
$dingTalkService = Mockery::mock(DingTalkService::class);
|
||||
$configService = Mockery::mock(ConfigService::class);
|
||||
$sentMessages = [];
|
||||
|
||||
$configService->shouldReceive('get')
|
||||
->once()
|
||||
->with(ErpRequestReportService::DINGTALK_TOKEN_CONFIG_KEY)
|
||||
->andReturn('report-token');
|
||||
|
||||
$database->shouldReceive('connection')->once()->with('agentslave')->andReturn($connection);
|
||||
$connection->shouldReceive('table')->once()->with('request_records')->andReturn($query);
|
||||
$query->shouldReceive('selectRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('leftJoin')->once()->andReturnSelf();
|
||||
$query->shouldReceive('where')->times(3)->andReturnSelf();
|
||||
$query->shouldReceive('groupByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('orderBy')->twice()->andReturnSelf();
|
||||
$query->shouldReceive('orderByRaw')->once()->andReturnSelf();
|
||||
$query->shouldReceive('get')->once()->andReturn(collect(range(1, 300))->map(
|
||||
fn (int $index) => (object) [
|
||||
'agent_name' => '广州医路精密医疗器械有限公司',
|
||||
'agent_code' => 'G201704010003',
|
||||
'request_uri' => '/openapi/erp/'.str_pad((string) $index, 100, 'x'),
|
||||
'request_count' => 1,
|
||||
]
|
||||
));
|
||||
$dingTalkService->shouldReceive('sendTextToToken')
|
||||
->atLeast()->once()
|
||||
->withArgs(function (string $token, string $message) use (&$sentMessages): bool {
|
||||
$sentMessages[] = $message;
|
||||
|
||||
return $token === 'report-token';
|
||||
})
|
||||
->andReturnTrue();
|
||||
|
||||
(new ErpRequestReportService($database, $dingTalkService, $configService))->sendReport('2026-08-02');
|
||||
|
||||
$this->assertGreaterThan(1, count($sentMessages));
|
||||
$this->assertContainsOnly('string', $sentMessages);
|
||||
$this->assertTrue(collect($sentMessages)->every(fn (string $message) => strlen($message) <= 18_000));
|
||||
$this->assertStringContainsString('/openapi/erp/'.str_pad('300', 100, 'x').' 1次', implode("\n", $sentMessages));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user