Files
zyt/server/tests/pharmacy/route_contracts.php
T
2026-07-22 14:50:34 +08:00

99 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
$routeSource = (string) file_get_contents(dirname(__DIR__, 2) . '/app/api/route/app.php');
$assertTrue(
!str_contains($routeSource, 'Controller@'),
'API routes must use controller dispatch so InitMiddleware receives controller and action names'
);
$assertTrue(
str_contains($routeSource, "'EjPharmacyCallback/webhook'"),
'ej pharmacy webhook must use ThinkPHP controller dispatch'
);
$assertTrue(
str_contains($routeSource, "'QywxExternalContactCallback/notify'"),
'QYWX callback must use ThinkPHP controller dispatch'
);
$controllerSource = (string) file_get_contents(dirname(__DIR__, 2) . '/app/adminapi/controller/tcm/PrescriptionOrderController.php');
$migrationSource = (string) file_get_contents(dirname(__DIR__, 2) . '/sql/1.9.20260721/luoyang_pharmacy_erp.sql');
$assertTrue(
str_contains($controllerSource, 'confirmGancaoSubmission'),
'admin API must expose an actionable Gancao reconciliation endpoint'
);
$assertTrue(
str_contains($migrationSource, '`lease_expires_at`'),
'pharmacy submission claims must persist an explicit lease expiry'
);
$assertTrue(
str_contains($migrationSource, 'zyt_pharmacy_submission_claim_audit'),
'manual submission reconciliation must have an append-only audit table'
);
$bootstrapItemPath = dirname(__DIR__, 2) . '/app/common/service/pharmacy/EjMedicineBootstrapItem.php';
$bootstrapServicePath = dirname(__DIR__, 2) . '/app/common/service/pharmacy/EjMedicineBootstrapService.php';
$bootstrapCommandPath = dirname(__DIR__, 2) . '/app/command/EjPharmacyBootstrapMedicines.php';
$assertTrue(is_file($bootstrapItemPath), 'ZYT must provide a dedicated EJ medicine bootstrap item normalizer');
$assertTrue(is_file($bootstrapServicePath), 'ZYT must provide an atomic EJ medicine bootstrap service');
$assertTrue(is_file($bootstrapCommandPath), 'ZYT must provide the ej-pharmacy:bootstrap-medicines command');
$clientSource = (string) file_get_contents(dirname(__DIR__, 2) . '/app/common/service/pharmacy/EjPharmacyClient.php');
$configSource = (string) file_get_contents(dirname(__DIR__, 2) . '/config/ej_pharmacy.php');
$consoleSource = (string) file_get_contents(dirname(__DIR__, 2) . '/config/console.php');
$syncServiceSource = (string) file_get_contents(dirname(__DIR__, 2) . '/app/common/service/pharmacy/EjMedicineCatalogSyncService.php');
$mappingLogicSource = (string) file_get_contents(dirname(__DIR__, 2) . '/app/adminapi/logic/pharmacy/MedicineMappingLogic.php');
$mappingPageSource = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/views/pharmacy/medicine_mapping/index.vue');
$mappingApiSource = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/api/pharmacy.ts');
$exampleEnvSource = (string) file_get_contents(dirname(__DIR__, 2) . '/.example.env');
$assertTrue(
str_contains($clientSource, 'function importMedicines(')
&& str_contains($clientSource, "'/api/openapi/v1/medicine-imports'"),
'EJ client must post structured medicine import batches through the existing HMAC transport'
);
$assertTrue(
str_contains($consoleSource, "'ej-pharmacy:bootstrap-medicines'")
&& str_contains((string) file_get_contents($bootstrapCommandPath), 'RESET_TEST_CATALOG'),
'bootstrap command must be registered and guard destructive replacement with the exact confirmation token'
);
$assertTrue(
str_contains($configSource, "'catalog_sync_enabled'")
&& str_contains($configSource, "env('EJ_PHARMACY_CATALOG_SYNC_ENABLED', false)"),
'legacy EJ catalog sync must default disabled'
);
$assertTrue(
str_contains($exampleEnvSource, 'EJ_PHARMACY_CATALOG_SYNC_ENABLED = false'),
'example environment must explicitly disable legacy catalog sync'
);
$assertTrue(
strpos($syncServiceSource, "Config::get('ej_pharmacy.catalog_sync_enabled', false)")
< strpos($syncServiceSource, 'ensureStateRow()'),
'disabled catalog sync must fail before any synchronization state write'
);
$assertTrue(
str_contains($mappingLogicSource, "'sync_enabled'")
&& str_contains($mappingApiSource, 'sync_enabled: boolean'),
'mapping status must expose the legacy sync feature gate end to end'
);
$assertTrue(
str_contains($mappingPageSource, 'v-if="status.sync_enabled"'),
'mapping page must hide the incremental sync button when legacy sync is disabled'
);
$assertTrue(
str_contains($migrationSource, 'UNIQUE KEY `uk_medicine_code` (`medicine_code`)'),
'bootstrap mapping projection must reject duplicate remote medicine codes at the database boundary'
);
$bootstrapServiceSource = (string) file_get_contents($bootstrapServicePath);
$assertTrue(
strpos($bootstrapServiceSource, "Db::name('ej_pharmacy_submission')")
< strpos($bootstrapServiceSource, "'submissions' => (int) Db::name('ej_pharmacy_submission')->count()"),
'bootstrap replacement must lock reference sources before checking the zero-reference gate'
);
$assertTrue(
str_contains($bootstrapServiceSource, "Db::name('doctor_medicine')->where('id', '>=', 0)")
&& str_contains($bootstrapServiceSource, '本地药材源快照在远端导入期间发生变化'),
'bootstrap replacement must lock and revalidate the complete local medicine source snapshot'
);