package service

import (
	"cold-delivery/app/admin/model"
	"cold-delivery/app/admin/service/dto"
	"cold-delivery/common/actions"
	cDto "cold-delivery/common/dto"
	"cold-delivery/common/global"
	"cold-delivery/common/lib"
	model2 "cold-delivery/common/model"
	"cold-delivery/common/nats/nats_server"
	"cold-delivery/conf"
	"encoding/json"
	"errors"
	"fmt"
	http "net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"

	"go.uber.org/zap"
	"gogs.baozhida.cn/zoie/OAuth-core/pkg/sms"
	"gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
	"gogs.baozhida.cn/zoie/OAuth-core/service"
	"gorm.io/gorm"
)

type Waybill struct {
	service.Service
}

func orStatus(id int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if id == 0 {
			return db
		}
		return db.Where("status = ? ", id).Or("status =? ", model.WaybillStatusoverrule)
	}
}

// GetPage 获取Waybill列表
//
//	func (e *Waybill) GetPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
//		var err error
//		var data model.Waybill
//		if c.PageSize == 9999 {
//			err = e.Orm.Model(&data).
//				Scopes(
//					cDto.MakeCondition(c.GetNeedSearch()),
//					actions.Permission(data.TableName(), p),
//				).
//				Preload("CoolerBox").
//				Preload("Delivery").
//				Preload("ReCheck").
//				Find(list).Limit(-1).Offset(-1).
//				Count(count).Error
//			if err != nil {
//				e.Log.Errorf("db error: %s", err)
//				return global.GetFailedErr
//			}
//			return nil
//		}
//
//		err = e.Orm.Model(&data).
//			Scopes(
//				cDto.MakeCondition(c.GetNeedSearch()),
//				cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
//				actions.Permission(data.TableName(), p),
//			).
//			Preload("CoolerBox").
//			Preload("Delivery").
//			Preload("ReCheck").
//			Find(list).Limit(-1).Offset(-1).
//			Count(count).Error
//		if err != nil {
//			e.Log.Errorf("db error: %s", err)
//			return global.GetFailedErr
//		}
//		return nil
//	}
//
//	func (e *Waybill) GetUserPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
//		var err error
//		var data model.Waybill
//		if c.PageSize == 9999 {
//			err = e.Orm.Model(&data).
//				Scopes(
//					cDto.MakeCondition(c.GetNeedSearch()),
//				).
//				Where("create_by = ?", p.UserId).
//				Find(list).Limit(-1).Offset(-1).
//				Count(count).Error
//			if err != nil {
//				e.Log.Errorf("db error: %s", err)
//				return global.GetFailedErr
//			}
//			return nil
//		}
//
//		err = e.Orm.Model(&data).
//			Scopes(
//				cDto.MakeCondition(c.GetNeedSearch()),
//				cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
//			).
//			Where("delivery_id = ? or re_check_id = ? or create_by = ?", p.UserId, p.UserId, p.UserId).
//			Preload("CoolerBox").
//			Preload("Delivery").
//			Preload("ReCheck").
//			Find(list).Limit(-1).Offset(-1).
//			Count(count).Error
//		if err != nil {
//			e.Log.Errorf("db error: %s", err)
//			return global.GetFailedErr
//		}
//		return nil
//	}
func (e *Waybill) GetPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
	var err error
	var data model.Waybill

	// 构建基础查询
	db := e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			actions.Permission(data.TableName(), p),
			orStatus(c.Status),
		).
		Preload("CoolerBox").
		Preload("Delivery").
		Preload("ReCheck")
	// 先计算总条目数
	if err = db.Count(count).Error; err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}

	// 如果PageSize设置为9999，则不分页
	if c.PageSize == 9999 {
		err = db.Find(list).Error
	} else {
		// 应用分页
		err = db.Scopes(
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).Find(list).Error
	}
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	//查询对应药品信息
	for i, _ := range *list {
		var drugs []model.Drug
		e.Orm.Where("drug.waybill_no = ?", (*list)[i].WaybillNo).Find(&drugs)
		(*list)[i].Drugs = drugs
	}
	return nil
}
func (e *Waybill) GetUserPage(c *dto.WaybillGetPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
	var err error
	var data model.Waybill
	// 构建基础查询
	db := e.Orm.Model(&data).
		Scopes(
			orStatus(c.Status),
			cDto.MakeCondition(c.GetNeedSearch()),
		)
	// 添加用户相关的条件
	db = db.Where("delivery_id = ?", p.UserId)
	// 先计算总条目数
	if err = db.Count(count).Error; err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}

	// 如果PageSize设置为9999，则不分页
	if c.PageSize == 9999 {
		err = db.Find(list).Error
	} else {
		// 应用分页
		err = db.Scopes(
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
			Preload("CoolerBox").
			Preload("Delivery").
			Preload("ReCheck").
			Find(list).Error
	}

	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	//查询对应药品信息
	for i, _ := range *list {
		var drugs []model.Drug
		e.Orm.Where("drug.waybill_no = ?", (*list)[i].WaybillNo).Find(&drugs)
		(*list)[i].Drugs = drugs
	}
	return nil
}
func (e *Waybill) GetAppletPage(c *dto.WaybillGetAppletPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
	var err error
	//var data model.Waybill
	var logistics model.WaybillLogistics
	err = e.Orm.Table("waybill").
		Select("waybill.*,waybill_logistics.status as status").
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			actions.Permission(logistics.TableName(), p)).
		Where("waybill_logistics.id in (SELECT MAX(id) FROM waybill_logistics where user_id = ? group by waybill_no )", p.UserId).
		Joins("left join waybill_logistics on waybill.waybill_no = waybill_logistics.waybill_no").
		Find(&list).Limit(-1).Offset(-1).Count(count).Error

	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

func (e *Waybill) GetAppletCount(list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
	var err error
	//var data model.Waybill
	var logistics model.WaybillLogistics
	err = e.Orm.Table("waybill").
		Select("waybill.*,waybill_logistics.status as status").
		Scopes(
			actions.Permission(logistics.TableName(), p)).
		Where("waybill_logistics.id in (SELECT MAX(id) FROM waybill_logistics where user_id = ? group by waybill_no )", p.UserId).
		Joins("left join waybill_logistics on waybill.waybill_no = waybill_logistics.waybill_no").
		Find(list).Count(count).Error

	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

func (e *Waybill) GetCustomerPage(c *dto.WaybillGetCustomerPageReq, list *[]model.Waybill, count *int64, p *actions.DataPermission) error {
	var err error
	var data model.Waybill

	if c.PageSize == 9999 {
		err = e.Orm.Model(&data).
			Scopes(
				cDto.MakeCondition(c.GetNeedSearch()),
				actions.Permission(data.TableName(), p),
			).
			Find(list).Limit(-1).Offset(-1).
			Count(count).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return global.GetFailedErr
		}
		return nil
	}

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			actions.Permission(data.TableName(), p),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

// Get 获取Waybill对象
func (e *Waybill) Get(d *dto.WaybillGetReq, waybillModel *model.Waybill, p *actions.DataPermission) error {
	err := e.Orm.
		Scopes(actions.Permission(waybillModel.TableName(), p)).
		Preload("User").
		First(waybillModel, d.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}

	return nil
}
func (e *Waybill) GetByWaybillNo(d *dto.WaybillGetByWaybillPdfReq, waybillModel *model.Waybill, p *actions.DataPermission) error {
	err := e.Orm.
		Scopes(actions.Permission(waybillModel.TableName(), p)).
		Where("waybill.waybill_no = ?", d.WaybillNo).
		Joins("left join drug on drug.waybill_no = waybill.waybill_no").
		Preload("Dept").
		Preload("CoolerBox").
		Preload("Delivery").
		Preload("ReCheck").
		First(waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}
	var drugs []model.Drug
	e.Orm.Where("drug.waybill_no = ?", waybillModel.WaybillNo).Find(&drugs)
	waybillModel.Drugs = drugs

	return nil
}

// Insert 创建Waybill对象
func (e *Waybill) Insert(c *dto.WaybillInsertReq) error {
	var err error
	var data model.Waybill

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var no string
	for {
		no = time.Now().Format("200601021504") + utils.GetRandString(6, "0123456789", 0)
		var j int64
		err = e.Orm.Model(&data).Where("waybill_no = ?", no).Count(&j).Error
		if err != nil {
			continue
		}
		if j == 0 {
			break
		}
	}

	// 添加运单
	data.WaybillNo = no
	sole, err := e.CreateSole()
	if err != nil {
		err = errors.New("生成运单号失败")
		return err
	}
	data.OrderNo = sole
	c.Generate(&data)
	if c.IsPhone {
		data.Status = model.WaybillStatusInDeliverys
		data.AssignmentStatus = 2
	}
	err = tx.Create(&data).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	c.Id = data.Id

	// 保存发货地址
	if c.SaveConsigneeAddress {
		// 查询地址是否存在
		address := model.Address{}
		err = e.Orm.Where("address = ? and phone = ? and name = ? and dept_id = ? and address_type = 'consignee'",
			c.ConsigneeAddressDetails, c.ConsigneeAddressPhone, c.ConsigneeAddressName, c.DeptId).First(&address).Error
		if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
			address.Address = c.ConsigneeAddressDetails
			address.Phone = c.ConsigneeAddressPhone
			address.Name = c.ConsigneeAddressName
			address.DeptId = c.DeptId
			address.AddressType = "consignee"
			err = tx.Create(&address).Error
			if err != nil {
				e.Log.Errorf("创建地址失败: %s", err)
				return global.CreateFailedErr
			}
		}
	}
	if len(c.Drugs) > 0 {
		for _, drug := range c.Drugs {
			//var count int64
			//e.Orm.Model(&model.Drug{}).Where("code = ?", drug.Code).Count(&count)
			//if count > 0 {
			//	return errors.New("药品编号已存在")
			//}
			var drugs model.Drug
			drugs.WaybillNo = no
			drugs.Drug_ent_base_info_id = drug.Drug_ent_base_info_id
			drugs.Ent_name = drug.Ent_name
			drugs.Physic_name = drug.Physic_name
			drugs.Approval_licence_no = drug.Approval_licence_no
			drugs.Prepn_spec = drug.Prepn_spec
			drugs.Physic_type_desc = drug.Physic_type_desc
			drugs.Pkg_spec_crit = drug.Pkg_spec_crit
			drugs.Prepn_type_desc = drug.Prepn_type_desc
			drugs.Code = drug.Code
			err = tx.Save(&drugs).Error
			if err != nil {
				e.Log.Errorf("db error: %s", err)
				return errors.New("保存药品信息失败")
			}
		}
	}
	return nil
}

