99 lines
5.1 KiB
PHP
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'
|
|
);
|