package service

import (
	"XT_New/models"
	"XT_New/utils"
	"errors"
	"fmt"
	"github.com/jinzhu/gorm"
	"math"
	"strconv"
	"strings"
	"time"
)

func GetPharmacyDrugList(storehouse_id int64, orgid int64, keywords string) (drug []*models.PharmacyBaseDrug, err error) {

	db := XTReadDB().Model(&drug).Where("org_id=? and status=1  and drug_status<>'停用 and is_pharmacy = 1' ", orgid)
	if len(keywords) > 0 {
		likekey := "%" + keywords + "%"
		err = db.Where("(drug_name LIKE ?)", likekey).Preload("DrugWarehouseInfo", func(db *gorm.DB) *gorm.DB {
			return XTReadDB().Where("org_id=? and status = 1 and warehousing_count <> 0 and storehouse_id = ?", orgid, storehouse_id).Group("id")
		}).Find(&drug).Error
	} else {
		err = db.Preload("DrugWarehouseInfo", func(db *gorm.DB) *gorm.DB {
			return XTReadDB().Where("org_id=? and status = 1 and warehousing_count <> 0 and storehouse_id = ?", orgid, storehouse_id).Group("id")
		}).Find(&drug).Error
	}
	return
}

func GetBloodAdviceList(advice_date int64, drug_id int64, org_id int64) (advice []*models.PharmacyDoctorAdvice, err error) {

	err = XTReadDB().Where("advice_date = ? and drug_id = ? and user_org_id = ? and status = 1 and advice_type =2 and is_medicine= 0", advice_date, drug_id, org_id).Find(&advice).Error
	return advice, err
}

func GetHisAdviceList(advice_date int64, drug_id int64, org_id int64) (advice []*models.PharmacyHisDoctorAdviceInfo, err error) {

	err = XTReadDB().Where("advice_date = ? and drug_id =? and user_org_id =? and status = 1 and is_medicine = 0", advice_date, drug_id, org_id).Order("prescription_id asc").Find(&advice).Error
	return advice, err
}

func UpdatePharmacyAdviceBaseDrug(ids []string, orgid int64) (models.PharmacyDoctorAdvice, error) {

	drug := models.PharmacyDoctorAdvice{}

	err := XTWriteDB().Where("id in(?) and user_org_id = ? and status = 1", ids, orgid).Update(map[string]interface{}{"is_medicine": 1}).Error

	return drug, err
}

func UpdatePharmacyHisAdviceBaseDrug(ids []string, orgid int64) (models.PharmacyHisDoctorAdviceInfo, error) {

	info := models.PharmacyHisDoctorAdviceInfo{}
	err := XTWriteDB().Where("id in(?) and user_org_id = ? and status = 1", ids, orgid).Update(map[string]interface{}{"is_medicine": 1}).Error
	return info, err
}

func GetPharmacyAdviceList(ids []string, orgid int64) (advice []*models.PharmacyDoctorAdvice, err error) {

	err = XTReadDB().Where("id in(?) and user_org_id = ?", ids, orgid).Find(&advice).Error
	return advice, err
}

func GetPharmacyHisAdviceList(ids []string, orgid int64) (advice []*models.PharmacyHisDoctorAdviceInfo, err error) {

	err = XTReadDB().Where("id in(?) and user_org_id = ?", ids, orgid).Find(&advice).Error
	return advice, err
}

func FindPharmacyConfig(orgid int64) (models.PharmacyConfig, error) {

	config := models.PharmacyConfig{}
	err := XTReadDB().Where("user_org_id = ? and status = 1", orgid).Find(&config).Error
	return config, err
}

// 药品出库

func PharmacyDrugsDelivery(orgID int64, creater int64, advice *models.PharmacyDoctorAdvice, id int64) (err error) {
	// 1.判断药品是否来自专用字典的药品库
	// 2.判断当天当前机构有没有创建出库单，没有则创建
	// 3.创建出库流程
	// 3.1 实现先进先出逻辑 由于药品执行后，不可以修改和删除，所以不考虑出库后的退库和修改出库数量等
	isHasWay := false
	record_time := int64(0)
	if advice.Way == 1 {
		isHasWay = true
		record_time = advice.RecordDate
	}

	if isHasWay {
		//判断当天当前机构有没有创建出库单，没有则创建
		out, err := FindDrugStockOutByIsSys(orgID, 15, record_time)
		if err == gorm.ErrRecordNotFound {
			timeStr := time.Now().Format("2006-01-02")
			timeArr := strings.Split(timeStr, "-")
			total, _ := FindAllDrugWarehouseOut(orgID)
			total = total + 1
			warehousing_out_order := strconv.FormatInt(orgID, 10) + timeArr[0] + timeArr[1] + timeArr[2] + "000"
			number, _ := strconv.ParseInt(warehousing_out_order, 10, 64)
			number = number + total
			warehousing_out_order = "YPCKD" + strconv.FormatInt(number, 10)
			storeConfig, _ := GetAllStoreHouseConfig(orgID)
			warehouseOut := models.DrugWarehouseOut{
				WarehouseOutOrderNumber: warehousing_out_order,
				OperationTime:           time.Now().Unix(),
				OrgId:                   orgID,
				Creater:                 creater,
				Ctime:                   time.Now().Unix(),
				Status:                  1,
				WarehouseOutTime:        record_time,
				Dealer:                  0,
				Manufacturer:            0,
				Type:                    1,
				IsSys:                   15,
				StorehouseId:            storeConfig.DrugStorehouseOut,
			}
			err := AddSigleDrugWarehouseOut(&warehouseOut)
			if err != nil {
				utils.TraceLog("创建出库单失败 err = %v", err)
				return err
			} else {
				out = warehouseOut
			}
		}

		// 出库流程
		// 1.查询该药品在药品库的规格信息，并将处方里的规格进行换算（尽量将拆零单位转换成包装单位）
		drup, _ := FindBaseDrugLibRecord(orgID, advice.DrugId)
		if drup.ID > 0 {
			prescribingNumber := advice.PrescribingNumber

			PharmacyDrugDeliverInfo(orgID, prescribingNumber, &out, &drup, advice, id)

		} else {
			return errors.New("药品信息不存在")
		}

	}

	return
}