// Update 修改Waybill对象
func (e *Waybill) Update(c *dto.WaybillUpdateReq, p *actions.DataPermission) error {
	var err error

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var waybillModel = model.Waybill{}
	// 查询运单是否存在
	err = e.Orm.Scopes(actions.Permission(waybillModel.TableName(), p)).
		First(&waybillModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}
	c.Generate(&waybillModel)
	var count int64
	//var codes []string
	//tx.Model(&model.Drug{}).Select("code").Where("waybill_no = ?", waybillModel.WaybillNo).Find(&codes)
	tx.Model(&model.Drug{}).Where("waybill_no = ?", waybillModel.WaybillNo).Count(&count)
	for _, drug := range c.Drugs {
		if count > 0 {
			err = tx.Model(&model.Drug{}).Where("waybill_no = ?", waybillModel.WaybillNo).Delete(&model.Drug{}).Error
			if err != nil {
				e.Log.Errorf("删除药品信息失败: %s", err)
				return errors.New("删除药品信息失败")
			}
		}
		var drugs model.Drug
		drugs.WaybillNo = waybillModel.WaybillNo
		drugs.Drug_ent_base_info_id = drug.Drug_ent_base_info_id
		drugs.Ent_name = drug.Ent_name
		drugs.Physic_name = drug.Physic_name
		drugs.Approval_licence_no = drug.Approval_licence_no
		drugs.Prepn_spec = drug.Prepn_spec
		drugs.Physic_type_desc = drug.Physic_type_desc
		drugs.Pkg_spec_crit = drug.Pkg_spec_crit
		drugs.Prepn_type_desc = drug.Prepn_type_desc
		drugs.Code = drug.Code
		err = tx.Save(&drugs).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return errors.New("保存药品信息失败")
		}

	}
	err = tx.Where("id = ?", waybillModel.Id).Updates(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}

	c.Id = waybillModel.Id
	return nil
}

// 审核订单
func (e *Waybill) Audit(c *dto.WaybillUpdateReqaudit, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var waybillModel = model.Waybill{}
	// 查询运单是否存在
	err = e.Orm.Scopes(actions.Permission(waybillModel.TableName(), p)).
		First(&waybillModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}
	c.Generate(&waybillModel)
	waybillModel.Status = c.Status
	waybillModel.ReCheckId = p.UserId
	err = tx.Updates(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}
	c.Id = waybillModel.Id
	return nil
}

// AdminAudit 管理员审核订单
func (e *Waybill) AdminAudit(c *dto.WaybillAdmin, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var waybillModel = model.Waybill{}
	// 查询运单是否存在
	err = e.Orm.Scopes(actions.Permission(waybillModel.TableName(), p)).
		First(&waybillModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}
	c.Generate(&waybillModel)
	waybillModel.AdminAuditRemark = c.AdminAuditRemark
	err = tx.Updates(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.UpdateFailedErr
	}
	c.Id = waybillModel.Id
	return nil
}
func (e *Waybill) UpdateStatus(c *dto.UpdateStatusReq, p *actions.DataPermission) error {
	var err error
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 查询运单是否存在
	for _, v := range c.Id {
		var waybillModel = model.Waybill{}
		err = e.Orm.Scopes(actions.Permission(waybillModel.TableName(), p)).
			First(&waybillModel, v).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return global.UpdateNotFoundOrNoPermissionErr
			}
			return global.UpdateFailedErr
		}
		//添加确认人信息
		if c.Status == model.WaybillStatusAudits {
			err, sysUser := GetUserProfile(e.Orm, p.UserId)
			if err != nil {
				e.Log.Errorf("db 获取用户信息失败: %s", err)
				return errors.New("获取用户信息失败")
			}
			waybillModel.Confirmer = sysUser.NickName
			waybillModel.ConfirmerPhone = sysUser.Phone
		}
		waybillModel.Status = c.Status
		err = tx.Table(waybillModel.TableName()).Where("id=?", v).Updates(&waybillModel).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return global.UpdateFailedErr
		}
	}
	return nil
}

// 待取药装箱（分配保温箱、冰排、防伪标签）
func (e *Waybill) Packing(c *dto.WaybillPackingReq, p *actions.DataPermission) error {
	var err error

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 处理冰排出库逻辑
	if !lib.StrListEqual(c.IceRaftCode, c.OldIceRaftCode) {
		extraData := lib.FindStrListExtraData(c.OldIceRaftCode, c.IceRaftCode)
		if len(extraData) > 0 {
			for _, code := range extraData {
				var iceRaft model.IceRaft
				err = tx.Model(&model.IceRaft{}).Where("code = ?", code).Preload("IceRaftRecord").First(&iceRaft).Error
				if err != nil {
					e.Log.Errorf("db error: %s", err)
					if errors.Is(err, gorm.ErrRecordNotFound) {
						return errors.New(fmt.Sprintf("冰排【%s】不存在", code))
					}
					return errors.New(fmt.Sprintf("获取冰排【%s】信息失败", code))
				}
				// 更新冰排记录为使用中
				err = tx.Model(&model.IceRaftRecord{}).
					Where("ice_raft_id = ? and status in (?)", iceRaft.Id, []string{
						model.IceRaftRecordStatusFreezing,
						model.IceRaftRecordStatusWaitUse,
						model.IceRaftRecordReleasedInTheCold,
					}).
					Updates(map[string]interface{}{
						"status":           model.IceRaftRecordStatusUsing,
						"out_storage_time": time.Now(),
						"cooler_box_id":    c.CoolerBoxId,
					}).Error
				if err != nil {
					e.Log.Errorf("db error: %s", err)
					return errors.New(fmt.Sprintf("冰排【%s】出库失败", iceRaft.Code))
				}
			}
		}
	}

	for _, id := range c.WaybillIds {
		var waybillModel = model.Waybill{}
		err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
			First(&waybillModel, id).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return global.UpdateNotFoundOrNoPermissionErr
			}
			return global.UpdateFailedErr
		}

		// 只有待取药装箱状态(9)才能进行装箱操作
		if waybillModel.Status != model.WaybillStatusPacking {
			return errors.New("当前订单状态不允许装箱操作")
		}

		// 装箱完成，状态变更为待配送(3)
		waybillModel.Status = model.WaybillStatusInDeliverys
		waybillModel.CoolerBoxId = c.CoolerBoxId
		waybillModel.IceRaftCode = c.IceRaftCode
		waybillModel.TamperProofLabel = c.TamperProofLabel
		waybillModel.TamperProofLabelImg = c.TamperProofLabelImg

		err = tx.Save(&waybillModel).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return global.UpdateFailedErr
		}
	}

	return nil
}

