Merge branch 'dev'
Build Docker / build (push) Canceled after 0s

多药房配置
This commit is contained in:
haomingming
2026-09-24 09:00:24 +08:00
21 changed files with 1150 additions and 196 deletions
+128 -74
View File
@@ -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;
}
+126 -61
View File
@@ -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;
}
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Request\DoctorPharmacyRequest;
use App\Services\DoctorPharmacyService;
use Psr\Http\Message\ResponseInterface;
class DoctorPharmacyController extends AbstractController
{
/**
* 获取医生绑定的药房列表
*/
public function getDoctorPharmacyList(): ResponseInterface
{
$service = new DoctorPharmacyService();
$data = $service->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);
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
declare(strict_types=1);
namespace App\Model;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Model\Relations\HasOne;
use Hyperf\Snowflake\Concern\Snowflake;
/**
* @property int|string $doctor_pharmacy_id 主键ID
* @property int|string $doctor_id 医生ID
* @property int|string $pharmacy_id 药房ID
* @property int $is_default 是否默认药房(0:否 1:是)
* @property int $status 绑定状态(0:禁用 1:正常)
* @property \Carbon\Carbon $created_at 创建时间
* @property \Carbon\Carbon $updated_at 修改时间
* @property-read Pharmacy|null $Pharmacy
* @property-read UserDoctor|null $UserDoctor
*/
class DoctorPharmacy extends Model
{
use Snowflake;
/**
* The table associated with the model.
*/
protected ?string $table = 'doctor_pharmacy';
/**
* The primary key for the model.
*/
protected string $primaryKey = 'doctor_pharmacy_id';
/**
* The attributes that are mass assignable.
*/
protected array $fillable = [
'doctor_pharmacy_id',
'doctor_id',
'pharmacy_id',
'is_default',
'status',
'created_at',
'updated_at',
];
/**
* The attributes that should be cast to native types.
*/
protected array $casts = [
'doctor_pharmacy_id' => '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);
}
}
+17 -1
View File
@@ -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');
}
/**
* 关联处方疾病表
*/
+19 -1
View File
@@ -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表
*/
+133
View File
@@ -0,0 +1,133 @@
<?php
declare(strict_types=1);
namespace App\Model;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\Snowflake\Concern\Snowflake;
/**
* @property int|string $pharmacy_id 主键ID
* @property string $pharmacy_name 药房名称
* @property string $pharmacy_code 药房代码
* @property string $postage 基础邮费
* @property string $free_shipping_threshold 满额包邮门槛
* @property int $is_pickup 是否支持自提(0:否 1:是)
* @property string $telephone 联系电话
* @property int $province_id 省份ID
* @property string $province 省份名称
* @property int $city_id 城市ID
* @property string $city 城市名称
* @property int $county_id 区县ID
* @property string $county 区县名称
* @property string $address 详细地址
* @property int $status 状态(0:禁用 1:正常 2:删除)
* @property \Carbon\Carbon $created_at 创建时间
* @property \Carbon\Carbon $updated_at 修改时间
* @property-read Collection|DoctorPharmacy[] $DoctorPharmacy
*/
class Pharmacy extends Model
{
use Snowflake;
/**
* The table associated with the model.
*/
protected ?string $table = 'pharmacy';
/**
* The primary key for the model.
*/
protected string $primaryKey = 'pharmacy_id';
/**
* The attributes that are mass assignable.
*/
protected array $fillable = [
'pharmacy_id',
'pharmacy_name',
'pharmacy_code',
'postage',
'free_shipping_threshold',
'is_pickup',
'telephone',
'province_id',
'province',
'city_id',
'city',
'county_id',
'county',
'address',
'status',
'created_at',
'updated_at',
];
/**
* The attributes that should be cast to native types.
*/
protected array $casts = [
'pharmacy_id' => '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(),
];
}
}
+7 -1
View File
@@ -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";
+2 -1
View File
@@ -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";
+9
View File
@@ -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
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App\Request;
use Hyperf\Validation\Request\FormRequest;
class DoctorPharmacyRequest extends FormRequest
{
protected array $scenes = [
'setDefault' => ['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必须为数字',
];
}
}
+3 -1
View File
@@ -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',
+2
View File
@@ -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',
];
}
+42
View File
@@ -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);
+137
View File
@@ -0,0 +1,137 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Constants\HttpEnumCode;
use App\Model\DoctorPharmacy;
use App\Model\Pharmacy;
use Hyperf\DbConnection\Db;
class DoctorPharmacyService extends BaseService
{
/**
* 获取医生已绑定的药房列表
*/
public function getDoctorPharmacyList(): array
{
$user_info = $this->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());
}
}
+6 -1
View File
@@ -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']; // 就诊人联系方式
+101 -45
View File
@@ -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);
}
+40 -1
View File
@@ -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']) {
// 库存不足
+13
View File
@@ -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']);
});
// 获取医生评价
+13 -9
View File
@@ -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());
+140
View File
@@ -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
);