// 药品自动出库 递归方式
func PharmacyDrugDeliverInfo(orgID int64, prescribingNumber float64, warehouseout *models.DrugWarehouseOut, drup *models.BaseDrugLib, advice *models.PharmacyDoctorAdvice, id int64) (err error) {

	// 判断处方里药品单位是拆零单位还是包装单位,	如果是包装单位，则根据规格，将包装数量转为拆零数量
	var deliver_number int64 = 0
	var stock_number int64 = 0

	prescribingNumber_temp := strconv.FormatFloat(math.Abs(prescribingNumber), 'f', 0, 64)
	count, _ := strconv.ParseInt(prescribingNumber_temp, 10, 64)

	var drug_price float64
	if advice.PrescribingNumberUnit == drup.MaxUnit {
		deliver_number = count * drup.MinNumber

	} else {
		deliver_number = count

	}

	if advice.PrescribingNumberUnit == drup.MaxUnit {
		drug_price = drup.RetailPrice
	}
	fmt.Println(drug_price)

	if advice.PrescribingNumberUnit == drup.MinUnit {
		drug_price = drup.MinPrice
	}

	if advice.PrescribingNumberUnit != drup.MaxUnit || advice.PrescribingNumberUnit != drup.MinUnit {
		drug_price = drup.RetailPrice
	}

	// 根据先进先出原则，查询最先入库的批次，进行出库
	// 如果没有对应的库存，则报错
	storeConfig, _ := GetAllStoreHouseConfig(advice.UserOrgId)
	warehouse, err := FindLastDrugWarehousingInfoByID(advice.DrugId, storeConfig.DrugStorehouseOut)

	if err != nil {

		return err
	}

	// 将该批次的剩余库存数量转换为拆零数量

	stock_number = warehouse.StockMaxNumber*drup.MinNumber + warehouse.StockMinNumber

	// 当库存数量大于或等于出库数量的话，则正常出库该批次
	if stock_number >= deliver_number {

		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			RetailPrice:             warehouse.RetailPrice,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number, //出最小单位
			WarehouseInfoId:         warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number, //按最小单位计算,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			SystemTime:              advice.AdviceDate,
			WarehousingDetailId:     warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		CreateDrugFlowOne(drugflow)

		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		fmt.Println(errOne)
		//查询是否存在数据

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   count,
			CountUnit:               advice.PrescribingNumberUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		var maxNumber int64 = 0
		var minNumber int64 = 0
		var stock_max_number int64 = 0
		stock_max_number = warehouse.StockMaxNumber

		maxNumber = deliver_number / drup.MinNumber
		minNumber = deliver_number % drup.MinNumber

		if warehouse.StockMaxNumber == 0 && drup.MaxUnit == drup.MinUnit {
			minNumber = maxNumber
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < maxNumber && warehouse.StockMinNumber < minNumber {
				return errors.New("库存数量不足")
			}
		}

		warehouse.StockMaxNumber = warehouse.StockMaxNumber - maxNumber

		if warehouse.StockMaxNumber < 0 {
			warehouse.StockMaxNumber = 0
		}
		if warehouse.StockMinNumber < 0 {
			warehouse.StockMinNumber = 0
		}

		warehouse.Mtime = time.Now().Unix()

		if warehouse.StockMinNumber < minNumber {

			warehouse.StockMaxNumber = warehouse.StockMaxNumber - 1
			warehouse.StockMinNumber = warehouse.StockMinNumber + drup.MinNumber - minNumber
		} else {
			if minNumber > 0 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - minNumber
			}

			if minNumber == 0 && maxNumber != 1 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			}

		}

		if maxNumber == 1 && minNumber == 0 && drup.MaxUnit != drup.MinUnit {
			warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			if warehouse.StockMinNumber == 0 {
				warehouse.StockMaxNumber = stock_max_number
			}
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < 0 && warehouse.StockMinNumber < 0 {
				return errors.New("库存数量不足")
			}
		}
		if warehouse.StockMinNumber <= 0 {
			warehouse.StockMinNumber = 0
		}

		errThree := UpDateDrugWarehouseInfoByStock(&warehouse)
		if errThree != nil {
			return errThree
		}

		return nil
	} else {
		// 当该批次的库存数量小于出库数量的话，则先把该批次出库完后，再进行递归出库
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number,
			WarehouseInfoId:         warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseOutInfo.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   deliver_number,
			CountUnit:               drup.MinUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		info := models.XtDrugWarehouseInfo{
			ID:                warehouse.ID,
			WarehousingId:     warehouse.WarehousingId,
			DrugId:            warehouse.DrugId,
			Number:            warehouse.Number,
			ProductDate:       warehouse.ProductDate,
			ExpiryDate:        warehouse.ExpiryDate,
			WarehousingCount:  warehouse.WarehousingCount,
			Price:             warehouse.RetailPrice,
			TotalPrice:        warehouse.TotalPrice,
			Dealer:            warehouse.Dealer,
			Manufacturer:      warehouse.Manufacturer,
			Remark:            warehouse.Remark,
			Ctime:             warehouse.Ctime,
			Mtime:             warehouse.Mtime,
			Status:            1,
			OrgId:             warehouse.OrgId,
			IsReturn:          warehouse.IsReturn,
			WarehousingOrder:  warehouse.WarehousingOrder,
			Type:              warehouse.Type,
			RetailPrice:       warehouse.RetailPrice,
			RetailTotalPrice:  warehouse.RetailPrice,
			StockMaxNumber:    0,
			StockMinNumber:    0,
			BatchNumber:       warehouse.BatchNumber,
			MaxUnit:           warehouse.MaxUnit,
			WarehousingInfoId: warehouse.WarehousingInfoId,
			SupplyWarehouseId: warehouse.SupplyWarehouseId,
		}
		//扣减库存
		errThree := UpDateDrugWarehouseInfoByStock(&info)

		if errThree != nil {
			return errThree
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   stock_number,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		CreateDrugFlowOne(drugflow)

		// 清零完该库存后，还有剩余出库未出完，进行对应的递归操作
		prescribingNumber_two_temp := deliver_number - stock_number

		overPlusNumber := float64(prescribingNumber_two_temp)

		advice.PrescribingNumber = float64(prescribingNumber_two_temp)
		advice.PrescribingNumberUnit = advice.PrescribingNumberUnit

		NewPharmacyDrugDeliverInfo(orgID, overPlusNumber, warehouseout, drup, advice, id)
	}

	return
}