func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission) error {
	var err error
	e.Log.Errorf("DELIVERY_V2_NEW_SMS_ENABLED")

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 只分配配送员
	for _, id := range c.WaybillIds {
		var waybillModel = model.Waybill{}
		err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
			First(&waybillModel, id).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return global.UpdateNotFoundOrNoPermissionErr
			}
			return global.UpdateFailedErr
		}

		// 只有待配送状态(3)才能进行派单
		if waybillModel.Status != model.WaybillStatusInDeliverys {
			return errors.New("当前订单状态不允许派单操作")
		}

		waybillModel.DeliveryId = c.DeliveryId
		waybillModel.AssignmentStatus = 2
		waybillModel.DeliveryTime = model2.Time(time.Now())
		waybillModel.SecondaryTime = model2.Time(time.Now())

		// 分配配送员后向配送员发送通知短信
		if c.Status != model.WaybillStatusInShippeds && c.DeliveryId > 0 {
			var deliveryUser model.SysUser
			if e.Orm.Where("id = ?", c.DeliveryId).First(&deliveryUser).Error == nil && deliveryUser.Phone != "" {
				if smsErr := SendSmsToDeliveryPerson(deliveryUser.Phone, waybillModel.OrderNo); smsErr != nil {
					e.Log.Errorf("配送通知短信发送失败, phone=%s, orderNo=%s, err=%s", deliveryUser.Phone, waybillModel.OrderNo, smsErr)
				} else {
					waybillModel.SendLog = model.WaybillSendLog{
						Phone:   deliveryUser.Phone,
						Content: BuildSmsSendLog(deliveryUser.Phone, waybillModel.OrderNo),
					}
				}
			}
		}

		// 如果传入状态为配送中(4)，则直接变为配送中
		if c.Status == model.WaybillStatusInShippeds {
			waybillModel.Status = c.Status

			// 配送中状态下发送短信
			addr := conf.ExtConfig.Applet.WaybillUrl + url.QueryEscape(lib.AesEncryptCBC(waybillModel.WaybillNo, lib.AesKey))
			res, err1 := CustomSmsXSend(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature, waybillModel.ConsigneeAddressPhone, addr)
			if err1 != nil || res.Status != sms.SUCCESS {
				e.Log.Errorf("派单短信发送失败", zap.Any("res", res), zap.Error(err1))
				err = errors.New("派单短信发送失败，请检查收件人电话是否正确！")
				return err
			}
			waybillModel.SendLog = model.WaybillSendLog{
				Phone:   waybillModel.ConsigneeAddressPhone,
				Content: "【贵州宝智达冷链科技公司】您的订单正在派送中，点击查看详情：" + addr,
			}
		}

		err = tx.Save(&waybillModel).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return global.UpdateFailedErr
		}
	}
	return nil
}

// Delivery 派单
//func (e *Waybill) Delivery(c *dto.WaybillDeliveryReq, p *actions.DataPermission) error {
//	var err error
//
//	tx := e.Orm.Begin()
//	defer func() {
//		if err != nil {
//			tx.Rollback()
//		} else {
//			tx.Commit()
//		}
//	}()
//	var user model.SysUser
//	first := e.Orm.Table(user.TableName()).Where("id = ?", p.UserId).First(&user)
//	if first.Error != nil {
//		return global.GetFailedErr
//	}
//
//	if !lib.StrListEqual(c.IceRaftCode, c.OldIceRaftCode) {
//		// 获取删除的冰排列表
//		//missingIceRaftCode = lib.FindStrListMissingData(c.OldIceRaftCode, c.IceRaftCode)
//
//		//if len(missingIceRaftCode) > 0 {
//		//	// 删除冰排出库记录
//		//	IceRaftList := []model.IceRaft{}
//		//	err = tx.Model(&model.IceRaft{}).Where("code in (?)", missingIceRaftCode).Find(&IceRaftList).Error
//		//	if err != nil {
//		//		e.Log.Errorf("db error: %s", err)
//		//		return errors.New("获取冰排列表失败")
//		//	}
//		//	for _, iceRaft := range IceRaftList {
//		//		// 获取冰排记录
//		//		err = tx.Model(&model.IceRaftRecord{}).
//		//			Where("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordStatusUsing).
//		//			Updates(map[string]interface{}{
//		//				"status":           model.IceRaftRecordStatusWaitUse,
//		//				"out_storage_time": nil,
//		//				"cooler_box_id":    0,
//		//			}).Error
//		//		if err != nil {
//		//			e.Log.Errorf("db error: %s", err)
//		//			return errors.New(fmt.Sprintf("冰排【%s】返库失败", iceRaft.Code))
//		//		}
//		//	}
//		//}
//		// 获取新增的冰排列表
//		//判断是否可以随时出库冰排
//		extraData := lib.FindStrListExtraData(c.OldIceRaftCode, c.IceRaftCode)
//		if len(extraData) > 0 {
//			for _, code := range extraData {
//				var iceRaft model.IceRaft
//				err = tx.Model(&model.IceRaft{}).Where("code = ?", code).Preload("IceRaftRecord").First(&iceRaft).Error
//				if err != nil {
//					e.Log.Errorf("db error: %s", err)
//					if errors.Is(err, gorm.ErrRecordNotFound) {
//						return errors.New(fmt.Sprintf("冰排【%s】不存在", code))
//					} else {
//						return errors.New(fmt.Sprintf("获取冰排【%s】信息失败", code))
//					}
//
//				}
//				if user.Dept.IsOutStorage {
//					if iceRaft.IceRaftRecord.Status != model.IceRaftRecordStatusWaitUse {
//						err = errors.New(fmt.Sprintf("冰排【%s】状态为%s，出库保温箱失败！", code, model.GetIceRaftRecordStatus(iceRaft.IceRaftRecord.Status)))
//						return err
//					}
//					err = tx.Model(&model.IceRaftRecord{}).
//						Where("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordStatusWaitUse).
//						Updates(map[string]interface{}{
//							"status":           model.IceRaftRecordStatusUsing,
//							"out_storage_time": time.Now(),
//							"cooler_box_id":    c.CoolerBoxId,
//						}).Error
//					if err != nil {
//						e.Log.Errorf("db error: %s", err)
//						return errors.New(fmt.Sprintf("冰排【%s】出库失败", iceRaft.Code))
//					}
//
//				} else {
//					err = tx.Model(&model.IceRaftRecord{}).
//						Where("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordStatusFreezing).
//						Or("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordStatusWaitUse).
//						Or("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordReleasedInTheCold).
//						Updates(map[string]interface{}{
//							"status":           model.IceRaftRecordStatusUsing,
//							"out_storage_time": time.Now(),
//							"cooler_box_id":    c.CoolerBoxId,
//						}).Error
//					if err != nil {
//						e.Log.Errorf("db error: %s", err)
//						return errors.New(fmt.Sprintf("冰排【%s】出库失败", iceRaft.Code))
//					}
//				}
//				// 获取冰排记录
//				//err = tx.Model(&model.IceRaftRecord{}).
//				//	Where("ice_raft_id = ? and status = ?", iceRaft.Id, model.IceRaftRecordStatusWaitUse).
//				//	Updates(map[string]interface{}{
//				//		"status":           model.IceRaftRecordStatusUsing,
//				//		"out_storage_time": time.Now(),
//				//		"cooler_box_id":    c.CoolerBoxId,
//				//	}).Error
//				//if err != nil {
//				//	e.Log.Errorf("db error: %s", err)
//				//	return errors.New(fmt.Sprintf("冰排【%s】出库失败", iceRaft.Code))
//				//}
//			}
//		}
//	}
//
//	var coolerBox = model.CoolerBox{}
//	// 查询保温箱信息
//	if c.CoolerBoxId != 0 {
//		err = tx.Scopes(actions.Permission(coolerBox.TableName(), p)).
//			First(&coolerBox, c.CoolerBoxId).Error
//		if err != nil {
//			e.Log.Errorf("获取保温箱信息失败: %s", err)
//			return errors.New("获取保温箱信息失败")
//		}
//	}
//
//	for _, id := range c.WaybillIds {
//
//		var waybillModel = model.Waybill{}
//		// 查询运单是否存在
//		err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
//			First(&waybillModel, id).Error
//		if err != nil {
//			e.Log.Errorf("db error: %s", err)
//			if errors.Is(err, gorm.ErrRecordNotFound) {
//				return global.UpdateNotFoundOrNoPermissionErr
//			}
//			return global.UpdateFailedErr
//		}
//		//派单时添加
//		//waybillModeStatus := waybillModel.Status
//		if waybillModel.Status == model.WaybillStatusInDeliverys || (waybillModel.Status == model.WaybillStatusInDeliverys && waybillModel.CoolerBoxId != c.CoolerBoxId) || (waybillModel.Status == model.WaybillStatusInDeliverys && !lib.StrListEqual(c.IceRaftCode, c.OldIceRaftCode)) {
//			waybillModel.Status = model.WaybillStatusInDeliverys
//			waybillModel.TamperProofLabel = c.TamperProofLabel
//			waybillModel.TamperProofLabelImg = c.TamperProofLabelImg // 防拆标签
//			waybillModel.DeliveryId = c.DeliveryId
//			waybillModel.AssignmentStatus = 2 // 分配状态 2 已派单
//			waybillModel.CoolerBoxId = c.CoolerBoxId
//			waybillModel.DeliveryTime = model2.Time(time.Now())
//			waybillModel.IceRaftCode = c.IceRaftCode
//			waybillModel.SecondaryTime = model2.Time(time.Now()) //分配时间
//			if c.Status == model.WaybillStatusInShippeds {
//				waybillModel.Status = c.Status
//				var data model.IceRaft
//				var list []string
//				err := e.Orm.Model(&data).
//					Select("ice_raft.code").
//					Scopes(
//						actions.Permission(data.TableName(), p),
//						IceRaftNameRecordStatusScopes(model.IceRaftRecordStatusUsing),
//						IceRaftNameRecordCoolerBoxIdScopes(c.CoolerBoxId),
//					).
//					Joins("left join ice_raft_record on ice_raft.ice_raft_record_id = ice_raft_record.id").
//					Find(&list).Error
//				if err != nil {
//					e.Log.Errorf("db error: %s", err)
//					return errors.New("获取冰排编号失败")
//				}
//				//查询保温箱记录信息状态为1使用中
//				var cooler model.CoolerBoxRecord
//				var count int64
//				e.Orm.Scopes(actions.Permission(cooler.TableName(), p)).
//					Where("cooler_box_id = ?", c.CoolerBoxId).Where("status = ?", 1).First(&cooler).Count(&count)
//				if count == 0 {
//					cooler.CoolerBoxId = c.CoolerBoxId
//					cooler.Name = coolerBox.Name
//					cooler.Sn = coolerBox.Sn
//					cooler.CoolerUseUsers = user.NickName
//					cooler.CoolerUserTime = model2.Time(time.Now())
//					cooler.Status = "1" //使用结束
//					cooler.DeptId = user.DeptId
//					if len(list) == 0 {
//						cooler.HistoryCode = append(cooler.HistoryCode, c.IceRaftCode...)
//						cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
//					} else {
//						cooler.HistoryCode = append(cooler.HistoryCode, list...)
//						cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
//					}
//					err := e.Orm.Save(&cooler).Error
//					if err != nil {
//						e.Log.Errorf("保存保温箱记录失败: %s", err)
//						return errors.New("保存保温箱记录失败")
//					}
//				} else {
//					cooler.CoolerUseUsers = user.NickName
//					if len(list) == 0 {
//						cooler.HistoryCode = append(cooler.HistoryCode, c.IceRaftCode...)
//						cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
//					} else {
//						cooler.HistoryCode = append(cooler.HistoryCode, list...)
//						cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
//					}
//					err = e.Orm.Updates(&cooler).Where("id = ?", cooler.Id).Error
//					if err != nil {
//						e.Log.Errorf("保存保温箱记录失败: %s", err)
//						return errors.New("保存保温箱记录失败")
//					}
//				}
//				// 配送中状态下才发送短信 （改用普通短信 Send，无需模板）
//				// 配送中状态下才发送短信（改用自定义模板发送）
//				addr := conf.ExtConfig.Applet.WaybillUrl + url.QueryEscape(lib.AesEncryptCBC(waybillModel.WaybillNo, lib.AesKey))
//				res, err1 := CustomSmsXSend(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature, waybillModel.ConsigneeAddressPhone, addr)
//				if err1 != nil || res.Status != sms.SUCCESS {
//					e.Log.Errorf("派单短信发送失败", zap.Any("res", res), zap.Error(err1))
//					err = errors.New("派单短信发送失败，请检查收件人电话是否正确！")
//					return err
//				}
//				waybillModel.SendLog = model.WaybillSendLog{
//					Phone:   waybillModel.ConsigneeAddressPhone,
//					Content: "【贵州宝智达冷链科技公司】您的订单正在派送中，点击查看详情：" + addr, // 同步改成新模板的文案
//				}
//				//// 查询任务
//				//var logistics model.WaybillLogistics
//				// 添加物流
//				//logisticsObj := model.WaybillLogistics{
//				//	WaybillNo:   waybillModel.WaybillNo,
//				//	Status:      waybillModel.Status,
//				//	CoolerBoxId: coolerBox.Id,
//				//	ControlBy: model2.ControlBy{
//				//		CreateBy: p.UserId,
//				//	},
//				//	DeptBy: model2.DeptBy{
//				//		DeptId: p.DeptId,
//				//	},
//				//}
//				//err = tx.Create(&logisticsObj).Error
//				//if err != nil {
//				//	e.Log.Errorf("db error: %s", err)
//				//	return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//				//}
//				//logistics.CoolerBoxId = coolerBox.Id
//				//err = tx.Save(&logistics).Error
//				//if err != nil {
//				//	e.Log.Errorf("db error: %s", err)
//				//	return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//				//}
//			}
//			// 查询任务
//			err = tx.Save(&waybillModel).Error
//			if err != nil {
//				e.Log.Errorf("db error: %s", err)
//				return global.UpdateFailedErr
//			}
//			// 查询任务
//			//var logistics model.WaybillLogistics
//			//err = tx.Model(&logistics).Where("waybill_no = ?", waybillModel.WaybillNo).
//			//	Last(&logistics).Error
//			//if err != nil {
//			//	if errors.Is(err, gorm.ErrRecordNotFound) {
//			//		// 添加物流
//			//		logisticsObj := model.WaybillLogistics{
//			//			WaybillNo:   waybillModel.WaybillNo,
//			//			Status:      waybillModel.Status,
//			//			CoolerBoxId: coolerBox.Id,
//			//			ControlBy: model2.ControlBy{
//			//				CreateBy: p.UserId,
//			//			},
//			//			DeptBy: model2.DeptBy{
//			//				DeptId: p.DeptId,
//			//			},
//			//		}
//			//		err = tx.Create(&logisticsObj).Error
//			//		if err != nil {
//			//			e.Log.Errorf("db error: %s", err)
//			//			return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//			//		}
//			//	} else {
//			//		e.Log.Errorf("db error: %s", err)
//			//		return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//			//	}
//			//	logistics.CoolerBoxId = coolerBox.Id
//			//	err = tx.Save(&logistics).Error
//			//	if err != nil {
//			//		e.Log.Errorf("db error: %s", err)
//			//		return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//			//	}
//			//}
//			// 添加物流
//			logisticsObj := model.WaybillLogistics{
//				WaybillNo:   waybillModel.WaybillNo,
//				Status:      waybillModel.Status,
//				CoolerBoxId: coolerBox.Id,
//				ControlBy: model2.ControlBy{
//					CreateBy: p.UserId,
//				},
//				DeptBy: model2.DeptBy{
//					DeptId: p.DeptId,
//				},
//			}
//			err = tx.Create(&logisticsObj).Error
//			if err != nil {
//				e.Log.Errorf("db error: %s", err)
//				return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
//			}
//			// 查询任务
//			var task model.WaybillTask
//			err = tx.Model(&task).Where("waybill_no = ? ", waybillModel.WaybillNo).
//				Last(&task).Error
//			if err != nil {
//				if errors.Is(err, gorm.ErrRecordNotFound) {
//					// 添加任务
//					taskObj := model.WaybillTask{
//						WaybillNo:   waybillModel.WaybillNo,
//						CoolerBoxId: coolerBox.Id,
//						UserId:      p.UserId,
//						Sn:          coolerBox.Sn,
//						StartTime:   model2.Time(time.Now()),
//						ControlBy: model2.ControlBy{
//							CreateBy: p.UserId,
//						},
//						DeptBy: model2.DeptBy{
//							DeptId: p.DeptId,
//						},
//					}
//					err = tx.Create(&taskObj).Error
//					if err != nil {
//						e.Log.Errorf("db error: %s", err)
//						return errors.New(fmt.Sprintf("保存运单任务信息失败：%s", err))
//					}
//				} else {
//					//task.StartTime = model2.Time(time.Now())
//					task.UpdateBy = p.UserId
//					task.CoolerBoxId = coolerBox.Id
//					task.Sn = coolerBox.Sn
//					err = tx.Save(&task).Error
//					if err != nil {
//						e.Log.Errorf("db error: %s", err)
//						return errors.New(fmt.Sprintf("保存运单任务信息失败：%s", err))
//					}
//				}
//			} else {
//				task.UpdateBy = p.UserId
//				task.CoolerBoxId = coolerBox.Id
//				task.Sn = coolerBox.Sn
//				err = tx.Save(&task).Error
//				if err != nil {
//					e.Log.Errorf("db error: %s", err)
//					return errors.New(fmt.Sprintf("保存运单任务信息失败：%s", err))
//				}
//			}
//		}
//	}
//	return nil
//}

