You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
10 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace Tests\Feature;
use App\Services\Admin\YeWu\PlanListService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Tests\TestCase;
class PlanListServiceTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->initTestData();
}
protected function tearDown(): void
{
$this->cleanupTestData();
parent::tearDown();
}
private function initTestData()
{
$this->cleanupTestData();
DB::table('s_department')->insert([
'id' => 9999,
'department_name' => '测试科室',
'department_number' => 'TEST001',
'department_status' => 1,
'is_del' => 0,
]);
DB::table('s_appointment_type')->insert([
'id' => 9999,
'name' => '测试渠道',
'jiancheng' => '测试',
'status' => 1,
'is_del' => 0,
]);
DB::table('s_period')->insert([
'id' => 9999,
'period_name' => '测试时段',
'period_begin_time' => '08:00:00',
'period_end_time' => '10:00:00',
'department_id' => 9999,
'date_type' => 1,
'period_status' => 1,
]);
DB::table('s_department_resources')->insert([
'id' => 9999,
'department_id' => 9999,
'department_resources_name' => '测试资源',
'is_del' => 0,
]);
DB::table('s_source_roster_detail')->insert([
'id' => 9999,
'department_id' => 9999,
'resources_id' => 9999,
'period_id' => 9999,
'device_id' => '1',
'date' => date('Y-m-d', strtotime('+1 day')),
'begin_time' => '08:00:00',
'end_time' => '10:00:00',
'end_reservation_time' => '23:59:59',
'patient_type' => '0,1,2,3',
'weekname' => '1',
'status' => 1,
'is_del' => 0,
]);
DB::table('s_source_roster_detail_count')->insert([
'id' => 9999,
'roster_detail_id' => 9999,
'appointment_type_id' => 9999,
'count' => 10,
'used_count' => 3,
'locked_count' => 0,
'version' => 1,
]);
}
private function cleanupTestData()
{
DB::table('s_list')->where('reg_num', 'like', 'TEST_REG_%')->delete();
DB::table('s_list_log')->where('reg_num', 'like', 'TEST_REG_%')->delete();
$tables = [
's_source_roster_detail_count',
's_source_roster_detail', 's_department_resources',
's_period', 's_appointment_type', 's_department'
];
foreach ($tables as $table) {
DB::table($table)->where('id', '>=', 9999)->delete();
}
}
private function createTestList($status = 1, $detail = 'default')
{
if ($detail === 'default') {
$detail = json_encode([['roster_detail_count_id' => 9999, 'count' => 2]]);
}
return DB::table('s_list')->insertGetId([
'list_status' => $status,
'reg_num' => 'TEST_REG_' . time() . '_' . rand(1000, 9999),
'user_name' => '测试患者',
'entrust' => '测试检查项目',
'entrust_code' => 'TEST001',
'patient_type' => 1,
'roster_id' => 9999,
'appointment_type_id' => 9999,
'appointment_use_plan_detail' => $detail,
'reservation_date' => date('Y-m-d', strtotime('+1 day')),
'reservation_time' => 9999,
'is_del' => 0,
'is_nullify' => 0,
]);
}
public function test_release_source_from_detail()
{
$countBefore = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(3, $countBefore->used_count);
$detail = json_encode([['roster_detail_count_id' => 9999, 'count' => 2]]);
$listId = $this->createTestList(1, $detail);
$service = new PlanListService();
$result = $service->releaseSourceFromDetail($listId);
$this->assertTrue($result);
$countAfter = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(1, $countAfter->used_count);
$this->assertEquals(2, $countAfter->version);
echo "\n✅ 测试1通过: releaseSourceFromDetail 精确释放号源成功\n";
echo " 释放前 used_count=3, 释放后 used_count=1, version从1变为2\n";
}
public function test_release_source_with_version_check()
{
DB::table('s_source_roster_detail_count')->where('id', 9999)->update(['version' => 5]);
$detail = json_encode([['roster_detail_count_id' => 9999, 'count' => 1]]);
$listId = $this->createTestList(1, $detail);
$service = new PlanListService();
$result = $service->releaseSourceFromDetail($listId);
$this->assertTrue($result);
$countAfter = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(6, $countAfter->version);
echo "\n✅ 测试2通过: 乐观锁version正确递增\n";
echo " 释放前 version=5, 释放后 version=6\n";
}
public function test_release_source_fallback_when_no_detail()
{
DB::table('s_source_roster_detail_count')->where('id', 9999)->update(['used_count' => 3, 'version' => 1]);
DB::table('s_list')->where('reg_num', 'like', 'TEST_REG_%')->delete();
$listId = $this->createTestList(1, null);
$mainInfo = DB::table('s_list')->where('id', $listId)->first();
$countBefore = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(3, $countBefore->used_count, '初始used_count应为3');
$service = new PlanListService();
$result = $service->releaseSourceFromDetail($listId, $mainInfo);
$this->assertTrue($result, 'releaseSourceFromDetail应返回true');
$countAfter = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(2, $countAfter->used_count, '释放后used_count应为2');
echo "\n✅ 测试3通过: 无明细时fallback降级释放成功\n";
echo " 无appointment_use_plan_detail时按roster_id+appointment_type_id释放1个名额\n";
}
public function test_release_source_multiple_channels()
{
DB::table('s_source_roster_detail_count')->insert([
'id' => 10000,
'roster_detail_id' => 9999,
'appointment_type_id' => 10000,
'count' => 5,
'used_count' => 3,
'locked_count' => 0,
'version' => 1,
]);
$detail = json_encode([
['roster_detail_count_id' => 9999, 'count' => 2],
['roster_detail_count_id' => 10000, 'count' => 1],
]);
$listId = $this->createTestList(1, $detail);
$service = new PlanListService();
$result = $service->releaseSourceFromDetail($listId);
$this->assertTrue($result);
$count1 = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$count2 = DB::table('s_source_roster_detail_count')->where('id', 10000)->first();
$this->assertEquals(1, $count1->used_count);
$this->assertEquals(2, $count2->used_count);
DB::table('s_source_roster_detail_count')->where('id', 10000)->delete();
echo "\n✅ 测试4通过: 多渠道合并号源精确释放成功\n";
echo " 渠道9999: used_count从3变为1\n";
echo " 渠道10000: used_count从3变为2\n";
}
public function test_release_source_with_insufficient_used_count()
{
DB::table('s_source_roster_detail_count')->where('id', 9999)->update(['used_count' => 1]);
$detail = json_encode([['roster_detail_count_id' => 9999, 'count' => 5]]);
$listId = $this->createTestList(1, $detail);
$service = new PlanListService();
$result = $service->releaseSourceFromDetail($listId);
$this->assertTrue($result);
$countAfter = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(0, $countAfter->used_count);
echo "\n✅ 测试5通过: 释放数量大于used_count时置零并记录警告日志\n";
echo " 尝试释放5个实际只有1个已置零并记录日志\n";
}
public function test_cancel_yu_yue_clears_detail()
{
$detail = json_encode([['roster_detail_count_id' => 9999, 'count' => 2]]);
$listId = $this->createTestList(1, $detail);
$listInfo = DB::table('s_list')->where('id', $listId)->first();
$service = new PlanListService();
$result = $service->CancelYuYue($listId, $listInfo->reg_num);
$this->assertTrue($result['status']);
$listAfter = DB::table('s_list')->where('id', $listId)->first();
$this->assertEquals(0, $listAfter->list_status);
$this->assertNull($listAfter->appointment_use_plan_detail);
$countAfter = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$this->assertEquals(1, $countAfter->used_count);
echo "\n✅ 测试6通过: CancelYuYue正确释放号源并清空明细\n";
echo " list_status变为0, appointment_use_plan_detail被清空\n";
echo " used_count从3变为1\n";
}
public function test_optimistic_lock_conflict_detection()
{
$countRecord = DB::table('s_source_roster_detail_count')->where('id', 9999)->first();
$oldVersion = $countRecord->version;
$affected = DB::table('s_source_roster_detail_count')
->where(['id' => 9999, 'version' => $oldVersion])
->update([
'used_count' => DB::raw('used_count + 1'),
'version' => DB::raw('version + 1'),
]);
$this->assertEquals(1, $affected);
$conflictAffected = DB::table('s_source_roster_detail_count')
->where(['id' => 9999, 'version' => $oldVersion])
->update([
'used_count' => DB::raw('used_count + 1'),
'version' => DB::raw('version + 1'),
]);
$this->assertEquals(0, $conflictAffected);
echo "\n✅ 测试7通过: 乐观锁冲突检测生效\n";
echo " 第一次更新成功(affected=1)\n";
echo " 第二次使用旧version更新失败(affected=0)\n";
}
}