// 药品出库 递归方式
func NewPharmacyDrugDeliverInfo(orgID int64, prescribingNumber float64, warehouseout *models.DrugWarehouseOut, drup *models.BaseDrugLib, advice *models.PharmacyDoctorAdvice, id int64) (err error) {

	// 判断处方里药品单位是拆零单位还是包装单位,	如果是包装单位，则根据规格，将包装数量转为拆零数量
	var deliver_number int64 = 0
	var stock_number int64 = 0

	prescribingNumber_temp := strconv.FormatFloat(math.Abs(prescribingNumber), 'f', 0, 64)
	count, _ := strconv.ParseInt(prescribingNumber_temp, 10, 64)

	var drug_price float64

	//按最小单位数据计算
	deliver_number = count

	if advice.PrescribingNumberUnit == drup.MaxUnit {
		drug_price = drup.RetailPrice
	}

	if advice.PrescribingNumberUnit == drup.MinUnit {
		drug_price = drup.MinPrice
	}

	if advice.PrescribingNumberUnit != drup.MaxUnit || advice.PrescribingNumberUnit != drup.MinUnit {
		drug_price = drup.RetailPrice
	}

	// 根据先进先出原则，查询最先入库的批次，进行出库
	// 如果没有对应的库存，则报错
	//查询默认仓库
	storeConfig, _ := GetAllStoreHouseConfig(advice.UserOrgId)
	warehouse, err := FindLastDrugWarehousingInfoByID(advice.DrugId, storeConfig.DrugStorehouseOut)

	if err != nil {

		return err
	}

	// 将该批次的剩余库存数量转换为拆零数量

	stock_number = warehouse.StockMaxNumber*drup.MinNumber + warehouse.StockMinNumber

	// 当库存数量大于或等于出库数量的话，则正常出库该批次
	if stock_number >= deliver_number {
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			RetailPrice:             drug_price,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number, //出最小单位
			WarehouseInfoId:         warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number, //按最小单位计算,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		CreateDrugFlowOne(drugflow)
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   count,
			CountUnit:               advice.PrescribingNumberUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		// 出库完成后，要减去对应批次的库存数量
		// 判断处方里药品单位是拆零单位还是包装单位,	如果是拆零单位，则根据规格，将拆零数量转为包装数量
		var maxNumber int64 = 0
		var minNumber int64 = 0
		var stock_max_number int64 = 0
		stock_max_number = warehouse.StockMaxNumber

		maxNumber = deliver_number / drup.MinNumber
		minNumber = deliver_number % drup.MinNumber

		if warehouse.StockMaxNumber == 0 && drup.MaxUnit == drup.MinUnit {
			minNumber = maxNumber
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < maxNumber && warehouse.StockMinNumber < minNumber {
				return errors.New("库存数量不足")
			}
		}

		warehouse.StockMaxNumber = warehouse.StockMaxNumber - maxNumber

		if warehouse.StockMaxNumber < 0 {
			warehouse.StockMaxNumber = 0
		}
		if warehouse.StockMinNumber < 0 {
			warehouse.StockMinNumber = 0
		}

		warehouse.Mtime = time.Now().Unix()

		if warehouse.StockMinNumber < minNumber {

			warehouse.StockMaxNumber = warehouse.StockMaxNumber - 1
			warehouse.StockMinNumber = warehouse.StockMinNumber + drup.MinNumber - minNumber
		} else {

			if minNumber > 0 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - minNumber
			}

			if minNumber == 0 && maxNumber != 1 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			}
		}

		if maxNumber == 1 && minNumber == 0 && drup.MaxUnit != drup.MinUnit {

			warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			if warehouse.StockMinNumber == 0 {
				warehouse.StockMaxNumber = stock_max_number
			}
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < 0 && warehouse.StockMinNumber < 0 {
				return errors.New("库存数量不足")
			}
		}
		if warehouse.StockMinNumber <= 0 {
			warehouse.StockMinNumber = 0
		}

		errThree := UpDateDrugWarehouseInfoByStock(&warehouse)

		if errThree != nil {
			return errThree
		}

		return nil
	} else {
		// 当该批次的库存数量小于出库数量的话，则先把该批次出库完后，再进行递归出库
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number,
			WarehouseInfoId:         warehouse.ID,
			AdviceId:                advice.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}
		//查询是否存在数据

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseOutInfo.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   deliver_number,
			CountUnit:               drup.MinUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		// 出库完成后，要将该批次库存清零
		//warehouse.StockMaxNumber = 0
		//warehouse.StockMinNumber = 0
		//warehouse.Mtime = time.Now().Unix()

		info := models.XtDrugWarehouseInfo{
			ID:                warehouse.ID,
			WarehousingId:     warehouse.WarehousingId,
			DrugId:            warehouse.DrugId,
			Number:            warehouse.Number,
			ProductDate:       warehouse.ProductDate,
			ExpiryDate:        warehouse.ExpiryDate,
			WarehousingCount:  warehouse.WarehousingCount,
			Price:             warehouse.Price,
			TotalPrice:        warehouse.TotalPrice,
			Dealer:            warehouse.Dealer,
			Manufacturer:      warehouse.Manufacturer,
			Remark:            warehouse.Remark,
			Ctime:             warehouse.Ctime,
			Mtime:             warehouse.Mtime,
			Status:            1,
			OrgId:             warehouse.OrgId,
			IsReturn:          warehouse.IsReturn,
			WarehousingOrder:  warehouse.WarehousingOrder,
			Type:              warehouse.Type,
			RetailPrice:       warehouse.RetailPrice,
			RetailTotalPrice:  warehouse.RetailPrice,
			StockMaxNumber:    0,
			StockMinNumber:    0,
			BatchNumber:       warehouse.BatchNumber,
			MaxUnit:           warehouse.MaxUnit,
			WarehousingInfoId: warehouse.WarehousingInfoId,
			SupplyWarehouseId: warehouse.SupplyWarehouseId,
			StorehouseId:      storeConfig.DrugStorehouseOut,
		}
		//扣减库存
		errThree := UpDateDrugWarehouseInfoByStock(&info)

		if errThree != nil {
			return errThree
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			PharmacyId:              id,
		}

		CreateDrugFlowOne(drugflow)

		// 清零完该库存后，还有剩余出库未出完，进行对应的递归操作
		prescribingNumber_two_temp := deliver_number - stock_number

		overPlusNumber := float64(prescribingNumber_two_temp)

		advice.PrescribingNumber = float64(prescribingNumber_two_temp)
		advice.PrescribingNumberUnit = advice.PrescribingNumberUnit

		NewPharmacyDrugDeliverInfo(orgID, overPlusNumber, warehouseout, drup, advice, id)
	}

	return
}