// Remove 删除Waybill
func (e *Waybill) Remove(c *dto.WaybillDeleteReq, p *actions.DataPermission) error {
	var err error

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var waybillModel model.Waybill

	// 查询运单是否存在
	err = e.Orm.Scopes(actions.Permission(waybillModel.TableName(), p)).
		First(&waybillModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.DeleteNotFoundOrNoPermissionErr
		}
		return global.DeleteFailedErr
	}
	if waybillModel.Status != model.WaybillStatusWaitDelivery {
		return errors.New(fmt.Sprintf("运单状态为%s，禁止删除", model.WaybillStatusMap[waybillModel.Status]))
	}

	db := tx.Delete(&waybillModel)

	if err = db.Error; err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.DeleteFailedErr
	}
	if db.RowsAffected == 0 {
		return global.DeleteNotFoundOrNoPermissionErr
	}

	return nil
}

func (e *Waybill) Receipt(c *dto.WaybillReceiptReq, p *actions.DataPermission) error {
	var err error

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var waybillModel = model.Waybill{}
	// 查询运单是否存在
	err = tx.
		Where("waybill_no = ?", c.WaybillNo).
		First(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New(fmt.Sprintf("运单号%s不存在", c.WaybillNo))
		}
		return errors.New(fmt.Sprintf("运单号%s查询失败", c.WaybillNo))
	}
	err, user := GetUserProfile(e.Orm, waybillModel.DeliveryId)
	if err != nil {
		return errors.New("获取用户信息失败")
	}

	// 查询保温箱信息，无保温箱时跳过
	var coolerBox model.CoolerBox
	if waybillModel.CoolerBoxId > 0 {
		err = tx.First(&coolerBox, waybillModel.CoolerBoxId).Error
		if err != nil {
			e.Log.Errorf("db error: %s", err)
			return errors.New("获取保温箱信息失败")
		}
	}
	// 查询保温箱信息
	//var coolerBox = model.CoolerBox{}
	//err = tx.
	//	First(&coolerBox, waybillModel.CoolerBoxId).Error
	//if err != nil {
	//	e.Log.Errorf("db error: %s", err)
	//	return errors.New("获取保温箱信息失败")
	//}
	if waybillModel.Status == model.WaybillStatusWaitDelivery {
		err = errors.New(fmt.Sprintf("运单状态为%s，禁止操作", model.WaybillStatusMap[waybillModel.Status]))
		return err
	}
	//更新保温箱状态为默认状态0，无保温箱时跳过
	if waybillModel.CoolerBoxId > 0 {
		err = tx.Model(&model.CoolerBox{}).Where("id =?", coolerBox.Id).Update("use_status", 0).Error
		if err != nil {
			e.Log.Errorf("更新保温箱状态失败: %s", err)
			return errors.New("更新保温箱状态失败")
		}
	}
	//更新保温箱状态为默认状态0
	//err = tx.Model(&model.CoolerBox{}).Where("id =?", coolerBox.Id).Update("use_status", 0).Error
	//if err != nil {
	//	e.Log.Errorf("更新保温箱状态失败: %s", err)
	//	return errors.New("更新保温箱状态失败")
	//}

	if waybillModel.Status == model.WaybillStatusReceipts || waybillModel.Status == model.WaybillStatusRejections {
		return nil
	}
	waybillModel.Status = c.Status
	waybillModel.RejectionReason = c.RejectionReason
	waybillModel.ReceiptTime = model2.Time(time.Now())
	waybillModel.ReceiptImg = c.ReceiptImg
	waybillModel.Receiptsign = c.Receiptsign
	waybillModel.PaymentStatus = c.PaymentStatus
	waybillModel.PaymentType = c.PaymentType
	waybillModel.PaymentRemark = c.PaymentRemark
	waybillModel.AssessContent = c.AssessContent
	waybillModel.AssessStar = c.AssessStar
	waybillModel.DeliveryDuration = int(time.Now().Sub(waybillModel.DeliveryTime.Local()).Minutes())
	err = tx.Save(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return errors.New(fmt.Sprintf("保存运单信息失败：%s", err))
	}
	var lng, lat string
	// 获取定位信息，无保温箱时跳过，失败不阻塞签收
	if waybillModel.CoolerBoxId > 0 {
		lng, lat, err = e.GetSite(waybillModel.DeptId, coolerBox.Sn, waybillModel.ReceiptTime.String())
		if err != nil {
			e.Log.Errorf("获取定位信息失败: %s", err)
		}
	}
	// 获取定位信息
	//var lng, lat string
	//lng, lat, err = e.GetSite(waybillModel.DeptId, coolerBox.Sn, waybillModel.ReceiptTime.String())
	//if err != nil {
	//	e.Log.Errorf("获取定位信息失败: %s", err)
	//	return err
	//}
	// 保温箱记录和任务处理，无保温箱时跳过
	if waybillModel.CoolerBoxId > 0 {
		//查询保温箱记录信息状态为1使用中
		var cooler model.CoolerBoxRecord
		var count int64
		tx.Where("cooler_box_id = ?", coolerBox.Id).Where("status = ?", 1).First(&cooler).Count(&count)
		if count == 0 {
			cooler.CoolerBoxId = coolerBox.Id
			cooler.Name = coolerBox.Name
			cooler.Sn = coolerBox.Sn
			cooler.CoolerUseUsers = user.NickName
			cooler.CoolerEndUseTime = model2.Time(time.Now())
			cooler.Status = "2"
			cooler.DeptId = user.DeptId
			if len(waybillModel.IceRaftCode) == 0 {
				cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
			} else {
				cooler.HistoryCode = append(cooler.HistoryCode, waybillModel.IceRaftCode...)
				cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
			}
			err := tx.Save(&cooler).Error
			if err != nil {
				e.Log.Errorf("保存保温箱记录失败: %s", err)
				return errors.New("保存保温箱记录失败")
			}
		} else {
			cooler.CoolerUseUsers = user.NickName
			if len(waybillModel.IceRaftCode) == 0 {
				cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
			} else {
				cooler.HistoryCode = append(cooler.HistoryCode, waybillModel.IceRaftCode...)
				cooler.HistoryCode = cDto.UniqueSlice(cooler.HistoryCode)
			}
			err = tx.Updates(&cooler).Where("id = ?", cooler.Id).Error
			if err != nil {
				e.Log.Errorf("保存保温箱记录失败: %s", err)
				return errors.New("保存保温箱记录失败")
			}
		}

		// 查询任务
		var task model.WaybillTask
		err = tx.Model(&task).Where("waybill_no = ? and cooler_box_id = ?", c.WaybillNo, coolerBox.Id).
			Last(&task).Error
		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			e.Log.Errorf("db error: %s", err)
			return errors.New(fmt.Sprintf("查询运单任务信息失败：%s", err))
		}
		// 未下车 直接点签收
		if err == nil && time.Time(task.EndTime).IsZero() {
			task.EndTime = model2.Time(time.Now())
			task.CoolerBoxId = coolerBox.Id
			err = tx.Save(&task).Error
			if err != nil {
				e.Log.Errorf("db error: %s", err)
				return errors.New(fmt.Sprintf("保存运单任务信息失败：%s", err))
			}
		}
	}
	var userId int
	if p != nil {
		userId = p.UserId
	}
	// 添加签收记录
	Logistics := model.WaybillLogistics{
		WaybillNo:   c.WaybillNo,
		Status:      c.Status,
		CoolerBoxId: coolerBox.Id,
		UserId:      userId,
		Lng:         lng,
		Lat:         lat,
		ControlBy: model2.ControlBy{
			CreateBy: userId,
		},
		DeptBy: model2.DeptBy{
			DeptId: waybillModel.DeptId,
		},
		ModelTime: model2.ModelTime{
			CreatedAt: waybillModel.ReceiptTime,
		},
	}
	err = tx.Create(&Logistics).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
	}

	return nil
}

