package purchasemanage

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	model "go-admin/app/admin/models"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools"
	"go-admin/tools/app"
	"golang.org/x/time/rate"
	"math"
	"net/http"
	"time"
)

// ErpPurchaseCreate 新建采购订单
// @Summary 新建采购订单
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseCreateReq true "新建采购订单模型"
// @Success 200 {object} models.ErpPurchaseOrder
// @Router /api/v1/erp_purchase/create [post]
func ErpPurchaseCreate(c *gin.Context) {
	req := new(model.ErpPurchaseCreateReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误"+err.Error())
		return
	}
	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 检验参数
	err = model.CheckCreateErpPurchaseOrderParam(req)
	if err != nil {
		logger.Error("CheckCreateErpPurchaseOrderParam err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, err.Error())
		return
	}

	if len(req.ErpPurchaseCommodities) == 0 {
		logger.Error("erp purchase commodities is nil")
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 如果是采购退货，则门店改为采购退货单的门店ID
	if req.PurchaseType == model.ErpRejectOrder && req.PurchaseOrderSn != "" {
		var erpPurchaseOrder model.ErpPurchaseOrder
		err = orm.Eloquent.Table("erp_purchase_order").Where("serial_number=?", req.PurchaseOrderSn).Find(&erpPurchaseOrder).Error
		if err != nil {
			app.Error(c, http.StatusInternalServerError, err, "新增失败:"+err.Error())
			return
		}

		req.StoreId = erpPurchaseOrder.StoreId

		//// 判断对应的采购退货单是否在月结时间内
		//if model.IsMonthEndClosed(*erpPurchaseOrder.AuditTime) {
		//	app.Error(c, http.StatusInternalServerError, errors.New("新增失败：对应订单财务已月结"), "新增失败：对应订单财务已月结")
		//	return
		//}
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !model.CheckUserStore(req.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	purchaseOrder, err := model.CreateErpPurchaseOrder(req, sysUser)
	if err != nil {
		logger.Error("CreateErpPurchaseOrder err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "新增失败:"+err.Error())
		return
	}

	purchaseOrder.Commodities = req.ErpPurchaseCommodities

	app.OK(c, purchaseOrder, "")
	return
}

// ErpPurchaseEdit 编辑采购订单
// @Summary 编辑采购订单
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseEditReq true "编辑采购订单模型"
// @Success 200 {object} models.ErpPurchaseOrder
// @Router /api/v1/erp_purchase/edit [post]
func ErpPurchaseEdit(c *gin.Context) {
	req := new(model.ErpPurchaseEditReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误"+err.Error())
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 检验参数
	err = model.CheckEditErpPurchaseOrderParam(req)
	if err != nil {
		logger.Error("CheckCreateErpPurchaseOrderParam err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, err.Error())
		return
	}

	if len(req.ErpPurchaseCommodities) == 0 {
		logger.Error("erp purchase commodities is nil")
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !model.CheckUserStore(req.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	// 更新订单信息
	purchaseOrder, err := model.EditErpPurchaseOrder(req, sysUser)
	if err != nil {
		logger.Error("EditErpPurchaseOrder err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "编辑失败:"+err.Error())
		return
	}

	purchaseOrder.Commodities = req.ErpPurchaseCommodities
	app.OK(c, purchaseOrder, "")
	return
}

// ErpPurchaseList 查询采购订单列表
// @Summary 查询采购订单列表
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseOrderListReq true "查询采购订单列表模型"
// @Success 200 {object} models.ErpPurchaseOrderListResp
// @Router /api/v1/erp_purchase/list [post]
func ErpPurchaseList(c *gin.Context) {
	req := &model.ErpPurchaseOrderListReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := req.List(c)
	if err != nil {
		logger.Error("ErpPurchaseList err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "获取失败"+err.Error())
		return
	}

	app.OK(c, resp, "")
	return
}

// ErpPurchaseDetail 查询采购订单详情
// @Summary 查询采购订单详情
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseDetailReq true "查询采购订单详情模型"
// @Success 200 {object} models.ErpPurchaseOrder
// @Router /api/v1/erp_purchase/detail [post]
func ErpPurchaseDetail(c *gin.Context) {
	req := new(model.ErpPurchaseDetailReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	var purchaseOrder model.ErpPurchaseOrder
	err := orm.Eloquent.Table("erp_purchase_order").Where("id=?", req.ErpPurchaseOrderId).Find(&purchaseOrder).Error
	if err != nil {
		logger.Error("purchase order err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, "获取失败")
		return
	}
	if purchaseOrder.ID == 0 {
		logger.Error("purchase commodities err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, fmt.Sprintf("未查询到采购订单[%d]", req.ErpPurchaseOrderId))
		return
	}
	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		sysUser, err := model.GetSysUserByCtx(c)
		if err != nil {
			logger.Error("sys user err:", logger.Field("err", err))
			app.Error(c, http.StatusInternalServerError, err, "操作失败")
			return
		}

		if !model.CheckUserStore(purchaseOrder.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	// 校验时间，如果为01-01-01 08:05，则赋值为空
	if purchaseOrder.MakerTime != nil && purchaseOrder.MakerTime.IsZero() {
		purchaseOrder.MakerTime = nil
	}

	if purchaseOrder.AuditTime != nil && purchaseOrder.AuditTime.IsZero() {
		purchaseOrder.AuditTime = nil
	}

	var purchaseCommodities []model.ErpPurchaseCommodity
	err = orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id=?", req.ErpPurchaseOrderId).
		Find(&purchaseCommodities).Error
	if err != nil {
		logger.Error("purchase commodities err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, "获取失败")
		return
	}

	// 添加实际采购入库信息
	var commodityList []model.ErpPurchaseCommodity
	for _, v := range purchaseCommodities {
		// 查询默认员工成本价
		erpCommodity, err := model.GetCommodity(v.ErpCommodityId)
		if err != nil {
			logger.Error("ErpPurchaseDetail GetCommodity err:", logger.Field("err", err))
			app.Error(c, http.StatusBadRequest, err, "获取失败")
			return
		}
		if purchaseOrder.PurchaseType == model.ErpProcureOrder {
			v.DefaultEmployeePrice = v.Price + erpCommodity.StaffCostPrice
		} else if purchaseOrder.PurchaseType == model.ErpProcureOrder {
			v.DefaultEmployeePrice = v.RejectedPrice + erpCommodity.StaffCostPrice
		}

		// 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价
		//result, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId, v.ErpPurchaseOrderId)
		result, err := model.GetTotalsAndAveragesByCommodityID(v.ID)
		if err != nil {
			logger.Error("GetTotalsAndAveragesByCommodityID err:", logger.Field("err", err))
			app.Error(c, http.StatusBadRequest, err, "获取失败")
			return
		}
		v.ExecutionCount = result.TotalCount
		v.ExecutionAmount = result.TotalAmount
		v.ExecutionEmployeePrice = result.AvgEmployeePrice
		v.ExecutionPrice = result.AvgImplementationPrice

		v.ExecutionAmount = math.Round(v.ExecutionAmount*100) / 100
		v.ExecutionEmployeePrice = math.Round(v.ExecutionEmployeePrice*100) / 100
		v.ExecutionPrice = math.Round(v.ExecutionPrice*100) / 100

		serialNumber := purchaseOrder.SerialNumber
		if purchaseOrder.PurchaseType == model.ErpRejectOrder && purchaseOrder.State == model.ErpPurchaseOrderUnAudit { // 采购退货订单
			serialNumber = purchaseOrder.RejectedSerialNumber

			// 查询原始采购订单的信息
			var rejectOrder model.ErpPurchaseOrder
			err := orm.Eloquent.Table("erp_purchase_order").Where("serial_number=?", serialNumber).Find(&rejectOrder).Error
			if err != nil {
				logger.Error("purchase order err:", logger.Field("err", err))
				app.Error(c, http.StatusBadRequest, err, "获取失败")
				return
			}

			// 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价
			//rejectResult, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId, rejectOrder.ID)
			rejectResult, err := model.GetTotalsAndAveragesByCommodityID(v.ID)
			if err != nil {
				logger.Error("GetTotalsAndAveragesByCommodityID err:", logger.Field("err", err))
				app.Error(c, http.StatusBadRequest, err, "获取失败")
				return
			}
			v.ExecutionCount = rejectResult.TotalCount
			v.ExecutionPrice = rejectResult.AvgImplementationPrice
			v.ExecutionAmount = rejectResult.TotalAmount
		}
		// 查询入库商品实际库存详情处剩余有效数，不包含已出库的数量
		nCount, err := model.GetCommodityStockByPurchaseId(serialNumber, v.ErpCommodityId)
		if err != nil {
			logger.Error("ErpPurchaseDetail GetCommodityStockByPurchaseId err:", logger.Field("err", err))
			app.Error(c, http.StatusBadRequest, err, "获取失败")
			return
		}
		v.EffectiveCount = nCount // 有效数量
		v.ErpCategoryID = erpCommodity.ErpCategoryId
		v.ErpCategoryName = erpCommodity.ErpCategoryName

		commodityList = append(commodityList, v)
	}

	purchaseOrder.Commodities = commodityList

	// 添加最新入库人信息
	purchaseOrder.InventoryId, purchaseOrder.InventoryName, _ = model.GetInventoryIdAndName(purchaseOrder.ID)

	app.OK(c, purchaseOrder, "")
	return
}

// ErpPurchaseAudit 审核采购订单
// @Summary 审核采购订单
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseAuditReq true "审核采购订单模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/audit [post]
func ErpPurchaseAudit(c *gin.Context) {
	var req = new(model.ErpPurchaseAuditReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
		return
	}

	err := tools.Validate(req) //必填参数校验
	if err != nil {
		app.Error(c, http.StatusBadRequest, err, err.Error())
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}
	// todo 需要校验当前用户是否有权限

	var erpPurchaseOrder model.ErpPurchaseOrder
	err = orm.Eloquent.Table("erp_purchase_order").Where("serial_number = ?", req.SerialNumber).Find(&erpPurchaseOrder).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
		return
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !model.CheckUserStore(erpPurchaseOrder.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	begin := orm.Eloquent.Begin()
	// 判断入参state：1-审核，2-取消审核
	orderState := 0
	switch req.State {
	case 1: // 1-审核：待审核状态可以审核
		if erpPurchaseOrder.State == model.ErpPurchaseOrderUnAudit {
			if erpPurchaseOrder.PurchaseType == model.ErpProcureOrder { // 采购
				orderState = model.ErpPurchaseOrderWaitInventory
			} else if erpPurchaseOrder.PurchaseType == model.ErpRejectOrder { // 退货
				orderState = model.ErpPurchaseOrderWaitReject
			} else {
				logger.Error("order err, PurchaseType is:", logger.Field("PurchaseType", erpPurchaseOrder.PurchaseType))
				app.Error(c, http.StatusInternalServerError, err, "审核失败:采购类型有误")
				return
			}
		} else {
			app.OK(c, nil, "订单已审核")
			return
		}
	case 2: // 2-取消审核：5-已终止不能取消，2/3/4其他正常取消，取消后对应的退库或入库
		if erpPurchaseOrder.State == model.ErpPurchaseOrderUnAudit {
			app.OK(c, nil, "订单已取消审核")
			return
		} else if erpPurchaseOrder.State == model.ErpPurchaseOrderEnd {
			logger.Error("order err, erpPurchaseOrder.State is:", logger.Field("erpPurchaseOrder.State", erpPurchaseOrder.State))
			app.Error(c, http.StatusInternalServerError, err, "取消审核失败:[已终止]订单不能取消")
			return
		} else {
			if model.IsMonthEndClosed(*erpPurchaseOrder.AuditTime) {
				app.Error(c, http.StatusInternalServerError, errors.New("反审核失败，财务已月结"), "反审核失败，财务已月结")
				return
			}
			orderState = model.ErpPurchaseOrderUnAudit
			// 更新库存信息
			err = model.CancelAuditUpdateStock(begin, erpPurchaseOrder)
			if err != nil {
				begin.Rollback()
				app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
				return
			}
		}
	default:
		logger.Error("order err, req.State is:", logger.Field("req.State", req.State))
		app.Error(c, http.StatusInternalServerError, err, "审核失败:参数有误")
		return
	}

	err = begin.Table("erp_purchase_order").Where("id = ?", erpPurchaseOrder.ID).Updates(map[string]interface{}{
		"state":        orderState,
		"auditor_id":   sysUser.UserId,
		"audit_time":   time.Now(),
		"auditor_name": sysUser.NickName,
	}).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_purchase_order err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
		return
	}

	// 同步更新指导零售价，商品资料表、库存表
	if orderState == model.ErpPurchaseOrderWaitInventory {
		var purchaseCommodities []model.ErpPurchaseCommodity
		err = orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id=?", erpPurchaseOrder.ID).
			Find(&purchaseCommodities).Error
		if err != nil {
			logger.Error("purchase commodities err:", logger.Field("err", err))
			app.Error(c, http.StatusBadRequest, err, "审核失败:"+err.Error())
			return
		}
		for _, v := range purchaseCommodities {
			err = model.UpdateRetailPrice(begin, v.ErpCommodityId, v.RetailPrice)
			if err != nil {
				begin.Rollback()
				app.Error(c, http.StatusBadRequest, err, "审核失败:"+err.Error())
				return
			}
		}
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Errorf("commit err:", err)
		app.Error(c, http.StatusInternalServerError, err, "审核失败")
		return
	}

	app.OK(c, nil, "操作成功")
	return
}

// ErpPurchaseDelete 删除采购订单
// @Summary 删除采购订单
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseDeleteReq true "删除采购订单模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/delete [post]
func ErpPurchaseDelete(c *gin.Context) {
	var req = new(model.ErpPurchaseDeleteReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
		return
	}

	err := tools.Validate(req) //必填参数校验
	if err != nil {
		app.Error(c, http.StatusBadRequest, err, err.Error())
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}
	// todo 需要校验当前用户是否有权限

	var erpPurchaseOrder model.ErpPurchaseOrder
	err = orm.Eloquent.Table("erp_purchase_order").Where("serial_number = ?", req.SerialNumber).Find(&erpPurchaseOrder).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
		return
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !model.CheckUserStore(erpPurchaseOrder.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	if erpPurchaseOrder.SerialNumber == "" {
		logger.Error("order is null")
		app.Error(c, http.StatusInternalServerError, err, "删除失败:订单不存在")
		return
	}

	// 仅待审核订单可删除
	if erpPurchaseOrder.State != model.ErpPurchaseOrderUnAudit {
		logger.Error("order err, erpPurchaseOrder.State is:", logger.Field("erpPurchaseOrder.State", erpPurchaseOrder.State))
		app.Error(c, http.StatusInternalServerError, err, "删除失败:仅待审核订单可删除")
		return
	}

	begin := orm.Eloquent.Begin()
	// 1-删除采购订单表
	err = begin.Delete(erpPurchaseOrder).Error
	if err != nil {
		begin.Rollback()
		logger.Error("order delete1 err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
		return
	}

	// 2-删除采购订单商品表
	var commodities []model.ErpPurchaseCommodity
	err = orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id = ?", erpPurchaseOrder.ID).Find(&commodities).Error
	if err != nil {
		logger.Error("query erp_purchase_commodity err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
		return
	}

	if len(commodities) != 0 {
		err = begin.Delete(&commodities).Error
		if err != nil {
			begin.Rollback()
			logger.Error("更新商品订单信息-删除 error")
			app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
			return
		}
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit err:", logger.Field("err", err))
		return
	}

	app.OK(c, nil, "删除成功")
	return
}

// ErpPurchaseInventory 入库（退货）
// @Summary 入库（退货）
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseInventoryReq true "入库（退货）模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/inventory [post]
func ErpPurchaseInventory(c *gin.Context) {
	req := new(model.ErpPurchaseInventoryReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	if req.PurchaseType == model.ErpProcureOrder {
		if req.InventoryId == 0 {
			app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误，入库人id为0")
			return
		} else if req.InventoryName == "" {
			app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误，入库人姓名为空")
			return
		}
	}

	err := model.InventoryErpPurchase(req, c)
	if err != nil {
		logger.Error("InventoryErpPurchase err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败:"+err.Error())
		return
	}

	app.OK(c, nil, "操作成功")
	return
}

// ErpPurchaseTerminate 终止采购
// @Summary 终止采购
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseTerminateReq true "终止采购模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/terminate [post]
func ErpPurchaseTerminate(c *gin.Context) {
	var req = new(model.ErpPurchaseTerminateReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, err, "参数错误:"+err.Error())
		return
	}

	err := tools.Validate(req) //必填参数校验
	if err != nil {
		app.Error(c, http.StatusBadRequest, err, err.Error())
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}
	// todo 需要校验当前用户是否有权限

	var erpPurchaseOrder model.ErpPurchaseOrder
	err = orm.Eloquent.Table("erp_purchase_order").Where("serial_number = ?", req.SerialNumber).Find(&erpPurchaseOrder).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
		return
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !model.CheckUserStore(erpPurchaseOrder.StoreId, sysUser) {
			app.Error(c, http.StatusInternalServerError, errors.New("操作失败：您没有该门店权限"), "操作失败：您没有该门店权限")
			return
		}
	}

	// 仅待入库、待退货订单可以终止
	orderState := 0
	if erpPurchaseOrder.State == model.ErpPurchaseOrderWaitInventory || erpPurchaseOrder.State == model.ErpPurchaseOrderWaitReject {
		orderState = model.ErpPurchaseOrderEnd
	} else {
		logger.Error("order err, erpPurchaseOrder.State is:", logger.Field("erpPurchaseOrder.State", erpPurchaseOrder.State))
		app.Error(c, http.StatusInternalServerError, err, "终止失败:仅待入库、待退货订单可以终止")
		return
	}

	updateRemark := ""
	if erpPurchaseOrder.Remark != "" {
		updateRemark = erpPurchaseOrder.Remark + "," + req.Remark
	} else {
		updateRemark = req.Remark
	}

	err = orm.Eloquent.Table("erp_purchase_order").Where("id = ?", erpPurchaseOrder.ID).Updates(map[string]interface{}{
		"state":  orderState,
		"remark": updateRemark,
	}).Error
	if err != nil {
		logger.Error("update erp_purchase_order err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
		return
	}

	app.OK(c, nil, "")
	return
}

// ErpPurchaseExecute 执行（入库/退货）
// @Summary 执行（入库/退货）
// @Tags 采购管理, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseExecuteReq true "执行（入库/退货）模型"
// @Success 200 {object} models.ErpPurchaseExecuteResp
// @Router /api/v1/erp_purchase/execute [post]
func ErpPurchaseExecute(c *gin.Context) {
	req := new(model.ErpPurchaseExecuteReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := model.ExecuteErpPurchase(req, c)
	if err != nil {
		logger.Error("InventoryErpPurchase err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败:"+err.Error())
		return
	}

	app.OK(c, resp, "执行成功")
	return
}

// ErpPurchaseDemandCreate 创建采购需求
// @Summary 创建采购需求
// @Tags 采购需求，V1.4.1
// @Produce json
// @Accept json
// @Param request body models.CreateErpPurchaseDemandReq true "创建采购需求模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/demand/create [post]
func ErpPurchaseDemandCreate(c *gin.Context) {
	req := new(model.CreateErpPurchaseDemandReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	err = model.CreateErpPurchaseDemand(req, sysUser)
	if err != nil {
		logger.Error("CreateErpPurchaseDemand err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "创建失败:"+err.Error())
		return
	}

	app.OK(c, nil, "创建成功")
	return
}

// ErpPurchaseDemandGet 获取采购需求
// @Summary 获取采购需求
// @Tags 采购需求，V1.4.1
// @Produce json
// @Accept json
// @Param request body models.GetErpPurchaseDemandReq true "获取采购需求模型"
// @Success 200 {object} models.GetErpPurchaseDemandResp
// @Router /api/v1/erp_purchase/demand/get [post]
func ErpPurchaseDemandGet(c *gin.Context) {
	req := new(model.GetErpPurchaseDemandReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := model.GetErpPurchaseDemand(req, c)
	if err != nil {
		logger.Error("GetErpPurchaseDemand err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "获取失败:"+err.Error())
		return
	}

	app.OK(c, resp, "获取成功")
	return
}

// ErpPurchaseDemandFinish 完成采购需求
// @Summary 完成采购需求
// @Tags 采购需求，V1.4.1
// @Produce json
// @Accept json
// @Param request body models.FinishErpPurchaseDemandReq true "完成采购需求模型"
// @Success 200 {object} app.Response
// @Router /api/v1/erp_purchase/demand/finish [post]
func ErpPurchaseDemandFinish(c *gin.Context) {
	req := new(model.FinishErpPurchaseDemandReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	err = model.FinishErpPurchaseDemand(req, sysUser)
	if err != nil {
		logger.Error("CreateErpPurchaseDemand err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败:"+err.Error())
		return
	}

	app.OK(c, nil, "操作成功")
	return
}

// ErpPurchaseReportByOrder 采购报表（按单）
// @Summary 采购报表（按单）
// @Tags 采购报表, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseReportByOrderReq true "采购报表（按单）模型"
// @Success 200 {object} models.ErpPurchaseReportByOrderResp
// @Router /api/v1/erp_purchase/report/order [post]
func ErpPurchaseReportByOrder(c *gin.Context) {
	req := new(model.ErpPurchaseReportByOrderReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := model.GetReportByOrder(req, c)
	if err != nil {
		logger.Error("GetReportByOrder err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
		return
	}

	app.OK(c, resp, "查询成功")
	return
}

// ErpPurchaseReportByCommodity 采购报表（按商品）
// @Summary 采购报表（按商品）
// @Tags 采购报表, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseReportByCommodityReq true "采购报表（按商品）模型"
// @Success 200 {object} models.ErpPurchaseReportByCommodityResp
// @Router /api/v1/erp_purchase/report/commodity [post]
func ErpPurchaseReportByCommodity(c *gin.Context) {
	req := new(model.ErpPurchaseReportByCommodityReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	var limiter = rate.NewLimiter(5, 10) // 每秒最多5个请求
	if !limiter.Allow() {
		app.Error(c, http.StatusTooManyRequests, errors.New("too Many Requests"), "Too Many Requests")
		return
	}

	resp, err := model.GetReportByCommodity(req, c)
	if err != nil {
		logger.Error("GetReportByCommodity err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
		return
	}
	//fmt.Println(resp)

	app.OK(c, resp, "查询成功")
	return
}

// ErpPurchaseReportBySupplier 供应商采购汇总
// @Summary 供应商采购汇总
// @Tags 采购报表, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseReportBySupplierReq true "供应商采购汇总模型"
// @Success 200 {object} models.ErpPurchaseReportBySupplierResp
// @Router /api/v1/erp_purchase/report/supplier [post]
func ErpPurchaseReportBySupplier(c *gin.Context) {
	req := new(model.ErpPurchaseReportBySupplierReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := model.GetReportBySupplier(req, c)
	if err != nil {
		logger.Error("GetReportBySupplier err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
		return
	}

	app.OK(c, resp, "查询成功")
	return
}

// ErpPurchaseReportDetail 采购明细
// @Summary 采购明细
// @Tags 采购报表, V1.3.0
// @Produce json
// @Accept json
// @Param request body models.ErpPurchaseReportDetailReq true "采购明细模型"
// @Success 200 {object} models.ErpPurchaseReportDetailResp
// @Router /api/v1/erp_purchase/report/detail [post]
func ErpPurchaseReportDetail(c *gin.Context) {
	req := new(model.ErpPurchaseReportDetailReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		logger.Error("ShouldBindJSON err:", logger.Field("err", err))
		app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
		return
	}

	resp, err := model.GetReportDetail(req, c)
	if err != nil {
		logger.Error("GetReportBySupplier err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
		return
	}

	app.OK(c, resp, "查询成功")
	return
}