func FindAllPharmacyDrugWarehouseOut(org_id int64) (total int64, err error) {
	err = readDb.Model(&models.DrugWarehouseOut{}).Where("org_id = ? and is_sys = 15", org_id).Count(&total).Error
	return total, err

}

func CreatePharmacy(pharmacy models.Pharmacy) error {

	err := XTWriteDB().Create(&pharmacy).Error
	return err
}

// 药品出库

func PharmacyHisDrugsDelivery(orgID int64, creater int64, advice *models.PharmacyHisDoctorAdviceInfo, id int64) (err error) {
	// 1.判断药品是否来自专用字典的药品库
	// 2.判断当天当前机构有没有创建出库单，没有则创建
	// 3.创建出库流程
	// 3.1 实现先进先出逻辑 由于药品执行后，不可以修改和删除，所以不考虑出库后的退库和修改出库数量等
	isHasWay := false
	record_time := int64(0)
	if advice.Way == 1 {
		isHasWay = true
		record_time = advice.RecordDate
	}

	if isHasWay {
		//判断当天当前机构有没有创建出库单，没有则创建
		out, err := FindDrugStockOutByIsSys(orgID, 15, record_time)
		if err == gorm.ErrRecordNotFound {
			timeStr := time.Now().Format("2006-01-02")
			timeArr := strings.Split(timeStr, "-")
			total, _ := FindAllDrugWarehouseOut(orgID)
			total = total + 1
			warehousing_out_order := strconv.FormatInt(orgID, 10) + timeArr[0] + timeArr[1] + timeArr[2] + "000"
			number, _ := strconv.ParseInt(warehousing_out_order, 10, 64)
			number = number + total
			warehousing_out_order = "YPCKD" + strconv.FormatInt(number, 10)
			storeConfig, _ := GetAllStoreHouseConfig(orgID)
			warehouseOut := models.DrugWarehouseOut{
				WarehouseOutOrderNumber: warehousing_out_order,
				OperationTime:           time.Now().Unix(),
				OrgId:                   orgID,
				Creater:                 creater,
				Ctime:                   time.Now().Unix(),
				Status:                  1,
				WarehouseOutTime:        record_time,
				Dealer:                  0,
				Manufacturer:            0,
				Type:                    1,
				IsSys:                   15,
				StorehouseId:            storeConfig.DrugStorehouseOut,
			}
			err := AddSigleDrugWarehouseOut(&warehouseOut)
			if err != nil {
				utils.TraceLog("创建出库单失败 err = %v", err)
				return err
			} else {
				out = warehouseOut
			}
		}

		// 出库流程
		// 1.查询该药品在药品库的规格信息，并将处方里的规格进行换算（尽量将拆零单位转换成包装单位）
		drup, _ := FindBaseDrugLibRecord(orgID, advice.DrugId)
		if drup.ID > 0 {
			prescribingNumber := advice.PrescribingNumber

			PharmacyHisDrugDeliverInfo(orgID, prescribingNumber, &out, &drup, advice, id)

		} else {
			return errors.New("药品信息不存在")
		}

	}

	return
}