// 获取入库 出库 上车 下车 定位信息
func (e *Waybill) GetSite(companyId int, sn string, time string) (lng, lat string, err error) {
	// 获取公司秘钥
	var company model.SysDept
	company, err = model.GetCompanyById(companyId)
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return lng, lat, model.GetCompanyKeyErr
	}
	// 获取传感器信息
	var deviceSensorList = []nats_server.DeviceSensor_R{}
	var count int64
	deviceSensorList, count, err = nats_server.Cold_CompanyDeviceSensor_List_ByKey(sn, company.ColdKey)
	if err != nil || count == 0 {
		err = errors.New("查询设备定位信息失败")
		return lng, lat, err
	}
	var deviceData nats_server.DeviceData_
	deviceData, err = nats_server.Cold_ReadDeviceDataBy_T_snid_T_time(deviceSensorList[0].T_sn, deviceSensorList[0].T_id, time)
	if err != nil {
		err = errors.New("查询设备定位信息失败")
		return lng, lat, err
	}
	if len(deviceData.T_site) > 0 {
		site := strings.Split(deviceSensorList[0].T_DeviceSensorData.T_site, ",")
		if len(site) == 2 {
			lng = site[0]
			lat = site[1]
		}
	}
	return lng, lat, nil
}

// 获取今日运单数 未派单 未装车 未入库 运送中
// 本月运单总数 上月运单总数 本年运单总数 上年运单总数
func (e *Waybill) GetBasicsStats(c *dto.WaybillStatsReq, p *actions.DataPermission) dto.WaybillStatsRes {
	var res dto.WaybillStatsRes
	var data model.Waybill
	type DateCount struct {
		Date  string
		Count int64
	}
	yearCount := make([]DateCount, 0)
	monthCount := make([]DateCount, 0)
	now := time.Now()
	todayStartTime := now.Format("2006-01-02") + " 00:00:00"
	todayEndTime := now.Format("2006-01-02") + " 23:59:59"

	// 获取上个月第一天
	firstDayOfLastMonth := time.Date(now.Year(), now.Month()-1, 1, 0, 0, 0, 0, now.Location())

	// 获取去年的第一天
	firstDayOfLastYear := time.Date(now.Year()-1, time.January, 1, 0, 0, 0, 0, now.Location())
	monthStartTime := firstDayOfLastMonth.Format("2006-01-02") + " 00:00:00"
	yearStartTime := firstDayOfLastYear.Format("2006-01-02") + " 00:00:00"

	// 今日总运单数
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("order_time between ? and ?", todayStartTime, todayEndTime).Count(&res.TodayNum)
	// 待确定
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusWaitDelivery).Count(&res.WaitDeliveryNum)
	// 配送中
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusInDeliverys).Count(&res.InDeliveryNum)
	// 已签收
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusReceipts).Count(&res.ReceiptNum)
	// 已取消
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p)).Where("status = ?", model.WaybillStatusRejections).Count(&res.RejectionNum)
	// 获取本月，上月数据
	e.Orm.Model(&data).Select("date_format(order_time,'%Y%m') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p)).
		Where("order_time between ? and ?", monthStartTime, now).Group("date").Find(&monthCount)

	for _, month := range monthCount {
		if month.Date == now.Format("200601") {
			res.ThisMonthNum = month.Count
		}
		if month.Date == firstDayOfLastMonth.Format("200601") {
			res.LastMonthNum = month.Count
		}
	}

	// 获取本年，上年数据
	e.Orm.Model(&data).Select("date_format(order_time,'%Y') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p)).
		Where("order_time between ? and ?", yearStartTime, now).Group("date").Find(&yearCount)

	for _, month := range yearCount {
		if month.Date == now.Format("2006") {
			res.ThisYearNum = month.Count
		}
		if month.Date == firstDayOfLastYear.Format("2006") {
			res.LastYearNum = month.Count
		}
	}

	if c.Type == "year" {
		// 获取上个月第一天
		year, _ := strconv.Atoi(c.Date)
		firstDayOfyear := time.Date(year, 1, 1, 0, 0, 0, 0, now.Location())
		lastDayOfyear := time.Date(year, 12, 31, 23, 59, 59, 0, now.Location())

		// 年度数据统计
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p)).
			Where("order_time between ? and ?", firstDayOfyear, lastDayOfyear).Group("date").Find(&res.Stats)
	}

	if c.Type == "month" {
		// 获取上个月第一天
		month, _ := time.ParseInLocation("2006-01", c.Date, time.Local)
		firstDayOfMonth := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, now.Location())
		lastDayOfMonth := time.Date(month.Year(), month.Month()+1, 1, 23, 59, 59, 0, now.Location()).Add(-time.Hour * 24)
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m-%d') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p)).
			Where("order_time between ? and ?", firstDayOfMonth, lastDayOfMonth).Group("date").Find(&res.Stats)
	}

	return res
}

