diff --git a/app/Command/getProductCommand.php b/app/Command/getProductCommand.php index 9d61b2b..53b57f1 100644 --- a/app/Command/getProductCommand.php +++ b/app/Command/getProductCommand.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Command; +use App\Model\Pharmacy; use App\Model\Product; use App\Model\ProductPlatform; use App\Utils\Log; @@ -21,6 +22,18 @@ use Symfony\Component\Console\Input\InputArgument; #[Command] class getProductCommand extends HyperfCommand { + protected array $active_pharmacies = []; + + protected function getPharmacy(string $code) + { + if (empty($this->active_pharmacies)) { + $list = Pharmacy::where('status', 1)->get(); + foreach ($list as $p) { + $this->active_pharmacies[$p->pharmacy_code] = $p; + } + } + return $this->active_pharmacies[$code] ?? null; + } public function __construct(protected ContainerInterface $container) { parent::__construct('getProduct:command'); @@ -32,48 +45,109 @@ class getProductCommand extends HyperfCommand $this->setDescription('获取处方平台商品数据'); } + protected function logInfo(string $message): void + { + $this->line(date('Y-m-d H:i:s') . ' [INFO] ' . $message); + Log::getInstance('getProductCommand')->info($message); + } + + protected function logWarn(string $message): void + { + $this->warn(date('Y-m-d H:i:s') . ' [WARN] ' . $message); + Log::getInstance('getProductCommand')->warning($message); + } + + protected function logError(string $message): void + { + $this->error(date('Y-m-d H:i:s') . ' [ERROR] ' . $message); + Log::getInstance('getProductCommand')->error($message); + } + // 主逻辑处理 public function handle() { - $this->line("商品更新开始"); + $startTime = microtime(true); + $this->logInfo("================== [getProductCommand] 处方平台商品目录同步开始 =================="); + + $stats = [ + 'total_received' => 0, + 'created' => 0, + 'updated' => 0, + 'unchanged' => 0, + 'skipped_invalid' => 0, + 'skipped_pharmacy' => 0, + 'failed' => 0, + ]; try { - $prescription = new Prescription(); + // 预加载已启用的药房列表 + if (empty($this->active_pharmacies)) { + $list = Pharmacy::where('status', 1)->get(); + foreach ($list as $p) { + $this->active_pharmacies[$p->pharmacy_code] = $p; + } + } + if (empty($this->active_pharmacies)) { + $this->logError("未找到任何已启用的药房配置,请先在药房管理中添加并启用药房后再执行同步"); + return; + } + + $pharmacyListStr = implode(', ', array_map(function ($p) { + return "{$p->pharmacy_name}({$p->pharmacy_code})"; + }, array_values($this->active_pharmacies))); + $this->logInfo("当前系统已启用药房 (" . count($this->active_pharmacies) . " 个): [{$pharmacyListStr}]"); + + $prescription = new Prescription(); $page = 1; $page_size = 100; - $result = $prescription->getProd(1, 100); - if (!empty($result['rows'])) { - foreach ($result['rows'] as $item) { - // 执行入库 - $this->handleData($item); - } - $count = ceil($result['count'] / ($page * $page_size)); + $this->logInfo("正在请求第 1 页商品目录数据 (pageSize={$page_size})..."); + $result = $prescription->getProd(1, $page_size); - if ($result['count'] > $page * $page_size) { - for ($i = 2; $i < $count; $i++) { - try { - $result = $prescription->getProd($i, $page_size); - if (!isset($result['rows'])) { - continue; - } + if (empty($result) || !isset($result['rows'])) { + $this->logWarn("处方平台未返回有效的商品目录数据,任务结束"); + return; + } - foreach ($result['rows'] as $item) { - // 执行入库 - $this->handleData($item); - } - } catch (\Exception $e) { - $this->line("部分商品更新失败:" . $e->getMessage()); + $totalCount = (int)($result['count'] ?? count($result['rows'])); + $totalPages = (int)ceil($totalCount / $page_size); + $this->logInfo("处方平台商品目录查询成功: 平台总数据量={$totalCount} 条,总页数={$totalPages} 页"); + + // 处理第 1 页 + $this->logInfo(">>> 正在处理第 1/{$totalPages} 页数据 (当前页 " . count($result['rows']) . " 条)..."); + foreach ($result['rows'] as $item) { + $stats['total_received']++; + $this->handleData($item, $stats); + } + + // 处理后续页 + if ($totalPages > 1) { + for ($i = 2; $i <= $totalPages; $i++) { + $this->logInfo(">>> 正在请求并处理第 {$i}/{$totalPages} 页数据..."); + try { + $pageResult = $prescription->getProd($i, $page_size); + if (!isset($pageResult['rows']) || empty($pageResult['rows'])) { + $this->logWarn("第 {$i} 页返回空数据,跳过"); + continue; } + + foreach ($pageResult['rows'] as $item) { + $stats['total_received']++; + $this->handleData($item, $stats); + } + } catch (\Throwable $e) { + $this->logError("第 {$i} 页商品同步失败: " . $e->getMessage()); } } } - } catch (\Exception $e) { - $this->line("商品更新失败:" . $e->getMessage()); + } catch (\Throwable $e) { + $this->logError("商品同步全局异常: " . $e->getMessage()); } - $this->line("商品更新成功"); + $duration = round(microtime(true) - $startTime, 2); + $this->logInfo("================== [getProductCommand] 处方平台商品目录同步完成 =================="); + $this->logInfo("总耗时: {$duration}s | 平台接收: {$stats['total_received']} 条 | 新增入库: {$stats['created']} 条 | 变更更新: {$stats['updated']} 条 | 资料无变动: {$stats['unchanged']} 条 | 非本院药房忽略: {$stats['skipped_pharmacy']} 条 | 字段缺失跳过: {$stats['skipped_invalid']} 条 | 处理失败: {$stats['failed']} 条"); } /** @@ -90,41 +164,25 @@ class getProductCommand extends HyperfCommand /** * 入库 * @param array $item + * @param array $stats * @return bool */ - protected function handleData(array $item): bool + protected function handleData(array $item, array &$stats): bool { - if (empty($item['drugCode'])) { - return false; - } - - if (empty($item['drugPrice'])) { - return false; - } - - if (empty($item['thirdCode'])) { - return false; - } - - if (empty($item['thirdDrugCode'])) { - return false; - } - - if (empty($item['approvalNumber'])) { + if (empty($item['drugCode']) || empty($item['drugPrice']) || empty($item['thirdCode']) || empty($item['thirdDrugCode']) || empty($item['approvalNumber'])) { + $drugName = $item['tradeName'] ?? '未知名'; + $this->logWarn("【跳过-字段缺失】药品 [{$drugName}] 缺少必要字段(drugCode/drugPrice/thirdCode/thirdDrugCode/approvalNumber)"); + $stats['skipped_invalid']++; return false; } try { Db::beginTransaction(); - $pharmacy_code = \Hyperf\Config\config("prescription_platform.pharmacy_code"); - if (empty($pharmacy_code)) { - $pharmacy_code = "JG-10009"; - } - - // 非药店编码 - if ($pharmacy_code != $item['thirdCode']) { + $pharmacy = $this->getPharmacy($item['thirdCode']); + if (empty($pharmacy)) { Db::rollBack(); + $stats['skipped_pharmacy']++; return false; } @@ -133,6 +191,7 @@ class getProductCommand extends HyperfCommand $params['product_platform_code'] = $item['drugCode']; $params['product_pharmacy_code'] = $item['thirdDrugCode']; $params['license_number'] = $item['approvalNumber']; + $params['pharmacy_code'] = $item['thirdCode']; $product_platform = ProductPlatform::getOne($params); if (!empty($product_platform)) { // 已存在,更新 @@ -189,7 +248,7 @@ class getProductCommand extends HyperfCommand if (isset($item['packingUnit'])) { if ($product_platform['retail_unit'] != $item['packingUnit']) { $product_platform_data['retail_unit'] = $item['packingUnit']; - $product_data['packaging_unit'] = $item['packingUnit']; // 平台返回零售包装单位为:盒,此结果适用于商品表的基本包装单位 + $product_data['packaging_unit'] = $item['packingUnit']; } } @@ -214,6 +273,10 @@ class getProductCommand extends HyperfCommand } } + $product_platform_data['pharmacy_code'] = $item['thirdCode']; + $product_data['pharmacy_code'] = $item['thirdCode']; + $product_data['pharmacy_id'] = (string)$pharmacy->pharmacy_id; + if (!empty($product_platform_data)) { // 更新商品表-处方平台 $params = array(); @@ -232,19 +295,20 @@ class getProductCommand extends HyperfCommand Product::edit($params, $product_data); } } + $this->logInfo("【更新药品】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] (ID: {$product_platform['product_platform_id']}, 价格: {$item['drugPrice']})"); + $stats['updated']++; + } else { + $stats['unchanged']++; } } else { // 不存在,创建 $data = array(); - // 商品名称 + $data['pharmacy_code'] = $item['thirdCode']; if (isset($item['tradeName'])) { $data['product_name'] = $item['tradeName']; } - - // 商品价格 $data['product_price'] = $item['drugPrice']; - // 药品类型 if (isset($item['drugClassCode'])) { if ($item['drugClassCode'] == 1) { $data['product_type'] = 1; @@ -255,41 +319,25 @@ class getProductCommand extends HyperfCommand } } - // 处方平台商品编码 $data['product_platform_code'] = $item['drugCode']; - - // 第三方药店商品编码 $data['product_pharmacy_code'] = $item['thirdDrugCode']; - // 商品规格 if (isset($item['specifications'])) { $data['product_spec'] = $item['specifications']; } - - // 批准文号 $data['license_number'] = $item['approvalNumber']; - - // 生产厂家 if (isset($item['manufacturer'])) { $data['manufacturer'] = $item['manufacturer']; } - - // 单次剂量单位 if (isset($item['defaultSingleDosageUnit'])) { $data['single_unit'] = $item['defaultSingleDosageUnit']; } - - // 基本包装单位 if (isset($item['basicPackingUnit'])) { $data['packaging_unit'] = $item['basicPackingUnit']; } - - // 基本包装数量 if (isset($item['basicPackingCount'])) { $data['packaging_count'] = $item['basicPackingCount']; } - - // 零售包装单位 if (isset($item['packingUnit'])) { $data['retail_unit'] = $item['packingUnit']; } @@ -297,14 +345,20 @@ class getProductCommand extends HyperfCommand $product_platform = ProductPlatform::addProductPlatform($data); if (empty($product_platform)) { Db::rollBack(); - $this->line("商品更新失败:" . json_encode($data, JSON_UNESCAPED_UNICODE)); + $this->logError("【新增失败】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] 写入数据库失败"); + $stats['failed']++; + return false; } + $this->logInfo("【新增入库】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] (平台编码: {$item['drugCode']}, 批准文号: {$item['approvalNumber']}, 价格: {$item['drugPrice']})"); + $stats['created']++; } Db::commit(); - } catch (\Exception $e) { + } catch (\Throwable $e) { Db::rollBack(); - $this->line("商品更新失败:" . $e->getMessage()); + $drugName = $item['tradeName'] ?? '未知名'; + $this->logError("【更新异常】药品 [{$drugName}] (thirdDrugCode: {$item['thirdDrugCode']}) 异常: " . $e->getMessage()); + $stats['failed']++; return false; } diff --git a/app/Command/getProductStockCommand.php b/app/Command/getProductStockCommand.php index 356bd37..2f48bbb 100644 --- a/app/Command/getProductStockCommand.php +++ b/app/Command/getProductStockCommand.php @@ -7,6 +7,7 @@ namespace App\Command; use App\Model\Product; use App\Model\ProductAmountRecord; use App\Model\ProductPlatformAmount; +use App\Utils\Log; use Extend\Prescription\Prescription; use Hyperf\Command\Command as HyperfCommand; use Hyperf\Command\Annotation\Command; @@ -30,124 +31,188 @@ class getProductStockCommand extends HyperfCommand $this->setDescription('获取处方平台商品库存数据'); } + protected function logInfo(string $message): void + { + $this->line(date('Y-m-d H:i:s') . ' [INFO] ' . $message); + Log::getInstance('getProductStockCommand')->info($message); + } + + protected function logWarn(string $message): void + { + $this->warn(date('Y-m-d H:i:s') . ' [WARN] ' . $message); + Log::getInstance('getProductStockCommand')->warning($message); + } + + protected function logError(string $message): void + { + $this->error(date('Y-m-d H:i:s') . ' [ERROR] ' . $message); + Log::getInstance('getProductStockCommand')->error($message); + } + public function handle() { - $this->line("商品库存更新开始"); + $startTime = microtime(true); + $this->logInfo("================== [getProductStockCommand] 商品库存更新开始 =================="); + + $stats = [ + 'total' => 0, + 'success' => 0, + 'stock_changed' => 0, + 'stock_unchanged' => 0, + 'skipped' => 0, + 'failed' => 0, + ]; try { - // 获取商品 + $pageSize = 20; $params = array(); $params['product_status'] = 1; - $product = Product::getPage($params,['*'],1,10); - if (empty($product['data'])){ - $this->line("商品库存更新成功,无可更新库存商品"); + $product = Product::getPage($params, ['*'], 1, $pageSize); + if (empty($product['data'])) { + $this->logInfo("当前无可更新库存的在架商品,任务结束"); return; } + $totalCount = (int)($product['total'] ?? count($product['data'])); + $lastPage = (int)($product['last_page'] ?? 1); + $this->logInfo("在架商品总数: {$totalCount} 件,共 {$lastPage} 页,每页批次: {$pageSize} 件"); + $prescription = new Prescription(); - foreach ($product['data'] as $item){ - if (!empty($item['product_pharmacy_code'])){ - $result = $prescription->getProdStock($item['product_pharmacy_code']); - $this->handleData($item['product_platform_id'],$item['product_platform_code'],$result[0]); + for ($page = 1; $page <= $lastPage; $page++) { + if ($page > 1) { + $product = Product::getPage($params, ['*'], $page, $pageSize); + if (empty($product['data'])) { + break; + } } - } - if ($product['last_page'] > 1){ - for ($i = 2; $i <= $product['last_page']; $i++) { - // 获取商品 - $params = array(); - $product = Product::getPage($params,['*'],$i,10); - if (empty($product['data'])){ - $this->line("商品库存更新成功,无可更新库存商品"); - return; + $this->logInfo(">>> 正在处理第 {$page}/{$lastPage} 页商品库存 (当前页 " . count($product['data']) . " 件)..."); + + foreach ($product['data'] as $item) { + $stats['total']++; + + if (empty($item['product_pharmacy_code'])) { + $this->logWarn("【跳过】商品 [{$item['product_name']}] (ID: {$item['product_id']}) 未配置第三方药品编码(product_pharmacy_code)"); + $stats['skipped']++; + continue; } - $prescription = new Prescription(); - - foreach ($product['data'] as $item){ - if (!empty($item['product_pharmacy_code'])){ - $result = $prescription->getProdStock($item['product_pharmacy_code']); - $this->handleData($item['product_platform_id'],$item['product_platform_code'],$result[0]); + $pharmacy_code = $item['pharmacy_code'] ?? ''; + try { + $result = $prescription->getProdStock($item['product_pharmacy_code'], $pharmacy_code); + if (empty($result) || !isset($result[0])) { + $this->logWarn("【库存响应空】商品 [{$item['product_name']}] 药房 [{$pharmacy_code}] 平台未返回库存数据"); + $stats['failed']++; + continue; } + + $res = $this->handleData($item, $result[0], $stats); + if ($res) { + $stats['success']++; + } else { + $stats['failed']++; + } + } catch (\Throwable $e) { + $this->logError("【查询库存失败】商品 [{$item['product_name']}] (药店编码: {$item['product_pharmacy_code']}, 药房: {$pharmacy_code}) 异常: " . $e->getMessage()); + $stats['failed']++; } } } - } catch (\Exception $e) { - $this->line("商品库存更新失败:" . $e->getMessage()); + } catch (\Throwable $e) { + $this->logError("商品库存更新全局异常:" . $e->getMessage()); } - $this->line("商品库存更新成功"); + $duration = round(microtime(true) - $startTime, 2); + $this->logInfo("================== [getProductStockCommand] 商品库存更新完成 =================="); + $this->logInfo("总耗时: {$duration}s | 检查总数: {$stats['total']} | 成功: {$stats['success']} (变动: {$stats['stock_changed']}, 未变: {$stats['stock_unchanged']}) | 跳过: {$stats['skipped']} | 失败: {$stats['failed']}"); } /** * 入库 - * @param string $product_platform_id - * @param string $product_platform_code + * @param Product|array $item * @param array $resultData + * @param array $stats * @return bool */ - public function handleData(string $product_platform_id,string $product_platform_code,array $resultData): bool + public function handleData(Product|array $item, array $resultData, array &$stats = []): bool { - if (empty($resultData['quantity'])){ - $resultData['quantity'] = 0; - } + $quantity = (int)($resultData['quantity'] ?? 0); + $product_platform_id = (string)$item['product_platform_id']; + $product_platform_code = (string)$item['product_platform_code']; + $product_name = (string)($item['product_name'] ?? ''); + $pharmacy_code = (string)($item['pharmacy_code'] ?? ''); + try { Db::beginTransaction(); - // 当前库存数量 - $stock = 0; - $params = array(); $params['product_platform_id'] = $product_platform_id; $params['product_platform_code'] = $product_platform_code; $product_platform_amount = ProductPlatformAmount::getSharedLockOne($params); - if (empty($product_platform_amount)){ + + $old_stock = 0; + if (empty($product_platform_amount)) { // 无库存数据,新增 $data = array(); $data['product_platform_id'] = $product_platform_id; $data['product_platform_code'] = $product_platform_code; - $data['stock'] = $resultData['quantity']; + $data['stock'] = $quantity; $product_platform_amount = ProductPlatformAmount::addProductPlatformAmount($data); - if (empty($product_platform_amount)){ + if (empty($product_platform_amount)) { Db::rollBack(); - $this->line("商品库存更新失败,无法新增库存数据" . json_encode($data, JSON_UNESCAPED_UNICODE)); + $this->logError("商品 [{$product_name}] 新增库存数据失败: " . json_encode($data, JSON_UNESCAPED_UNICODE)); + return false; } - }else{ - $stock = $product_platform_amount['stock']; + $this->logInfo("【初始化库存】商品 [{$product_name}] 药房 [{$pharmacy_code}] 初始库存: {$quantity}"); + $stats['stock_changed']++; + } else { + $old_stock = (int)$product_platform_amount['stock']; // 存在库存数据,修改 $data = array(); - $data['stock'] = $resultData['quantity']; + $data['stock'] = $quantity; $params = array(); $params['amount_id'] = $product_platform_amount['amount_id']; - ProductPlatformAmount::edit($params,$data); + ProductPlatformAmount::edit($params, $data); + + if ($old_stock !== $quantity) { + $diff = $quantity - $old_stock; + $diffStr = ($diff > 0 ? "+{$diff}" : "{$diff}"); + $this->logInfo("【库存变动】商品 [{$product_name}] 药房 [{$pharmacy_code}] 原库存: {$old_stock} -> 最新库存: {$quantity} (变动: {$diffStr})"); + $stats['stock_changed']++; + } else { + $this->logInfo("【库存无变化】商品 [{$product_name}] 药房 [{$pharmacy_code}] 当前库存: {$quantity}"); + $stats['stock_unchanged']++; + } } - // 获取商品数据 - $params = array(); - $params['product_platform_id'] = $product_platform_id; - $product = Product::getOne($params); - if (!empty($product)){ - // 增加库存记录 - $data = array(); - $data['product_id'] = $product['product_id']; - $data['change_quantity'] = $resultData['quantity'] - $stock; // 库存变动的数量 变动的库存-原库存 - $data['quantity'] = $resultData['quantity']; // 变动后库存数量 - $data['change_time'] = date('Y-m-d H:i:s',time()); - $data['remark'] = "库存同步"; - $product_amount_record = ProductAmountRecord::addProductAmountRecord($data); - if (empty($product_amount_record)){ - Db::rollBack(); - $this->line("商品库存更新失败,增加库存记录失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + // 增加库存记录(仅在库存发生变动或首次初始化时记录) + if ($old_stock !== $quantity || empty($product_platform_amount)) { + $params = array(); + $params['product_platform_id'] = $product_platform_id; + $product = Product::getOne($params); + if (!empty($product)) { + $data = array(); + $data['product_id'] = $product['product_id']; + $data['change_quantity'] = $quantity - $old_stock; + $data['quantity'] = $quantity; + $data['change_time'] = date('Y-m-d H:i:s', time()); + $data['remark'] = "处方平台库存定时同步"; + $product_amount_record = ProductAmountRecord::addProductAmountRecord($data); + if (empty($product_amount_record)) { + Db::rollBack(); + $this->logError("商品 [{$product_name}] 增加库存流水记录失败: " . json_encode($data, JSON_UNESCAPED_UNICODE)); + return false; + } } } Db::commit(); } catch (\Throwable $e) { Db::rollBack(); - $this->line("商品库存更新失败:" . $e->getMessage()); + $this->logError("商品 [{$product_name}] 更新库存事务异常: " . $e->getMessage()); return false; } diff --git a/app/Controller/DoctorPharmacyController.php b/app/Controller/DoctorPharmacyController.php new file mode 100644 index 0000000..c6ba813 --- /dev/null +++ b/app/Controller/DoctorPharmacyController.php @@ -0,0 +1,45 @@ +getDoctorPharmacyList(); + return $this->response->json($data); + } + + /** + * 设置医生默认药房 + */ + public function setDoctorDefaultPharmacy(): ResponseInterface + { + $request = $this->container->get(DoctorPharmacyRequest::class); + $request->scene('setDefault')->validateResolved(); + + $service = new DoctorPharmacyService(); + $data = $service->setDoctorDefaultPharmacy(); + return $this->response->json($data); + } + + /** + * 获取平台公开正常运营的药房列表 + */ + public function getPublicPharmacyList(): ResponseInterface + { + $service = new DoctorPharmacyService(); + $data = $service->getPublicPharmacyList(); + return $this->response->json($data); + } +} diff --git a/app/Model/DoctorPharmacy.php b/app/Model/DoctorPharmacy.php new file mode 100644 index 0000000..2e29916 --- /dev/null +++ b/app/Model/DoctorPharmacy.php @@ -0,0 +1,132 @@ + 'string', + 'doctor_id' => 'string', + 'pharmacy_id' => 'string', + 'is_default' => 'integer', + 'status' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + + /** + * 关联药房信息表 + */ + public function Pharmacy(): HasOne + { + return $this->hasOne(Pharmacy::class, 'pharmacy_id', 'pharmacy_id'); + } + + /** + * 关联医生表 + */ + public function UserDoctor(): HasOne + { + return $this->hasOne(UserDoctor::class, 'doctor_id', 'doctor_id'); + } + + /** + * 获取医生当前绑定的有效默认药房(包含药房有效性及 pharmacy_code 非空校验) + */ + public static function getDoctorDefaultPharmacy(int|string $doctorId): ?Pharmacy + { + $bind = self::where([ + 'doctor_id' => (string) $doctorId, + 'is_default' => 1, + 'status' => 1, + ])->first(); + + if (empty($bind)) { + return null; + } + + $pharmacy = Pharmacy::getValidPharmacy($bind->pharmacy_id); + if (empty($pharmacy) || empty($pharmacy->pharmacy_code)) { + return null; + } + + return $pharmacy; + } + + /** + * 获取单条数据 + */ + public static function getOne(array $params, array $fields = ['*']): ?self + { + return self::where($params)->first($fields); + } + + /** + * 获取列表数据 + */ + public static function getList(array $params = [], array $fields = ['*']): Collection + { + return self::where($params)->get($fields); + } + + /** + * 新增绑定 + */ + public static function addDoctorPharmacy(array $data): self + { + return self::create($data); + } + + /** + * 修改 + */ + public static function edit(array $params, array $data): int + { + return self::where($params)->update($data); + } +} diff --git a/app/Model/OrderPrescription.php b/app/Model/OrderPrescription.php index 3c33adf..0303a6a 100644 --- a/app/Model/OrderPrescription.php +++ b/app/Model/OrderPrescription.php @@ -36,12 +36,16 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property string $patient_name 患者姓名-就诊人 * @property int $patient_sex 患者性别-就诊人(1:男 2:女) * @property int $patient_age 患者年龄-就诊人 + * @property int|string $pharmacy_id 开方药房id + * @property string $pharmacy_code 开方药房代码快照 + * @property string $pharmacy_name 开方药房名称快照 * @property string $doctor_advice 医嘱 * @property \Carbon\Carbon $created_at 创建时间 * @property \Carbon\Carbon $updated_at 修改时间 * @property-read \Hyperf\Database\Model\Collection|OrderPrescriptionIcd[] $OrderPrescriptionIcd * @property-read \Hyperf\Database\Model\Collection|OrderPrescriptionProduct[] $OrderPrescriptionProduct * @property-read UserDoctor $UserDoctor + * @property-read Pharmacy|null $Pharmacy */ class OrderPrescription extends Model { @@ -55,10 +59,22 @@ class OrderPrescription extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['order_prescription_id', 'order_inquiry_id', 'doctor_id', 'patient_id', 'family_id', 'pharmacist_id', 'prescription_status', 'pharmacist_audit_status', 'pharmacist_verify_time', 'pharmacist_fail_reason', 'platform_audit_status', 'platform_fail_time', 'platform_fail_reason', 'is_auto_phar_verify', 'doctor_created_time', 'expired_time', 'is_delete', 'prescription_code', 'doctor_name', 'patient_name', 'patient_sex', 'patient_age', 'doctor_advice', 'created_at', 'updated_at']; + protected array $fillable = ['order_prescription_id', 'order_inquiry_id', 'doctor_id', 'pharmacy_id', 'pharmacy_code', 'pharmacy_name', 'patient_id', 'family_id', 'pharmacist_id', 'prescription_status', 'pharmacist_audit_status', 'pharmacist_verify_time', 'pharmacist_fail_reason', 'platform_audit_status', 'platform_fail_time', 'platform_fail_reason', 'is_auto_phar_verify', 'doctor_created_time', 'expired_time', 'is_delete', 'prescription_code', 'doctor_name', 'patient_name', 'patient_sex', 'patient_age', 'doctor_advice', 'created_at', 'updated_at']; + + protected array $casts = [ + 'pharmacy_id' => 'string', + ]; protected string $primaryKey = "order_prescription_id"; + /** + * 关联药房表 + */ + public function Pharmacy(): HasOne + { + return $this->hasOne(Pharmacy::class, 'pharmacy_id', 'pharmacy_id'); + } + /** * 关联处方疾病表 */ diff --git a/app/Model/OrderProduct.php b/app/Model/OrderProduct.php index 56e31e9..4c75ab4 100644 --- a/app/Model/OrderProduct.php +++ b/app/Model/OrderProduct.php @@ -55,12 +55,17 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property string $consignee_name_mask 收货人姓名(掩码) * @property string $consignee_tel 收货人电话 * @property string $consignee_tel_mask 收货人电话(掩码) + * @property int|string $pharmacy_id 发货药房id + * @property string $pharmacy_code 发货药房代码快照 + * @property string $pharmacy_name 发货药房名称快照 + * @property int $delivery_type 配送方式(1:自提 2:快递) * @property Carbon $created_at 创建时间 * @property Carbon $updated_at 修改时间 * @property-read Collection|OrderProductItem[]|null $OrderProductItem * @property-read OrderPrescription|null $OrderPrescription * @property-read PatientFamily|null $PatientFamily * @property-read Collection|OrderPrescriptionIcd[]|null $OrderPrescriptionIcd + * @property-read Pharmacy|null $Pharmacy */ class OrderProduct extends Model { @@ -74,10 +79,23 @@ class OrderProduct extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['order_product_id', 'order_inquiry_id', 'order_prescription_id', 'order_id', 'doctor_id', 'patient_id', 'family_id', 'order_product_no', 'escrow_trade_no', 'order_product_status', 'pay_channel', 'pay_status', 'is_delete', 'cancel_reason', 'amount_total', 'coupon_amount_total', 'payment_amount_total', 'logistics_fee', 'logistics_no', 'logistics_company_code', 'sub_logistics_status', 'delivery_time', 'pay_time', 'remarks', 'refund_status', 'cancel_time', 'cancel_remarks', 'report_pre_status', 'report_pre_time', 'report_pre_fail_reason', 'province_id', 'province', 'city_id', 'city', 'county_id', 'county', 'address', 'address_mask', 'consignee_name', 'consignee_name_mask', 'consignee_tel', 'consignee_tel_mask', 'created_at', 'updated_at']; + protected array $fillable = ['order_product_id', 'order_inquiry_id', 'order_prescription_id', 'order_id', 'doctor_id', 'pharmacy_id', 'pharmacy_code', 'pharmacy_name', 'delivery_type', 'patient_id', 'family_id', 'order_product_no', 'escrow_trade_no', 'order_product_status', 'pay_channel', 'pay_status', 'is_delete', 'cancel_reason', 'amount_total', 'coupon_amount_total', 'payment_amount_total', 'logistics_fee', 'logistics_no', 'logistics_company_code', 'sub_logistics_status', 'delivery_time', 'pay_time', 'remarks', 'refund_status', 'cancel_time', 'cancel_remarks', 'report_pre_status', 'report_pre_time', 'report_pre_fail_reason', 'province_id', 'province', 'city_id', 'city', 'county_id', 'county', 'address', 'address_mask', 'consignee_name', 'consignee_name_mask', 'consignee_tel', 'consignee_tel_mask', 'created_at', 'updated_at']; + + protected array $casts = [ + 'pharmacy_id' => 'string', + 'delivery_type' => 'integer', + ]; protected string $primaryKey = "order_product_id"; + /** + * 关联药房表 + */ + public function Pharmacy(): HasOne + { + return $this->hasOne(Pharmacy::class, 'pharmacy_id', 'pharmacy_id'); + } + /** * 关联订单商品item表 */ diff --git a/app/Model/Pharmacy.php b/app/Model/Pharmacy.php new file mode 100644 index 0000000..cf95664 --- /dev/null +++ b/app/Model/Pharmacy.php @@ -0,0 +1,133 @@ + 'string', + 'postage' => 'string', + 'free_shipping_threshold' => 'string', + 'is_pickup' => 'integer', + 'province_id' => 'integer', + 'city_id' => 'integer', + 'county_id' => 'integer', + 'status' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + + /** + * 关联医生药房绑定表 + */ + public function DoctorPharmacy(): HasMany + { + return $this->hasMany(DoctorPharmacy::class, 'pharmacy_id', 'pharmacy_id'); + } + + /** + * 获取单条有效药房数据 + */ + public static function getValidPharmacy(int|string $pharmacyId): ?self + { + return self::where([ + 'pharmacy_id' => (string) $pharmacyId, + 'status' => 1, + ])->first(); + } + + /** + * 获取单条药房信息 + */ + public static function getOne(array $params, array $fields = ['*']): ?self + { + return self::where($params)->first($fields); + } + + /** + * 获取药房列表 + */ + public static function getList(array $params = [], array $fields = ['*']): Collection + { + return self::where($params)->get($fields); + } + + /** + * 分页查询药房 + */ + public static function getPage(array $params, array $fields = ['*'], ?int $page = null, ?int $per_page = 10): array + { + $raw = self::where($params)->paginate($per_page, $fields, 'page', $page); + return [ + 'current_page' => $raw->currentPage(), + 'total' => $raw->total(), + 'data' => $raw->items(), + 'per_page' => $raw->perPage(), + 'last_page' => $raw->lastPage(), + ]; + } +} diff --git a/app/Model/Product.php b/app/Model/Product.php index 42dfb44..269ed0e 100644 --- a/app/Model/Product.php +++ b/app/Model/Product.php @@ -23,6 +23,8 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property int $product_type 药品类型(0:未知 1:中成药 2:西药) * @property string $product_platform_code 处方平台商品编码 * @property string $product_pharmacy_code 第三方药店商品编码 + * @property int|string $pharmacy_id 所属药房ID + * @property string $pharmacy_code 所属药房编码 * @property string $product_cover_img 商品封面图 * @property string $product_spec 商品规格 * @property string $license_number 批准文号 @@ -49,7 +51,11 @@ class Product extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['product_id', 'product_platform_id', 'product_status', 'is_delete', 'prescription_num', 'product_name', 'common_name', 'product_price', 'mnemonic_code', 'product_type', 'product_platform_code', 'product_pharmacy_code', 'product_cover_img', 'product_spec', 'license_number', 'manufacturer', 'single_unit', 'single_use', 'packaging_unit', 'frequency_use', 'available_days', 'product_remarks', 'created_at', 'updated_at']; + protected array $fillable = ['product_id', 'product_platform_id', 'pharmacy_id', 'pharmacy_code', 'product_status', 'is_delete', 'prescription_num', 'product_name', 'common_name', 'product_price', 'mnemonic_code', 'product_type', 'product_platform_code', 'product_pharmacy_code', 'product_cover_img', 'product_spec', 'license_number', 'manufacturer', 'single_unit', 'single_use', 'packaging_unit', 'frequency_use', 'available_days', 'product_remarks', 'created_at', 'updated_at']; + + protected array $casts = [ + 'pharmacy_id' => 'string', + ]; protected string $primaryKey = "product_id"; diff --git a/app/Model/ProductPlatform.php b/app/Model/ProductPlatform.php index f5ddd8a..47466b5 100644 --- a/app/Model/ProductPlatform.php +++ b/app/Model/ProductPlatform.php @@ -16,6 +16,7 @@ use Hyperf\Snowflake\Concern\Snowflake; * @property int $product_type 药品类型(0:未知 1:中成药 2:西药) * @property string $product_platform_code 处方平台商品编码 * @property string $product_pharmacy_code 第三方药店商品编码 + * @property string $pharmacy_code 所属药房编码 * @property string $product_spec 商品规格 * @property string $license_number 批准文号 * @property string $manufacturer 生产厂家 @@ -38,7 +39,7 @@ class ProductPlatform extends Model /** * The attributes that are mass assignable. */ - protected array $fillable = ['product_platform_id', 'product_name', 'product_price', 'product_type', 'product_platform_code', 'product_pharmacy_code', 'product_spec', 'license_number', 'manufacturer', 'single_unit', 'packaging_unit', 'packaging_count', 'retail_unit', 'created_at', 'updated_at']; + protected array $fillable = ['product_platform_id', 'pharmacy_code', 'product_name', 'product_price', 'product_type', 'product_platform_code', 'product_pharmacy_code', 'product_spec', 'license_number', 'manufacturer', 'single_unit', 'packaging_unit', 'packaging_count', 'retail_unit', 'created_at', 'updated_at']; protected string $primaryKey = "product_platform_id"; diff --git a/app/Model/UserDoctor.php b/app/Model/UserDoctor.php index 286a9e1..ffd7586 100644 --- a/app/Model/UserDoctor.php +++ b/app/Model/UserDoctor.php @@ -121,6 +121,15 @@ class UserDoctor extends Model return $this->hasMany(OrderInquiry::class, "doctor_id", "doctor_id"); } + /** + * 关联医生药房绑定表 + * @return HasMany + */ + public function DoctorPharmacy(): HasMany + { + return $this->hasMany(DoctorPharmacy::class, "doctor_id", "doctor_id"); + } + /** * 获取医生信息-单条 * @param array $params diff --git a/app/Request/DoctorPharmacyRequest.php b/app/Request/DoctorPharmacyRequest.php new file mode 100644 index 0000000..4d64424 --- /dev/null +++ b/app/Request/DoctorPharmacyRequest.php @@ -0,0 +1,35 @@ + ['pharmacy_id'], + 'bindPharmacy' => ['pharmacy_id'], + ]; + + public function authorize(): bool + { + return true; + } + + public function rules(): array + { + return [ + 'pharmacy_id' => 'required|numeric', + ]; + } + + public function messages(): array + { + return [ + 'pharmacy_id.required' => '药房ID不能为空', + 'pharmacy_id.numeric' => '药房ID必须为数字', + ]; + } +} diff --git a/app/Request/PatientOrderRequest.php b/app/Request/PatientOrderRequest.php index d561500..437363f 100644 --- a/app/Request/PatientOrderRequest.php +++ b/app/Request/PatientOrderRequest.php @@ -32,6 +32,7 @@ class PatientOrderRequest extends FormRequest "address_id", "product_ids", "client_type", + "delivery_type", ], 'getPatientPrescriptionOrderList' => [ // 获取处方订单列表 ], @@ -84,7 +85,8 @@ class PatientOrderRequest extends FormRequest 'order_no' => 'required', 'order_prescription_id' => 'required', - 'address_id' => 'required', + 'address_id' => 'nullable', + 'delivery_type' => ['nullable', 'integer', Rule::in([1, 2])], 'product_ids' => 'required|array|min:1', 'detection_status' => 'required|integer|min:0|max:5', 'order_service_status' => 'required|integer|min:0|max:4', diff --git a/app/Request/UserDoctorRequest.php b/app/Request/UserDoctorRequest.php index 29d741d..79c9036 100644 --- a/app/Request/UserDoctorRequest.php +++ b/app/Request/UserDoctorRequest.php @@ -56,6 +56,7 @@ class UserDoctorRequest extends FormRequest 'prescription_icd',// 诊断疾病[] // 'doctor_advice', // 医嘱 'prescription_product',// 处方药品[] + 'pharmacy_id', // 药房id(可选,未传则取默认药房) ], 'getDoctorMessageList' => [ // 获取医生问诊消息列表 'message_inquiry_type',// 消息订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:结束) @@ -94,6 +95,7 @@ class UserDoctorRequest extends FormRequest 'prescription_icd' => 'required|array|min:1', 'doctor_advice' => 'required', 'prescription_product' => 'required|array|min:1|max:5', + 'pharmacy_id' => 'nullable|numeric', 'message_inquiry_type' => 'required|integer|min:1|max:5', ]; } diff --git a/app/Services/BasicDataService.php b/app/Services/BasicDataService.php index 04d6b0f..88c6472 100644 --- a/app/Services/BasicDataService.php +++ b/app/Services/BasicDataService.php @@ -16,6 +16,8 @@ use App\Model\HospitalDepartmentCustom; use App\Model\HotSearchKeyword; use App\Model\OperationManual; use App\Model\Product; +use App\Model\DoctorPharmacy; +use App\Model\Pharmacy; use Hyperf\Redis\Redis; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -242,6 +244,23 @@ class BasicDataService extends BaseService $params = array(); $params['product_status'] = 1; $params['is_delete'] = 0; + + // 若是医生端,则只展示医生选定/默认药房下的药品 + if (isset($user_info['user_type']) && $user_info['user_type'] == 2) { + $doctor_id = $user_info['client_user_id'] ?? 0; + $pharmacy_id = $this->request->input('pharmacy_id'); + if (isset($pharmacy_id) && $pharmacy_id !== '') { + $pharmacy = Pharmacy::getValidPharmacy($pharmacy_id); + } else { + $pharmacy = DoctorPharmacy::getDoctorDefaultPharmacy($doctor_id); + } + + if (empty($pharmacy) || empty($pharmacy->pharmacy_code)) { + return success([]); + } + $params['pharmacy_code'] = $pharmacy->pharmacy_code; + } + $product = Product::getSearchKeywordList($params, $product_keyword,$fields); if (empty($product)) { return success(); @@ -449,6 +468,29 @@ class BasicDataService extends BaseService $params = array(); $params['product_status'] = 1; $params['is_delete'] = 0; + + // 若是医生端,则只展示医生选定/默认药房下的药品 + if (isset($user_info['user_type']) && $user_info['user_type'] == 2) { + $doctor_id = $user_info['client_user_id'] ?? 0; + $pharmacy_id = $this->request->input('pharmacy_id'); + if (isset($pharmacy_id) && $pharmacy_id !== '') { + $pharmacy = Pharmacy::getValidPharmacy($pharmacy_id); + } else { + $pharmacy = DoctorPharmacy::getDoctorDefaultPharmacy($doctor_id); + } + + if (empty($pharmacy) || empty($pharmacy->pharmacy_code)) { + return success([ + 'total' => 0, + 'per_page' => (int)$per_page, + 'current_page' => (int)$page, + 'last_page' => 0, + 'data' => [], + ]); + } + $params['pharmacy_code'] = $pharmacy->pharmacy_code; + } + $product = Product::getWithAmountPage($params, $keyword,$fields, $page, $per_page); if (empty($product['data'])) { return success($product); diff --git a/app/Services/DoctorPharmacyService.php b/app/Services/DoctorPharmacyService.php new file mode 100644 index 0000000..d729d0b --- /dev/null +++ b/app/Services/DoctorPharmacyService.php @@ -0,0 +1,137 @@ +request->getAttribute("userInfo") ?? []; + $doctor_id = $user_info['client_user_id'] ?? 0; + + if (empty($doctor_id)) { + return fail(HttpEnumCode::CLIENT_HTTP_UNAUTHORIZED, "用户未登录"); + } + + $list = DoctorPharmacy::with(['Pharmacy'])->where([ + 'doctor_id' => (string) $doctor_id, + 'status' => 1, + ])->get(); + + $data = []; + foreach ($list as $item) { + $pharmacy = $item->Pharmacy; + if (empty($pharmacy) || $pharmacy->status != 1) { + continue; + } + + $data[] = [ + 'doctor_pharmacy_id' => $item->doctor_pharmacy_id, + 'pharmacy_id' => $pharmacy->pharmacy_id, + 'pharmacy_name' => $pharmacy->pharmacy_name, + 'pharmacy_code' => $pharmacy->pharmacy_code, + 'postage' => $pharmacy->postage, + 'free_shipping_threshold' => $pharmacy->free_shipping_threshold, + 'is_pickup' => $pharmacy->is_pickup, + 'telephone' => $pharmacy->telephone, + 'province' => $pharmacy->province, + 'city' => $pharmacy->city, + 'county' => $pharmacy->county, + 'address' => $pharmacy->address, + 'full_address' => $pharmacy->province . $pharmacy->city . $pharmacy->county . $pharmacy->address, + 'is_default' => $item->is_default, + ]; + } + + return success($data); + } + + /** + * 设置医生默认药房 + */ + public function setDoctorDefaultPharmacy(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + $doctor_id = $user_info['client_user_id'] ?? 0; + $pharmacy_id = $this->request->input('pharmacy_id'); + + if (empty($doctor_id)) { + return fail(HttpEnumCode::CLIENT_HTTP_UNAUTHORIZED, "用户未登录"); + } + + if (!isset($pharmacy_id) || $pharmacy_id === '') { + return fail(HttpEnumCode::HTTP_ERROR, "缺少药房ID"); + } + + // 验证医生是否绑定了该药房 + $bind = DoctorPharmacy::where([ + 'doctor_id' => (string) $doctor_id, + 'pharmacy_id' => (string) $pharmacy_id, + 'status' => 1, + ])->first(); + + if (empty($bind)) { + return fail(HttpEnumCode::HTTP_ERROR, "未绑定该药房或绑定已被禁用"); + } + + // 验证药房是否存在且有效 + $pharmacy = Pharmacy::getValidPharmacy($pharmacy_id); + if (empty($pharmacy)) { + return fail(HttpEnumCode::HTTP_ERROR, "药房不存在或已暂停服务"); + } + + if (empty($pharmacy->pharmacy_code)) { + return fail(HttpEnumCode::HTTP_ERROR, "该药房未配置药房编码,无法设为默认药房"); + } + + Db::beginTransaction(); + try { + // 将该医生所有绑定的 is_default 置为 0 + DoctorPharmacy::where('doctor_id', (string) $doctor_id)->update(['is_default' => 0]); + + // 将目标药房的 is_default 置为 1 + DoctorPharmacy::where([ + 'doctor_id' => (string) $doctor_id, + 'pharmacy_id' => (string) $pharmacy_id, + ])->update(['is_default' => 1]); + + Db::commit(); + return success(null, "设置默认药房成功"); + } catch (\Throwable $e) { + Db::rollBack(); + return fail(HttpEnumCode::SERVER_ERROR, "设置默认药房失败:" . $e->getMessage()); + } + } + + /** + * 获取平台公开正常运营的药房列表 + */ + public function getPublicPharmacyList(): array + { + $list = Pharmacy::where('status', 1)->get([ + 'pharmacy_id', + 'pharmacy_name', + 'pharmacy_code', + 'postage', + 'free_shipping_threshold', + 'is_pickup', + 'telephone', + 'province', + 'city', + 'county', + 'address', + ]); + + return success($list->toArray()); + } +} diff --git a/app/Services/OrderPrescriptionService.php b/app/Services/OrderPrescriptionService.php index 36e0213..bcb794e 100644 --- a/app/Services/OrderPrescriptionService.php +++ b/app/Services/OrderPrescriptionService.php @@ -405,7 +405,11 @@ class OrderPrescriptionService extends BaseService $arg['payDate'] = $order_product['pay_time']; // 支付时间 $arg['money'] = $order_product['payment_amount_total']; // 订单金额 $arg['freight'] = $order_product['logistics_fee']; // 运费(单位:元) - $arg['takeTypeCode'] = 2; // 取货方式 1 自提 2 快递,目前只支持快递,传固定值 2 + $arg['takeTypeCode'] = ($order_product['delivery_type'] == 1) ? 1 : 2; // 取货方式 1 自提 2 快递 + if (empty($order_product['pharmacy_code'])) { + throw new BusinessException("订单药房编码缺失,无法上报处方平台"); + } + $arg['pharmacyCode'] = $order_product['pharmacy_code']; $arg['buyerName'] = $order_product['consignee_name'];// 收货人姓名 $arg['buyerPhone'] = $order_product['consignee_tel'];// 收货人联系方式 $arg['buyerAddress'] = $order_product['address'];// 收货人地址 @@ -417,6 +421,7 @@ class OrderPrescriptionService extends BaseService $arg['districtName'] = $order_product['county']; // 收货地址(区 县)名称 $arg['presList'][0]['prescriptionNo'] = $order_prescription['prescription_code']; // 处方编号 + $arg['presList'][0]['pharmacyCode'] = $order_product['pharmacy_code']; $arg['presList'][0]['prescriptionSubType'] = 1; // 处方类型 0:无类型 1:普 通处方 2:儿科处 方 $arg['presList'][0]['patientName'] = $order_prescription['patient_name']; // 就诊人姓名 $arg['presList'][0]['patientPhone'] = $user['mobile']; // 就诊人联系方式 diff --git a/app/Services/PatientOrderService.php b/app/Services/PatientOrderService.php index 6cb7cff..af1e586 100644 --- a/app/Services/PatientOrderService.php +++ b/app/Services/PatientOrderService.php @@ -42,6 +42,7 @@ use App\Model\PatientFamily; use App\Model\PatientFamilyHealth; use App\Model\PatientFamilyPersonal; use App\Model\PatientFollow; +use App\Model\Pharmacy; use App\Model\Product; use App\Model\ProductPlatformAmount; use App\Model\SystemInquiryConfig; @@ -1482,6 +1483,7 @@ class PatientOrderService extends BaseService $address_id = $this->request->input('address_id'); $product_ids = $this->request->input('product_ids'); $client_type = $this->request->input('client_type'); + $delivery_type = (int)$this->request->input('delivery_type', 2); // 1: 自提 2: 快递 // 获取处方数据 $params = array(); @@ -1493,6 +1495,13 @@ class PatientOrderService extends BaseService return fail(); } + // 获取处方药房信息 + $pharmacy_id = $order_prescription['pharmacy_id'] ?? 0; + $pharmacy = Pharmacy::getValidPharmacy($pharmacy_id); + if (empty($pharmacy) || empty($pharmacy['pharmacy_code'])) { + return fail(HttpEnumCode::HTTP_ERROR, "处方所属药房异常,无法下单"); + } + // 验证处方状态 if ($order_prescription['prescription_status'] == 1) { return fail(HttpEnumCode::HTTP_ERROR, "处方未审核"); @@ -1516,13 +1525,28 @@ class PatientOrderService extends BaseService return fail(HttpEnumCode::HTTP_ERROR, "创建订单失败"); } - // 检测收货地址 - $params = array(); - $params['user_id'] = $user_info['user_id']; - $params['address_id'] = $address_id; - $user_ship_address = UserShipAddress::getOne($params); - if (empty($user_ship_address)) { - return fail(HttpEnumCode::HTTP_ERROR, "收货地址错误"); + // 检测收货方式及收货地址 + $user_ship_address = null; + if ($delivery_type == 1) { + // 自提模式,检查药房是否支持自提 + if ($pharmacy['is_pickup'] != 1) { + return fail(HttpEnumCode::HTTP_ERROR, "该药房不支持到店自提"); + } + if (!empty($address_id)) { + $params = array(); + $params['user_id'] = $user_info['user_id']; + $params['address_id'] = $address_id; + $user_ship_address = UserShipAddress::getOne($params); + } + } else { + // 快递模式,必须有收货地址 + $params = array(); + $params['user_id'] = $user_info['user_id']; + $params['address_id'] = $address_id; + $user_ship_address = UserShipAddress::getOne($params); + if (empty($user_ship_address)) { + return fail(HttpEnumCode::HTTP_ERROR, "收货地址错误"); + } } $not_enough_product_ids = []; @@ -1710,17 +1734,17 @@ class PatientOrderService extends BaseService // 处理运费数据 $app_env = config('app_env', 'prod'); - if (env("APP_ENV") == "prod") { - // $Prescription = new Prescription(); - // $result = $Prescription->getLogisticsFee(); - // if ($freight_calculation_amount < $result['drugCost']) { - // $logistics_fee = $result['freight']; - // } - //测试环境 运费 - $logistics_fee = 7; - }else{ - //测试环境 运费 - $logistics_fee = 0; + $logistics_fee = 0.00; + if ($delivery_type == 1) { + $logistics_fee = 0.00; + } else { + $postage = (float)($pharmacy['postage'] ?? 0.00); + $threshold = (float)($pharmacy['free_shipping_threshold'] ?? 0.00); + if ($threshold > 0 && (float)$freight_calculation_amount >= $threshold) { + $logistics_fee = 0.00; + } else { + $logistics_fee = $postage; + } } // 实际支付金额=商品总金额-优惠卷金额+运费金额 @@ -1730,7 +1754,7 @@ class PatientOrderService extends BaseService (string)$coupon_amount_total, 2 ), - $logistics_fee, + (string)$logistics_fee, 2 ); @@ -1792,18 +1816,37 @@ class PatientOrderService extends BaseService $data['coupon_amount_total'] = $coupon_amount_total; // 优惠卷总金额 $data['payment_amount_total'] = $payment_amount_total; // 实际付款金额 $data['logistics_fee'] = $logistics_fee; // 运费金额 - $data['province_id'] = $user_ship_address['province_id']; - $data['province'] = $user_ship_address['province']; - $data['city_id'] = $user_ship_address['city_id']; - $data['city'] = $user_ship_address['city']; - $data['county_id'] = $user_ship_address['county_id']; - $data['county'] = $user_ship_address['county']; - $data['address'] = $user_ship_address['address']; - $data['address_mask'] = $user_ship_address['address_mask']; - $data['consignee_name'] = $user_ship_address['consignee_name']; - $data['consignee_name_mask'] = $user_ship_address['consignee_name_mask']; - $data['consignee_tel'] = $user_ship_address['consignee_tel']; - $data['consignee_tel_mask'] = $user_ship_address['consignee_tel_mask']; + $data['pharmacy_id'] = $pharmacy['pharmacy_id']; + $data['pharmacy_code'] = $pharmacy['pharmacy_code']; + $data['pharmacy_name'] = $pharmacy['pharmacy_name']; + $data['delivery_type'] = $delivery_type; + if (!empty($user_ship_address)) { + $data['province_id'] = $user_ship_address['province_id']; + $data['province'] = $user_ship_address['province']; + $data['city_id'] = $user_ship_address['city_id']; + $data['city'] = $user_ship_address['city']; + $data['county_id'] = $user_ship_address['county_id']; + $data['county'] = $user_ship_address['county']; + $data['address'] = $user_ship_address['address']; + $data['address_mask'] = $user_ship_address['address_mask']; + $data['consignee_name'] = $user_ship_address['consignee_name']; + $data['consignee_name_mask'] = $user_ship_address['consignee_name_mask']; + $data['consignee_tel'] = $user_ship_address['consignee_tel']; + $data['consignee_tel_mask'] = $user_ship_address['consignee_tel_mask']; + } else { + $data['province_id'] = 0; + $data['province'] = ""; + $data['city_id'] = 0; + $data['city'] = ""; + $data['county_id'] = 0; + $data['county'] = ""; + $data['address'] = $pharmacy['pickup_address'] ?? "到店自提"; + $data['address_mask'] = $pharmacy['pickup_address'] ?? "到店自提"; + $data['consignee_name'] = $order_prescription['patient_name'] ?? ""; + $data['consignee_name_mask'] = $order_prescription['patient_name'] ?? ""; + $data['consignee_tel'] = ""; + $data['consignee_tel_mask'] = ""; + } $order_product = OrderProduct::addOrderProduct($data); if (empty($order_product)) { Db::rollBack(); @@ -2154,7 +2197,10 @@ class PatientOrderService extends BaseService $fields = [ "order_prescription_id", - "order_inquiry_id" + "order_inquiry_id", + "pharmacy_id", + "pharmacy_code", + "pharmacy_name", ]; $params = array(); @@ -2357,19 +2403,19 @@ class PatientOrderService extends BaseService // 获取可用优惠卷总金额 $coupon_amount_total = $userCouponService->getCouponTotalPrice($user_coupons); - // 获取运费金额 - $logistics_fee = 0; - if (env("APP_ENV") == "prod") { - // $Prescription = new Prescription(); - // $result = $Prescription->getLogisticsFee(); - // if ($freight_calculation_amount < $result['drugCost']) { - // $logistics_fee = $result['freight']; - // } - //测试环境 运费 - $logistics_fee = 7; - }else{ - //测试环境 运费 - $logistics_fee = 0; + // 获取运费金额及药房信息 + $pharmacy_id = $order_prescription['pharmacy_id'] ?? 0; + $pharmacy = Pharmacy::getValidPharmacy($pharmacy_id); + + $logistics_fee = 0.00; + if (!empty($pharmacy)) { + $postage = (float)($pharmacy['postage'] ?? 0.00); + $threshold = (float)($pharmacy['free_shipping_threshold'] ?? 0.00); + if ($threshold > 0 && (float)$freight_calculation_amount >= $threshold) { + $logistics_fee = 0.00; + } else { + $logistics_fee = $postage; + } } // 实际支付金额=商品总金额-优惠卷金额+运费金额 @@ -2399,6 +2445,16 @@ class PatientOrderService extends BaseService $result['logistics_fee'] = $logistics_fee; $result['user_ship_address'] = $user_ship_address; $result['order_prescription_product'] = $order_prescription_products; + $result['pharmacy_info'] = !empty($pharmacy) ? [ + 'pharmacy_id' => (string)$pharmacy['pharmacy_id'], + 'pharmacy_code' => $pharmacy['pharmacy_code'], + 'pharmacy_name' => $pharmacy['pharmacy_name'], + 'telephone' => $pharmacy['telephone'] ?? '', + 'is_pickup' => $pharmacy['is_pickup'] ?? 0, + 'postage' => (string)($pharmacy['postage'] ?? '0.00'), + 'free_shipping_threshold' => (string)($pharmacy['free_shipping_threshold'] ?? '0.00'), + 'pickup_address' => $pharmacy['pickup_address'] ?? '', + ] : null; return success($result); } diff --git a/app/Services/UserDoctorService.php b/app/Services/UserDoctorService.php index b321dee..eeb17ec 100644 --- a/app/Services/UserDoctorService.php +++ b/app/Services/UserDoctorService.php @@ -40,6 +40,8 @@ use App\Model\OrderServicePackageInquiry; use App\Model\PatientFollow; use App\Model\PatientHistoryInquiry; use App\Model\PatientHistoryInquiry as PatientHistoryInquiryModel; +use App\Model\DoctorPharmacy; +use App\Model\Pharmacy; use App\Model\Popup; use App\Model\Product; use App\Model\ProductPlatformAmount; @@ -1199,9 +1201,24 @@ class UserDoctorService extends BaseService $result['message'] = "成功"; $result['data'] = []; + // 校验医生是否已配置有效的默认药房 + $doctor_id = $user_info['client_user_id'] ?? 0; + $default_pharmacy = DoctorPharmacy::getDoctorDefaultPharmacy($doctor_id); + if (empty($default_pharmacy)) { + $result['status'] = 2; + $result['message'] = "您尚未配置默认药房或药房已停用,请联系客服人员完成绑定后再开具处方"; + return success($result); + } + + $result['data']['default_pharmacy'] = [ + 'pharmacy_id' => (string)$default_pharmacy->pharmacy_id, + 'pharmacy_code' => $default_pharmacy->pharmacy_code, + 'pharmacy_name' => $default_pharmacy->pharmacy_name, + ]; + $params = array(); $params['order_inquiry_id'] = $order_inquiry_id; - $params['doctor_id'] = $user_info['client_user_id']; + $params['doctor_id'] = $doctor_id; $order_prescription = OrderPrescription::getOne($params); if (empty($order_prescription)){ return success($result); @@ -1462,6 +1479,19 @@ class UserDoctorService extends BaseService $doctor_advice = $this->request->input('doctor_advice'); $prescription_product = $this->request->input('prescription_product'); $disease_desc = $this->request->input('disease_desc'); // 病情主诉 + $input_pharmacy_id = $this->request->input('pharmacy_id'); + + // 获取开方药房 + $pharmacy = null; + if (isset($input_pharmacy_id) && $input_pharmacy_id !== '') { + $pharmacy = Pharmacy::getValidPharmacy($input_pharmacy_id); + } else { + $pharmacy = DoctorPharmacy::getDoctorDefaultPharmacy($user_info['client_user_id'] ?? 0); + } + + if (empty($pharmacy) || empty($pharmacy['pharmacy_code'])) { + return fail(HttpEnumCode::HTTP_ERROR, "未找到有效的开方药房或药房已被停用,无法开具处方"); + } // 获取医生信息 $params = array(); @@ -1635,6 +1665,9 @@ class UserDoctorService extends BaseService $data['patient_sex'] = $order_inquiry['patient_sex']; $data['patient_age'] = $order_inquiry['patient_age']; $data['doctor_advice'] = $doctor_advice; + $data['pharmacy_id'] = $pharmacy['pharmacy_id']; + $data['pharmacy_code'] = $pharmacy['pharmacy_code']; + $data['pharmacy_name'] = $pharmacy['pharmacy_name']; $order_prescription = OrderPrescription::addOrderPrescription($data); if (empty($order_prescription)) { Db::rollBack(); @@ -1689,6 +1722,12 @@ class UserDoctorService extends BaseService return fail(HttpEnumCode::HTTP_ERROR,"药品" . $product['product_name'] . "已被删除,无法开具"); } + // 校验药品所属药房是否与处方药房一致 + if (!empty($product['pharmacy_code']) && $product['pharmacy_code'] !== $pharmacy['pharmacy_code']) { + Db::rollBack(); + return fail(HttpEnumCode::HTTP_ERROR, "药品【" . $product['product_name'] . "】不属于当前药房"); + } + // 检测药品是否超出最大可开数 if ($item['prescription_product_num'] > $product['prescription_num']) { // 库存不足 diff --git a/config/routes.php b/config/routes.php index 1ffdbde..22bfc62 100644 --- a/config/routes.php +++ b/config/routes.php @@ -18,6 +18,7 @@ use App\Controller\DetectionController; use App\Controller\DoctorAccountController; use App\Controller\DoctorAuthController; use App\Controller\DoctorInquiryConfigController; +use App\Controller\DoctorPharmacyController; use App\Controller\IndexController; use App\Controller\InquiryController; use App\Controller\LoginController; @@ -259,6 +260,15 @@ Router::addGroup('/doctor', function () { Router::get('/check', [UserDoctorController::class, 'checkOpenPrescription']); }); + // 药房 + Router::addGroup('/pharmacy', function () { + // 获取医生绑定的药房列表 + Router::get('', [DoctorPharmacyController::class, 'getDoctorPharmacyList']); + + // 设置医生默认药房 + Router::put('/default', [DoctorPharmacyController::class, 'setDoctorDefaultPharmacy']); + }); + // 常用语 Router::addGroup('/words', function () { // 获取常用语列表 @@ -772,6 +782,9 @@ Router::addGroup('/basic', function () { // 获取检测疾病分类列表 Router::get('/detection/disease', [BasicDataController::class, 'getDetectionDiseaseList']); + + // 获取公共药房列表 + Router::get('/pharmacy', [DoctorPharmacyController::class, 'getPublicPharmacyList']); }); // 获取医生评价 diff --git a/extend/Prescription/Prescription.php b/extend/Prescription/Prescription.php index 75dd198..ba593a7 100644 --- a/extend/Prescription/Prescription.php +++ b/extend/Prescription/Prescription.php @@ -106,7 +106,7 @@ class Prescription ), ]; - // Log::getInstance()->info("处方平台获取药品请求数据:" . json_encode($option,JSON_UNESCAPED_UNICODE)); + Log::getInstance()->info("处方平台获取药品请求数据:" . json_encode($option,JSON_UNESCAPED_UNICODE)); try { $response = $this->httpRequest($this->api_url . $this->version . '/drug/syncDrugCatalogue', $option); if (empty($response['data'])){ @@ -121,11 +121,11 @@ class Prescription if (empty($response['data']['result'])){ // 返回值为空 - // Log::getInstance()->error("处方平台获取药品返回result为空:" . json_encode($response,JSON_UNESCAPED_UNICODE)); + Log::getInstance()->error("处方平台获取药品返回result为空:" . json_encode($response,JSON_UNESCAPED_UNICODE)); throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); } - // Log::getInstance()->info("处方平台获取药品返回数据:" . json_encode($response,JSON_UNESCAPED_UNICODE)); + Log::getInstance()->info("处方平台获取药品返回数据:" . json_encode($response,JSON_UNESCAPED_UNICODE)); return $response['data']['result']; } catch (GuzzleException $e) { Log::getInstance()->error("处方平台获取药品请求异常:" . $e->getMessage()); @@ -136,13 +136,15 @@ class Prescription /** * 获取商品库存 * @param string $product_platform_code 处方平台商品编码(此处使用第三方药店商品编码!) + * @param string $pharmacy_code 药房编码 * @return array */ - public function getProdStock(string $product_platform_code): array + public function getProdStock(string $product_platform_code, string $pharmacy_code = ""): array { + $code = !empty($pharmacy_code) ? $pharmacy_code : $this->pharmacy_code; $option = [ "json" => array( - "pharmacyCode" => $this->pharmacy_code, + "pharmacyCode" => $code, "drugCode" => $product_platform_code, ), ]; @@ -165,13 +167,15 @@ class Prescription /** * 获取运费 + * @param string $pharmacy_code 药房编码 * @return array */ - public function getLogisticsFee(): array + public function getLogisticsFee(string $pharmacy_code = ""): array { + $code = !empty($pharmacy_code) ? $pharmacy_code : $this->pharmacy_code; $option = [ "json" => array( - "pharmacyCode" => $this->pharmacy_code, + "pharmacyCode" => $code, ), ]; @@ -204,14 +208,14 @@ class Prescription "json" => $arg ]; - // Log::getInstance()->info("处方平台上报数据:" . json_encode($option,JSON_UNESCAPED_UNICODE)); + Log::getInstance()->info("处方平台上报数据:" . json_encode($option,JSON_UNESCAPED_UNICODE)); try { $response = $this->httpRequest($this->api_url . $this->version . '/preOrder/receivePreOrder', $option); if (empty($response)){ // 返回值错误为空 throw new BusinessException(HttpEnumCode::getMessage(HttpEnumCode::SERVER_ERROR)); } - // Log::getInstance()->info("处方平台返回数据:" . json_encode($response,JSON_UNESCAPED_UNICODE)); + Log::getInstance()->info("处方平台返回数据:" . json_encode($response,JSON_UNESCAPED_UNICODE)); return $response; } catch (GuzzleException $e) { throw new BusinessException($e->getMessage()); diff --git a/sql/20260908_multi_pharmacy_isolation.sql b/sql/20260908_multi_pharmacy_isolation.sql new file mode 100644 index 0000000..8a69b2e --- /dev/null +++ b/sql/20260908_multi_pharmacy_isolation.sql @@ -0,0 +1,140 @@ +-- ============================================================================== +-- 数据库变更脚本:多药房独立药品与库存隔离方案 +-- 适用系统:hospital-applets-api +-- 执行说明: +-- 1. 本脚本默认表前缀为 `gdxz_`,若数据库未配置表前缀,请全局替换删除 `gdxz_`。 +-- 2. 请在业务低峰期执行,按顺序分批执行:第一部分(新建表)-> 第二部分(修改表)-> 第三部分(数据回填初始化)。 +-- 3. 脚本具有幂等性设计(IF NOT EXISTS / ON DUPLICATE KEY UPDATE)。 +-- ============================================================================== + +-- ============================================================================== +-- 第一部分:新建两张药房核心表 +-- ============================================================================== + +-- 1.1 药房基础信息表(gdxz_pharmacy) +CREATE TABLE IF NOT EXISTS `gdxz_pharmacy` ( + `pharmacy_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '药房ID(雪花算法ID,0表示系统默认/老数据)', + `pharmacy_name` varchar(128) NOT NULL DEFAULT '' COMMENT '药房名称', + `pharmacy_code` varchar(64) NOT NULL DEFAULT '' COMMENT '药房编码(对接第三方药房的thirdCode/pharmacyCode)', + `postage` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '基础运费/邮费(单位:元)', + `free_shipping_threshold` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '满额包邮门槛(单位:元,0表示不免邮)', + `is_pickup` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否支持到店自提(0:不支持 1:支持)', + `telephone` varchar(32) NOT NULL DEFAULT '' COMMENT '药房联系电话', + `province` varchar(64) NOT NULL DEFAULT '' COMMENT '省份名称', + `city` varchar(64) NOT NULL DEFAULT '' COMMENT '城市名称', + `county` varchar(64) NOT NULL DEFAULT '' COMMENT '区县名称', + `address` varchar(255) NOT NULL DEFAULT '' COMMENT '详细地址', + `pickup_address` varchar(255) NOT NULL DEFAULT '' COMMENT '自提详细地址', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用 1:启用)', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`pharmacy_id`), + UNIQUE KEY `uk_pharmacy_code` (`pharmacy_code`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='药房基础信息表'; + +-- 1.2 医生-药房关联表(gdxz_doctor_pharmacy) +CREATE TABLE IF NOT EXISTS `gdxz_doctor_pharmacy` ( + `doctor_pharmacy_id` bigint(20) unsigned NOT NULL COMMENT '关联主键ID(雪花算法ID)', + `doctor_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '医生ID', + `pharmacy_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '药房ID', + `is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否默认药房(0:否 1:是)', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用/解绑 1:正常)', + `created_at` datetime DEFAULT NULL COMMENT '创建时间', + `updated_at` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`doctor_pharmacy_id`), + UNIQUE KEY `uk_doctor_pharmacy` (`doctor_id`, `pharmacy_id`), + KEY `idx_doctor_default` (`doctor_id`, `is_default`, `status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='医生-药房绑定关联表'; + + +-- ============================================================================== +-- 第二部分:现有业务表字段扩展(ALTER TABLE) +-- ============================================================================== + +-- 2.1 处方主表增加药房快照字段(gdxz_order_prescription) +ALTER TABLE `gdxz_order_prescription` + ADD COLUMN `pharmacy_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '开方药房ID' AFTER `doctor_advice`, + ADD COLUMN `pharmacy_code` varchar(64) NOT NULL DEFAULT '' COMMENT '开方药房编码' AFTER `pharmacy_id`, + ADD COLUMN `pharmacy_name` varchar(128) NOT NULL DEFAULT '' COMMENT '开方药房名称' AFTER `pharmacy_code`, + ADD KEY `idx_pharmacy_code` (`pharmacy_code`); + +-- 2.2 药品订单表增加药房快照及配送类型字段(gdxz_order_product) +ALTER TABLE `gdxz_order_product` + ADD COLUMN `pharmacy_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '所属药房ID' AFTER `logistics_fee`, + ADD COLUMN `pharmacy_code` varchar(64) NOT NULL DEFAULT '' COMMENT '所属药房编码' AFTER `pharmacy_id`, + ADD COLUMN `pharmacy_name` varchar(128) NOT NULL DEFAULT '' COMMENT '所属药房名称' AFTER `pharmacy_code`, + ADD COLUMN `delivery_type` tinyint(1) NOT NULL DEFAULT '2' COMMENT '配送方式(1:到店自提 2:快递配送)' AFTER `pharmacy_name`, + ADD KEY `idx_pharmacy_code` (`pharmacy_code`), + ADD KEY `idx_delivery_type` (`delivery_type`); + +-- 2.3 药品表增加所属药房隔离字段(gdxz_product) +ALTER TABLE `gdxz_product` + ADD COLUMN `pharmacy_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '所属药房ID' AFTER `product_platform_id`, + ADD COLUMN `pharmacy_code` varchar(64) NOT NULL DEFAULT '' COMMENT '所属药房编码' AFTER `pharmacy_id`, + ADD KEY `idx_pharmacy_code` (`pharmacy_code`); + +-- 2.4 处方平台药品目录表增加第三方药房编码(gdxz_product_platform) +ALTER TABLE `gdxz_product_platform` + ADD COLUMN `pharmacy_code` varchar(64) NOT NULL DEFAULT '' COMMENT '第三方药房编码' AFTER `product_pharmacy_code`, + ADD KEY `idx_pharmacy_code` (`pharmacy_code`); + + +-- ============================================================================== +-- 第三部分:历史数据回填与初始化(DML) +-- ============================================================================== + +-- 3.1 初始化系统默认药房记录(pharmacy_id = 0,编码 ZD-10198) +INSERT INTO `gdxz_pharmacy` ( + `pharmacy_id`, `pharmacy_name`, `pharmacy_code`, + `postage`, `free_shipping_threshold`, `is_pickup`, + `telephone`, `province`, `city`, `county`, `address`, `pickup_address`, + `status`, `created_at`, `updated_at` +) VALUES ( + 0, '总院默认药房', 'ZD-10198', + 7.00, 0.00, 1, + '010-87573022', '北京市', '北京市', '海淀区', '医疗机构总院院内药房', '医疗机构总院门诊楼1层药房自提窗口', + 1, NOW(), NOW() +) ON DUPLICATE KEY UPDATE + `pharmacy_code` = VALUES(`pharmacy_code`), + `pharmacy_name` = VALUES(`pharmacy_name`), + `status` = 1; + +-- 3.2 回填现有药品表(gdxz_product)的药房归属为默认药房 +UPDATE `gdxz_product` +SET `pharmacy_id` = 0, `pharmacy_code` = 'ZD-10198' +WHERE `pharmacy_code` = '' OR `pharmacy_code` IS NULL; + +-- 3.3 回填处方平台目录表(gdxz_product_platform)的药房编码 +UPDATE `gdxz_product_platform` +SET `pharmacy_code` = 'ZD-10198' +WHERE `pharmacy_code` = '' OR `pharmacy_code` IS NULL; + +-- 3.4 回填历史处方表(gdxz_order_prescription)快照数据 +UPDATE `gdxz_order_prescription` +SET `pharmacy_id` = 0, `pharmacy_code` = 'ZD-10198', `pharmacy_name` = '总院默认药房' +WHERE `pharmacy_code` = '' OR `pharmacy_code` IS NULL; + +-- 3.5 回填历史药品订单表(gdxz_order_product)快照与配送方式(历史订单默认为快递=2) +UPDATE `gdxz_order_product` +SET `pharmacy_id` = 0, `pharmacy_code` = 'ZD-10198', `pharmacy_name` = '总院默认药房', `delivery_type` = 2 +WHERE `pharmacy_code` = '' OR `pharmacy_code` IS NULL; + +-- 3.6 为现有所有正常在职的医生,初始化绑定默认药房(避免上线后老医生无法开方) +INSERT IGNORE INTO `gdxz_doctor_pharmacy` ( + `doctor_pharmacy_id`, `doctor_id`, `pharmacy_id`, `is_default`, `status`, `created_at`, `updated_at` +) +SELECT + -- 结合时间戳与医生ID生成唯一大整数ID + (UNIX_TIMESTAMP(NOW()) * 1000000 + (d.doctor_id % 1000000)) AS `doctor_pharmacy_id`, + d.doctor_id, + 0 AS `pharmacy_id`, + 1 AS `is_default`, + 1 AS `status`, + NOW() AS `created_at`, + NOW() AS `updated_at` +FROM `gdxz_user_doctor` d +WHERE d.status = 1 + AND NOT EXISTS ( + SELECT 1 FROM `gdxz_doctor_pharmacy` dp WHERE dp.doctor_id = d.doctor_id + );