From 6fb869758531fb5e1ff1b1d904042541b345922a Mon Sep 17 00:00:00 2001 From: chenlin Date: Fri, 19 Jul 2024 10:06:02 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E8=BF=9B=E9=94=80=E5=AD=98?= =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E7=AD=9B=E9=80=89=E6=97=B6=E9=97=B4=E5=90=8E?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98=EF=BC=9B=202.=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=9F=A5=E8=AF=A2=E9=87=87=E8=B4=AD=E6=8A=A5=E8=A1=A8?= =?UTF-8?q?=EF=BC=88=E6=8C=89=E5=95=86=E5=93=81=EF=BC=89=E5=B7=B2=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=87=91=E9=A2=9D=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B=203.=E9=87=87=E8=B4=AD=E6=98=8E=E7=BB=86=E5=AF=BC?= =?UTF-8?q?=E5=87=BAexcel=E6=94=AF=E6=8C=81=E5=AD=97=E6=AE=B5=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=9B=204.=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=85=8D=E7=BD=AE=E5=BA=97=E5=91=98=E5=85=91?= =?UTF-8?q?=E6=8D=A2=E7=A0=81=E5=92=8C=E5=AF=BC=E5=87=BAexcel=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/apis/system/sysuser.go | 115 +++++-- app/admin/models/commodity.go | 11 +- app/admin/models/decision.go | 56 +-- app/admin/models/menu.go | 9 + app/admin/models/purchase.go | 83 ++++- app/admin/models/sysuser.go | 321 +++++++++++++++++- .../version/1599190683670_migrate.go | 2 +- docs/docs.go | 19 ++ docs/swagger.json | 19 ++ docs/swagger.yaml | 14 + 10 files changed, 566 insertions(+), 83 deletions(-) diff --git a/app/admin/apis/system/sysuser.go b/app/admin/apis/system/sysuser.go index f68929b..868cd07 100644 --- a/app/admin/apis/system/sysuser.go +++ b/app/admin/apis/system/sysuser.go @@ -2,6 +2,7 @@ package system import ( "encoding/json" + "fmt" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/google/uuid" @@ -25,6 +26,8 @@ import ( // @Param roleId query string false "角色id" // @Param nickName query string false "昵称" // @Param storeId query string false "门店id" +// @Param shopper_code query string false "店员兑换码" +// @Param is_export query string false "是否导出:1-导出" // @Success 200 {object} models.SysUserListResp // @Router /api/v1/sysUserList [get] // @Security Bearer @@ -43,17 +46,20 @@ func GetSysUserList(c *gin.Context) { if index != "" { pageIndex, err = tools.StringToInt(index) } + data.Username = c.Request.FormValue("username") // 用户名称 + data.Status = c.Request.FormValue("status") // 状态 + data.Phone = c.Request.FormValue("phone") // 手机号 + strRoleId := c.Request.FormValue("roleId") // 用户角色 + data.NickName = c.Request.FormValue("nickName") // 用户昵称 + strStoreId := c.Request.FormValue("storeId") // 门店id + data.ShopperCode = c.Request.FormValue("shopper_code") // 店员兑换码 + exportFlag := c.Request.FormValue("is_export") // 是否导出excel + export := 0 + if exportFlag != "" { + export, _ = tools.StringToInt(exportFlag) + } - data.Username = c.Request.FormValue("username") // 用户名称 - data.Status = c.Request.FormValue("status") // 状态 - data.Phone = c.Request.FormValue("phone") // 手机号 - - strRoleId := c.Request.FormValue("roleId") // 用户角色 data.RoleId, _ = tools.StringToInt(strRoleId) - - data.NickName = c.Request.FormValue("nickName") // 用户昵称 - - strStoreId := c.Request.FormValue("storeId") // 门店id nStoreId, _ := tools.StringToInt(strStoreId) data.StoreId = uint32(nStoreId) @@ -64,10 +70,17 @@ func GetSysUserList(c *gin.Context) { data.DeptId, _ = tools.StringToInt(deptId) data.DataScope = tools.GetUserIdStr(c) - result, count, err := data.GetPage(pageSize, pageIndex) + result, count, exportUrl, err := data.GetPage(pageSize, pageIndex, export) tools.HasError(err, "", -1) + var resp models.SysUserListResp + resp.List = result + resp.ExportUrl = exportUrl + resp.Total = count + resp.PageSize = pageSize + resp.PageIndex = pageIndex - app.PageOK(c, result, count, pageIndex, pageSize, "") + app.OK(c, resp, "查询成功") + return } // GetSysUser @@ -182,6 +195,27 @@ func InsertSysUser(c *gin.Context) { tools.HasError(err, "数据解析失败", 500) } + if req.ShopperCode != "" { + if len(req.ShopperCode) != 6 { + logger.Error("兑换码不是6位") + app.Error(c, http.StatusInternalServerError, err, "兑换码长度不符合要求[6位]") + return + } + + if req.Uid == 0 { + logger.Error("uid为0") + app.Error(c, http.StatusInternalServerError, err, "配置店员兑换码需填写小程序账号ID") + return + } + + // 判断店员兑换码是否重复 + if models.IsShopperCodeExists(req.ShopperCode) { + logger.Error("兑换码重复") + app.Error(c, http.StatusInternalServerError, err, fmt.Sprintf("兑换码[%s]重复,请更换", req.ShopperCode)) + return + } + } + // 判断小程序账号ID是否正常 if req.Uid != 0 { userInfo, err := models.GetUserInfoByUid(req.Uid) @@ -259,6 +293,16 @@ func InsertSysUser(c *gin.Context) { } } + if req.ShopperCode != "" { + err = models.AddShopperCode(req, begin) + if err != nil { + begin.Rollback() + logger.Error("AddShopperCode err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, err.Error()) + return + } + } + err = begin.Commit().Error if err != nil { begin.Rollback() @@ -286,6 +330,20 @@ func UpdateSysUser(c *gin.Context) { err := c.BindWith(&req, binding.JSON) tools.HasError(err, "非法数据格式", 500) + if req.ShopperCode != "" { + if len(req.ShopperCode) != 6 { + logger.Error("兑换码不是6位") + app.Error(c, http.StatusInternalServerError, err, "兑换码长度不符合要求[6位]") + return + } + + if req.Uid == 0 { + logger.Error("uid为0") + app.Error(c, http.StatusInternalServerError, err, "配置店员兑换码需填写小程序账号ID") + return + } + } + SalesCommRateFloat, err := models.StringToFloat(req.SalesCommRate) if err != nil { //logger.Error("brokerage1 err:", err) @@ -293,6 +351,16 @@ func UpdateSysUser(c *gin.Context) { } sysInfo := models.GetUserById(uint32(req.UserId)) + if sysInfo.Uid != 0 { + // 添加店员兑换码 + var shopperCode models.ShopperPromotionCode + err = orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", sysInfo.Uid).Find(&shopperCode).Error + if err != nil { + logger.Error("query shopper_promotion_code err:", logger.Field("err", err)) + } + sysInfo.ShopperCode = shopperCode.Code + } + // 判断小程序账号ID是否正常 if req.Uid != 0 && sysInfo.Uid != req.Uid { userInfo, err := models.GetUserInfoByUid(req.Uid) @@ -359,16 +427,11 @@ func UpdateSysUser(c *gin.Context) { if sysInfo.Uid != req.Uid { // 原uid的状态更新为1 err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeConsumer, 0) - if err != nil { - begin.Rollback() - logger.Error("UpdateUserType err:", logger.Field("err", err)) - app.Error(c, http.StatusInternalServerError, err, "修改失败") - return - } - - if req.Uid != 0 { - // 新uid状态更新为2 - err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId)) + if err == nil { + if req.Uid != 0 { + // 新uid状态更新为2 + err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId)) + } } } else if sysInfo.Uid == req.Uid && sysInfo.RoleId != req.RoleId { // 更改了用户角色 err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeShopAssistant, uint32(req.RoleId)) @@ -381,6 +444,16 @@ func UpdateSysUser(c *gin.Context) { return } + if req.ShopperCode != "" { // 添加店员兑换码:删除原兑换码,添加新兑换码 + err = models.UpdateShopperCode(req, begin, sysInfo) + if err != nil { + begin.Rollback() + logger.Error("UpdateShopperCode err:", logger.Field("err", err)) + app.Error(c, http.StatusInternalServerError, err, "修改失败") + return + } + } + err = begin.Commit().Error if err != nil { begin.Rollback() diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index 945dd2f..69a17bb 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -35,9 +35,6 @@ const ( SystemOut = 5 // 系统出库 CheckOut = 6 // 盘点出库 OnSale = 7 // 销售锁定中 - - PurchasePrice = "erp:stock:stockDetails:list:purchasePrice" // 入库采购价 - EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 入库员工成本价 ) // ErpStock 库存列表 @@ -1560,19 +1557,19 @@ func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice boo row = append(row, state) row = append(row, list[rowId].Remark) - cell, _ := excelize.CoordinatesToCellName(1, rowId+2) - if err := streamWriter.SetRow(cell, row); err != nil { + cell, _ = excelize.CoordinatesToCellName(1, rowId+2) + if err = streamWriter.SetRow(cell, row); err != nil { fmt.Println(err) return "", err } } - if err := streamWriter.Flush(); err != nil { + if err = streamWriter.Flush(); err != nil { fmt.Println(err) return "", err } fmt.Println("save fileName:", config.ExportConfig.Path+fileName) - if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { + if err = file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) return "", err } diff --git a/app/admin/models/decision.go b/app/admin/models/decision.go index ebadff3..133aab6 100644 --- a/app/admin/models/decision.go +++ b/app/admin/models/decision.go @@ -149,7 +149,7 @@ func (m *ErpDecisionReportReq) DecisionReportList(c *gin.Context) (*ErpDecisionR } var commodities []ErpStock - if len(m.StoreId) == 1 { // 只查询1个门店数据 + if len(m.StoreId) == 1 && m.IsExport != 1 { // 只查询1个门店数据 err = qs.Order("erp_commodity_id, store_id desc").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error } else { err = qs.Order("erp_commodity_id, store_id desc").Find(&commodities).Error @@ -159,7 +159,7 @@ func (m *ErpDecisionReportReq) DecisionReportList(c *gin.Context) (*ErpDecisionR return nil, err } - if len(m.StoreId) != 1 { // 查询所有门店数据 + if len(m.StoreId) != 1 || (len(m.StoreId) == 1 && m.IsExport == 1) { // 查询所有门店数据 // 剔除商品id重复的数据 var trimCommodities []ErpStock tempCommodityMap := make(map[uint32]ErpStock) @@ -353,7 +353,7 @@ func getSystemStartCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRep logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("first_stock_time <= ?", parse) } var err error @@ -392,7 +392,7 @@ func getPurchaseStockCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionR logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("erp_purchase_inventory.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -401,7 +401,7 @@ func getPurchaseStockCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionR logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("erp_purchase_inventory.created_at <= ?", parse) } var err error @@ -455,7 +455,7 @@ func getPurchaseReturnCount(req *ErpDecisionReportReq, stock ErpStock) (Decision logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("first_stock_time <= ?", parse) } var err error @@ -497,7 +497,7 @@ func getSaleOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportD if err != nil { logger.Errorf("err:", err) } - qs = qs.Where("erp_order.audit_time < ?", parse) + qs = qs.Where("erp_order.audit_time <= ?", parse) } var err error @@ -548,7 +548,7 @@ func getSaleReturnCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRepo logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_order.audit_time > ?", parse) + qs = qs.Where("erp_order.audit_time <= ?", parse) } var err error @@ -602,7 +602,7 @@ func getProductCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportD logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("first_stock_time <= ?", parse) } var err error @@ -638,7 +638,7 @@ func getChangeAddCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRepor logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) + qs = qs.Where("erp_inventory_change_order.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -647,7 +647,7 @@ func getChangeAddCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRepor logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) + qs = qs.Where("erp_inventory_change_order.created_at <= ?", parse) } var err error @@ -698,7 +698,7 @@ func getChangeReduceCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRe logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) + qs = qs.Where("erp_inventory_change_order.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -707,7 +707,7 @@ func getChangeReduceCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRe logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_change_order.audit_time > ?", parse) + qs = qs.Where("erp_inventory_change_order.created_at <= ?", parse) } var err error @@ -767,7 +767,7 @@ func getSystemOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRepor logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("first_stock_time <= ?", parse) } var err error @@ -812,7 +812,7 @@ func getAllotWaitInCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRep logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("updated_at > ?", parse) + qs = qs.Where("updated_at <= ?", parse) } var err error @@ -848,7 +848,7 @@ func getAllotWaitOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRe logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -857,7 +857,7 @@ func getAllotWaitOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRe logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at <= ?", parse) } var err error @@ -908,7 +908,7 @@ func getAllotInCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportD logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -917,7 +917,7 @@ func getAllotInCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReportD logger.Errorf("getChangeAddCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at <= ?", parse) } var err error @@ -968,7 +968,7 @@ func getAllotOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReport logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -977,7 +977,7 @@ func getAllotOutCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionReport logger.Errorf("getAllotOutCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at <= ?", parse) } var err error @@ -1037,7 +1037,7 @@ func getSystemEndCount(req *ErpDecisionReportReq, stock ErpStock) (DecisionRepor logger.Errorf("getSystemStartCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("first_stock_time <= ?", parse) } var err error @@ -1129,7 +1129,7 @@ func getSumPurchaseData(req *ErpDecisionReportReq) (DecisionReportData, error) { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("erp_purchase_inventory.created_at > ?", parse) } if req.EndTime != "" { // 出入库结束时间 @@ -1138,7 +1138,7 @@ func getSumPurchaseData(req *ErpDecisionReportReq) (DecisionReportData, error) { logger.Errorf("getPurchaseCount err:", err) return DecisionReportData{}, err } - qs = qs.Where("first_stock_time > ?", parse) + qs = qs.Where("erp_purchase_inventory.created_at <= ?", parse) } if len(req.StoreId) > 0 { @@ -1183,7 +1183,7 @@ func getSumSalesData(req *ErpDecisionReportReq) (DecisionReportData, error) { logger.Errorf("getSalesAndReturns err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_order.audit_time < ?", parse) + qs = qs.Where("erp_order.audit_time <= ?", parse) } if len(req.StoreId) > 0 { @@ -1230,7 +1230,7 @@ func getSumInventoryData(req *ErpDecisionReportReq) (DecisionReportData, error) logger.Errorf("getInventoryChanges err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_change_order.audit_time < ?", parse) + qs = qs.Where("erp_inventory_change_order.audit_time <= ?", parse) } if len(req.StoreId) > 0 { @@ -1270,7 +1270,7 @@ func getSumAllotData(req *ErpDecisionReportReq) (DecisionReportData, error) { logger.Errorf("getAllotCounts err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time > ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at > ?", parse) } if req.EndTime != "" { @@ -1279,7 +1279,7 @@ func getSumAllotData(req *ErpDecisionReportReq) (DecisionReportData, error) { logger.Errorf("getAllotCounts err:", err) return DecisionReportData{}, err } - qs = qs.Where("erp_inventory_allot_commodity.audit_time < ?", parse) + qs = qs.Where("erp_inventory_allot_commodity.created_at <= ?", parse) } // Apply store_id filter if provided diff --git a/app/admin/models/menu.go b/app/admin/models/menu.go index a906546..de4b805 100644 --- a/app/admin/models/menu.go +++ b/app/admin/models/menu.go @@ -7,6 +7,15 @@ import ( "go-admin/tools" ) +const ( + PurchasePrice = "erp:stock:stockDetails:list:purchasePrice" // 入库采购价 + EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 入库员工成本价 + + PriceMenu = "erp:purchase:purchaseDetails:list:price" // 采购/退货价 + EmployeePriceMenu = "erp:purchase:purchaseDetails:list:employee_price" // 员工成本价 + DifferencePriceMenu = "erp:purchase:purchaseDetails:list:difference_price" // 差额 +) + type Menu struct { MenuId int `json:"menuId" gorm:"primary_key;AUTO_INCREMENT"` MenuName string `json:"menuName" gorm:"size:128;"` diff --git a/app/admin/models/purchase.go b/app/admin/models/purchase.go index dad4814..f7e036e 100644 --- a/app/admin/models/purchase.go +++ b/app/admin/models/purchase.go @@ -4606,7 +4606,7 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin reportData.PlanCount += v.PlanCount reportData.PlanAmount += v.PlanAmount - reportData.Amount += v.Amount * 100 + reportData.Amount += v.Amount reportData.Count += v.Count reportData.NonExecutionAmount += v.NonExecutionAmount reportData.NonExecutionCount += v.NonExecutionCount @@ -5843,7 +5843,19 @@ func GetReportDetail(req *ErpPurchaseReportDetailReq, c *gin.Context) (*ErpPurch if req.IsExport == 1 { resp.List = reportList - filePath, err := reportDetailExport(resp) + + // 判断是否有入库采购价、入库员工成本价的权限 + priceFlag, _ := checkRoleMenu(c, PriceMenu) + employeePriceFlag, _ := checkRoleMenu(c, EmployeePriceMenu) + differencePriceFlag, _ := checkRoleMenu(c, DifferencePriceMenu) + fmt.Println("priceFlag is:", priceFlag) + fmt.Println("employeePriceFlag is:", employeePriceFlag) + fmt.Println("differencePriceFlag is:", differencePriceFlag) + logger.Info("priceFlag is:", logger.Field("priceFlag", priceFlag)) + logger.Info("employeePriceFlag is:", logger.Field("employeePriceFlag", employeePriceFlag)) + logger.Info("differencePriceFlag is:", logger.Field("differencePriceFlag", differencePriceFlag)) + + filePath, err := reportDetailExport(resp, priceFlag, employeePriceFlag, differencePriceFlag) if err != nil { return nil, err } @@ -5891,7 +5903,8 @@ func calculatePrices(list []ReportDetailData) (price, employeePrice, rejectPrice } // 导出采购明细excel -func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { +func reportDetailExport(req *ErpPurchaseReportDetailResp, exportPrice bool, + exportEmployeePrice bool, exportDifferencePrice bool) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" @@ -5899,9 +5912,23 @@ func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { fileName := time.Now().Format(TimeFormat) + "采购明细" + ".xlsx" fmt.Println("url fileName:", url+fileName) + nEndCount := 0 // 组合标题栏数据 - title := []interface{}{"单据编号", "单据类型", "出/入库时间", "店铺名称", "供应商", "商品名称", "商品分类", "是否串码", "串码", - "采购价", "员工成本价", "退货价", "差价"} + title := []interface{}{"单据编号", "单据类型", "出/入库时间", "店铺名称", "供应商", "商品名称", "商品分类", "是否串码", "串码"} + + if exportPrice { // 采购/退货价 + title = append(title, "采购/退货价") + nEndCount += 1 + } + if exportEmployeePrice { // 员工成本价 + title = append(title, "员工成本价") + nEndCount += 1 + } + if exportDifferencePrice { // 差额 + title = append(title, "差额") + nEndCount += 1 + } + for i, _ := range title { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title[i]) @@ -5912,13 +5939,16 @@ func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { var row []interface{} nExcelStartRow := 0 + price := float64(0) for _, detailData := range req.List { var orderType string switch detailData.PurchaseType { case "procure": orderType = "采购入库" + price = detailData.Price case "reject": orderType = "采购退货" + price = detailData.RejectPrice } var IMEIType string @@ -5939,10 +5969,16 @@ func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { detailData.ErpCategoryName, // 商品分类 IMEIType, // 是否串码 detailData.IMEI, // 串码 - detailData.Price, // 采购价 - detailData.EmployeePrice, // 员工成本价 - detailData.RejectPrice, // 退货价 - detailData.DifferencePrice, // 差价 + } + // 控制是否导出:采购/退货价、员工成本价、差额 + if exportPrice { // 采购/退货价 + row = append(row, price) + } + if exportEmployeePrice { // 员工成本价 + row = append(row, detailData.EmployeePrice) + } + if exportDifferencePrice { // 差额 + row = append(row, detailData.DifferencePrice) } for j, _ := range row { @@ -5956,12 +5992,18 @@ func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { } totalData := "记录数:" + strconv.FormatInt(int64(req.Total), 10) - end := []interface{}{totalData, "", "", "", "", "", "", "", "", - req.Price, // 采购价 - req.EmployeePrice, // 员工成本价 - req.RejectPrice, // 退货价 - req.DifferencePrice, // 差价 + end := []interface{}{totalData, "", "", "", "", "", "", "", ""} + // 控制是否导出:采购/退货价、员工成本价、差额 + if exportPrice { // 采购/退货价 + end = append(end, req.Price) } + if exportEmployeePrice { // 员工成本价 + end = append(end, req.EmployeePrice) + } + if exportDifferencePrice { // 差额 + end = append(end, req.DifferencePrice) + } + for i, _ := range end { cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2) err := file.SetCellValue(fSheet, cell, end[i]) @@ -5987,7 +6029,18 @@ func reportDetailExport(req *ErpPurchaseReportDetailResp) (string, error) { file.SetColWidth("Sheet1", "F", "F", 18) file.SetColWidth("Sheet1", "I", "I", 18) - endRow := fmt.Sprintf("M"+"%d", nExcelStartRow+2) + var endRow string + switch nEndCount { + case 1: + endRow = fmt.Sprintf("J"+"%d", nExcelStartRow+2) + case 2: + endRow = fmt.Sprintf("K"+"%d", nExcelStartRow+2) + case 3: + endRow = fmt.Sprintf("L"+"%d", nExcelStartRow+2) + default: + endRow = fmt.Sprintf("I"+"%d", nExcelStartRow+2) + } + // 应用样式到整个表格 _ = file.SetCellStyle("Sheet1", "A1", endRow, style) diff --git a/app/admin/models/sysuser.go b/app/admin/models/sysuser.go index 368c294..b80fa7d 100644 --- a/app/admin/models/sysuser.go +++ b/app/admin/models/sysuser.go @@ -4,6 +4,9 @@ import ( "encoding/json" "errors" "fmt" + "github.com/xuri/excelize/v2" + "go-admin/logger" + "go-admin/tools/config" "gorm.io/gorm" "log" "sort" @@ -68,6 +71,8 @@ type SysUserB struct { StoreList []StoreInfo `json:"store_list" gorm:"-" ` // 有效门店列表 SalesCommRate float64 `json:"sales_comm_rate"` // 销售提成比例 Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // 用户uid todo 待添加 + ShopperCode string `json:"shopper_code" gorm:"-"` // 店员兑换码 + BaseModel DataScope string `gorm:"-" json:"dataScope"` @@ -108,6 +113,7 @@ type InsertSysUserReq struct { SalesCommRate string `json:"sales_comm_rate"` // 销售提成比例 StoreList []StoreInfo `json:"store_list"` // 有效门店 Uid uint32 `json:"uid"` // 用户uid + ShopperCode string `json:"shopper_code"` // 店员兑换码 } func (SysUser) TableName() string { @@ -257,17 +263,31 @@ func (e *SysUser) GetList() (SysUserView []SysUserView, err error) { } type SysUserListResp struct { - Total int `json:"count"` // 总条数 - PageIndex int `json:"pageIndex"` // 页码 - PageSize int `json:"pageSize"` // 页面条数 - List []SysUserPage `json:"list"` // 采购报表信息 + Total int `json:"count"` // 总条数 + PageIndex int `json:"pageIndex"` // 页码 + PageSize int `json:"pageSize"` // 页面条数 + ExportUrl string `json:"export_url"` // 导出excel路径 + List []SysUserPage `json:"list"` // 采购报表信息 } -func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, error) { +func (e *SysUser) GetPage(pageSize int, pageIndex int, exportFlag int) ([]SysUserPage, int, string, error) { + if e.ShopperCode != "" { + var shopperCode ShopperPromotionCode + err := orm.Eloquent.Table("shopper_promotion_code").Where("code = ?", e.ShopperCode).Find(&shopperCode).Error + if err != nil { + logger.Error("query shopper_promotion_code err:", logger.Field("err", err)) + return nil, 0, "", err + } + e.Uid = shopperCode.Uid + } + var doc []SysUserPage table := orm.Eloquent.Select("sys_user.*,sys_dept.dept_name").Table(e.TableName()) table = table.Joins("left join sys_dept on sys_dept.dept_id = sys_user.dept_id") //es := orm.Eloquent.Select("sys_user.*,sys_dept.dept_name").Table(e.TableName()) //es = table.Joins("left join sys_dept on sys_dept.dept_id = sys_user.dept_id") + if e.Uid != 0 { + table = table.Where("uid = ?", e.Uid) + } if e.Username != "" { table = table.Where("username = ?", e.Username) } @@ -300,7 +320,7 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro dataPermission.UserId, _ = tools.StringToInt(e.DataScope) table, err := dataPermission.GetDataScope(e.TableName(), table) if err != nil { - return nil, 0, err + return nil, 0, "", err } es := table @@ -308,7 +328,7 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro err = es.Count(&count).Error if err != nil { //logger.Error("count err:", err) - return nil, 0, err + return nil, 0, "", err } //if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Order("sys_user.created_at DESC").Offset(-1).Limit(-1).Total(&count).Error; err != nil { @@ -316,10 +336,11 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro //} if err = table.Order("sys_user.user_id DESC").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil { - return nil, 0, err + return nil, 0, "", err } var resp []SysUserPage + var exportUrl string // 反序列化 StoreData for i, v := range doc { if doc[i].StoreData != "" { @@ -340,10 +361,148 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro } } + if doc[i].Uid != 0 { + // 添加店员兑换码 + var shopperCode ShopperPromotionCode + err = orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", doc[i].Uid).Find(&shopperCode).Error + if err != nil { + logger.Error("query shopper_promotion_code err:", logger.Field("err", err)) + } + doc[i].ShopperCode = shopperCode.Code + } + resp = append(resp, doc[i]) } - return resp, int(count), nil + if exportFlag == 1 { // 导出excel + exportUrl, err = sysUserExport(resp) + if err != nil { + return nil, 0, "", err + } + resp = nil + } + + return resp, int(count), exportUrl, nil +} + +func getValidStoreNames(storeList []StoreInfo) (string, error) { + var validStoreNames []string + currentTime := time.Now() + + for _, store := range storeList { + expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime) + if err != nil { + return "", fmt.Errorf("invalid expire time format for store ID %d: %v", store.StoreID, err) + } + if expireTime.After(currentTime) { + validStoreNames = append(validStoreNames, store.StoreName) + } + } + + return strings.Join(validStoreNames, ","), nil +} + +// 导出系统用户列表 +func sysUserExport(req []SysUserPage) (string, error) { + file := excelize.NewFile() + fSheet := "Sheet1" + + url := ExportUrl + fileName := time.Now().Format(TimeFormat) + "系统用户" + ".xlsx" + fmt.Println("url fileName:", url+fileName) + + // 组合标题栏数据 + title := []interface{}{"用户名称", "用户昵称", "角色", "合作商", "门店", "手机号", "店员识别码", "状态"} + for i, _ := range title { + cell, _ := excelize.CoordinatesToCellName(1+i, 1) + err := file.SetCellValue(fSheet, cell, title[i]) + if err != nil { + logger.Errorf("file set value err:", err) + } + } + + // 查询系统角色 + var doc []SysRole + err := orm.Eloquent.Table("sys_role").Find(&doc).Error + if err != nil { + logger.Errorf("query sys_role error:", err) + } + roleMap := make(map[int]string) + for _, item := range doc { + roleMap[item.RoleId] = item.RoleName + } + + var row []interface{} + nExcelStartRow := 0 + for _, userData := range req { + // 门店 + storeName, _ := getValidStoreNames(userData.StoreList) + + var status string + if userData.Status == "0" { + status = "正常" + } else { + status = "停用" + } + + row = []interface{}{ + userData.UserName.Username, // 用户名称 + userData.NickName, // 用户昵称 + roleMap[userData.RoleId], // 角色 + userData.CooperativeName, // 合作商 + storeName, // 门店 + userData.Phone, // 手机号 + userData.ShopperCode, // 店员识别码 + status, // 状态 + } + + for j, _ := range row { + cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) + err := file.SetCellValue(fSheet, cell, row[j]) + if err != nil { + logger.Error("file set value err:", logger.Field("err", err)) + } + } + nExcelStartRow++ + } + + // 设置所有单元格的样式: 居中、加边框 + style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + // 设置单元格的样式: 居中、加边框、自动换行 + style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, + "border":[{"type":"left","color":"000000","style":1}, + {"type":"top","color":"000000","style":1}, + {"type":"right","color":"000000","style":1}, + {"type":"bottom","color":"000000","style":1}]}`) + + //设置单元格高度 + file.SetRowHeight("Sheet1", 1, 20) + + // 设置单元格大小 + file.SetColWidth("Sheet1", "B", "B", 15) + file.SetColWidth("Sheet1", "C", "C", 15) + file.SetColWidth("Sheet1", "D", "D", 15) + file.SetColWidth("Sheet1", "E", "E", 30) + file.SetColWidth("Sheet1", "F", "F", 15) + file.SetColWidth("Sheet1", "G", "G", 15) + + endRow := fmt.Sprintf("H"+"%d", nExcelStartRow+2) + // 应用样式到整个表格 + _ = file.SetCellStyle("Sheet1", "A1", endRow, style) + + endRow1 := fmt.Sprintf("E%d", nExcelStartRow+2) + _ = file.SetCellStyle("Sheet1", "E2", endRow1, style1) + + fmt.Println("save fileName:", config.ExportConfig.Path+fileName) + if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { + fmt.Println(err) + } + return url + fileName, nil } // 反序列化 StoreData @@ -432,8 +591,14 @@ func (e *SysUser) Update(begin *gorm.DB, id int) (update SysUser, err error) { //参数1:是要修改的数据 //参数2:是修改的数据 - if err = begin.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil { - return + if e.Password != "" { // 更新密码时其他信息为空,需要update + if err = begin.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil { + return + } + } else { + if err = begin.Table(e.TableName()).Model(&update).Save(&e).Error; err != nil { + return + } } return } @@ -596,3 +761,137 @@ func GetUserEffectiveStoreById(id uint32) ([]StoreInfo, error) { return validStores, nil } + +// AddShopperCode 添加店员兑换码 +func AddShopperCode(req InsertSysUserReq, begin *gorm.DB) error { + // 获取有效门店id + now := time.Now() + // 过滤掉过期的门店 + validStores := make([]StoreInfo, 0) + for _, store := range req.StoreList { + expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime) + if err != nil { + log.Println("Error parsing time:", err, "ExpireTime:", store.ExpireTime) + continue + } + + // 包含当天有效时间 + expireTime = expireTime.Add(24*time.Hour - time.Second) + if expireTime.After(now) { + validStores = append(validStores, store) + } + } + + if len(validStores) == 0 { + return errors.New("设置兑换码失败,无有效门店") + } + + // 按有效时间和 store_id 排序 + sort.Slice(validStores, func(i, j int) bool { + timeI, _ := time.Parse(StoreDateTimeFormat, validStores[i].ExpireTime) + timeJ, _ := time.Parse(StoreDateTimeFormat, validStores[j].ExpireTime) + + if timeI.Equal(timeJ) { + return validStores[i].StoreID < validStores[j].StoreID + } + return timeI.Before(timeJ) + }) + + var shopperCode ShopperPromotionCode + shopperCode.Code = req.ShopperCode + shopperCode.Uid = req.Uid + shopperCode.State = 2 + shopperCode.StoreId = uint32(validStores[0].StoreID) + if err := begin.Table("shopper_promotion_code").Create(&shopperCode).Error; err != nil { + logger.Error("create shopper_promotion_code err:", logger.Field("err", err)) + return err + } + + return nil +} + +// UpdateShopperCode 更新店员兑换码 +func UpdateShopperCode(req InsertSysUserReq, begin *gorm.DB, sysInfo *SysUserB) error { + if req.Uid == sysInfo.Uid && req.ShopperCode == sysInfo.ShopperCode { // 兑换码没变化 + return nil + } + + var oldShopperCode ShopperPromotionCode + orm.Eloquent.Debug().Model(&ShopperPromotionCode{}). + Where("code = ? and state = ?", req.ShopperCode, 2).Find(&oldShopperCode) + if oldShopperCode.ID != 0 && oldShopperCode.Uid != sysInfo.Uid { + return errors.New(fmt.Sprintf("兑换码[%s]重复,请更换", req.ShopperCode)) + } + + // 获取有效门店id + now := time.Now() + // 过滤掉过期的门店 + validStores := make([]StoreInfo, 0) + for _, store := range req.StoreList { + expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime) + if err != nil { + log.Println("Error parsing time:", err, "ExpireTime:", store.ExpireTime) + continue + } + + // 包含当天有效时间 + expireTime = expireTime.Add(24*time.Hour - time.Second) + if expireTime.After(now) { + validStores = append(validStores, store) + } + } + + if len(validStores) == 0 { + return errors.New("设置兑换码失败,无有效门店") + } + + // 按有效时间和 store_id 排序 + sort.Slice(validStores, func(i, j int) bool { + timeI, _ := time.Parse(StoreDateTimeFormat, validStores[i].ExpireTime) + timeJ, _ := time.Parse(StoreDateTimeFormat, validStores[j].ExpireTime) + + if timeI.Equal(timeJ) { + return validStores[i].StoreID < validStores[j].StoreID + } + return timeI.Before(timeJ) + }) + + // 删除原有的兑换码 + if sysInfo.Uid != 0 && sysInfo.ShopperCode != "" { + err := orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", sysInfo.Uid).Delete(&ShopperPromotionCode{}).Error + if err != nil { + logger.Error("delete shopper_promotion_code err:", logger.Field("err", err)) + return err + } + } + + // 删除新配置的uid的兑换码 + err := orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", req.Uid).Delete(&ShopperPromotionCode{}).Error + if err != nil { + logger.Error("delete shopper_promotion_code err:", logger.Field("err", err)) + return err + } + + // 添加新的兑换码 + var shopperCode ShopperPromotionCode + shopperCode.Code = req.ShopperCode + shopperCode.Uid = req.Uid + shopperCode.State = 2 + shopperCode.StoreId = uint32(validStores[0].StoreID) + if err := begin.Table("shopper_promotion_code").Create(&shopperCode).Error; err != nil { + logger.Error("create shopper_promotion_code err:", logger.Field("err", err)) + return err + } + + return nil +} + +// IsShopperCodeExists 查询兑换码是否重复 +func IsShopperCodeExists(code string) bool { + var count int64 + orm.Eloquent.Debug().Model(&ShopperPromotionCode{}). + Where("code = ? and state = ?", code, 2). + Count(&count) + + return count > 0 +} diff --git a/cmd/migrate/migration/version/1599190683670_migrate.go b/cmd/migrate/migration/version/1599190683670_migrate.go index 4fc226a..7edeedc 100644 --- a/cmd/migrate/migration/version/1599190683670_migrate.go +++ b/cmd/migrate/migration/version/1599190683670_migrate.go @@ -290,7 +290,7 @@ func _1599190683670Test(db *gorm.DB, version string) error { } list8 := []models.SysUser{ - {SysUserId: models.SysUserId{1}, LoginM: models.LoginM{models.UserName{"admin"}, models.PassWord{"$2a$10$cKFFTCzGOvaIHHJY2K45Zuwt8TD6oPzYi4s5MzYIBAWCLL6ZhouP2"}}, SysUserB: models.SysUserB{"zhangwj", "13818888888", 1, "", "", "0", "1@qq.com", 1, 1, "1", "1", "", "0", 1, "总店", 1, "迪为", 1, "", []models.StoreInfo{{1, "", ""}}, 0, 0, models.BaseModel{CreatedAt: time.Now(), UpdatedAt: time.Now()}, "", ""}}, + {SysUserId: models.SysUserId{1}, LoginM: models.LoginM{models.UserName{"admin"}, models.PassWord{"$2a$10$cKFFTCzGOvaIHHJY2K45Zuwt8TD6oPzYi4s5MzYIBAWCLL6ZhouP2"}}, SysUserB: models.SysUserB{"zhangwj", "13818888888", 1, "", "", "0", "1@qq.com", 1, 1, "1", "1", "", "0", 1, "总店", 1, "迪为", 1, "", []models.StoreInfo{{1, "", ""}}, 0, 0, "", models.BaseModel{CreatedAt: time.Now(), UpdatedAt: time.Now()}, "", ""}}, } list9 := []models.DictData{ diff --git a/docs/docs.go b/docs/docs.go index 7ffaa6f..c0342df 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -10922,6 +10922,13 @@ const docTemplate = `{ "description": "创建时间", "type": "string" }, + "decision_store_id": { + "description": "门店编号列表(查询进销存的时候使用)", + "type": "array", + "items": { + "type": "integer" + } + }, "dispatch_count": { "description": "调拨中数量(调拨中调入)", "type": "integer" @@ -11987,6 +11994,10 @@ const docTemplate = `{ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" @@ -16044,6 +16055,10 @@ const docTemplate = `{ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" @@ -16195,6 +16210,10 @@ const docTemplate = `{ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" diff --git a/docs/swagger.json b/docs/swagger.json index fa03de3..fe0a346 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -10911,6 +10911,13 @@ "description": "创建时间", "type": "string" }, + "decision_store_id": { + "description": "门店编号列表(查询进销存的时候使用)", + "type": "array", + "items": { + "type": "integer" + } + }, "dispatch_count": { "description": "调拨中数量(调拨中调入)", "type": "integer" @@ -11976,6 +11983,10 @@ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" @@ -16033,6 +16044,10 @@ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" @@ -16184,6 +16199,10 @@ "description": "性别", "type": "string" }, + "shopper_code": { + "description": "店员兑换码", + "type": "string" + }, "status": { "description": "状态", "type": "string" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index c915816..2c6007a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -3489,6 +3489,11 @@ definitions: createdAt: description: 创建时间 type: string + decision_store_id: + description: 门店编号列表(查询进销存的时候使用) + items: + type: integer + type: array dispatch_count: description: 调拨中数量(调拨中调入) type: integer @@ -4253,6 +4258,9 @@ definitions: sex: description: 性别 type: string + shopper_code: + description: 店员兑换码 + type: string status: description: 状态 type: string @@ -7180,6 +7188,9 @@ definitions: sex: description: 性别 type: string + shopper_code: + description: 店员兑换码 + type: string status: description: 状态 type: string @@ -7290,6 +7301,9 @@ definitions: sex: description: 性别 type: string + shopper_code: + description: 店员兑换码 + type: string status: description: 状态 type: string