func GetDeliveryStatsScopes(userId int) func(db *gorm.DB) *gorm.DB {

	return func(db *gorm.DB) *gorm.DB {
		if userId == 0 {
			return db
		}
		return db.Where("delivery_id = ?", userId)
	}
}
func GetReCheckStatsScopes(userId int) func(db *gorm.DB) *gorm.DB {

	return func(db *gorm.DB) *gorm.DB {
		if userId == 0 {
			return db
		}
		return db.Where("re_check_id = ?", userId)
	}
}

// 获取配送员统计信息
func (e *Waybill) GetDeliveryStats(c *dto.WaybillUserStatsReq, p *actions.DataPermission) (res []dto.WaybillUserStats) {
	// 获取用户列表
	var userList []model.SysUser
	if err := e.Orm.Model(&userList).Scopes(actions.Permission(model.SysUser{}.TableName(), p), WaybillUserStatsUserIdScopes(c.UserIds)).
		Where("status = 2").Order("created_at desc").Find(&userList).Error; err != nil {
		return nil
	}
	for _, user := range userList {
		stats := e.GetUserStats(c, p, GetDeliveryStatsScopes(user.Id))
		stats.Name = user.NickName
		res = append(res, stats)
	}
	return
}
func (e *Waybill) GetReCheckStats(c *dto.WaybillUserStatsReq, p *actions.DataPermission) (res []dto.WaybillUserStats) {
	// 获取用户列表
	var userList []model.SysUser
	if err := e.Orm.Model(&userList).Scopes(actions.Permission(model.SysUser{}.TableName(), p), WaybillUserStatsUserIdScopes(c.UserIds)).
		Where("status = 2").Order("created_at desc").Find(&userList).Error; err != nil {
		return nil
	}
	for _, user := range userList {
		stats := e.GetUserStats(c, p, GetReCheckStatsScopes(user.Id))
		stats.Name = user.NickName
		res = append(res, stats)
	}
	return
}

func WaybillUserStatsUserIdScopes(userIds []int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if len(userIds) == 0 {
			return db
		}
		if len(userIds) == 1 {
			return db.Where("id = ?", userIds[0])
		}
		return db.Where("id in (?)", userIds)
	}
}

func GetUserBasicsStatsScopes(userId int) func(db *gorm.DB) *gorm.DB {

	return func(db *gorm.DB) *gorm.DB {
		if userId == 0 {
			return db
		}
		return db.Where("delivery_id = ? or re_check_id = ? or create_by = ?", userId, userId, userId)
	}
}
func (e *Waybill) GetUserBasicsStats(c *dto.WaybillStatsReq, p *actions.DataPermission, scopes func(*gorm.DB) *gorm.DB) dto.WaybillStatsRes {
	var res dto.WaybillStatsRes
	var data model.Waybill
	type DateCount struct {
		Date  string
		Count int64
	}
	yearCount := make([]DateCount, 0)
	monthCount := make([]DateCount, 0)
	now := time.Now()
	todayStartTime := now.Format("2006-01-02") + " 00:00:00"
	todayEndTime := now.Format("2006-01-02") + " 23:59:59"

	// 获取上个月第一天
	firstDayOfLastMonth := time.Date(now.Year(), now.Month()-1, 1, 0, 0, 0, 0, now.Location())

	// 获取去年的第一天
	firstDayOfLastYear := time.Date(now.Year()-1, time.January, 1, 0, 0, 0, 0, now.Location())
	monthStartTime := firstDayOfLastMonth.Format("2006-01-02") + " 00:00:00"
	yearStartTime := firstDayOfLastYear.Format("2006-01-02") + " 00:00:00"

	// 今日总运单数
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("order_time between ? and ?", todayStartTime, todayEndTime).Count(&res.TodayNum)
	// 待派单
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("status = ?", model.WaybillStatusWaitDelivery).Count(&res.WaitDeliveryNum)
	// 配送中
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("status = ?", model.WaybillStatusInDeliverys).Count(&res.InDeliveryNum)
	// 已送达
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("status = ?", model.WaybillStatusReceipts).Count(&res.ReceiptNum)
	// 已取消
	e.Orm.Model(&data).Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("status = ?", model.WaybillStatusRejections).Count(&res.RejectionNum)
	// 获取本月，上月数据
	e.Orm.Model(&data).Select("date_format(order_time,'%Y%m') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("order_time between ? and ?", monthStartTime, now).Group("date").Find(&monthCount)

	for _, month := range monthCount {
		if month.Date == now.Format("200601") {
			res.ThisMonthNum = month.Count
		}
		if month.Date == firstDayOfLastMonth.Format("200601") {
			res.LastMonthNum = month.Count
		}
	}

	// 获取本年，上年数据
	e.Orm.Model(&data).Select("date_format(order_time,'%Y') date,count(1) as count ").Scopes(actions.Permission(data.TableName(), p), scopes).
		Where("order_time between ? and ?", yearStartTime, now).Group("date").Find(&yearCount)

	for _, month := range yearCount {
		if month.Date == now.Format("2006") {
			res.ThisYearNum = month.Count
		}
		if month.Date == firstDayOfLastYear.Format("2006") {
			res.LastYearNum = month.Count
		}
	}

	if c.Type == "year" {
		// 获取上个月第一天
		year, _ := strconv.Atoi(c.Date)
		firstDayOfyear := time.Date(year, 1, 1, 0, 0, 0, 0, now.Location())
		lastDayOfyear := time.Date(year, 12, 31, 23, 59, 59, 0, now.Location())

		// 年度数据统计
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p), scopes).
			Where("order_time between ? and ?", firstDayOfyear, lastDayOfyear).Group("date").Find(&res.Stats)
	}

	if c.Type == "month" {
		// 获取上个月第一天
		month, _ := time.ParseInLocation("2006-01", c.Date, time.Local)
		firstDayOfMonth := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, now.Location())
		lastDayOfMonth := time.Date(month.Year(), month.Month()+1, 1, 23, 59, 59, 0, now.Location()).Add(-time.Hour * 24)
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m-%d') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p), scopes).
			Where("order_time between ? and ?", firstDayOfMonth, lastDayOfMonth).Group("date").Find(&res.Stats)
	}

	return res
}
func (e *Waybill) GetUserStats(c *dto.WaybillUserStatsReq, p *actions.DataPermission, scopes func(*gorm.DB) *gorm.DB) dto.WaybillUserStats {
	var res dto.WaybillUserStats
	var data model.Waybill
	type DateCount struct {
		Date  string
		Count int64
	}

	now := time.Now()

	if c.Type == "year" {
		// 获取上个月第一天
		year, _ := strconv.Atoi(c.Date)
		firstDayOfyear := time.Date(year, 1, 1, 0, 0, 0, 0, now.Location())
		lastDayOfyear := time.Date(year, 12, 31, 23, 59, 59, 0, now.Location())

		// 年度数据统计
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p), scopes).
			Where("order_time between ? and ?", firstDayOfyear, lastDayOfyear).Group("date").Find(&res.Stats)
		// 获取这个月的所有日期
		allDates := getAllDatesInYear(c.Date)
		// 补齐缺失日期的数据
		res.Stats = completeMissingDates(allDates, res.Stats)
	}

	if c.Type == "month" {
		// 获取上个月第一天
		month, _ := time.ParseInLocation("2006-01", c.Date, time.Local)
		firstDayOfMonth := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, now.Location())
		lastDayOfMonth := time.Date(month.Year(), month.Month()+1, 1, 23, 59, 59, 0, now.Location()).Add(-time.Hour * 24)
		e.Orm.Model(&data).Select("date_format(order_time,'%Y-%m-%d') date,count(1) as num ").Scopes(actions.Permission(data.TableName(), p), scopes).
			Where("order_time between ? and ?", firstDayOfMonth, lastDayOfMonth).Group("date").Find(&res.Stats)
		// 获取这个月的所有日期
		allDates := getAllDatesInMonth(c.Date)
		// 补齐缺失日期的数据
		res.Stats = completeMissingDates(allDates, res.Stats)
	}

	return res
}

