2025-12-02 13:26:17 +08:00

432 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package prescription 处方平台
package prescription
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"hospital-admin-api/config"
"hospital-admin-api/global"
"hospital-admin-api/utils"
"io"
"net/http"
"time"
)
// 获取token请求值
type getTokeRequest struct {
ClientId string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
}
// 通知处方平台订单取消
type noticePreOrderCancelRequest struct {
OrgCode string `json:"orgCode"` // 机构编码
OrderNo string `json:"orderNo"` // 院内订单编号
OptCode string `json:"optCode"` // 操作状态
}
// 通知处方平台订单取消返回数据
type noticePreOrderCancelResponse struct {
ResultCode string `json:"resultCode"` // 操作编码
ResultDesc string `json:"resultDesc"` // 描述
}
// ReportPreRequest 上报处方请求值-基础数据
type ReportPreRequest struct {
TerminalCode string `json:"terminalCode"` // 终端代码
OrderNo string `json:"orderNo"` // 订单编号
TransactNo string `json:"transactNo"` // 流水单号
PayDate string `json:"payDate"` // 支付时间
Money float64 `json:"money"` // 订单金额
Freight float64 `json:"freight"` // 运费(单位:元)
TakeTypeCode int `json:"takeTypeCode"` // 取货方式 1 自提 2 快递,目前只支持快递,传固定值 2
BuyerName string `json:"buyerName"` // 收货人姓名
BuyerPhone string `json:"buyerPhone"` // 收货人联系方式
BuyerAddress string `json:"buyerAddress"` // 收货人地址
ProvinceCode string `json:"provinceCode"` // 收货地址(省) 编码
ProvinceName string `json:"provinceName"` // 收货地址(省) 名称
CityCode string `json:"cityCode"` // 收货地址(市) 编码
CityName string `json:"cityName"` // 收货地址(市) 名称
DistrictCode string `json:"districtCode"` // 收货地址(区 县)编码
DistrictName string `json:"districtName"` // 收货地址(区 县)名称
PresList []PresRequest `json:"presList"` // 处方列表
}
// PresRequest 上报处方请求值-处方数据
type PresRequest struct {
PrescriptionNo string `json:"prescriptionNo"` // 处方编号
PrescriptionSubType int `json:"prescriptionSubType"` // 处方类型 0无类型 1普通处方 2儿科处方
PatientName string `json:"patientName"` // 就诊人姓名
PatientPhone string `json:"patientPhone"` // 就诊人联系方式
IdCard string `json:"idCard"` // 身份证号
Advice string `json:"advice"` // 医嘱
DiagnosisName string `json:"diagnosisName"` // 诊断
ThirdDoctorName string `json:"thirdDoctorName"` // 开方医生姓名
ThirdDeptName string `json:"thirdDeptName"` // 开方科室名称
ThirdDoctorNameImg string `json:"thirdDoctorNameImg"` // 开方医生签名链接
PrescriptionTime string `json:"prescriptionTime"` // 开方时间
ThirdFirstPharmacist string `json:"thirdFirstPharmacist"` // 初审药师姓名
ThirdFirstPharmacistImg string `json:"thirdFirstPharmacistImg"` // 初审药师签名链接
ThirdFirstTime string `json:"thirdFirstTime"` // 初审时间
ThirdLastPharmacist string `json:"thirdLastPharmacist"` // 终审药师姓名
ThirdLastPharmacistImg string `json:"thirdLastPharmacistImg"` // 终审药师签名链接
ThirdLastTime string `json:"ThirdLastTime"` // 终审时间
ThirdSignImg string `json:"thirdSignImg"` // 处方签章链接
ReferenceCharge float64 `json:"referenceCharge"` // 处方费用(不包含运费)
ChiefComplaint string `json:"chiefComplaint"` // 主诉
HistoryPresent string `json:"historyPresent"` // 现病史
PastHistory string `json:"pastHistory"` // 既往史
PhysicalExamination string `json:"physicalExamination"` // 体格检查
SupplementaryExamination string `json:"supplementaryExamination"` // 辅助检查
AllergicHistory string `json:"allergicHistory"` // 过敏史
DrugList []DrugListRequest `json:"drugList"` // 药品列表
OrderDrugList []OrderDrugListRequest `json:"orderDrugList"` // 订单药品列表
}
// DrugListRequest 上报处方请求值-药品数据1
type DrugListRequest struct {
DrugCode string `json:"drugCode"` // 药品编码
ApprovalNumber string `json:"approvalNumber"` // 批准文号
DrugName string `json:"drugName"` // 药品名称
Specifications string `json:"specifications"` // 药品规格
Price float64 `json:"price"` // 药品单价
PackingCount int `json:"packingCount"` // 药品数量
SurplusPackingCount int `json:"surplusPackingCount"` // 处方药品剩余使用数量
PackingUnit string `json:"packingUnit"` // 药品单位
SingleDosage int `json:"singleDosage"` // 单次用量
SingleDosageUnit string `json:"singleDosageUnit"` // 单次用量单位
UseName string `json:"useName"` // 用法名称
FrequencyName string `json:"frequencyName"` // 频次名称
UseDays int `json:"useDays"` // 使用天数
}
// OrderDrugListRequest 上报处方请求值-药品数据2
type OrderDrugListRequest struct {
DrugCode string `json:"drugCode"` // 药品编码
ApprovalNumber string `json:"approvalNumber"` // 批准文号
DrugName string `json:"drugName"` // 药品名称
Specifications string `json:"specifications"` // 药品规格
Price float64 `json:"price"` // 药品单价
DrugCount int `json:"drugCount"` // 药品数量
PackingUnit string `json:"packingUnit"` // 药品单位
ActualSellingPrice float64 `json:"actual_product_price"` // 药品实际销售单价
}
// GetProdStockRequest 获取商品库存请求值
type GetProdStockRequest struct {
PharmacyCode string `json:"pharmacyCode"` // 药房编码
DrugCode string `json:"drugCode"` // 三方药房药品编码
}
// 上报处方返回数据
type reportPreResponse struct {
ResultCode string `json:"resultCode"` // 操作编码
ResultDesc string `json:"resultDesc"` // 描述
}
// 获取商品库存返回数据
type getProdStockResponse struct {
ResultCode string `json:"resultCode"` // 操作编码
ResultDesc string `json:"resultDesc"` // 描述
Data []GetProdStockDataResponse `json:"data"` // 具体内容
}
type GetProdStockDataResponse struct {
Quantity string `json:"quantity"` // 库存
Threshold string `json:"threshold"` // 库存阈值
}
// GetToken 获取token
func GetToken() (string, error) {
// 准备要发送的 JSON 数据
requestData := getTokeRequest{
ClientId: config.C.Pre.PrePlatClientId,
ClientSecret: config.C.Pre.PrePlatClientSecret,
}
// 将 JSON 数据编码为字节数组
jsonData, err := json.Marshal(requestData)
if err != nil {
return "", err
}
// 准备请求体
requestBody := bytes.NewBuffer(jsonData)
// 设置请求 URL
url := config.C.Pre.PrePlatAppUrl + "v1/user_thrid/token"
// 创建 POST 请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
return "", err
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
// 检查响应状态码
if resp.StatusCode != 200 {
return "", errors.New("返回数据错误")
}
// 读取响应体
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return "", errors.New("返回数据错误")
}
// 获取 result 字段
result, ok := response["data"].(map[string]interface{})["result"].(map[string]interface{})
if !ok {
return "", errors.New("返回数据错误2")
}
// 获取 token 值
token, ok := result["token"].(string)
if !ok {
return "", errors.New("返回数据错误3")
}
// 添加缓存
_, err = global.Redis.Set(context.Background(), "prescription_token", token, (60*60*1.5)*time.Second).Result()
if err != nil {
return "", errors.New("添加缓存失败")
}
return token, nil
}
// NoticePreOrderCancel 通知处方平台订单取消
func NoticePreOrderCancel(orderNo string) (bool, error) {
// 准备要发送的 JSON 数据
data := noticePreOrderCancelRequest{
OrgCode: config.C.Pre.PrePlatPharmacyCode,
OrderNo: orderNo,
OptCode: "EVTDOD-04",
}
// 将 JSON 数据编码为字节数组
jsonData, err := json.Marshal(data)
if err != nil {
return false, err
}
// 准备请求体
requestBody := bytes.NewBuffer(jsonData)
// 设置请求 URL
url := config.C.Pre.PrePlatAppUrl + "v1/preOrder/changeOrderByOrg"
// 创建 POST 请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
return false, err
}
// 设置请求头,指定 Content-Type 为 application/json
req.Header.Set("Content-Type", "application/json")
token, _ := global.Redis.Get(context.Background(), "prescription_token").Result()
if token == "" {
token, err = GetToken()
if err != nil {
return false, err
}
}
req.Header.Set("Authorization", "Bearer "+token)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return false, err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
// 检查响应状态码
if resp.StatusCode != 200 {
return false, errors.New("返回数据错误")
}
var response noticePreOrderCancelResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return false, err
}
fmt.Println(response)
if response.ResultCode != "1000" {
if response.ResultDesc != "" {
return false, errors.New(response.ResultDesc)
}
return false, errors.New("取消处方平台订单失败")
}
return true, nil
}
// ReportPre 上报处方
func (r ReportPreRequest) ReportPre() (bool, error) {
jsonData, err := json.Marshal(r)
if err != nil {
return false, err
}
utils.LogJsonInfo("上报处方平台:", jsonData)
// 准备请求体
requestBody := bytes.NewBuffer(jsonData)
// 设置请求 URL
url := config.C.Pre.PrePlatAppUrl + "v1/preOrder/receivePreOrder"
// 创建 POST 请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
return false, err
}
// 设置请求头,指定 Content-Type 为 application/json
req.Header.Set("Content-Type", "application/json")
token, _ := global.Redis.Get(context.Background(), "prescription_token").Result()
if token == "" {
token, err = GetToken()
if err != nil {
return false, err
}
}
req.Header.Set("Authorization", "Bearer "+token)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return false, err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
// 检查响应状态码
if resp.StatusCode != 200 {
return false, errors.New("返回数据错误")
}
var response reportPreResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return false, err
}
if response.ResultCode != "1000" {
if response.ResultDesc != "" {
return false, errors.New(response.ResultDesc)
}
return false, errors.New("上报处方平台失败")
}
return true, nil
}
// GetProdStock 获取商品库存
func (r GetProdStockRequest) GetProdStock() (*GetProdStockDataResponse, error) {
r.PharmacyCode = config.C.Pre.PrePlatPharmacyCode
jsonData, err := json.Marshal(r)
if err != nil {
utils.LogJsonErr("获取商品库存-序列化请求参数失败", err)
return nil, err
}
utils.LogJsonInfo("获取商品库存-请求参数:", r)
// 准备请求体
requestBody := bytes.NewBuffer(jsonData)
// 设置请求 URL
url := config.C.Pre.PrePlatAppUrl + "v1/pharmacy/pharmacyInventory"
// 打印请求信息
utils.LogJsonInfo("获取商品库存-请求URL", url)
utils.LogJsonInfo("获取商品库存-请求体:", requestBody.String())
// 创建 POST 请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
utils.LogJsonErr("获取商品库存-创建请求失败", err)
return nil, err
}
// 设置请求头,指定 Content-Type 为 application/json
req.Header.Set("Content-Type", "application/json")
token, _ := global.Redis.Get(context.Background(), "prescription_token").Result()
if token == "" {
token, err = GetToken()
if err != nil {
utils.LogJsonErr("获取商品库存-获取token失败", err)
return nil, err
}
}
req.Header.Set("Authorization", "Bearer "+token)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
utils.LogJsonErr("获取商品库存-发送请求失败", err)
return nil, err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
// 检查响应状态码
if resp.StatusCode != 200 {
utils.LogJsonErr("获取商品库存-响应状态码错误", fmt.Sprintf("statusCode: %d", resp.StatusCode))
return nil, errors.New("返回数据错误")
}
var response getProdStockResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
utils.LogJsonErr("获取商品库存-解析响应数据失败", err)
return nil, err
}
if response.ResultCode != "1000" {
utils.LogJsonErr("获取商品库存-业务处理失败", response)
if response.ResultDesc != "" {
return nil, errors.New(response.ResultDesc)
}
return nil, errors.New("获取商品库存失败")
}
utils.LogJsonInfo("获取商品库存-成功", response.Data)
return &response.Data[0], nil
}