// 药品自动出库 递归方式
func PharmacyHisDrugDeliverInfo(orgID int64, prescribingNumber float64, warehouseout *models.DrugWarehouseOut, drup *models.BaseDrugLib, advice *models.PharmacyHisDoctorAdviceInfo, id int64) (err error) {

	// 判断处方里药品单位是拆零单位还是包装单位,	如果是包装单位，则根据规格，将包装数量转为拆零数量
	var deliver_number int64 = 0
	var stock_number int64 = 0

	prescribingNumber_temp := strconv.FormatFloat(math.Abs(prescribingNumber), 'f', 0, 64)
	count, _ := strconv.ParseInt(prescribingNumber_temp, 10, 64)

	var drug_price float64
	if advice.PrescribingNumberUnit == drup.MaxUnit {
		deliver_number = count * drup.MinNumber

	} else {
		deliver_number = count

	}

	if advice.PrescribingNumberUnit == drup.MaxUnit {
		drug_price = drup.RetailPrice
	}
	fmt.Println(drug_price)

	if advice.PrescribingNumberUnit == drup.MinUnit {
		drug_price = drup.MinPrice
	}

	if advice.PrescribingNumberUnit != drup.MaxUnit || advice.PrescribingNumberUnit != drup.MinUnit {
		drug_price = drup.RetailPrice
	}

	// 根据先进先出原则，查询最先入库的批次，进行出库
	// 如果没有对应的库存，则报错
	storeConfig, _ := GetAllStoreHouseConfig(advice.UserOrgId)
	warehouse, err := FindLastDrugWarehousingInfoByID(advice.DrugId, storeConfig.DrugStorehouseOut)

	if err != nil {

		return err
	}

	// 将该批次的剩余库存数量转换为拆零数量

	stock_number = warehouse.StockMaxNumber*drup.MinNumber + warehouse.StockMinNumber

	// 当库存数量大于或等于出库数量的话，则正常出库该批次
	if stock_number >= deliver_number {

		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			RetailPrice:             warehouse.RetailPrice,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number, //出最小单位
			WarehouseInfoId:         warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number, //按最小单位计算,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			SystemTime:              advice.AdviceDate,
			WarehousingDetailId:     warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		CreateDrugFlowOne(drugflow)

		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		fmt.Println(errOne)
		//查询是否存在数据

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   count,
			CountUnit:               advice.PrescribingNumberUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		var maxNumber int64 = 0
		var minNumber int64 = 0
		var stock_max_number int64 = 0
		stock_max_number = warehouse.StockMaxNumber

		maxNumber = deliver_number / drup.MinNumber
		minNumber = deliver_number % drup.MinNumber

		if warehouse.StockMaxNumber == 0 && drup.MaxUnit == drup.MinUnit {
			minNumber = maxNumber
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < maxNumber && warehouse.StockMinNumber < minNumber {
				return errors.New("库存数量不足")
			}
		}

		warehouse.StockMaxNumber = warehouse.StockMaxNumber - maxNumber

		if warehouse.StockMaxNumber < 0 {
			warehouse.StockMaxNumber = 0
		}
		if warehouse.StockMinNumber < 0 {
			warehouse.StockMinNumber = 0
		}

		warehouse.Mtime = time.Now().Unix()

		if warehouse.StockMinNumber < minNumber {

			warehouse.StockMaxNumber = warehouse.StockMaxNumber - 1
			warehouse.StockMinNumber = warehouse.StockMinNumber + drup.MinNumber - minNumber
		} else {
			if minNumber > 0 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - minNumber
			}

			if minNumber == 0 && maxNumber != 1 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			}

		}

		if maxNumber == 1 && minNumber == 0 && drup.MaxUnit != drup.MinUnit {
			warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			if warehouse.StockMinNumber == 0 {
				warehouse.StockMaxNumber = stock_max_number
			}
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < 0 && warehouse.StockMinNumber < 0 {
				return errors.New("库存数量不足")
			}
		}
		if warehouse.StockMinNumber <= 0 {
			warehouse.StockMinNumber = 0
		}

		errThree := UpDateDrugWarehouseInfoByStock(&warehouse)
		if errThree != nil {
			return errThree
		}

		return nil
	} else {
		// 当该批次的库存数量小于出库数量的话，则先把该批次出库完后，再进行递归出库
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number,
			WarehouseInfoId:         warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseOutInfo.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   deliver_number,
			CountUnit:               drup.MinUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		info := models.XtDrugWarehouseInfo{
			ID:                warehouse.ID,
			WarehousingId:     warehouse.WarehousingId,
			DrugId:            warehouse.DrugId,
			Number:            warehouse.Number,
			ProductDate:       warehouse.ProductDate,
			ExpiryDate:        warehouse.ExpiryDate,
			WarehousingCount:  warehouse.WarehousingCount,
			Price:             warehouse.RetailPrice,
			TotalPrice:        warehouse.TotalPrice,
			Dealer:            warehouse.Dealer,
			Manufacturer:      warehouse.Manufacturer,
			Remark:            warehouse.Remark,
			Ctime:             warehouse.Ctime,
			Mtime:             warehouse.Mtime,
			Status:            1,
			OrgId:             warehouse.OrgId,
			IsReturn:          warehouse.IsReturn,
			WarehousingOrder:  warehouse.WarehousingOrder,
			Type:              warehouse.Type,
			RetailPrice:       warehouse.RetailPrice,
			RetailTotalPrice:  warehouse.RetailPrice,
			StockMaxNumber:    0,
			StockMinNumber:    0,
			BatchNumber:       warehouse.BatchNumber,
			MaxUnit:           warehouse.MaxUnit,
			WarehousingInfoId: warehouse.WarehousingInfoId,
			SupplyWarehouseId: warehouse.SupplyWarehouseId,
		}
		//扣减库存
		errThree := UpDateDrugWarehouseInfoByStock(&info)

		if errThree != nil {
			return errThree
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   stock_number,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		CreateDrugFlowOne(drugflow)

		// 清零完该库存后，还有剩余出库未出完，进行对应的递归操作
		prescribingNumber_two_temp := deliver_number - stock_number

		overPlusNumber := float64(prescribingNumber_two_temp)

		advice.PrescribingNumber = float64(prescribingNumber_two_temp)
		advice.PrescribingNumberUnit = advice.PrescribingNumberUnit

		NewPharmacyHisDrugDeliverInfo(orgID, overPlusNumber, warehouseout, drup, advice, id)
	}

	return
}

