1.修改进销存报表筛选时间后报错问题;

2.修复查询采购报表(按商品)已执行金额错误问题;
3.采购明细导出excel支持字段配置;
4.系统用户支持配置店员兑换码和导出excel表格;
This commit is contained in:
chenlin 2024-07-19 10:06:02 +08:00
parent 973b77d5e9
commit 6fb8697585
10 changed files with 566 additions and 83 deletions

View File

@ -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()

View File

@ -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
}

View File

@ -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

View File

@ -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;"`

View File

@ -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)

View File

@ -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
}

View File

@ -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{

View File

@ -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"

View File

@ -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"

View File

@ -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