// 获取指定月份的所有日期
func getAllDatesInMonth(month string) []string {
	var dates []string
	layout := "2006-01-02"
	firstDay, _ := time.Parse(layout, month+"-01")
	if time.Now().Before(firstDay) {
		return dates
	}
	lastDay := firstDay.AddDate(0, 1, -1)
	if time.Now().Before(lastDay) {
		lastDay = time.Now()
	}

	for d := firstDay; !d.After(lastDay); d = d.AddDate(0, 0, 1) {
		dates = append(dates, d.Format(layout))
	}

	return dates
}

// 获取指定年份的所有日期
func getAllDatesInYear(year string) []string {
	var dates []string
	layout := "2006-01"
	firstDay, _ := time.Parse(layout, year+"-01")
	lastDay := firstDay.AddDate(1, 0, -1)
	if time.Now().Before(firstDay) {
		return dates
	}
	if time.Now().Before(lastDay) {
		lastDay = time.Now()
	}
	for d := firstDay; !d.After(lastDay); d = d.AddDate(0, 1, 0) {
		dates = append(dates, d.Format(layout))
	}
	return dates
}

// 补齐缺失日期的数据
func completeMissingDates(allDates []string, stats []dto.WaybillStats) []dto.WaybillStats {
	dateMap := make(map[string]int64)
	for _, stat := range stats {
		dateMap[stat.Date] = stat.Num
	}

	var completedStats []dto.WaybillStats
	for _, date := range allDates {
		num, exists := dateMap[date]
		if !exists {
			num = 0
		}
		completedStats = append(completedStats, dto.WaybillStats{Date: date, Num: num})
	}

	return completedStats
}

// 获取运单所有温湿度素具
func (e *Waybill) GetAllData(c *dto.WaybillGetByWaybillNoReq) ([]nats_server.DeviceData_R, []WaybillPDF, error) {
	var err error
	var data model.WaybillTask
	var waybill model.Waybill
	var taskList []model.WaybillTask
	var waybillPDF []WaybillPDF
	dataList := make([]nats_server.DeviceData_R, 0)

	err = e.Orm.Model(&waybill).Where("waybill_no = ?", c.WaybillNo).First(&waybill).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return dataList, waybillPDF, errors.New("获取运单信息失败")
	}

	// 未签收，不返回数据
	if waybill.Status != model.WaybillStatusReceipts {
		return dataList, waybillPDF, nil
	}

	// 获取公司秘钥
	var company model.SysDept
	company, err = model.GetCompanyById(waybill.DeptId)
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return dataList, waybillPDF, model.GetCompanyKeyErr
	}

	err = e.Orm.Model(&data).
		Where("waybill_no = ?", c.WaybillNo).
		Order("id desc").
		Find(&taskList).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return dataList, waybillPDF, global.GetFailedErr
	}

	// 获取最后一个任务id
	var lastWaybillTask model.WaybillTask
	err = e.Orm.Model(&lastWaybillTask).Where("waybill_no = ?", c.WaybillNo).Last(&lastWaybillTask).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		err = errors.New("获取运单信息错误！")
		return dataList, waybillPDF, err
	}

	// 创建名称到权重的映射
	orderMap := make(map[string]int)
	for i, v := range taskList {
		orderMap[v.Sn] = i
	}

	for i := 0; i < len(taskList); i++ {
		// 获取传感器信息
		deviceSensorList, _, _ := nats_server.Cold_CompanyDeviceSensor_List_ByKey(taskList[i].Sn, company.ColdKey)
		var T_snid string
		var list []nats_server.DeviceData_R
		for _, r := range deviceSensorList {
			T_snid += fmt.Sprintf("%s,%d|", r.T_sn, r.T_id)
		}
		var count int64
		list, count, err = nats_server.Cold_ReadDeviceDataListBy_T_snid(T_snid, taskList[i].StartTime.String(), taskList[i].EndTime.String(), 0, 9999)
		if err != nil {
			e.Log.Errorf("nats 获取温湿度信息失败: %s", err)
			return dataList, waybillPDF, global.GetFailedErr
		}

		firstMap := map[int]nats_server.DeviceData_R{}
		lastMap := map[int]nats_server.DeviceData_R{}
		if count > 0 {
			for _, v := range deviceSensorList {

				for j := 0; j < len(list); j++ {
					if v.T_id == list[j].T_id {
						if list[j].T_time != taskList[i].StartTime.String() {
							firstData := list[j]
							firstData.T_time = taskList[i].StartTime.String()
							firstMap[v.T_id] = firstData
							count += 1
						}
						break
					}
				}
				if waybill.Status == model.WaybillStatusReceipts {
					for k := len(list) - 1; k >= 0; k-- {
						if v.T_id == list[k].T_id {
							if taskList[i].Id == lastWaybillTask.Id && list[k].T_time != taskList[i].EndTime.String() && !time.Time(taskList[i].EndTime).IsZero() {
								lastData := list[k]
								lastData.T_time = taskList[i].EndTime.String()
								lastMap[v.T_id] = lastData
								count += 1
							}
							break
						}
					}
				}
			}
		}

		for _, v := range firstMap {
			list = append(list, v)
		}

		for _, v := range lastMap {
			list = append(list, v)
		}
		sort.Slice(list, func(x, y int) bool {
			if list[x].T_time == list[y].T_time {
				// 如果时间相同，则按预设顺序排序
				return orderMap[list[x].T_sn] < orderMap[list[y].T_sn]
			}
			return list[x].T_time > list[y].T_time
		})

		dataList = append(dataList, list...)
		waybillPDF = append(waybillPDF, WaybillPDF{
			Data:             list,
			DeviceSensorList: deviceSensorList,
			Task:             taskList[i],
		})
	}

	sort.Slice(dataList, func(i, j int) bool {
		if dataList[i].T_time == dataList[j].T_time {
			// 如果时间相同，则按预设顺序排序
			return orderMap[dataList[i].T_sn] < orderMap[dataList[j].T_sn]
		}
		return dataList[i].T_time < dataList[j].T_time
	})

	return dataList, waybillPDF, nil
}

type WaybillPDF struct {
	Data             []nats_server.DeviceData_R   `json:"data"`
	DeviceSensorList []nats_server.DeviceSensor_R `json:"deviceSensorList"`
	Task             model.WaybillTask            `json:"task"`
}

// Insert 创建Waybill对象
func (e *Waybill) InsertByOrderId(c *dto.WeianGetWaybillNoReq) error {
	var err error
	var data model.Waybill

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var company model.SysDept

	var i int64
	err = e.Orm.Model(&company).Where("name = ?", c.CompanyName).Count(&i).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	if i == 0 {
		err = errors.New("公司名称不存在！")
		e.Log.Errorf("db error: %s", err)
		return err
	}

	var no string
	for {
		no = time.Now().Format("200601021504") + utils.GetRandString(6, "0123456789", 0)
		var j int64
		err = e.Orm.Model(&data).Where("waybill_no = ?", no).Count(&j).Error
		if err != nil {
			continue
		}
		if j == 0 {
			break
		}
	}

	// 添加运单
	data.WaybillNo = no
	data.OrderNo = c.OrderId
	data.DeptId = company.Id
	data.Status = 1
	data.OrderTime = model2.Time(time.Now())
	err = tx.Create(&data).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	c.WaybillNo = data.WaybillNo

	return nil

}

// CreateSole 生成唯一订单编号
func (e *Waybill) CreateSole() (string, error) {
	var waybill model.Waybill
	var err error
	var count int64
	format := time.Now().Format("20060102")
	un := time.Now().Unix()
	waybillno := fmt.Sprintf("%v%v", format, un)
	err = e.Orm.Model(&waybill).Where("waybill_no = ?", waybillno).Count(&count).Error
	if count > 0 {
		return e.CreateSole()
	}
	if err != nil {
		e.Log.Errorf("生成订单号错误: %s", err)
		err = errors.New("生成订单号错误，请重新生成")
		return "", err
	}
	return waybillno, nil
}

// WaybillTurnarounds 订单转门店
func (e *Waybill) WaybillTurnarounds(c *dto.WaybillTurnarounds, p *actions.DataPermission) error {
	var err error
	var waybillModel model.Waybill
	var count int64
	//查询订单是否存在
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
		Where("waybill_no = ?", c.WaybillNo).
		First(&waybillModel).Count(&count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}
	if count == 0 {
		return errors.New("订单不存在")
	}
	//查询门店是否存在可以转换
	var data model.SysDept
	var Depts []model.SysDept
	err = e.Orm.Model(&data).
		Scopes(
			CompanyIdScopesUser(p.DeptId),
		).Find(&Depts).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	contains := false
	for _, v := range Depts {
		if v.Id == c.DeptId {
			contains = true
			break
		} else {
			contains = false
		}
	}
	if !contains {
		return errors.New("转门店不存在")
	}
	waybillModel.DeptId = c.DeptId
	update := tx.Updates(&waybillModel)
	if update.Error != nil {
		e.Log.Errorf("db error: %s", update.Error)
		return global.UpdateFailedErr
	}
	return nil
}