// 药品出库 递归方式
func NewPharmacyHisDrugDeliverInfo(orgID int64, prescribingNumber float64, warehouseout *models.DrugWarehouseOut, drup *models.BaseDrugLib, advice *models.PharmacyHisDoctorAdviceInfo, id int64) (err error) {

	// 判断处方里药品单位是拆零单位还是包装单位,	如果是包装单位，则根据规格，将包装数量转为拆零数量
	var deliver_number int64 = 0
	var stock_number int64 = 0

	prescribingNumber_temp := strconv.FormatFloat(math.Abs(prescribingNumber), 'f', 0, 64)
	count, _ := strconv.ParseInt(prescribingNumber_temp, 10, 64)

	var drug_price float64

	//按最小单位数据计算
	deliver_number = count

	if advice.PrescribingNumberUnit == drup.MaxUnit {
		drug_price = drup.RetailPrice
	}

	if advice.PrescribingNumberUnit == drup.MinUnit {
		drug_price = drup.MinPrice
	}

	if advice.PrescribingNumberUnit != drup.MaxUnit || advice.PrescribingNumberUnit != drup.MinUnit {
		drug_price = drup.RetailPrice
	}

	// 根据先进先出原则，查询最先入库的批次，进行出库
	// 如果没有对应的库存，则报错
	//查询默认仓库
	storeConfig, _ := GetAllStoreHouseConfig(advice.UserOrgId)
	warehouse, err := FindLastDrugWarehousingInfoByID(advice.DrugId, storeConfig.DrugStorehouseOut)

	if err != nil {

		return err
	}

	// 将该批次的剩余库存数量转换为拆零数量

	stock_number = warehouse.StockMaxNumber*drup.MinNumber + warehouse.StockMinNumber

	// 当库存数量大于或等于出库数量的话，则正常出库该批次
	if stock_number >= deliver_number {
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			RetailPrice:             drug_price,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number, //出最小单位
			WarehouseInfoId:         warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number, //按最小单位计算,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		CreateDrugFlowOne(drugflow)
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   count,
			CountUnit:               advice.PrescribingNumberUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		// 出库完成后，要减去对应批次的库存数量
		// 判断处方里药品单位是拆零单位还是包装单位,	如果是拆零单位，则根据规格，将拆零数量转为包装数量
		var maxNumber int64 = 0
		var minNumber int64 = 0
		var stock_max_number int64 = 0
		stock_max_number = warehouse.StockMaxNumber

		maxNumber = deliver_number / drup.MinNumber
		minNumber = deliver_number % drup.MinNumber

		if warehouse.StockMaxNumber == 0 && drup.MaxUnit == drup.MinUnit {
			minNumber = maxNumber
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < maxNumber && warehouse.StockMinNumber < minNumber {
				return errors.New("库存数量不足")
			}
		}

		warehouse.StockMaxNumber = warehouse.StockMaxNumber - maxNumber

		if warehouse.StockMaxNumber < 0 {
			warehouse.StockMaxNumber = 0
		}
		if warehouse.StockMinNumber < 0 {
			warehouse.StockMinNumber = 0
		}

		warehouse.Mtime = time.Now().Unix()

		if warehouse.StockMinNumber < minNumber {

			warehouse.StockMaxNumber = warehouse.StockMaxNumber - 1
			warehouse.StockMinNumber = warehouse.StockMinNumber + drup.MinNumber - minNumber
		} else {

			if minNumber > 0 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - minNumber
			}

			if minNumber == 0 && maxNumber != 1 {
				warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			}
		}

		if maxNumber == 1 && minNumber == 0 && drup.MaxUnit != drup.MinUnit {

			warehouse.StockMinNumber = warehouse.StockMinNumber - deliver_number
			if warehouse.StockMinNumber == 0 {
				warehouse.StockMaxNumber = stock_max_number
			}
		}

		if drup.MaxUnit != drup.MinUnit {
			if warehouse.StockMaxNumber < 0 && warehouse.StockMinNumber < 0 {
				return errors.New("库存数量不足")
			}
		}
		if warehouse.StockMinNumber <= 0 {
			warehouse.StockMinNumber = 0
		}

		errThree := UpDateDrugWarehouseInfoByStock(&warehouse)

		if errThree != nil {
			return errThree
		}

		return nil
	} else {
		// 当该批次的库存数量小于出库数量的话，则先把该批次出库完后，再进行递归出库
		warehouseOutInfo := &models.DrugWarehouseOutInfo{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			Remark:                  warehouse.Remark,
			OrgId:                   orgID,
			Type:                    1,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			IsSys:                   15,
			SysRecordTime:           advice.RecordDate,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			BatchNumber:             warehouse.BatchNumber,
			Price:                   warehouse.RetailPrice,
			CountUnit:               drup.MinUnit,
			ProductDate:             warehouse.ProductDate,
			ExpiryDate:              warehouse.ExpiryDate,
			PatientId:               advice.PatientId,
			Count:                   deliver_number,
			WarehouseInfoId:         warehouse.ID,
			AdviceId:                advice.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}
		errOne := AddSigleDrugWarehouseOutInfo(warehouseOutInfo)
		if errOne != nil {
			return errOne
		}
		//查询是否存在数据

		details := &models.DrugAutomaticReduceDetail{
			WarehouseOutId:          warehouseout.ID,
			WarehouseOutOrderNumber: warehouseOutInfo.WarehouseOutOrderNumber,
			PatientId:               advice.PatientId,
			Ctime:                   time.Now().Unix(),
			Mtime:                   time.Now().Unix(),
			Status:                  1,
			RecordTime:              advice.RecordDate,
			OrgId:                   orgID,
			DrugId:                  advice.DrugId,
			Count:                   deliver_number,
			CountUnit:               drup.MinUnit,
			WarehouseInfoId:         warehouse.ID,
			StorehouseId:            storeConfig.DrugStorehouseOut,
		}
		errTwo := AddSigleDrugAutoReduceRecordInfo(details)
		if errTwo != nil {
			return errTwo
		}

		// 出库完成后，要将该批次库存清零
		//warehouse.StockMaxNumber = 0
		//warehouse.StockMinNumber = 0
		//warehouse.Mtime = time.Now().Unix()

		info := models.XtDrugWarehouseInfo{
			ID:                warehouse.ID,
			WarehousingId:     warehouse.WarehousingId,
			DrugId:            warehouse.DrugId,
			Number:            warehouse.Number,
			ProductDate:       warehouse.ProductDate,
			ExpiryDate:        warehouse.ExpiryDate,
			WarehousingCount:  warehouse.WarehousingCount,
			Price:             warehouse.Price,
			TotalPrice:        warehouse.TotalPrice,
			Dealer:            warehouse.Dealer,
			Manufacturer:      warehouse.Manufacturer,
			Remark:            warehouse.Remark,
			Ctime:             warehouse.Ctime,
			Mtime:             warehouse.Mtime,
			Status:            1,
			OrgId:             warehouse.OrgId,
			IsReturn:          warehouse.IsReturn,
			WarehousingOrder:  warehouse.WarehousingOrder,
			Type:              warehouse.Type,
			RetailPrice:       warehouse.RetailPrice,
			RetailTotalPrice:  warehouse.RetailPrice,
			StockMaxNumber:    0,
			StockMinNumber:    0,
			BatchNumber:       warehouse.BatchNumber,
			MaxUnit:           warehouse.MaxUnit,
			WarehousingInfoId: warehouse.WarehousingInfoId,
			SupplyWarehouseId: warehouse.SupplyWarehouseId,
			StorehouseId:      storeConfig.DrugStorehouseOut,
		}
		//扣减库存
		errThree := UpDateDrugWarehouseInfoByStock(&info)

		if errThree != nil {
			return errThree
		}

		drugflow := models.DrugFlow{
			WarehouseOutOrderNumber: warehouseout.WarehouseOutOrderNumber,
			WarehouseOutId:          warehouseout.ID,
			DrugId:                  advice.DrugId,
			Number:                  warehouse.Number,
			ProductDate:             warehouse.ProductDate,
			ExpireDate:              warehouse.ExpiryDate,
			Count:                   deliver_number,
			Price:                   warehouse.RetailPrice,
			Status:                  1,
			Ctime:                   time.Now().Unix(),
			UserOrgId:               orgID,
			Manufacturer:            warehouse.Manufacturer,
			Dealer:                  warehouse.Dealer,
			BatchNumber:             warehouse.BatchNumber,
			MaxUnit:                 drup.MinUnit,
			ConsumableType:          3,
			IsEdit:                  1,
			Creator:                 advice.ExecutionStaff,
			IsSys:                   15,
			PatientId:               advice.PatientId,
			WarehousingDetailId:     warehouse.ID,
			AdviceId:                advice.ID,
			SupplyWarehouseId:       warehouse.SupplyWarehouseId,
			StorehouseId:            storeConfig.DrugStorehouseOut,
			ID:                      id,
		}

		CreateDrugFlowOne(drugflow)

		// 清零完该库存后，还有剩余出库未出完，进行对应的递归操作
		prescribingNumber_two_temp := deliver_number - stock_number

		overPlusNumber := float64(prescribingNumber_two_temp)

		advice.PrescribingNumber = float64(prescribingNumber_two_temp)
		advice.PrescribingNumberUnit = advice.PrescribingNumberUnit

		NewPharmacyHisDrugDeliverInfo(orgID, overPlusNumber, warehouseout, drup, advice, id)
	}
	return
}

func GetUseredBloodAdviceList(advice_date int64, drug_id int64, org_id int64) (advice []*models.PharmacyDoctorAdvice, err error) {

	err = XTReadDB().Where("advice_date = ? and drug_id = ? and user_org_id = ? and status = 1 and advice_type =2 and is_medicine= 1", advice_date, drug_id, org_id).Find(&advice).Error
	return advice, err
}

func GetUseredHisAdviceList(advice_date int64, drug_id int64, org_id int64) (advice []*models.PharmacyHisDoctorAdviceInfo, err error) {

	err = XTReadDB().Where("advice_date = ? and drug_id =? and user_org_id =? and status = 1 and is_medicine = 1", advice_date, drug_id, org_id).Order("prescription_id asc").Find(&advice).Error
	return advice, err
}

func UpdateReturnPharmacyAdviceBaseDrug(ids []string, orgid int64) (models.PharmacyDoctorAdvice, error) {

	advice := models.PharmacyDoctorAdvice{}

	err := XTWriteDB().Where("id in(?) and user_org_id = ? and status = 1", ids, orgid).Update(map[string]interface{}{"is_medicine": 0}).Error
	return advice, err
}

func UpdateReturnPharmacyHisAdviceBaseDrug(ids []string, orgid int64) (models.PharmacyHisDoctorAdviceInfo, error) {

	advice := models.PharmacyHisDoctorAdviceInfo{}

	err := XTWriteDB().Where("id in(?) and user_org_id = ? and status = 1", ids, orgid).Update(map[string]interface{}{"is_medicine": 0}).Error
	return advice, err
}