// SecondaryDistribution 二次分配订单
func (e *Waybill) SecondaryDistribution(c *dto.WaybillAssignment, p *actions.DataPermission) error {
	var err error
	var waybillModel model.Waybill
	var count int64
	//查询订单是否存在
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	err = tx.Scopes(actions.Permission(waybillModel.TableName(), p)).
		Where("waybill_no = ?", c.WaybillNo).
		First(&waybillModel).Count(&count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}
	if count == 0 {
		return errors.New("订单不存在")
	}
	if !waybillModel.IsSecondaryDistribution {
		return errors.New("该订单不允许二次分配")
	}
	var coolerBox = model.CoolerBox{}
	// 查询保温箱信息
	if c.CoolerBoxId != 0 {
		err = tx.Scopes(actions.Permission(coolerBox.TableName(), p)).
			First(&coolerBox, waybillModel.CoolerBoxId).Error
		if err != nil {
			e.Log.Errorf("获取保温箱信息失败: %s", err)
			return errors.New("获取保温箱信息失败")
		}
	}
	var waybil model.Waybill
	sole, err := e.CreateSole()
	var no string
	for {
		no = time.Now().Format("200601021504") + utils.GetRandString(6, "0123456789", 0)
		var j int64
		err = e.Orm.Model(&waybil).Where("waybill_no = ?", no).Count(&j).Error
		if err != nil {
			continue
		}
		if j == 0 {
			break
		}
	}
	// 添加运单
	waybil.WaybillNo = no
	sole, err = e.CreateSole()
	if err != nil {
		err = errors.New("生成运单号失败")
		return err
	}
	waybil.OrderNo = sole
	waybil.Status = model.WaybillStatusInShippeds
	waybil.DeptId = waybillModel.DeptId
	waybil.DeliveryName = waybillModel.DeliveryName
	waybil.DeliveryId = waybillModel.DeliveryId
	waybil.DeliveryPhone = waybillModel.DeliveryPhone
	waybil.OrderTime = model2.Time(time.Now())
	waybil.IsSecondaryDistribution = false
	waybil.ReCheckId = waybillModel.ReCheckId
	waybil.IceRaftCode = waybillModel.IceRaftCode
	waybil.CoolerBoxId = waybillModel.CoolerBoxId
	waybil.IsChild = true
	waybil.ConsigneeAddressDetails = c.ConsigneeAddressDetails
	waybil.ConsigneeAddressName = c.ConsigneeAddressName
	waybil.ConsigneeAddressPhone = c.ConsigneeAddressPhone
	waybil.AssignmentStatus = 2
	waybil.Prescription = c.Prescription
	//c.Generate(&waybil)
	err = tx.Create(&waybil).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	// 保存发货地址
	if c.SaveConsigneeAddress {
		// 查询地址是否存在
		address := model.Address{}
		err = e.Orm.Where("address = ? and phone = ? and name = ? and dept_id = ? and address_type = 'consignee'",
			c.ConsigneeAddressDetails, c.ConsigneeAddressPhone, c.ConsigneeAddressName, c.DeptId).First(&address).Error
		if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
			address.Address = c.ConsigneeAddressDetails
			address.Phone = c.ConsigneeAddressPhone
			address.Name = c.ConsigneeAddressName
			address.DeptId = c.DeptId
			address.AddressType = "consignee"
			err = tx.Create(&address).Error
			if err != nil {
				e.Log.Errorf("创建地址失败: %s", err)
				return global.CreateFailedErr
			}
		}
	}
	if len(c.Drugs) > 0 {
		for _, drug := range c.Drugs {
			var drugs model.Drug
			drugs.WaybillNo = no
			drugs.Drug_ent_base_info_id = drug.Drug_ent_base_info_id
			drugs.Ent_name = drug.Ent_name
			drugs.Physic_name = drug.Physic_name
			drugs.Approval_licence_no = drug.Approval_licence_no
			drugs.Prepn_spec = drug.Prepn_spec
			drugs.Physic_type_desc = drug.Physic_type_desc
			drugs.Pkg_spec_crit = drug.Pkg_spec_crit
			drugs.Prepn_type_desc = drug.Prepn_type_desc
			drugs.Code = drug.Code
			err = tx.Save(&drugs).Error
			if err != nil {
				e.Log.Errorf("保存药品信息失败: %s", err)
				return errors.New("保存药品信息失败")
			}
			err := e.Orm.Table(model.Drug{}.TableName()).Where("waybill_no = ?", waybillModel.WaybillNo).Where("code = ?", drug.Code).Update("is_assignment", true).Error
			if err != nil {
				e.Log.Errorf("更新药品状态失败: %s", err)
				return errors.New("更新药品状态失败")
			}
		}
	}
	waybillModel.ChildWaybills = append(waybillModel.ChildWaybills, waybil.WaybillNo)
	err = tx.Save(&waybillModel).Error
	if err != nil {
		e.Log.Errorf("更新运单失败: %s", err)
		return global.UpdateFailedErr
	}
	// 二次分配订单发送短信（改用自定义模板发送）
	addr := conf.ExtConfig.Applet.WaybillUrl + url.QueryEscape(lib.AesEncryptCBC(waybil.WaybillNo, lib.AesKey))
	res, err1 := CustomSmsXSend(conf.ExtConfig.SubMail.Appid, conf.ExtConfig.SubMail.Signature, c.ConsigneeAddressPhone, addr)
	if err1 != nil || res.Status != sms.SUCCESS {
		e.Log.Errorf("派单短信发送失败", zap.Any("res", res), zap.Error(err1))
		err = errors.New("派单短信发送失败，请检查收件人电话是否正确！")
		return err
	}
	waybil.SendLog = model.WaybillSendLog{
		Phone:   c.ConsigneeAddressPhone,
		Content: "【贵州宝智达冷链科技公司】您的订单正在派送中，点击查看详情：" + addr, // 同步改成新模板的文案
	}
	// 添加物流
	logisticsObj := model.WaybillLogistics{
		WaybillNo:   waybil.WaybillNo,
		Status:      waybil.Status,
		CoolerBoxId: waybil.CoolerBoxId,
		ControlBy: model2.ControlBy{
			CreateBy: p.UserId,
		},
		DeptBy: model2.DeptBy{
			DeptId: p.DeptId,
		},
	}
	err = tx.Create(&logisticsObj).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return errors.New(fmt.Sprintf("保存运单物流信息失败：%s", err))
	}
	// 查询任务
	var task model.WaybillTask
	err = tx.Model(&task).Where("waybill_no = ? ", waybil.WaybillNo).
		Last(&task).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 添加任务
			taskObj := model.WaybillTask{
				WaybillNo:   waybil.WaybillNo,
				CoolerBoxId: waybil.CoolerBoxId,
				UserId:      p.UserId,
				Sn:          coolerBox.Sn,
				StartTime:   model2.Time(time.Now()),
				ControlBy: model2.ControlBy{
					CreateBy: p.UserId,
				},
				DeptBy: model2.DeptBy{
					DeptId: p.DeptId,
				},
			}
			err = tx.Create(&taskObj).Error
			if err != nil {
				e.Log.Errorf("db error: %s", err)
				return errors.New(fmt.Sprintf("保存运单任务信息失败：%s", err))
			}
		} else {
			e.Log.Errorf("db error: %s", err)
			return errors.New(fmt.Sprintf("查询运单任务信息失败：%s", err))
		}
	}
	return nil
}

// CustomSmsXSend 自定义模板短信发送，使用新模板 Z5wH13
func CustomSmsXSend(appid, signature, to, addr string) (sms.XSendRes, error) {
	vars := map[string]string{"addr": addr}
	varsBytes, _ := json.Marshal(vars)

	payload := url.Values{}
	payload.Set("appid", appid)
	payload.Set("signature", signature)
	payload.Set("to", to)
	payload.Set("project", "Z5wH13") // 你的新模板ID
	payload.Set("vars", string(varsBytes))

	req, err := http.NewRequest("POST", "https://api-v4.mysubmail.com/sms/xsend", strings.NewReader(payload.Encode()))
	if err != nil {
		return sms.XSendRes{}, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return sms.XSendRes{}, err
	}
	defer resp.Body.Close()

	var res sms.XSendRes
	if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
		return sms.XSendRes{}, err
	}
	return res, nil
}

// 发送配送通知短信给配送员，使用新模板 gOK601
func SendDeliveryNotifySms(to, orderNo string) error {
	vars := map[string]string{"orderNo": orderNo}
	varsBytes, _ := json.Marshal(vars)

	payload := url.Values{}
	payload.Set("appid", conf.ExtConfig.SubMail.Appid)
	payload.Set("signature", conf.ExtConfig.SubMail.Signature)
	payload.Set("to", to)
	payload.Set("project", "gOK601")
	payload.Set("vars", string(varsBytes))

	req, err := http.NewRequest("POST", "https://api-v4.mysubmail.com/sms/xsend", strings.NewReader(payload.Encode()))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	var res sms.XSendRes
	if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
		return err
	}
	if res.Status != sms.SUCCESS {
		return errors.New(res.Msg)
	}
	return nil
}