func GetLastPharmary(orgid int64, advice_id int64, record_date int64) (models.Pharmacy, error) {

	pharmacy := models.Pharmacy{}

	err := XTReadDB().Where("user_org_id = ? and advice_id = ? and record_date =? and status =1 ", orgid, advice_id, record_date).Find(&pharmacy).Error

	return pharmacy, err
}

func GetLastHisPharmary(orgid int64, advice_id int64, record_date int64) (models.Pharmacy, error) {

	pharmacy := models.Pharmacy{}

	err := XTReadDB().Where("user_org_id = ? and his_advice_id = ? and record_date =? and status =1 ", orgid, advice_id, record_date).Find(&pharmacy).Error

	return pharmacy, err
}

func GetConfigSettingIsExsit(orgid int64) (*models.PharmacyConfig, error) {

	var pharmacy models.PharmacyConfig
	var err error
	err = readDb.Model(&models.PharmacyConfig{}).Where("user_org_id=? and status = 1", orgid).First(&pharmacy).Error
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &pharmacy, nil
}

func CreatePharmacyConfig(config *models.PharmacyConfig) error {

	err := XTWriteDB().Create(&config).Error
	return err
}

func UpdatePharmacyConfig(orgid int64, config *models.PharmacyConfig) error {

	err := XTWriteDB().Model(&models.PharmacyConfig{}).Where("user_org_id = ? and status = 1", orgid).Updates(map[string]interface{}{"is_open": config.IsOpen, "mtime": time.Now().Unix()}).Error
	return err
}

func GetPharmacyConfig(orgid int64) (models.PharmacyConfig, error) {

	config := models.PharmacyConfig{}
	err := XTReadDB().Where("user_org_id = ? and status = 1", orgid).Find(&config).Error
	if err == gorm.ErrRecordNotFound {
		tmp := models.PharmacyConfig{
			UserOrgId: orgid,
			IsOpen:    2,
			Status:    1,
			Ctime:     time.Now().Unix(),
			Mtime:     time.Now().Unix(),
		}
		errs := XTWriteDB().Create(&tmp).Error
		if errs != nil {
			err = errs
		} else {
			err = nil
		}
		return tmp, err
	}

	return config, err
}
