1.小程序调用erp登录接口不判断验证码; 2.修改原接口的翻页相关字段; 3.修复float64转int32精度丢失的缺陷; 4.注释库存导入时采购价需大于0的校验; 5.相关域名改成生产环境域名;
5203 lines
186 KiB
Go
5203 lines
186 KiB
Go
package models
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/xuri/excelize/v2"
|
||
"go-admin/app/admin/apis/pay"
|
||
orm "go-admin/common/global"
|
||
"go-admin/logger"
|
||
"go-admin/tools"
|
||
"go-admin/tools/config"
|
||
"gorm.io/gorm"
|
||
"math"
|
||
"math/rand"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
const (
|
||
ErpOrderStateUnAudit = "un_audit" // 未审核
|
||
ErpOrderStateAudited = "audited" // 已审核
|
||
|
||
ErpOrderMemberTypeGeneral = "general" // 普通
|
||
ErpOrderMemberTypeMember = "member" // 会员
|
||
|
||
RetailTypeSale = "sale" // 零售订单
|
||
RetailTypeRejected = "rejected" // 零售退货订单
|
||
|
||
NoCreatePayOrder = 0 // 未创建
|
||
WaitForPaying = 1 // 待支付
|
||
HavePaid = 2 // 已支付
|
||
|
||
NoPrint = 1 // 未打印
|
||
HavePrinted = 2 // 已打印
|
||
|
||
OnlinePay = 1 // 线上支付(微信/支付宝/云闪付扫码)
|
||
|
||
NoPayOrder = "no_pay_order"
|
||
PayInit = "pay_init"
|
||
Paying = "paying"
|
||
PayOk = "pay_ok"
|
||
PayFailed = "pay_failed"
|
||
PayUnknown = "pay_unknown"
|
||
)
|
||
|
||
// ErpOrder 零售订单表
|
||
type ErpOrder struct {
|
||
Model
|
||
|
||
BillSn string `json:"bill_sn" gorm:"index"` // 单据编号
|
||
RetailType string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
Uid int `json:"uid"` // 用户id
|
||
Tel string `json:"tel" gorm:"index"` // 客户手机号
|
||
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
|
||
StoreName string `json:"store_name"` // 门店名称
|
||
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
|
||
MakerName string `json:"maker_name"` // 制单人名称
|
||
MakerTime time.Time `json:"maker_time"` // 制单时间
|
||
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
|
||
AuditorName string `json:"auditor_name"` // 审核人姓名
|
||
AuditTime *time.Time `json:"audit_time"` // 审核时间
|
||
CashierList string `json:"cashier_list" gorm:"type:text"` // 付款方式,存储json数据
|
||
SalesmanList string `json:"salesman_list" gorm:"type:text"` // 销售员信息,存储json数据
|
||
MemberType string `json:"member_type"` // 会员类型:general 普通; member 会员
|
||
State string `json:"state" gorm:"index"` // 订单状态:un_audit 待审核; audited 已审核
|
||
TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价
|
||
TotalAmount float64 `json:"total_amount"` // 订单实收金额
|
||
TotalCount int32 `json:"total_count"` // 订单商品数量
|
||
TotalSalesProfit float64 `json:"total_sales_profit"` // 订单总销售毛利
|
||
TotalStaffProfit float64 `json:"total_staff_profit"` // 订单总员工毛利
|
||
VmCount uint32 `json:"vm_count"` // 使用会员积分
|
||
SaleOrderId uint32 `json:"sale_order_id"` // 销售订单id
|
||
PayStatus uint32 `json:"pay_status"` // 支付状态 0-未创建 ;1-待支付; 2-已支付
|
||
IsPrint uint32 `json:"is_print"` // 是否打印小票 1-未打印 2-已打印
|
||
PrintCount uint32 `json:"print_count"` // 小票打印次数
|
||
InvoiceCode string `json:"invoice_code"` // 发票代码
|
||
InvoiceNumber string `json:"invoice_number"` // 发票编码
|
||
RejectedTotalAmount float64 `json:"rejected_total_amount" gorm:"-"` // 订单总退货金额
|
||
RejectedTotalCount uint32 `json:"rejected_total_count" gorm:"-"` // 订单总退货数量
|
||
StorePer float64 `json:"store_per"` // 门店提成:订单总员工毛利X该门店设置好的提成比例,保留到小数后两位多余舍去
|
||
TotalDiscount float64 `json:"total_discount"` // 订单总优惠:订单所有商品零售优惠+会员优惠+会员积分抵扣之和
|
||
Commodities []ErpOrderCommodity `json:"commodities" gorm:"-"` // 零售订单商品信息
|
||
Cashiers []ErpOrderCashier `json:"cashiers" gorm:"-"` // 收付款方式
|
||
Salesman []ErpOrderSales `json:"salesman" gorm:"-"` // 销售员信息
|
||
}
|
||
|
||
// ErpOrderCommodity 零售订单商品表
|
||
type ErpOrderCommodity struct {
|
||
Model
|
||
|
||
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id(后端生成)
|
||
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
||
ErpCategoryName string `json:"erp_category_name"` // 分类名称
|
||
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 主供应商id
|
||
ErpSupplierName string `json:"erp_supplier_name"` // 主供应商名称
|
||
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
|
||
IMEI string `json:"imei" gorm:"index"` // 串码
|
||
PresentType uint32 `json:"present_type"` // 赠送类型:1-非赠送 2-赠送
|
||
RetailPrice float64 `json:"retail_price"` // 指导零售价
|
||
SalePrice float64 `json:"sale_price"` // 零售价
|
||
Count int32 `json:"count"` // 销售数量
|
||
SaleDiscount float64 `json:"sale_discount"` // 零售优惠
|
||
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
||
VmDiscount float64 `json:"vm_discount"` // 会员积分抵扣
|
||
Amount float64 `json:"amount"` // 实际零售价
|
||
ReceivedAmount float64 `json:"received_amount"` // 商品实收金额
|
||
Remark string `json:"remark"` // 销售备注
|
||
RejectedRemark string `json:"rejected_remark"` // 退货备注
|
||
RejectedPrice float64 `json:"rejected_price"` // 退货单价
|
||
RejectedCount uint32 `json:"rejected_count"` // 退货数量
|
||
RejectedAmount float64 `json:"rejected_amount"` // 退货金额
|
||
RejectedOrderCommodityId uint32 `json:"rejected_order_commodity_id"` // 退货订单商品id
|
||
StaffCostPrice float64 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格)
|
||
WholesalePrice float64 `json:"wholesale_price"` // 指导采购价
|
||
SalesProfit float64 `json:"sales_profit"` // 销售毛利:实际零售价-采购单价;如果为退货订单,则为实际退货价-采购单价
|
||
StaffProfit float64 `json:"staff_profit"` // 员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价
|
||
ErpStockCommodityID string `json:"erp_stock_commodity_id"` // 库存商品表主键id
|
||
StaffPrice float64 `json:"staff_price" gorm:"-"` // 员工成本价
|
||
}
|
||
|
||
// ErpOrderCashier 订单收款方式
|
||
type ErpOrderCashier struct {
|
||
CashierId uint32 `json:"cashier_id"` // 收付款方式id
|
||
Name string `json:"name"` // 收付款方式名称
|
||
Amount float64 `json:"amount"` // 金额
|
||
}
|
||
|
||
// ErpOrderPayWay 订单支付方式记录
|
||
type ErpOrderPayWay struct {
|
||
Model
|
||
|
||
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id(后端生成)
|
||
CashierId uint32 `json:"cashier_id"` // 收付款方式id
|
||
Name string `json:"name"` // 收付款方式名称
|
||
Amount float64 `json:"amount"` // 金额
|
||
}
|
||
|
||
// ErpOrderSales 销售员信息
|
||
type ErpOrderSales struct {
|
||
Model
|
||
|
||
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id(后端生成)
|
||
Uid uint32 `json:"userId" binding:"required"` // 销售员用户ID(20240322:更换为系统用户表主键id)
|
||
Name string `json:"name"` // 销售员用户姓名
|
||
SalesProfitPer float64 `json:"sales_profit_per"` // 销售毛利提成:每个商品销售毛利X其对应的提成比例后求和;如果是两个销售员参与则分别除以2 ,保留到小数后两位多余舍去
|
||
StaffProfitPer float64 `json:"staff_profit_per"` // 员工毛利提成:每个商品员工毛利X其对应的提成比例后求和;如果是两个销售员参与则分别除以2 ,保留到小数后两位多余舍去
|
||
SalesmanPer float64 `json:"salesman_per"` // 销售员提成:订单总员工毛利X该销售员设置好的提成比例;如果是两个销售员参与,那么两个人算出的提成均除以2,保留到小数后两位多余舍去
|
||
}
|
||
|
||
// ErpOrderRecord 订单支付记录表
|
||
type ErpOrderRecord struct {
|
||
Model
|
||
|
||
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id
|
||
BillSn string `json:"bill_sn" gorm:"index"` // 单据编号
|
||
OutOrderNo string `json:"out_order_no"` // 商户订单号
|
||
PlatTrxNo string `json:"plat_trx_no"` // 平台交易流水号
|
||
BankOrderNo string `json:"bank_order_no"` // 银行订单号
|
||
TotalAmount float64 `json:"total_amount"` // 订单总金额
|
||
PayWay string `json:"pay_way"` // 支付方式
|
||
Status string `json:"status"` // 支付状态
|
||
}
|
||
|
||
// ErpOrderCreateReq 订单创建入参
|
||
type ErpOrderCreateReq struct {
|
||
BillSn string `json:"bill_sn"` // 单据编号
|
||
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
|
||
StoreName string `json:"store_name" binding:"required"` // 门店名称
|
||
RetailType string `json:"retail_type" binding:"required"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
Tel string `json:"tel" binding:"required"` // 会员手机号
|
||
MemberType string `json:"member_type" binding:"required"` // 会员类型:general 普通; member 会员
|
||
TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价:如果是赠送商品,金额可以为0
|
||
TotalAmount float64 `json:"total_amount"` // 订单实收金额:如果只有1个赠送商品,金额可以为0
|
||
TotalCount uint32 `json:"total_count" binding:"required"` // 订单商品数量
|
||
VmAmount uint32 `json:"vm_count"` // 使用会员积分
|
||
Cashiers []ErpOrderCashier `json:"cashiers" binding:"required"` // 收付款方式
|
||
ErpOrderCommodities []ErpOrderCommodity `json:"erp_order_commodities" binding:"required"` // 零售订单商品信息
|
||
Salesman []ErpOrderSales `json:"salesman" binding:"required"` // 销售员信息
|
||
}
|
||
|
||
// ErpOrderListReq 查询零售订单列表入参
|
||
type ErpOrderListReq struct {
|
||
ScanCode string `json:"scan_code"` // 扫码枪扫码数据:串码
|
||
BillSn string `json:"bill_sn"` // 单据编号
|
||
RetailType string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
CommodityName string `json:"commodity_name"` // 商品名称
|
||
Uid int `json:"uid"` // 用户ID
|
||
Tel string `json:"tel"` // 客户手机号
|
||
Salesman uint32 `json:"salesman"` // 销售人员ID
|
||
StoreId uint32 `json:"store_id"` // 门店ID
|
||
State string `json:"state"` // 订单状态
|
||
PayStatus uint32 `json:"pay_status"` // 支付状态 0-未创建 ;1-待支付; 2-已支付
|
||
MakeTimeStart string `json:"make_time_start"` // 制单开始时间
|
||
MakeTimeEnd string `json:"make_time_end"` // 制单结束时间
|
||
AuditTimeStart string `json:"audit_time_start"` // 审核开始时间
|
||
AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
}
|
||
|
||
// ErpOrderListResp 查询零售订单列表出参
|
||
type ErpOrderListResp struct {
|
||
List []ErpOrder `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示条数
|
||
ShowAll string `json:"show_all" binding:"required"` // 展示所有订单配置:ON-打开,OFF-关闭
|
||
ExportUrl string `json:"export_url"`
|
||
}
|
||
|
||
// ErpOrderDeleteReq 删除零售订单入参
|
||
type ErpOrderDeleteReq struct {
|
||
BillSn string `json:"bill_sn" binding:"required"` // 单据编号
|
||
}
|
||
|
||
// ErpOrderPayReq 收款入参
|
||
type ErpOrderPayReq struct {
|
||
BillSn string `json:"bill_sn" binding:"required"` // 单据编号
|
||
AuthCode string `json:"auth_code" binding:"required"` // 用户付款码
|
||
}
|
||
|
||
// ErpOrderPayResp 收款出参
|
||
type ErpOrderPayResp struct {
|
||
Status string `json:"status"` // 支付成功:pay_ok;支付失败:pay_failed ;等待支付:paying; 未知状态:pay_unknown; 未创建支付订单:no_pay_order
|
||
}
|
||
|
||
// ErpOrderAuditReq 审核零售订单入参
|
||
type ErpOrderAuditReq struct {
|
||
BillSn string `json:"bill_sn" binding:"required"` // 单据编号
|
||
State int `json:"state" binding:"required"` // 审核操作: 1-审核 2-取消审核
|
||
}
|
||
|
||
// ErpOrderAddInvoiceReq 开发票入参
|
||
type ErpOrderAddInvoiceReq struct {
|
||
BillSn string `json:"bill_sn" binding:"required"` // 单据编号
|
||
InvoiceCode string `json:"invoice_code" binding:"required"` // 发票代码
|
||
InvoiceNumber string `json:"invoice_number" binding:"required"` // 发票编码
|
||
}
|
||
|
||
// ErpOrderStoreManageDataReq 查询门店经营入参
|
||
type ErpOrderStoreManageDataReq struct {
|
||
StoreId uint32 `json:"store_id"` // 门店ID
|
||
StartTime string `json:"start_time"` // 开始时间
|
||
EndTime string `json:"end_time"` // 结束时间
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
IsExport uint32 `json:"is_export"` // 1-导出
|
||
SortType string `json:"sort_type"` // 排序类型:desc 降序、asc 升序
|
||
}
|
||
|
||
// ErpOrderStoreManageDataResp 查询门店经营出参
|
||
type ErpOrderStoreManageDataResp struct {
|
||
List []StoreManageData `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示条数
|
||
ExportUrl string `json:"export_url"`
|
||
}
|
||
|
||
// StoreManageData 门店经营数据
|
||
type StoreManageData struct {
|
||
Date string `json:"date"` // 时间,如:"2023-12-25"
|
||
TotalSalesAmount float64 `json:"total_sales_amount"` // 销售额
|
||
PromotionFee float64 `json:"promotion_fee"` // 推广费
|
||
SalesProfit float64 `json:"sales_profit"` // 销售毛利
|
||
StaffProfit float64 `json:"staff_profit"` // 员工毛利
|
||
Count int64 `json:"count"` // 销售数量
|
||
}
|
||
|
||
// ErpOrderRetailMarginReq 查询商品零售毛利汇总入参
|
||
type ErpOrderRetailMarginReq struct {
|
||
StoreId []uint32 `json:"store_id"` // 门店ID
|
||
RetailType []string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
ErpCommodityName []string `json:"erp_commodity_name"` // 商品名称
|
||
ErpCategoryId []uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
||
StartTime string `json:"start_time"` // 开始时间
|
||
EndTime string `json:"end_time"` // 结束时间
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
IsExport uint32 `json:"is_export"` // 1-导出
|
||
}
|
||
|
||
// ErpOrderRetailMarginResp 查询商品零售毛利汇总出参
|
||
type ErpOrderRetailMarginResp struct {
|
||
List []RetailMarginData `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示条数
|
||
TotalCount int32 `json:"total_count"` // 总销售数量
|
||
TotalSalesAmount float64 `json:"total_sales_amount"` // 总销售/退货金额
|
||
TotalSalesCost float64 `json:"total_sales_cost"` // 总销售成本:销售采购价之和
|
||
TotalEmployeeCost float64 `json:"total_employee_cost"` // 总员工成本:商品员工成本价之和
|
||
TotalSalesMargin float64 `json:"total_sales_margin"` // 总销售毛利:销售/退货金额-销售成本
|
||
TotalGrossMargins string `json:"total_gross_margins"` // 销售毛利率:销售毛利/销售/退货金额
|
||
ExportUrl string `json:"export_url"`
|
||
}
|
||
|
||
// RetailMarginData 商品零售毛利数据
|
||
type RetailMarginData struct {
|
||
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
|
||
StoreName string `json:"store_name"` // 门店名称
|
||
RetailType string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
||
ErpCategoryName string `json:"erp_category_name"` // 分类名称
|
||
Count int32 `json:"count"` // 销售数量
|
||
SalesAmount float64 `json:"sales_amount"` // 销售/退货金额
|
||
SalesCost float64 `json:"sales_cost"` // 销售成本:销售采购价之和
|
||
EmployeeCost float64 `json:"employee_cost"` // 员工成本:商品员工成本价之和
|
||
SalesMargin float64 `json:"sales_margin"` // 销售毛利:销售/退货金额-销售成本
|
||
GrossMargins string `json:"gross_margins"` // 销售毛利率:销售毛利/销售/退货金额
|
||
}
|
||
|
||
// ErpOrderRetailDetailReq 零售明细汇总入参
|
||
type ErpOrderRetailDetailReq struct {
|
||
BillSn string `json:"bill_sn"` // 单据编号
|
||
RetailType string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
||
Uid int `json:"uid"` // 用户ID
|
||
Tel string `json:"tel"` // 客户手机号
|
||
StoreId uint32 `json:"store_id"` // 门店ID
|
||
ErpCategoryId uint32 `json:"erp_category_id"` // 分类id
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
Salesman uint32 `json:"salesman"` // 销售人员ID
|
||
IMEI string `json:"imei"` // 串码
|
||
StartTime string `json:"start_time"` // 开始时间
|
||
EndTime string `json:"end_time"` // 结束时间
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
IsExport uint32 `json:"is_export"` // 1-导出
|
||
}
|
||
|
||
// ErpOrderRetailDetailResp 零售明细汇总出参
|
||
type ErpOrderRetailDetailResp struct {
|
||
Total int `json:"total"` // 总条数(总订单数)
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示条数
|
||
ExportUrl string `json:"export_url"` // 导出excel地址
|
||
List []ErpOrder `json:"list"` // 零售明细
|
||
SumData RetailDetailTotalData `json:"sumData"` // 汇总数据
|
||
}
|
||
|
||
// RetailDetailTotalData 零售明细相关金额汇总
|
||
type RetailDetailTotalData struct {
|
||
Count int32 `json:"count"` // 销售数量
|
||
RetailPrice float64 `json:"retail_price"` // 指导零售价
|
||
SalePrice float64 `json:"sale_price"` // 零售价
|
||
SaleDiscount float64 `json:"sale_discount"` // 零售优惠
|
||
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
||
VmDiscount float64 `json:"vm_discount"` // 会员积分抵扣
|
||
Amount float64 `json:"amount"` // 实际零售价
|
||
WholesalePrice float64 `json:"wholesale_price"` // 采购单价
|
||
StaffPrice float64 `json:"staff_price"` // 员工成本价
|
||
SalesProfit float64 `json:"sales_profit"` // 销售毛利
|
||
StaffProfit float64 `json:"staff_profit"` // 员工毛利
|
||
TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价
|
||
TotalDiscount float64 `json:"total_discount"` // 订单总优惠:订单所有商品零售优惠+会员优惠+会员积分抵扣之和
|
||
TotalAmount float64 `json:"total_amount"` // 订单实收金额
|
||
TotalCashierData
|
||
TotalSalesProfit float64 `json:"total_sales_profit"` // 订单总销售毛利
|
||
TotalStaffProfit float64 `json:"total_staff_profit"` // 订单总员工毛利
|
||
TotalPerData
|
||
StorePer float64 `json:"store_per"` // 门店提成
|
||
}
|
||
|
||
// TotalPerData 员工提成
|
||
type TotalPerData struct {
|
||
TotalSalesProfitPer float64 `json:"total_sales_profit_per"` // 销售毛利提成
|
||
TotalStaffProfitPer float64 `json:"total_staff_profit_per"` // 员工毛利提成
|
||
SalesmanPer float64 `json:"salesman_per"` // 销售员提成
|
||
}
|
||
|
||
// TotalCashierData 支付方式金额汇总
|
||
type TotalCashierData struct {
|
||
ScanAmount float64 `json:"scan_amount"` // 扫码付
|
||
CashAmount float64 `json:"cash_amount"` // 现金收款
|
||
PosAmount float64 `json:"pos_amount"` // pos机收款
|
||
StoreVmAmount float64 `json:"store_vm_amount"` // 商场积分抵扣
|
||
OtherAmount float64 `json:"other_amount"` // 其他付款方式
|
||
}
|
||
|
||
// ErpOrderReceiptDataResp 查询小票数据出参
|
||
type ErpOrderReceiptDataResp struct {
|
||
StoreName string `json:"storeName"` // 门店名称
|
||
Barcode string `json:"barcode"` // 单据编号:条码
|
||
OddNum string `json:"oddNum" ` // 单据编号
|
||
Time time.Time `json:"time"` // 审核时间
|
||
CollectS string `json:"collectS"` // 收银人员:制单人
|
||
ChandiseObj map[string]TableData `json:"chandiseObj"` // 商品信息
|
||
TotalRetailP float64 `json:"totalRetailP"` // 零售价合计
|
||
TotalNum uint32 `json:"totalNum"` // 数量合计
|
||
TotalAmount float64 `json:"totalAmount"` // 零售优惠总金额
|
||
MembersAmount float64 `json:"membersAmount"` // 会员优惠总金额
|
||
IntegrationAmount float64 `json:"integrationAmount"` // 积分抵扣总金额
|
||
ToDealWith float64 `json:"toDealWith"` // 零售价合计 - 零售优惠总额 - 会员优惠总和 - 积分抵扣总额
|
||
ModeOfPayment map[string]ErpOrderCashier `json:"modeOfPayment"` // 支付信息
|
||
ActualPayment float64 `json:"actualPayment"` // 所有支付方式金额总和
|
||
Tel string `json:"tel"` // 买家电话
|
||
StoreTel string `json:"storeTel"` // 卖家电话
|
||
StoreAddress string `json:"storeAddress"` // 店铺地址
|
||
Uid int `json:"uid"` // 用户id
|
||
}
|
||
|
||
type TableData struct {
|
||
Name string `json:"name"`
|
||
SL uint32 `json:"SL"` // 销售数量
|
||
DJ float64 `json:"DJ"` // 商品指导零售价
|
||
JE float64 `json:"JE"` // 商品指导零售价乘以销售数量
|
||
}
|
||
|
||
// Contains 判断id是否在list中
|
||
func Contains(list []uint32, id uint32) bool {
|
||
for _, item := range list {
|
||
if item == id {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// CompareLists 返回共有的数据
|
||
func CompareLists(list1 []uint32, list2 []uint32) []uint32 {
|
||
if len(list2) == 0 { // 如果list2为空,则直接使用list1的数据
|
||
return list1
|
||
}
|
||
// 创建一个 map 用于存储 list1 中的数据
|
||
list1Map := make(map[uint32]bool)
|
||
for _, id := range list1 {
|
||
list1Map[id] = true
|
||
}
|
||
|
||
var commonIds []uint32
|
||
// 遍历 list2,如果在 list1Map 中找到相同的元素,则加入到 commonIds 中
|
||
for _, id := range list2 {
|
||
if list1Map[id] {
|
||
commonIds = append(commonIds, id)
|
||
}
|
||
}
|
||
|
||
return commonIds
|
||
}
|
||
|
||
// GetValidStoreIDs 返回未过期门店的ID列表
|
||
func GetValidStoreIDs(storeData string) []uint32 {
|
||
// 解析门店数据
|
||
var stores []StoreInfo
|
||
if err := json.Unmarshal([]byte(storeData), &stores); err != nil {
|
||
return nil
|
||
}
|
||
|
||
var validStoreIDs []uint32
|
||
// 遍历每个门店,检查是否过期
|
||
for _, store := range stores {
|
||
expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
expireTime = expireTime.Add(24*time.Hour - time.Second)
|
||
// 如果过期时间在当前时间之后,则未过期,将门店ID添加到列表中
|
||
if expireTime.After(time.Now()) {
|
||
validStoreIDs = append(validStoreIDs, uint32(store.StoreID))
|
||
}
|
||
}
|
||
|
||
return validStoreIDs
|
||
}
|
||
|
||
// List 查询零售订单列表
|
||
func (m *ErpOrderListReq) List(c *gin.Context) (*ErpOrderListResp, error) {
|
||
showConfig, err := GetErpOrderShowConfig()
|
||
if err != nil {
|
||
logger.Errorf("List err:", err)
|
||
showConfig.ShowAll = "ON"
|
||
}
|
||
resp := &ErpOrderListResp{
|
||
PageIndex: m.PageIndex,
|
||
PageSize: m.PageSize,
|
||
}
|
||
page := m.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if m.PageSize == 0 {
|
||
m.PageSize = 10
|
||
}
|
||
|
||
if m.ScanCode != "" { // 扫描了串码,需要查询已售的商品数据
|
||
return QueryListByScanCode(m.StoreId, m.ScanCode, showConfig.ShowAll, c)
|
||
}
|
||
|
||
if m.CommodityName != "" { // 输入了商品名称进行查询
|
||
return QueryListByCommodityName(m, showConfig.ShowAll, c)
|
||
}
|
||
|
||
qs := orm.Eloquent.Table("erp_order")
|
||
if showConfig.ShowAll == "OFF" { // 关闭后未开小票的零售销售订单隐藏
|
||
qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
}
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
if len(storeList) == 1 {
|
||
qs = qs.Where("store_id = ?", storeList[0])
|
||
} else {
|
||
qs = qs.Where("store_id IN (?)", storeList)
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
if m.BillSn != "" {
|
||
qs = qs.Where("bill_sn=?", m.BillSn)
|
||
} else {
|
||
if m.RetailType != "" {
|
||
qs = qs.Where("retail_type=?", m.RetailType)
|
||
}
|
||
if m.Uid != 0 {
|
||
qs = qs.Where("uid=?", m.Uid)
|
||
}
|
||
if m.Tel != "" {
|
||
qs = qs.Where("tel=?", m.Tel)
|
||
}
|
||
if m.StoreId != 0 {
|
||
qs = qs.Where("store_id=?", m.StoreId)
|
||
}
|
||
if m.Salesman != 0 {
|
||
qs = qs.Where("JSON_CONTAINS(salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, m.Salesman))
|
||
}
|
||
if m.PayStatus != 0 {
|
||
qs = qs.Where("pay_status=?", m.PayStatus)
|
||
}
|
||
if m.State != "" {
|
||
qs = qs.Where("state=?", m.State)
|
||
}
|
||
if m.MakeTimeStart != "" {
|
||
parse, err := time.Parse(QueryTimeFormat, m.MakeTimeStart)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
qs = qs.Where("maker_time > ?", parse)
|
||
}
|
||
if m.MakeTimeEnd != "" {
|
||
parse, err := time.Parse(QueryTimeFormat, m.MakeTimeEnd)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
//parse = parse.AddDate(0, 0, 1)
|
||
qs = qs.Where("maker_time < ?", parse)
|
||
}
|
||
if m.AuditTimeStart != "" {
|
||
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
qs = qs.Where("audit_time > ?", parse)
|
||
}
|
||
if m.AuditTimeEnd != "" {
|
||
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
//parse = parse.AddDate(0, 0, 1)
|
||
qs = qs.Where("audit_time < ?", parse)
|
||
}
|
||
}
|
||
|
||
var count int64
|
||
err = qs.Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("count err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
var orders []ErpOrder
|
||
err = qs.Debug().Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
// 添加付款、销售员、商品信息
|
||
erpOrderListSetCommodity(orders)
|
||
erpOrderListSetCashier(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
|
||
resp.List = orders
|
||
|
||
//跟之前保持一致
|
||
resp.Total = int(count)
|
||
resp.PageIndex = page + 1
|
||
resp.PageSize = m.PageSize
|
||
resp.ShowAll = showConfig.ShowAll
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// QueryListByScanCode 通过扫描串码查询列表
|
||
func QueryListByScanCode(storeId uint32, scanCode, showConfig string, c *gin.Context) (*ErpOrderListResp, error) {
|
||
resp := &ErpOrderListResp{}
|
||
|
||
// 查询扫码串码的零售销售订单的商品信息
|
||
var commodity []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").Where("imei = ? and rejected_count = 0", scanCode).Find(&commodity).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("get erp_order_commodity err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
if len(commodity) == 0 {
|
||
return &ErpOrderListResp{}, nil
|
||
}
|
||
|
||
// 判断该串码商品是否已经退货退回库存列表
|
||
var stockCount int64
|
||
err = orm.Eloquent.Table("erp_stock_commodity").
|
||
Where("state = 1 AND imei = ?", scanCode).Count(&stockCount).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if stockCount > 0 {
|
||
return nil, errors.New("库存已有该串码商品")
|
||
}
|
||
|
||
var orders []ErpOrder
|
||
for _, item := range commodity {
|
||
if showConfig == "OFF" {
|
||
err = orm.Eloquent.Table("erp_order").
|
||
Where("id = ? and pay_status = ? and is_print != ?", item.ErpOrderId, HavePaid, NoPrint).
|
||
Order("audit_time DESC").Find(&orders).Error
|
||
} else {
|
||
err = orm.Eloquent.Table("erp_order").
|
||
Where("id = ? and pay_status = ?", item.ErpOrderId, HavePaid).
|
||
Order("audit_time DESC").Find(&orders).Error
|
||
}
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("get erp_order err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
if len(orders) == 0 {
|
||
continue
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
if len(orders) != 0 {
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("查询失败:" + err.Error())
|
||
}
|
||
|
||
if !CheckUserStore(orders[0].StoreId, sysUser) {
|
||
return &ErpOrderListResp{}, errors.New("您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
if orders[0].StoreId != storeId && storeId != 0 {
|
||
return &ErpOrderListResp{}, errors.New("非当前门店所售商品,需前往对应门店退货")
|
||
}
|
||
}
|
||
|
||
// 添加付款、销售员、商品信息
|
||
erpOrderListSetCommodity(orders)
|
||
erpOrderListSetCashier(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
|
||
orders[0].Commodities = commodity
|
||
if len(orders) != 0 {
|
||
// 查询该串码商品是否已经退过货
|
||
resp.List = append(resp.List, orders[0])
|
||
} else {
|
||
resp.List = orders
|
||
}
|
||
|
||
//跟之前保持一致
|
||
resp.Total = len(resp.List)
|
||
resp.PageIndex = 1
|
||
resp.PageSize = 10
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// QueryListByCommodityName 通过商品名称查询列表
|
||
func QueryListByCommodityName(req *ErpOrderListReq, showConfig string, c *gin.Context) (*ErpOrderListResp, error) {
|
||
resp := &ErpOrderListResp{
|
||
PageIndex: req.PageIndex,
|
||
PageSize: req.PageSize,
|
||
}
|
||
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
qs := orm.Eloquent.Debug().Table("erp_order_commodity").
|
||
Select("erp_order_commodity.*, erp_order.*").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id")
|
||
if req.CommodityName != "" { // 商品名称
|
||
qs = qs.Where("erp_order_commodity.erp_commodity_name like ?", "%"+req.CommodityName+"%")
|
||
}
|
||
|
||
if showConfig == "OFF" {
|
||
qs = qs.Where("invoice_code != ?", 0)
|
||
}
|
||
|
||
if req.Tel != "" { // 用户手机号
|
||
qs = qs.Where("erp_order.tel=?", req.Tel)
|
||
}
|
||
if req.StoreId != 0 { // 门店ID
|
||
qs = qs.Where("erp_order.store_id=?", req.StoreId)
|
||
}
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
if len(storeList) == 1 {
|
||
qs = qs.Where("erp_order.store_id = ?", storeList[0])
|
||
} else {
|
||
qs = qs.Where("erp_order.store_id IN (?)", storeList)
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
qs.Where("erp_order.pay_status = ?", HavePaid)
|
||
es := qs
|
||
|
||
var result []RetailDetailByJoin
|
||
|
||
err := qs.Order("erp_order.audit_time DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&result).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var count int64
|
||
err = es.Count(&count).Error
|
||
if err != nil {
|
||
logger.Errorf("QueryRetailMargin count err:", err.Error())
|
||
return nil, err
|
||
}
|
||
|
||
orders := packData(result)
|
||
erpOrderListSetCashier(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
|
||
resp.List = orders
|
||
|
||
//跟之前保持一致
|
||
resp.Total = int(count)
|
||
resp.PageIndex = page + 1
|
||
resp.PageSize = req.PageSize
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 数组转字符串
|
||
func intArrayToString(arr []uint32) string {
|
||
var strArr []string
|
||
for _, num := range arr {
|
||
strArr = append(strArr, fmt.Sprintf("%d", num))
|
||
}
|
||
return strings.Join(strArr, ",")
|
||
}
|
||
|
||
// 字符串转数组
|
||
func stringToIntArray(str string) ([]uint32, error) {
|
||
var arr []uint32
|
||
strArr := strings.Split(str, ",")
|
||
for _, s := range strArr {
|
||
num, err := strconv.Atoi(s)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
arr = append(arr, uint32(num))
|
||
}
|
||
return arr, nil
|
||
}
|
||
|
||
// 更新零售订单商品表的库存商品表主键id字段
|
||
func updateErpStockCommodityID(gdb *gorm.DB, id uint32, nIdList []uint32) error {
|
||
strId := intArrayToString(nIdList)
|
||
|
||
// 查找在库的非串码商品
|
||
var stockCommodity ErpStockCommodity
|
||
err := orm.Eloquent.Table("erp_stock_commodity").Where("id = ?", strId).First(&stockCommodity).Error
|
||
if err != nil {
|
||
logger.Error("get erp_stock_commodity err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_order_commodity").Where("id = ?", id).
|
||
Updates(map[string]interface{}{
|
||
"erp_stock_commodity_id": strId,
|
||
"retail_price": stockCommodity.RetailPrice,
|
||
"wholesale_price": stockCommodity.WholesalePrice,
|
||
"staff_cost_price": stockCommodity.StaffCostPrice,
|
||
}).Error
|
||
//Update("erp_stock_commodity_id", strId).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 找一个可用的库存商品表主键ID
|
||
func findRightErpStockCommodityId(idList map[uint32][]uint32, commodityId uint32, stockCommodity []ErpStockCommodity) (uint32, error) {
|
||
// 获取给定商品ID对应的ID列表
|
||
existingIds, ok := idList[commodityId]
|
||
if !ok || len(existingIds) == 0 {
|
||
// 如果对应的ID列表不存在或为空,直接返回第一个库存商品的ID
|
||
if len(stockCommodity) > 0 {
|
||
return stockCommodity[0].ID, nil
|
||
}
|
||
return 0, fmt.Errorf("empty stock commodity list")
|
||
}
|
||
|
||
// 创建一个 map 用于快速查找已有的 ID
|
||
existingIdMap := make(map[uint32]bool)
|
||
for _, id := range existingIds {
|
||
existingIdMap[id] = true
|
||
}
|
||
|
||
// 遍历库存商品,找到第一个不在已有ID列表中的ID并返回
|
||
for _, item := range stockCommodity {
|
||
if _, found := existingIdMap[item.ID]; !found {
|
||
return item.ID, nil
|
||
}
|
||
}
|
||
|
||
// 如果所有库存商品的ID都在已有的ID列表中,则返回错误
|
||
return 0, fmt.Errorf("no available ID found for commodity ID: %d", commodityId)
|
||
}
|
||
|
||
// UpdateStock 扣减or添加库存
|
||
// 零售订单:
|
||
// 有串码,通过串码查找库存详情表,然后更改对应库存的状态为"已售";
|
||
// 非串码,通过门店id、商品id、商品名称查找库存详情表,找到库存时间最长的,然后更改其状态为"已售"。
|
||
// 同时扣减库存表对应的数量,-1
|
||
// 零售退货:
|
||
// 有串码,通过串码查找库存详情表,然后更改对应库存的状态为"在库";
|
||
// 非串码,通过门店id、商品id、商品名称查找库存详情表,找到状态为"已售"且时间最近的单,将其状态改为"在库"
|
||
// 同时扣减库存表对应的数量,+1
|
||
func UpdateStock(gdb *gorm.DB, erpOrder ErpOrder, state, auditState int) error {
|
||
var commodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").Where("erp_order_id = ?", erpOrder.ID).
|
||
Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
usedStockCommodityIdList := make(map[uint32][]uint32) // 记录非串码商品已使用的商品库存表主键id
|
||
|
||
if erpOrder.RetailType == RetailTypeSale { // 零售订单
|
||
for i, _ := range commodities {
|
||
if commodities[i].IMEIType == 2 || commodities[i].IMEIType == 3 { // 串码商品
|
||
if commodities[i].IMEI == "" {
|
||
return errors.New("串码为空")
|
||
}
|
||
|
||
err = gdb.Table("erp_stock_commodity").Where("imei = ?", commodities[i].IMEI).
|
||
Updates(map[string]interface{}{"state": state}).Error // 状态更新为已销售;反审核则更新为在库
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if state == SoldOut { // 已售的订单才更新库存数量
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else { // 反审核时则库存数量+1
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count + ?", 1)}).Error // 库存数量+1
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
} else { // 非串码商品
|
||
if state == InStock { // 零售订单反审核
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", commodities[i].ErpStockCommodityID).
|
||
Updates(map[string]interface{}{"state": state}).Error // 状态更新为在库
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count + ?", 1)}).Error // 库存数量+1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_order_commodity").Where("id = ?", commodities[i].ID).
|
||
Updates(map[string]interface{}{
|
||
"erp_stock_commodity_id": "",
|
||
}).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else { // 正常销售
|
||
if commodities[i].ErpStockCommodityID != "" { // 零售退货单反审核,默认当作销售单
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", commodities[i].ErpStockCommodityID).
|
||
Updates(map[string]interface{}{"state": SoldOut}).Error // 状态更新为在库
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else { // 正常销售
|
||
var stockCommodity []ErpStockCommodity
|
||
// 添加的一条零售商品包含的非串码商品可能不止1个
|
||
var stockCommodityIdList []uint32
|
||
// 通过门店id,商品id,查找状态为1-在库的非串码商品
|
||
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? "+
|
||
"and state = ? and imei_type = ?", commodities[i].ErpCommodityId, erpOrder.StoreId, InStock, 1).
|
||
Order("first_stock_time ASC").Find(&stockCommodity).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
if stockCommodity == nil || len(stockCommodity) == 0 {
|
||
return errors.New("find commodity no stock ")
|
||
}
|
||
|
||
// 找一个可用的库存商品表主键ID,使用零售商品表的主键ID作为key
|
||
rightId, err := findRightErpStockCommodityId(usedStockCommodityIdList,
|
||
commodities[i].ErpCommodityId, stockCommodity)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 优先出库库存时间最长的数据
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", rightId).
|
||
Updates(map[string]interface{}{"state": state}).Error // 状态更新为销售锁定中;反审核则更新为在库
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if state == SoldOut { // 已售的订单才更新库存数量
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
stockCommodityIdList = append(stockCommodityIdList, rightId)
|
||
usedStockCommodityIdList[commodities[i].ErpCommodityId] = append(usedStockCommodityIdList[commodities[i].ErpCommodityId], rightId)
|
||
|
||
err = updateErpStockCommodityID(gdb, commodities[i].ID, stockCommodityIdList)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else if erpOrder.RetailType == RetailTypeRejected { // 零售退货订单
|
||
for i, _ := range commodities {
|
||
if commodities[i].IMEIType == 2 { // 串码商品
|
||
if commodities[i].IMEI == "" {
|
||
return errors.New("串码为空")
|
||
}
|
||
|
||
err = gdb.Table("erp_stock_commodity").Where("imei = ?", commodities[i].IMEI).
|
||
Updates(map[string]interface{}{"state": InStock}).Error // 状态更新为在库
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count + ?", 1)}).Error // 库存数量+1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else { // 非串码商品
|
||
var stockCommodity []ErpStockCommodity
|
||
var stockCommodityIdList []uint32
|
||
|
||
if commodities[i].ErpStockCommodityID != "" {
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", commodities[i].ErpStockCommodityID).
|
||
Updates(map[string]interface{}{"state": InStock}).Error // 状态更新为在库
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count + ?", 1)}).Error // 库存数量+1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else {
|
||
// 添加的一条零售商品包含的非串码商品可能不止1个
|
||
for j := 0; j < int(commodities[i].Count); j++ {
|
||
// 通过门店id,商品id,查找状态为2-已售的非串码商品
|
||
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? "+
|
||
"and state = ? and imei_type = ?", commodities[i].ErpCommodityId, erpOrder.StoreId, SoldOut, NoIMEICommodity).
|
||
Order("first_stock_time DESC").Find(&stockCommodity).Error
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
if stockCommodity == nil {
|
||
return errors.New("RetailTypeRejected find no stock commodity")
|
||
}
|
||
|
||
// 找一个可用的库存商品表主键ID
|
||
rightId, err := findRightErpStockCommodityId(usedStockCommodityIdList,
|
||
commodities[i].ErpCommodityId, stockCommodity)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", rightId).
|
||
Updates(map[string]interface{}{"state": InStock}).Error // 状态更新为在库
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
erpOrder.StoreId, commodities[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count + ?", 1)}).Error // 库存数量+1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
stockCommodityIdList = append(stockCommodityIdList, rightId)
|
||
usedStockCommodityIdList[commodities[i].ID] = append(usedStockCommodityIdList[commodities[i].ID], rightId)
|
||
}
|
||
err = updateErpStockCommodityID(gdb, commodities[i].ID, stockCommodityIdList)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
return errors.New("订单类型错误")
|
||
}
|
||
|
||
// 判断用户是不是会员,只有会员才会积分,否则不积分
|
||
userInfo, err := GetUserInfoByUid(uint32(erpOrder.Uid))
|
||
if err != nil {
|
||
logger.Error("UpdateStock GetUserInfoByUid err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if IsInMemberLevels(userInfo.MemberLevel) {
|
||
// 更新用户积分
|
||
var vmCount int
|
||
var describe, event string
|
||
if erpOrder.RetailType == RetailTypeSale && state == SoldOut { // 零售订单,而且订单已支付,更新用户积分
|
||
if auditState == 2 {
|
||
describe = "零售退货反审核获得积分"
|
||
} else {
|
||
describe = "零售销售获得积分"
|
||
}
|
||
|
||
event = VmEventErpOrderSale
|
||
vmCount = tools.RoundFloat64(erpOrder.TotalAmount)
|
||
} else if erpOrder.RetailType == RetailTypeRejected { // 退货订单,扣减用户积分(需校验购物时已积分,有则扣除)
|
||
var count int64
|
||
err = orm.Eloquent.Table("user_vm_record").Where("erp_order_id = ?", erpOrder.SaleOrderId).
|
||
Count(&count).Error
|
||
if err != nil {
|
||
logger.Errorf("query user_vm_record error, erp_order_id is:", erpOrder.SaleOrderId)
|
||
}
|
||
|
||
// 积过分才扣除
|
||
if count > 0 {
|
||
describe = "零售退货扣除积分"
|
||
event = VmEventErpOrderReject
|
||
vmCount = 0 - tools.RoundFloat64(erpOrder.TotalAmount)
|
||
} else {
|
||
return nil
|
||
}
|
||
} else {
|
||
return nil
|
||
}
|
||
|
||
err = UserVmUpdate(gdb, erpOrder.ID, uint32(erpOrder.Uid), vmCount, event, describe)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// CheckIsOnlinePay 检查是否包含线上支付
|
||
func CheckIsOnlinePay(jCashier []ErpOrderCashier) bool {
|
||
for _, cashier := range jCashier {
|
||
if cashier.CashierId == OnlinePay || strings.Contains(cashier.Name, "微信") || strings.Contains(cashier.Name, "支付宝") {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// NewErpBillSn 生成零售订单号
|
||
func NewErpBillSn() string {
|
||
nowTime := time.Now()
|
||
rand.Seed(nowTime.UnixNano())
|
||
max := 1
|
||
for {
|
||
if max > 5 {
|
||
logger.Error("create sn err")
|
||
return ""
|
||
}
|
||
random := rand.Int31n(9999) + 1000
|
||
sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
|
||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_order WHERE bill_sn='%s'", sn))
|
||
if err != nil {
|
||
logger.Error("exist sn err")
|
||
}
|
||
if !exist {
|
||
return sn
|
||
}
|
||
|
||
max++
|
||
}
|
||
}
|
||
|
||
// ErpOrderRetailDetailSetCommodity 添加零售明细中订单的商品信息
|
||
func ErpOrderRetailDetailSetCommodity(list []ErpOrder) {
|
||
for i, _ := range list {
|
||
list[i].SetRetailDetailCommodity()
|
||
list[i].StorePer = tools.RoundToTwoDecimalPlaces(list[i].StorePer)
|
||
if list[i].RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
|
||
list[i].TotalRetailPrice = -math.Abs(list[i].TotalRetailPrice)
|
||
list[i].TotalAmount = -math.Abs(list[i].TotalAmount)
|
||
list[i].TotalCount = -int32(math.Abs(float64(list[i].TotalCount)))
|
||
//list[i].TotalSalesProfit = -math.Abs(list[i].TotalSalesProfit)
|
||
//list[i].TotalStaffProfit = -math.Abs(list[i].TotalStaffProfit)
|
||
list[i].TotalSalesProfit = -list[i].TotalSalesProfit
|
||
list[i].TotalStaffProfit = -list[i].TotalStaffProfit
|
||
list[i].TotalDiscount = -math.Abs(list[i].TotalDiscount)
|
||
list[i].VmCount = -uint32(math.Abs(float64(list[i].VmCount)))
|
||
if list[i].TotalStaffProfit > 0 {
|
||
list[i].StorePer = math.Abs(list[i].StorePer)
|
||
} else {
|
||
list[i].StorePer = -math.Abs(list[i].StorePer)
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetRetailDetailCommodity() {
|
||
var orderCommodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").Where("erp_order_id = ?", m.ID).Find(&orderCommodities).Error
|
||
if err != nil {
|
||
logger.Error("SetCommodity query erp_order_commodity err:", logger.Field("err", err))
|
||
}
|
||
|
||
var respOrderCommodities []ErpOrderCommodity
|
||
for _, item := range orderCommodities {
|
||
if m.RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
|
||
item.Count = -item.Count
|
||
item.RetailPrice = -item.RetailPrice
|
||
item.SalePrice = -item.SalePrice
|
||
item.Amount = -item.Amount
|
||
item.SaleDiscount = -item.SaleDiscount
|
||
item.MemberDiscount = -item.MemberDiscount
|
||
item.VmDiscount = -item.VmDiscount
|
||
item.ReceivedAmount = -item.ReceivedAmount
|
||
item.RejectedAmount = -item.RejectedAmount
|
||
item.SalesProfit = -item.SalesProfit
|
||
item.StaffProfit = -item.StaffProfit
|
||
item.StaffCostPrice = -item.StaffCostPrice
|
||
item.WholesalePrice = -item.WholesalePrice
|
||
}
|
||
item.StaffPrice = item.StaffCostPrice + item.WholesalePrice
|
||
|
||
if item.IMEIType == 2 || item.IMEIType == 3 || item.IMEI != "" { // 串码
|
||
respOrderCommodities = append(respOrderCommodities, item)
|
||
} else { // 非串码
|
||
idList, err := stringToIntArray(item.ErpStockCommodityID)
|
||
if err != nil {
|
||
respOrderCommodities = append(respOrderCommodities, item)
|
||
continue
|
||
}
|
||
|
||
for _, stockCommodityId := range idList {
|
||
var orderCommodity ErpOrderCommodity
|
||
orderCommodity = item
|
||
if m.RetailType == RetailTypeRejected { // 退货订单,数量需要转换为负值
|
||
orderCommodity.Count = -1
|
||
} else {
|
||
orderCommodity.Count = 1
|
||
}
|
||
|
||
nCount := math.Abs(float64(item.Count))
|
||
orderCommodity.SaleDiscount = item.SaleDiscount / nCount
|
||
orderCommodity.VmDiscount = item.VmDiscount / nCount
|
||
orderCommodity.ReceivedAmount = item.ReceivedAmount / nCount
|
||
orderCommodity.RejectedAmount = item.RejectedAmount / nCount
|
||
orderCommodity.SalesProfit = item.SalesProfit / nCount
|
||
orderCommodity.StaffProfit = item.StaffProfit / nCount
|
||
|
||
// 查询库存商品信息
|
||
var stockCommodity ErpStockCommodity
|
||
err = orm.Eloquent.Table("erp_stock_commodity").
|
||
Where("id = ?", stockCommodityId).Find(&stockCommodity).Error
|
||
if err != nil {
|
||
respOrderCommodities = append(respOrderCommodities, item)
|
||
continue
|
||
}
|
||
|
||
orderCommodity.ErpSupplierId = stockCommodity.ErpSupplierId
|
||
orderCommodity.ErpSupplierName = stockCommodity.ErpSupplierName
|
||
orderCommodity.WholesalePrice = stockCommodity.WholesalePrice
|
||
orderCommodity.StaffCostPrice = stockCommodity.StaffCostPrice
|
||
orderCommodity.StaffPrice = orderCommodity.WholesalePrice + orderCommodity.StaffCostPrice
|
||
if m.RetailType == RetailTypeRejected { // 退货订单,数量需要转换为负值
|
||
orderCommodity.WholesalePrice = -orderCommodity.WholesalePrice
|
||
orderCommodity.StaffCostPrice = -orderCommodity.StaffCostPrice
|
||
orderCommodity.StaffPrice = -orderCommodity.StaffPrice
|
||
}
|
||
respOrderCommodities = append(respOrderCommodities, orderCommodity)
|
||
}
|
||
}
|
||
}
|
||
|
||
m.Commodities = respOrderCommodities
|
||
}
|
||
|
||
// 添加订单的商品信息
|
||
func erpOrderListSetCommodity(list []ErpOrder) {
|
||
for i, _ := range list {
|
||
list[i].SetCommodity()
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetCommodity() {
|
||
var orderCommodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").Where("erp_order_id = ?", m.ID).Find(&orderCommodities).Error
|
||
if err != nil {
|
||
logger.Error("SetCommodity query erp_order_commodity err:", logger.Field("err", err))
|
||
}
|
||
|
||
m.Commodities = mergeOrderCommodities(orderCommodities)
|
||
}
|
||
|
||
// 合并重复的商品数据
|
||
func mergeOrderCommodities(orderCommodities []ErpOrderCommodity) []ErpOrderCommodity {
|
||
// 创建一个map来存储每个(ErpOrderId, ErpCommodityId)组合的合并结果
|
||
type key struct {
|
||
ErpOrderId uint32
|
||
ErpCommodityId uint32
|
||
IMEI string
|
||
}
|
||
commodityMap := make(map[key]*ErpOrderCommodity)
|
||
|
||
// 遍历orderCommodities,将相同ErpCommodityId的数量累加
|
||
for _, commodity := range orderCommodities {
|
||
comboKey := key{ErpOrderId: commodity.ErpOrderId, ErpCommodityId: commodity.ErpCommodityId, IMEI: commodity.IMEI}
|
||
if existingCommodity, exists := commodityMap[comboKey]; exists {
|
||
existingCommodity.Count += commodity.Count
|
||
existingCommodity.SalesProfit += commodity.SalesProfit
|
||
existingCommodity.StaffProfit += commodity.StaffProfit
|
||
existingCommodity.SaleDiscount += commodity.SaleDiscount
|
||
existingCommodity.MemberDiscount += commodity.MemberDiscount
|
||
existingCommodity.ReceivedAmount += commodity.ReceivedAmount
|
||
existingCommodity.ErpStockCommodityID = strings.Join([]string{existingCommodity.ErpStockCommodityID, commodity.ErpStockCommodityID}, ",")
|
||
} else {
|
||
// 使用commodity的副本避免对原始数据的修改
|
||
commodityCopy := commodity
|
||
commodityMap[comboKey] = &commodityCopy
|
||
}
|
||
}
|
||
|
||
// 将map转换回orderCommodities列表
|
||
var mergedCommodities []ErpOrderCommodity
|
||
for _, commodity := range commodityMap {
|
||
mergedCommodities = append(mergedCommodities, *commodity)
|
||
}
|
||
|
||
return mergedCommodities
|
||
}
|
||
|
||
// 添加订单的销售员信息
|
||
func erpOrderListSetSalesmanByRetailDetail(userId uint32, list []ErpOrder) {
|
||
for i, _ := range list {
|
||
_ = list[i].SetOrderSalesmanRetailDetail(userId)
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetOrderSalesmanRetailDetail(userId uint32) error {
|
||
var salesProfit, staffProfit, totalStaffProfit float64
|
||
//获取销售毛利、员工毛利数据
|
||
for _, item := range m.Commodities {
|
||
erpCommodity, err := GetCommodity(item.ErpCommodityId)
|
||
if err != nil {
|
||
logger.Error("GetCommodity err:", logger.Field("err", err))
|
||
}
|
||
salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01
|
||
staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01
|
||
totalStaffProfit += item.StaffProfit
|
||
}
|
||
// 四舍五入并保留两位小数
|
||
salesProfit = math.Round(salesProfit*100) / 100
|
||
staffProfit = math.Round(staffProfit*100) / 100
|
||
totalStaffProfit = math.Round(totalStaffProfit*100) / 100
|
||
|
||
var salesmanInfo []ErpOrderSales
|
||
err := orm.Eloquent.Model(&ErpOrderSales{}).Where("erp_order_id = ?", m.ID).Find(&salesmanInfo).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var salesmanList []ErpOrderSales
|
||
for _, item := range salesmanInfo {
|
||
item.SalesProfitPer = salesProfit / float64(len(salesmanInfo))
|
||
item.StaffProfitPer = staffProfit / float64(len(salesmanInfo))
|
||
|
||
// 获取员工毛利
|
||
userInfo, err := GetSysUserInfoById(item.Uid)
|
||
if err != nil {
|
||
logger.Error("GetSysUserInfoByUid err:", logger.Field("err", err))
|
||
}
|
||
item.Name = userInfo.NickName
|
||
item.SalesmanPer = totalStaffProfit * userInfo.SalesCommRate * 0.01 / float64(len(salesmanInfo))
|
||
|
||
//if m.RetailType == RetailTypeRejected {
|
||
// item.SalesProfitPer = -item.SalesProfitPer
|
||
// item.StaffProfitPer = -item.StaffProfitPer
|
||
// item.SalesmanPer = -item.SalesmanPer
|
||
//}
|
||
|
||
if userId != item.Uid {
|
||
item.SalesProfitPer = 0
|
||
item.StaffProfitPer = 0
|
||
item.SalesmanPer = 0
|
||
}
|
||
|
||
salesmanList = append(salesmanList, item)
|
||
}
|
||
|
||
if len(salesmanList) == 0 {
|
||
m.Salesman = []ErpOrderSales{}
|
||
} else {
|
||
m.Salesman = salesmanList
|
||
}
|
||
|
||
m.SalesmanList = ""
|
||
|
||
return nil
|
||
}
|
||
|
||
// 添加订单的销售员信息
|
||
func erpOrderListSetSalesman(list []ErpOrder) {
|
||
for i, _ := range list {
|
||
_ = list[i].SetOrderSalesman()
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetOrderSalesman() error {
|
||
var salesProfit, staffProfit, totalStaffProfit float64
|
||
//获取销售毛利、员工毛利数据
|
||
for _, item := range m.Commodities {
|
||
erpCommodity, err := GetCommodity(item.ErpCommodityId)
|
||
if err != nil {
|
||
logger.Error("GetCommodity err:", logger.Field("err", err))
|
||
}
|
||
salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01
|
||
staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01
|
||
totalStaffProfit += item.StaffProfit
|
||
}
|
||
// 四舍五入并保留两位小数
|
||
salesProfit = math.Round(salesProfit*100) / 100
|
||
staffProfit = math.Round(staffProfit*100) / 100
|
||
totalStaffProfit = math.Round(totalStaffProfit*100) / 100
|
||
|
||
var salesmanInfo []ErpOrderSales
|
||
err := orm.Eloquent.Model(&ErpOrderSales{}).Where("erp_order_id = ?", m.ID).Find(&salesmanInfo).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
var salesmanList []ErpOrderSales
|
||
for _, item := range salesmanInfo {
|
||
item.SalesProfitPer = salesProfit / float64(len(salesmanInfo))
|
||
item.StaffProfitPer = staffProfit / float64(len(salesmanInfo))
|
||
|
||
// 获取员工毛利
|
||
userInfo, err := GetSysUserInfoById(item.Uid)
|
||
if err != nil {
|
||
logger.Error("GetSysUserInfoByUid err:", logger.Field("err", err))
|
||
}
|
||
item.Name = userInfo.NickName
|
||
item.SalesmanPer = totalStaffProfit * userInfo.SalesCommRate * 0.01 / float64(len(salesmanInfo))
|
||
|
||
//if m.RetailType == RetailTypeRejected {
|
||
// item.SalesProfitPer = -item.SalesProfitPer
|
||
// item.StaffProfitPer = -item.StaffProfitPer
|
||
// item.SalesmanPer = -item.SalesmanPer
|
||
//}
|
||
|
||
salesmanList = append(salesmanList, item)
|
||
}
|
||
|
||
if len(salesmanList) == 0 {
|
||
m.Salesman = []ErpOrderSales{}
|
||
} else {
|
||
m.Salesman = salesmanList
|
||
}
|
||
|
||
m.SalesmanList = ""
|
||
|
||
return nil
|
||
}
|
||
|
||
func (m *ErpOrder) SetSalesman() {
|
||
if m.SalesmanList != "" {
|
||
var salesman []ErpOrderSales
|
||
err := json.Unmarshal([]byte(m.SalesmanList), &salesman)
|
||
if err != nil {
|
||
logger.Error("unmarshal err:", logger.Field("err", err))
|
||
}
|
||
m.Salesman = salesman
|
||
m.SalesmanList = ""
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrderCreateReq) GetSalesmanList() (string, error) {
|
||
var salesProfit, staffProfit, totalStaffProfit float64
|
||
//获取销售毛利、员工毛利数据
|
||
for _, item := range m.ErpOrderCommodities {
|
||
erpCommodity, err := GetCommodity(item.ErpCommodityId)
|
||
if err != nil {
|
||
logger.Error("GetCommodity err:", logger.Field("err", err))
|
||
}
|
||
salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01
|
||
staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01
|
||
totalStaffProfit += item.StaffProfit
|
||
}
|
||
|
||
var salesmanList []ErpOrderSales
|
||
for _, item := range m.Salesman {
|
||
item.SalesProfitPer = salesProfit / float64(len(m.Salesman))
|
||
item.StaffProfitPer = staffProfit / float64(len(m.Salesman))
|
||
|
||
// 获取员工毛利
|
||
userInfo, err := GetSysUserInfoById(item.Uid)
|
||
if err != nil {
|
||
logger.Error("GetSysUserInfoByUid err:", logger.Field("err", err))
|
||
}
|
||
item.Name = userInfo.NickName
|
||
//item.SalesmanPer = staffProfit * userInfo.SalesCommRate * 0.01 / float64(len(m.Salesman))
|
||
item.SalesmanPer = totalStaffProfit * userInfo.SalesCommRate * 0.01 / float64(len(m.Salesman))
|
||
|
||
// 四舍五入并保留两位小数
|
||
item.SalesProfitPer = math.Round(item.SalesProfitPer*100) / 100
|
||
item.StaffProfitPer = math.Round(item.StaffProfitPer*100) / 100
|
||
item.SalesmanPer = math.Round(item.SalesmanPer*100) / 100
|
||
|
||
salesmanList = append(salesmanList, item)
|
||
}
|
||
|
||
m.Salesman = salesmanList
|
||
jSalesman, err := json.Marshal(m.Salesman)
|
||
if err != nil {
|
||
logger.Error("salesman marshal err:", logger.Field("err", err))
|
||
return "", err
|
||
}
|
||
|
||
return string(jSalesman), nil
|
||
}
|
||
|
||
// 添加订单的付款信息
|
||
func erpOrderListSetCashier(list []ErpOrder) {
|
||
for i, _ := range list {
|
||
list[i].SetErpCashier()
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetErpCashier() {
|
||
//if m.CashierList != "" && m.RetailType == RetailTypeSale { // 临时限制,退货订单不展示具体付款方式
|
||
if m.CashierList != "" {
|
||
var cashiers []ErpOrderCashier
|
||
err := json.Unmarshal([]byte(m.CashierList), &cashiers)
|
||
if err != nil {
|
||
logger.Error("unmarshal err:", logger.Field("err", err))
|
||
}
|
||
if m.RetailType == RetailTypeRejected {
|
||
for i, _ := range cashiers {
|
||
cashiers[i].Amount = -cashiers[i].Amount
|
||
}
|
||
}
|
||
m.Cashiers = cashiers
|
||
m.CashierList = ""
|
||
}
|
||
}
|
||
|
||
// 添加订单的付款信息
|
||
func erpRetailDetailSetCashier(list []ErpOrder) {
|
||
for i, _ := range list {
|
||
list[i].SetErpRetailDetailCashier()
|
||
}
|
||
}
|
||
|
||
func (m *ErpOrder) SetErpRetailDetailCashier() {
|
||
if m.CashierList != "" {
|
||
var cashiers []ErpOrderCashier
|
||
err := json.Unmarshal([]byte(m.CashierList), &cashiers)
|
||
if err != nil {
|
||
logger.Error("unmarshal err:", logger.Field("err", err))
|
||
}
|
||
if m.RetailType == RetailTypeRejected {
|
||
for i, _ := range cashiers {
|
||
cashiers[i].Amount = -cashiers[i].Amount
|
||
}
|
||
}
|
||
|
||
var nTotalOtherAmount float64
|
||
var newCashiers []ErpOrderCashier
|
||
for _, item := range cashiers {
|
||
if item.CashierId > 4 {
|
||
nTotalOtherAmount += item.Amount
|
||
} else {
|
||
newCashiers = append(newCashiers, item)
|
||
}
|
||
}
|
||
// 将所有其他类型的支付方式合并到一起
|
||
newCashiers = append(newCashiers, ErpOrderCashier{8090, "", nTotalOtherAmount})
|
||
m.Cashiers = newCashiers
|
||
m.CashierList = ""
|
||
}
|
||
}
|
||
|
||
func GetErpOrderCommodityMap(ids []uint32, req *ErpOrderCreateReq) (map[uint32]ErpOrderCommodity, error) {
|
||
commodityMap := make(map[uint32]ErpOrderCommodity, 0)
|
||
if len(ids) == 0 {
|
||
return commodityMap, nil
|
||
}
|
||
|
||
var commodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id ").
|
||
Where("erp_order_commodity.erp_commodity_id IN (?) and erp_order.store_id = ? "+
|
||
"and erp_order.retail_type = ? and erp_order.pay_status = ? and erp_order.tel = ?",
|
||
ids, req.StoreId, RetailTypeSale, HavePaid, req.Tel).
|
||
Find(&commodities).Order("audit_time DESC").Error
|
||
//var commodities []ErpOrderCommodity
|
||
//err := orm.Eloquent.Table("erp_order_commodity").Where("erp_commodity_id IN (?)", ids).Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return commodityMap, err
|
||
}
|
||
// 合并数据
|
||
commodities = mergeOrderCommodities(commodities)
|
||
for i, _ := range commodities {
|
||
commodityMap[commodities[i].ErpCommodityId] = commodities[i]
|
||
}
|
||
return commodityMap, nil
|
||
}
|
||
|
||
func SetUserInfo(tel string) {
|
||
var user UserInfo
|
||
err := orm.Eloquent.Table("user").Where("tel=?", tel).Find(&user).Error
|
||
if err != nil {
|
||
logger.Error("user err:", logger.Field("err", err))
|
||
return
|
||
}
|
||
if user.FirstRetailOrder == nil {
|
||
err := orm.Eloquent.Table("user").Where("uid=?", user.Uid).
|
||
Updates(map[string]interface{}{"first_retail_order": time.Now()}).Error
|
||
if err != nil {
|
||
logger.Error("update user err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
}
|
||
|
||
// SetInvoice 设置发票内容
|
||
func SetInvoice(req *ErpOrderAddInvoiceReq, c *gin.Context) error {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
logger.Errorf("err:%#v", err)
|
||
return err
|
||
}
|
||
|
||
var orderInfo ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("bill_sn = ?", req.BillSn).Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("操作失败,未查询到订单", logger.Field("err", err))
|
||
return errors.New("未查询到订单")
|
||
}
|
||
|
||
if orderInfo.State == ErpOrderStateUnAudit {
|
||
logger.Errorf("order delete err, state is:", orderInfo.State)
|
||
return errors.New("订单未审核")
|
||
}
|
||
|
||
if orderInfo.PayStatus != 2 {
|
||
logger.Errorf("order delete err, state is:", orderInfo.State)
|
||
return errors.New("订单未支付")
|
||
}
|
||
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !CheckUserStore(orderInfo.StoreId, sysUser) {
|
||
return errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
err = orm.Eloquent.Table("erp_order").Where("id = ?", orderInfo.ID).Updates(map[string]interface{}{
|
||
"invoice_code": req.InvoiceCode,
|
||
"invoice_number": req.InvoiceNumber,
|
||
}).Error
|
||
if err != nil {
|
||
logger.Error("AddInvoice err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// DeleteOrder 删除订单
|
||
func DeleteOrder(req *ErpOrderDeleteReq, c *gin.Context) error {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
logger.Errorf("err:%#v", err)
|
||
return err
|
||
}
|
||
|
||
var orderInfo ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("bill_sn = ?", req.BillSn).Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("order delete err:", logger.Field("err", err))
|
||
return errors.New("未查询到订单")
|
||
}
|
||
|
||
if orderInfo.State != ErpOrderStateUnAudit {
|
||
logger.Errorf("order delete err, state is:", orderInfo.State)
|
||
return errors.New("已审核订单不能删除")
|
||
}
|
||
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !CheckUserStore(orderInfo.StoreId, sysUser) {
|
||
return errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
var orderCommodities []ErpOrderCommodity
|
||
err = orm.Eloquent.Table("erp_order_commodity").Where("erp_order_id = ?", orderInfo.ID).Find(&orderCommodities).Error
|
||
if err != nil {
|
||
logger.Error("order delete err:", logger.Field("err", err))
|
||
return errors.New("未查询到订单商品信息")
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
err = begin.Delete(&orderCommodities).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("order delete1 err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = begin.Delete(orderInfo).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("order delete2 err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("order delete3 err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 生成序列号
|
||
func genErpOrderSerialNo() string {
|
||
currentDate := time.Now().Format("20060102")
|
||
tradeNO := "sale" + currentDate + pay.RandomNumString(10000000, 99999999)
|
||
return tradeNO
|
||
}
|
||
|
||
// GetErpOrderSn 生成零售订单号
|
||
func GetErpOrderSn() string {
|
||
var erpOrderSn string
|
||
for {
|
||
erpOrderSn = genErpOrderSerialNo()
|
||
var count int64
|
||
err := orm.Eloquent.Table("erp_order_record").Where("out_order_no=?", erpOrderSn).Count(&count)
|
||
if err != nil {
|
||
logger.Error("err:", logger.Field("err", err))
|
||
}
|
||
if count == 0 {
|
||
break
|
||
}
|
||
}
|
||
return erpOrderSn
|
||
}
|
||
|
||
// 查询是否有已支付的订单
|
||
func checkIsPayOk(billSn string) bool {
|
||
var count int64
|
||
err := orm.Eloquent.Table("erp_order_record").Where("bill_sn = ? and status = ?", billSn, PayOk).
|
||
Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("checkIsPayOk err:", logger.Field("err", err))
|
||
}
|
||
|
||
return count > 0
|
||
}
|
||
|
||
// 查询是否有待支付的订单
|
||
func checkIsPaying(billSn string) bool {
|
||
var count int64
|
||
err := orm.Eloquent.Table("erp_order_record").Where("bill_sn = ? and status = ?", billSn, Paying).
|
||
Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("checkIsPayOk err:", logger.Field("err", err))
|
||
}
|
||
|
||
return count > 0
|
||
}
|
||
|
||
// 查询是否有刚初始化的订单
|
||
func checkIsPayInit(billSn string) bool {
|
||
var count int64
|
||
err := orm.Eloquent.Table("erp_order_record").Where("bill_sn = ? and status = ?", billSn, PayInit).
|
||
Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("checkIsPayOk err:", logger.Field("err", err))
|
||
}
|
||
|
||
return count > 0
|
||
}
|
||
|
||
// ErpOrderPay 零售订单支付
|
||
func ErpOrderPay(req *ErpOrderPayReq, c *gin.Context) (*ErpOrderPayResp, error) {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
logger.Errorf("err:%#v", err)
|
||
return nil, err
|
||
}
|
||
|
||
resp := &ErpOrderPayResp{
|
||
Status: PayFailed,
|
||
}
|
||
//通过单据号查询收款金额
|
||
var orderInfo ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("bill_sn = ?", req.BillSn).Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("未查询到订单:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !CheckUserStore(orderInfo.StoreId, sysUser) {
|
||
return nil, errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
if orderInfo.PayStatus == HavePaid {
|
||
logger.Error("ErpOrderPay err, 订单已支付")
|
||
return resp, errors.New("订单已支付")
|
||
}
|
||
|
||
if orderInfo.PayStatus != WaitForPaying {
|
||
logger.Error("ErpOrderPay err, 订单不是待支付状态")
|
||
return resp, errors.New("订单不是待支付状态")
|
||
}
|
||
|
||
var cashiers []ErpOrderCashier
|
||
err = json.Unmarshal([]byte(orderInfo.CashierList), &cashiers)
|
||
if err != nil {
|
||
logger.Error("unmarshal CashierList err:", logger.Field("err", err))
|
||
}
|
||
|
||
var amount float64
|
||
for i, _ := range cashiers {
|
||
if cashiers[i].CashierId == OnlinePay { //线上支付
|
||
amount = cashiers[i].Amount
|
||
break
|
||
}
|
||
}
|
||
if amount == 0 {
|
||
logger.Error("ErpOrderPay err, 订单金额为0")
|
||
return resp, errors.New("订单金额为0")
|
||
}
|
||
|
||
// dev环境测试默认金额都为0.1元
|
||
if config.ApplicationConfig.Mode == "dev" {
|
||
amount = 0.1
|
||
}
|
||
|
||
// 查询是否有已支付的订单
|
||
if checkIsPayOk(req.BillSn) {
|
||
// 更新零售订单表
|
||
err = orm.Eloquent.Model(&ErpOrder{}).Where("id = ?", orderInfo.ID).
|
||
Updates(map[string]interface{}{"pay_status": HavePaid}).Error
|
||
if err != nil {
|
||
logger.Error("ErpOrderPay update erp_order_record err:", logger.Field("err", err))
|
||
}
|
||
resp.Status = PayOk
|
||
logger.Error("ErpOrderPay err2, 订单已支付")
|
||
return resp, errors.New("订单已支付")
|
||
}
|
||
|
||
// 查询是否有待支付订单
|
||
if checkIsPaying(req.BillSn) {
|
||
queryResp, err := QueryErpOrderPayStatus(req.BillSn)
|
||
if err != nil {
|
||
logger.Error("查询订单失败", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
// 等待支付或成功支付则返回,否则新建订单
|
||
if queryResp.Status == Paying || queryResp.Status == PayOk {
|
||
resp.Status = queryResp.Status
|
||
return resp, nil
|
||
}
|
||
}
|
||
|
||
// 查询是否有刚初始化的订单
|
||
var orderSn string
|
||
if checkIsPayInit(req.BillSn) {
|
||
var orderRecordInfo ErpOrderRecord
|
||
err := orm.Eloquent.Table("erp_order_record").Where("bill_sn = ? and status = ?", req.BillSn, PayInit).
|
||
Find(&orderRecordInfo).Error
|
||
if err != nil {
|
||
logger.Error("未查询到订单:", logger.Field("err", err))
|
||
return resp, errors.New("未查询到待支付订单")
|
||
}
|
||
orderSn = orderRecordInfo.OutOrderNo
|
||
} else {
|
||
// 创建支付订单号,并记录到支付记录表,关联零售订单号
|
||
orderSn = GetErpOrderSn()
|
||
var erpOrderRecord ErpOrderRecord
|
||
erpOrderRecord.ErpOrderId = orderInfo.ID
|
||
erpOrderRecord.BillSn = orderInfo.BillSn
|
||
erpOrderRecord.OutOrderNo = orderSn
|
||
erpOrderRecord.Status = PayInit
|
||
err = orm.Eloquent.Table("erp_order_record").Create(&erpOrderRecord).Error
|
||
if err != nil {
|
||
logger.Error("Create erp_order_record err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
}
|
||
resp.Status = Paying
|
||
|
||
// 发起支付扣款
|
||
hmPayResp, err := pay.HmJsPayBToCOrder(orderSn, amount, req.AuthCode, "")
|
||
if err != nil {
|
||
logger.Error("HmJsPayBToCOrder err")
|
||
return resp, err
|
||
}
|
||
|
||
// 更新支付状态
|
||
var payStatus string
|
||
switch hmPayResp.SubCode {
|
||
case "SUCCESS":
|
||
payStatus = PayOk
|
||
case "FAILED":
|
||
payStatus = PayFailed
|
||
case "WAITING_PAYMENT":
|
||
payStatus = Paying
|
||
//default:
|
||
// payStatus = PayUnknown
|
||
}
|
||
updateInfo := map[string]interface{}{
|
||
"bank_order_no": hmPayResp.BankOrderNo,
|
||
"plat_trx_no": hmPayResp.PlatTrxNo,
|
||
"total_amount": hmPayResp.TotalAmount,
|
||
"pay_way": hmPayResp.PayWay,
|
||
"status": payStatus,
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
err = begin.Model(&ErpOrderRecord{}).Where("out_order_no = ?", orderSn).
|
||
Updates(updateInfo).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order_record err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
if payStatus == PayOk { // 支付成功
|
||
// 更新零售订单表
|
||
err = begin.Model(&ErpOrder{}).Where("id = ?", orderInfo.ID).
|
||
Updates(map[string]interface{}{"pay_status": HavePaid}).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order_record err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
//// 更新库存订单表
|
||
//err = updateErpStockCommodity(begin, req.BillSn)
|
||
//if err != nil {
|
||
// logger.Error("ErpOrderPay updateErpStockCommodity err:", logger.Field("err", err))
|
||
// return resp, err
|
||
//}
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
return resp, fmt.Errorf("ErpOrderPay[commit err]:%v", err)
|
||
}
|
||
|
||
resp.Status = payStatus
|
||
return resp, nil
|
||
}
|
||
|
||
// QueryErpOrderPayStatus 查询零售订单支付状态
|
||
func QueryErpOrderPayStatus(billSn string) (*ErpOrderPayResp, error) {
|
||
resp := &ErpOrderPayResp{
|
||
Status: Paying,
|
||
}
|
||
// 查询待支付订单
|
||
var orderRecordInfo ErpOrderRecord
|
||
err := orm.Eloquent.Table("erp_order_record").Where("bill_sn = ? and status in (?)", billSn, []string{Paying, PayOk}).
|
||
Find(&orderRecordInfo).Error
|
||
if err != nil {
|
||
logger.Error("未查询到订单:", logger.Field("err", err))
|
||
resp.Status = PayFailed
|
||
return resp, errors.New("未查询到待支付订单")
|
||
}
|
||
|
||
if orderRecordInfo.OutOrderNo == "" {
|
||
logger.Info("还未创建支付订单")
|
||
resp.Status = NoPayOrder
|
||
return resp, nil
|
||
}
|
||
|
||
if orderRecordInfo.Status == PayOk {
|
||
logger.Info("订单已支付")
|
||
resp.Status = PayOk
|
||
return resp, nil
|
||
}
|
||
|
||
// 查询支付状态
|
||
hmQueryResp, err := pay.HmQueryOrder(orderRecordInfo.OutOrderNo)
|
||
if err != nil {
|
||
logger.Error("查询失败:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
// 更新订单状态
|
||
var payStatus string
|
||
switch hmQueryResp.SubCode {
|
||
case "SUCCESS":
|
||
payStatus = PayOk
|
||
case "FAILED":
|
||
payStatus = PayFailed
|
||
case "WAITING_PAYMENT":
|
||
payStatus = Paying
|
||
//default:
|
||
// payStatus = PayUnknown
|
||
}
|
||
updateInfo := map[string]interface{}{
|
||
"bank_order_no": hmQueryResp.BankOrderNo,
|
||
"plat_trx_no": hmQueryResp.PlatTrxNo,
|
||
"total_amount": hmQueryResp.TotalAmount,
|
||
"pay_way": hmQueryResp.PayWayCode,
|
||
"status": payStatus,
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
err = begin.Model(&ErpOrderRecord{}).Where("out_order_no = ?", orderRecordInfo.OutOrderNo).
|
||
Updates(updateInfo).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("query update erp_order_record err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
if payStatus == PayOk { // 支付成功
|
||
// 更新零售订单表
|
||
err = begin.Model(&ErpOrder{}).Where("id = ?", orderRecordInfo.ErpOrderId).
|
||
Updates(map[string]interface{}{"pay_status": HavePaid}).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("query update erp_order_record err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
//// 更新库存订单表
|
||
//err = updateErpStockCommodity(begin, billSn)
|
||
//if err != nil {
|
||
// logger.Error("ErpOrderPay updateErpStockCommodity err:", logger.Field("err", err))
|
||
// return resp, err
|
||
//}
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
return resp, fmt.Errorf("QueryErpOrderPayStatus[commit err]:%v", err)
|
||
}
|
||
|
||
resp.Status = payStatus
|
||
return resp, nil
|
||
}
|
||
|
||
// 更新库存订单表
|
||
func updateErpStockCommodity(gdb *gorm.DB, billSn string) error {
|
||
//通过单据号查询订单
|
||
var erpOrderInfo []ErpOrder
|
||
err := orm.Eloquent.Table("erp_order").Where("bill_sn = ?", billSn).Find(&erpOrderInfo).Error
|
||
if err != nil {
|
||
logger.Error("erp_order 未查询到订单:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if len(erpOrderInfo) == 0 {
|
||
return errors.New("未查询到订单")
|
||
}
|
||
|
||
err = UpdateStock(gdb, erpOrderInfo[0], SoldOut, 0)
|
||
if err != nil {
|
||
gdb.Rollback()
|
||
logger.Error("updateErpStockCommodity UpdateStock err:", logger.Field("err", err))
|
||
return errors.New("审核失败:" + err.Error())
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// CommodityIsHaveStock 查询商品是否有库存
|
||
func CommodityIsHaveStock(req ErpOrderCommodity, storeId uint32) bool {
|
||
qs := orm.Eloquent.Table("erp_stock_commodity")
|
||
if req.IMEI != "" { // 串码商品
|
||
qs.Where("imei = ? and state = ?", req.IMEI, InStock)
|
||
} else { // 非串码商品
|
||
qs.Where("erp_commodity_id = ? and store_id = ? and state = ? and imei_type = ?",
|
||
req.ErpCommodityId, storeId, InStock, NoIMEICommodity)
|
||
}
|
||
|
||
var count int64
|
||
err := qs.Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("CommodityIsHaveStock err:", logger.Field("err", err))
|
||
}
|
||
|
||
return count > 0
|
||
}
|
||
|
||
// QueryStoreManageData 查询门店经营数据
|
||
func QueryStoreManageData(req *ErpOrderStoreManageDataReq, c *gin.Context) (*ErpOrderStoreManageDataResp, error) {
|
||
showConfig, err := GetErpOrderShowConfig()
|
||
if err != nil {
|
||
logger.Errorf("List err:", err)
|
||
showConfig.ShowAll = "ON"
|
||
}
|
||
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
resp := &ErpOrderStoreManageDataResp{
|
||
PageIndex: req.PageIndex,
|
||
PageSize: req.PageSize,
|
||
}
|
||
var storeManageDataList []StoreManageData
|
||
|
||
// 构建查询条件
|
||
qs := orm.Eloquent.Model(&ErpOrder{})
|
||
if req.StoreId != 0 {
|
||
qs = qs.Where("store_id = ?", req.StoreId)
|
||
}
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
if len(storeList) == 1 {
|
||
qs = qs.Where("store_id = ?", storeList[0])
|
||
} else {
|
||
qs = qs.Where("store_id IN (?)", storeList)
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
if showConfig.ShowAll == "OFF" {
|
||
qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
}
|
||
|
||
if req.StartTime != "" && req.EndTime != "" {
|
||
startTime, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||
if err != nil {
|
||
logger.Error("startTime parse err")
|
||
}
|
||
|
||
endTime, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||
if err != nil {
|
||
logger.Error("endTime parse err")
|
||
}
|
||
|
||
//startTime, _ := time.Parse("2006-01-02", req.StartTime)
|
||
//endTime, _ := time.Parse("2006-01-02", req.EndTime)
|
||
qs = qs.Where("maker_time BETWEEN ? AND ?", startTime, endTime)
|
||
} else {
|
||
qs = qs.Where("maker_time IS NOT NULL")
|
||
}
|
||
qs.Where("state = ?", ErpOrderStateAudited)
|
||
|
||
// 查询数据
|
||
if req.SortType == "asc" {
|
||
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS promotion_fee, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS sales_profit, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS staff_profit, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS count").
|
||
Group("date").
|
||
Order("date ASC").
|
||
Find(&storeManageDataList).Error
|
||
} else {
|
||
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS promotion_fee, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS sales_profit, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS staff_profit, " +
|
||
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS count").
|
||
Group("date").
|
||
Order("date DESC").
|
||
Find(&storeManageDataList).Error
|
||
}
|
||
if err != nil {
|
||
logger.Error("QueryStoreManageData err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
finalStoreManageDataList := constructFinalStoreManageDataList(storeManageDataList, req)
|
||
|
||
if req.IsExport == 1 { //导出excel
|
||
storeName := "所有门店"
|
||
if req.StoreId != 0 {
|
||
storeInfo, err := GetStore(req.StoreId)
|
||
if err != nil {
|
||
logger.Error("GetStore err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
storeName = storeInfo.Name
|
||
}
|
||
|
||
finalStoreManageDataList = constructFinalStoreManageDataList(storeManageDataList, req)
|
||
filePath, err := storeManageDataExport(finalStoreManageDataList, storeName)
|
||
if err != nil {
|
||
logger.Error("StoreManageDataExport err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
resp.ExportUrl = filePath
|
||
} else {
|
||
// 根据页码和页面条数截取结果
|
||
startIndex := (req.PageIndex - 1) * req.PageSize
|
||
endIndex := startIndex + req.PageSize
|
||
if endIndex > len(finalStoreManageDataList) {
|
||
endIndex = len(finalStoreManageDataList)
|
||
}
|
||
resp.List = finalStoreManageDataList[startIndex:endIndex]
|
||
|
||
resp.Total = len(finalStoreManageDataList)
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 查询门店经营数据,为空的日期默认填充数据为0
|
||
func constructFinalStoreManageDataList(storeManageDataList []StoreManageData, req *ErpOrderStoreManageDataReq) []StoreManageData {
|
||
// Create a map to store data by date for easier processing
|
||
storeDataMap := make(map[string]StoreManageData)
|
||
for _, data := range storeManageDataList {
|
||
storeDataMap[data.Date] = data
|
||
}
|
||
|
||
// Construct the final response with consecutive dates and defaulting to 0 for missing data
|
||
var finalStoreManageDataList []StoreManageData
|
||
startDate, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||
if err != nil {
|
||
logger.Error("constructFinalStoreManageDataList time Parse err:", logger.Field("err", err))
|
||
return storeManageDataList
|
||
}
|
||
endDate, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||
if err != nil {
|
||
logger.Error("constructFinalStoreManageDataList time Parse err:", logger.Field("err", err))
|
||
return storeManageDataList
|
||
}
|
||
|
||
for d := endDate; d.After(startDate) || d.Equal(startDate); d = d.AddDate(0, 0, -1) {
|
||
dateStr := d.Format("2006-01-02")
|
||
data, found := storeDataMap[dateStr]
|
||
if !found {
|
||
data = StoreManageData{
|
||
Date: dateStr,
|
||
TotalSalesAmount: 0,
|
||
PromotionFee: 0,
|
||
SalesProfit: 0,
|
||
StaffProfit: 0,
|
||
Count: 0,
|
||
}
|
||
}
|
||
finalStoreManageDataList = append(finalStoreManageDataList, data)
|
||
}
|
||
|
||
sortType := strings.ToLower(req.SortType)
|
||
switch sortType {
|
||
case "asc":
|
||
sort.Slice(finalStoreManageDataList, func(i, j int) bool {
|
||
return finalStoreManageDataList[i].Date < finalStoreManageDataList[j].Date
|
||
})
|
||
case "desc":
|
||
sort.Slice(finalStoreManageDataList, func(i, j int) bool {
|
||
return finalStoreManageDataList[i].Date > finalStoreManageDataList[j].Date
|
||
})
|
||
}
|
||
|
||
return finalStoreManageDataList
|
||
}
|
||
|
||
// StoreManageDataExport 导出门店经营数据
|
||
func storeManageDataExport(list []StoreManageData, storeName string) (string, error) {
|
||
file := excelize.NewFile()
|
||
fSheet := "Sheet1"
|
||
|
||
url := ExportUrl
|
||
fileName := time.Now().Format(TimeFormat) + storeName + "经营数据" + ".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 row []interface{}
|
||
nExcelStartRow := 0
|
||
for rowId := 0; rowId < len(list); rowId++ {
|
||
row = []interface{}{
|
||
list[rowId].Date,
|
||
list[rowId].TotalSalesAmount,
|
||
list[rowId].PromotionFee,
|
||
list[rowId].SalesProfit,
|
||
list[rowId].StaffProfit,
|
||
list[rowId].Count,
|
||
}
|
||
|
||
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}]}`)
|
||
|
||
//设置单元格高度
|
||
file.SetRowHeight("Sheet1", 1, 20)
|
||
|
||
// 设置单元格大小
|
||
file.SetColWidth("Sheet1", "A", "A", 18)
|
||
|
||
endRow := fmt.Sprintf("F"+"%d", nExcelStartRow+1)
|
||
// 应用样式到整个表格
|
||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||
|
||
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
|
||
}
|
||
|
||
// retailMarginDataExport 导出商品零售毛利汇总数据
|
||
func retailMarginDataExport(req *ErpOrderRetailMarginResp) (string, error) {
|
||
file := excelize.NewFile()
|
||
streamWriter, err := file.NewStreamWriter("Sheet1")
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
|
||
url := ExportUrl
|
||
fileName := time.Now().Format(TimeFormat) + "商品零售毛利汇总" + ".xlsx"
|
||
fmt.Println("url fileName:", url+fileName)
|
||
|
||
title := []interface{}{"店铺名称", "零售类型", "商品名称", "商品分类", "数量", "销售/退货金额", "销售成本", "销售毛利", "销售毛利率"}
|
||
cell, _ := excelize.CoordinatesToCellName(1, 1)
|
||
if err = streamWriter.SetRow(cell, title); err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
|
||
var row []interface{}
|
||
nExcelStartRow := 0
|
||
for rowId := 0; rowId < len(req.List); rowId++ {
|
||
var saleType string
|
||
if req.List[rowId].RetailType == RetailTypeSale {
|
||
saleType = "零售销售"
|
||
} else if req.List[rowId].RetailType == RetailTypeRejected {
|
||
saleType = "零售退货"
|
||
} else {
|
||
logger.Error("订单类型异常")
|
||
return "", errors.New("RetailMarginDataExport, 订单类型异常:" + req.List[rowId].RetailType)
|
||
}
|
||
row = []interface{}{
|
||
req.List[rowId].StoreName,
|
||
saleType,
|
||
req.List[rowId].ErpCommodityName,
|
||
req.List[rowId].ErpCategoryName,
|
||
req.List[rowId].Count,
|
||
req.List[rowId].SalesAmount,
|
||
req.List[rowId].SalesCost,
|
||
req.List[rowId].SalesMargin,
|
||
req.List[rowId].GrossMargins,
|
||
}
|
||
|
||
cell, _ := excelize.CoordinatesToCellName(1, nExcelStartRow+2)
|
||
if err := streamWriter.SetRow(cell, row); err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
nExcelStartRow++
|
||
}
|
||
|
||
totalData := "汇总 记录数:" + strconv.FormatInt(int64(req.TotalCount), 10)
|
||
end := []interface{}{totalData, "", "", "", req.TotalCount, fmt.Sprintf("%.2f", req.TotalSalesAmount),
|
||
fmt.Sprintf("%.2f", req.TotalSalesCost),
|
||
fmt.Sprintf("%.2f", req.TotalSalesMargin),
|
||
req.TotalGrossMargins}
|
||
cell, _ = excelize.CoordinatesToCellName(1, nExcelStartRow+2)
|
||
if err := streamWriter.SetRow(cell, end); err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
|
||
if err := streamWriter.Flush(); err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
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
|
||
}
|
||
|
||
// QueryRetailMargin 查询零售毛利汇总数据
|
||
func QueryRetailMargin(req *ErpOrderRetailMarginReq, c *gin.Context) (*ErpOrderRetailMarginResp, error) {
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
req.StoreId = CompareLists(storeList, req.StoreId)
|
||
if len(req.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
|
||
return &ErpOrderRetailMarginResp{}, nil
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
|
||
showConfig, err := GetErpOrderShowConfig()
|
||
if err != nil {
|
||
logger.Errorf("List err:", err)
|
||
showConfig.ShowAll = "ON"
|
||
}
|
||
resp := &ErpOrderRetailMarginResp{
|
||
PageIndex: req.PageIndex,
|
||
PageSize: req.PageSize,
|
||
}
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
qs := orm.Eloquent.Debug().Table("erp_order_commodity").
|
||
Select("erp_order_commodity.*, erp_order.store_id, erp_order.store_name, erp_order.retail_type").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id")
|
||
|
||
if len(req.StoreId) != 0 {
|
||
qs.Where("erp_order.store_id in ?", req.StoreId)
|
||
}
|
||
if len(req.RetailType) != 0 {
|
||
qs.Where("erp_order.retail_type in ?", req.RetailType)
|
||
}
|
||
if len(req.ErpCommodityName) != 0 {
|
||
qs.Where("erp_order_commodity.erp_commodity_name in ?", req.ErpCommodityName)
|
||
}
|
||
if len(req.ErpCategoryId) != 0 {
|
||
qs.Where("erp_order_commodity.erp_category_id in ?", req.ErpCategoryId)
|
||
}
|
||
if req.StartTime != "" {
|
||
startTime, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||
if err == nil {
|
||
qs = qs.Where("erp_order.audit_time>?", startTime)
|
||
} else {
|
||
logger.Errorf("QueryRetailMargin time start parse err:", err.Error())
|
||
}
|
||
}
|
||
if req.EndTime != "" {
|
||
endTime, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||
if err == nil {
|
||
qs = qs.Where("erp_order.audit_time<?", endTime)
|
||
} else {
|
||
logger.Errorf("QueryRetailMargin time end parse err:", err.Error())
|
||
}
|
||
}
|
||
if showConfig.ShowAll == "OFF" {
|
||
qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
}
|
||
|
||
var result []struct {
|
||
ErpOrderCommodity
|
||
StoreID uint32
|
||
StoreName string
|
||
RetailType string
|
||
}
|
||
qs.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
// 添加排序规则
|
||
//qs = qs.Order("erp_order_commodity.erp_commodity_id ASC, erp_order.store_id ASC, erp_order.retail_type ASC")
|
||
qs = qs.Order(`
|
||
erp_order_commodity.erp_commodity_id ASC,
|
||
erp_order.store_id ASC,
|
||
CASE erp_order.retail_type
|
||
WHEN 'sale' THEN 0
|
||
WHEN 'rejected' THEN 1
|
||
ELSE 2
|
||
END ASC`)
|
||
|
||
if req.IsExport == 1 { //导出excel
|
||
err := qs.Find(&result).Error
|
||
if err != nil {
|
||
logger.Errorf("QueryRetailMargin find err:", err.Error())
|
||
return nil, err
|
||
}
|
||
} else {
|
||
err := qs.Find(&result).Offset(page * req.PageSize).Limit(req.PageSize).Error
|
||
if err != nil {
|
||
logger.Errorf("QueryRetailMargin find err:", err.Error())
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
//var data RetailMarginData
|
||
var list []RetailMarginData
|
||
//for _, item := range result {
|
||
// data.StoreId = item.StoreID
|
||
// data.StoreName = item.StoreName
|
||
// data.RetailType = item.RetailType
|
||
// data.ErpCommodityId = item.ErpCommodityId
|
||
// data.ErpCommodityName = item.ErpCommodityName
|
||
// data.ErpCategoryId = item.ErpCategoryId
|
||
// data.ErpCategoryName = item.ErpCategoryName
|
||
// data.Total = item.Total
|
||
// data.SalesAmount = item.ReceivedAmount
|
||
// data.SalesCost = float64(item.WholesalePrice * item.Total)
|
||
// data.SalesMargin = data.SalesAmount - data.SalesCost
|
||
// data.GrossMargins = float64ToPercentage(data.SalesMargin / data.SalesAmount)
|
||
// if data.RetailType == RetailTypeRejected {
|
||
// data.SalesAmount = -data.SalesAmount
|
||
// data.SalesCost = -data.SalesCost
|
||
// data.SalesMargin = -data.SalesMargin
|
||
// }
|
||
// list = append(list, data)
|
||
//
|
||
// resp.TotalCount += data.Total
|
||
// resp.TotalSalesAmount += data.SalesAmount
|
||
// resp.TotalSalesCost += data.SalesCost
|
||
// resp.TotalSalesMargin += data.SalesMargin
|
||
//}
|
||
//
|
||
//if resp.TotalSalesAmount != 0 {
|
||
// resp.TotalGrossMargins = float64ToPercentage(resp.TotalSalesMargin / resp.TotalSalesAmount)
|
||
//}
|
||
|
||
// 创建一个 map 用来存储已经处理过的数据,key 是 StoreId 和 ErpCommodityId 的组合
|
||
processedData := make(map[string]*RetailMarginData)
|
||
|
||
// 遍历 result 中的每一条数据
|
||
for _, item := range result {
|
||
// 生成一个唯一的键,可以使用 StoreId 和 ErpCommodityId 的组合
|
||
key := fmt.Sprintf("%d_%d_%s", item.StoreID, item.ErpCommodityId, item.RetailType)
|
||
|
||
var nCount int32
|
||
var salesAmount, salesCost, employeeCost, salesMargin float64
|
||
if item.RetailType == RetailTypeRejected {
|
||
nCount = -int32(item.Count)
|
||
salesAmount = -item.RejectedAmount // 退货订单要以实际退货金额为准
|
||
salesCost = -item.WholesalePrice * float64(item.Count)
|
||
employeeCost = -(item.WholesalePrice + item.StaffCostPrice) * float64(item.Count)
|
||
salesMargin = -(item.ReceivedAmount - item.WholesalePrice*float64(item.Count))
|
||
} else {
|
||
nCount = int32(item.Count)
|
||
salesAmount = item.ReceivedAmount
|
||
salesCost = item.WholesalePrice * float64(item.Count)
|
||
employeeCost = (item.WholesalePrice + item.StaffCostPrice) * float64(item.Count)
|
||
salesMargin = item.ReceivedAmount - item.WholesalePrice*float64(item.Count)
|
||
}
|
||
// 检查是否已经处理过这个组合的数据
|
||
if existingData, ok := processedData[key]; ok {
|
||
// 如果存在,说明已经有数据,进行合并操作
|
||
existingData.Count += nCount
|
||
existingData.SalesAmount += salesAmount
|
||
existingData.SalesCost += salesCost
|
||
existingData.SalesMargin += salesMargin
|
||
existingData.EmployeeCost += employeeCost
|
||
|
||
if existingData.SalesAmount == 0 {
|
||
existingData.GrossMargins = "--"
|
||
} else {
|
||
existingData.GrossMargins = float64ToPercentage(existingData.SalesMargin / existingData.SalesAmount)
|
||
}
|
||
} else {
|
||
// 如果不存在,说明是新数据,直接添加到列表中
|
||
data := &RetailMarginData{
|
||
StoreId: item.StoreID,
|
||
StoreName: item.StoreName,
|
||
RetailType: item.RetailType,
|
||
ErpCommodityId: item.ErpCommodityId,
|
||
ErpCommodityName: item.ErpCommodityName,
|
||
ErpCategoryId: item.ErpCategoryId,
|
||
ErpCategoryName: item.ErpCategoryName,
|
||
Count: nCount,
|
||
SalesAmount: item.ReceivedAmount,
|
||
SalesCost: item.WholesalePrice * float64(item.Count),
|
||
EmployeeCost: (item.WholesalePrice + item.StaffCostPrice) * float64(item.Count),
|
||
SalesMargin: item.ReceivedAmount - item.WholesalePrice*float64(item.Count),
|
||
GrossMargins: "--",
|
||
//GrossMargins: float64ToPercentage((item.ReceivedAmount - float64(int32(item.WholesalePrice)*item.Total)) / item.ReceivedAmount),
|
||
}
|
||
if item.ReceivedAmount != 0 {
|
||
data.GrossMargins = float64ToPercentage((item.ReceivedAmount - item.WholesalePrice*float64(item.Count)) / item.ReceivedAmount)
|
||
}
|
||
|
||
// 如果是拒绝的销售,进行相应的处理
|
||
if data.RetailType == RetailTypeRejected {
|
||
data.SalesAmount = -data.SalesAmount
|
||
data.SalesCost = -data.SalesCost
|
||
data.SalesMargin = -data.SalesMargin
|
||
data.EmployeeCost = -data.EmployeeCost
|
||
}
|
||
|
||
// 处理数据,四舍五入保留2位小数
|
||
data.SalesAmount = math.Round(data.SalesAmount*100) / 100
|
||
data.SalesCost = math.Round(data.SalesCost*100) / 100
|
||
data.SalesMargin = math.Round(data.SalesMargin*100) / 100
|
||
data.EmployeeCost = math.Round(data.EmployeeCost*100) / 100
|
||
|
||
// 将新数据添加到 map 中
|
||
processedData[key] = data
|
||
}
|
||
}
|
||
|
||
// 将处理过的数据添加到 resp.List 中
|
||
for _, data := range processedData {
|
||
list = append(list, *data)
|
||
}
|
||
|
||
// 计算总数
|
||
for _, data := range list {
|
||
resp.TotalCount += data.Count
|
||
resp.TotalSalesAmount += data.SalesAmount
|
||
resp.TotalSalesCost += data.SalesCost
|
||
resp.TotalSalesMargin += data.SalesMargin
|
||
resp.TotalEmployeeCost += data.EmployeeCost
|
||
}
|
||
|
||
// 处理数据,四舍五入保留2位小数
|
||
resp.TotalSalesAmount = math.Round(resp.TotalSalesAmount*100) / 100
|
||
resp.TotalSalesCost = math.Round(resp.TotalSalesCost*100) / 100
|
||
resp.TotalSalesMargin = math.Round(resp.TotalSalesMargin*100) / 100
|
||
resp.TotalEmployeeCost = math.Round(resp.TotalEmployeeCost*100) / 100
|
||
if resp.TotalSalesAmount != 0 {
|
||
resp.TotalGrossMargins = float64ToPercentage(resp.TotalSalesMargin / resp.TotalSalesAmount)
|
||
} else {
|
||
resp.TotalGrossMargins = "--"
|
||
}
|
||
|
||
// 对列表按照您想要的顺序进行排序
|
||
sort.Slice(list, func(i, j int) bool {
|
||
// 按照 StoreId 升序排列
|
||
if list[i].StoreId != list[j].StoreId {
|
||
return list[i].StoreId < list[j].StoreId
|
||
}
|
||
// 按照 ErpCommodityId 升序排列
|
||
if list[i].ErpCommodityId != list[j].ErpCommodityId {
|
||
return list[i].ErpCommodityId < list[j].ErpCommodityId
|
||
}
|
||
// 按照 RetailType 的顺序进行排序
|
||
retailTypeOrder := map[string]int{"sale": 0, "rejected": 1}
|
||
return retailTypeOrder[list[i].RetailType] < retailTypeOrder[list[j].RetailType]
|
||
})
|
||
|
||
// 将结果赋值给 resp.List
|
||
resp.List = list
|
||
|
||
if req.IsExport == 1 { //导出excel
|
||
filePath, err := retailMarginDataExport(resp)
|
||
if err != nil {
|
||
logger.Error("StoreManageDataExport err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
resp.ExportUrl = filePath
|
||
} else {
|
||
// 计算分页所需的切片索引
|
||
startIndex := page * req.PageSize
|
||
endIndex := (page + 1) * req.PageSize
|
||
if endIndex > len(list) {
|
||
endIndex = len(list)
|
||
}
|
||
resp.List = list[startIndex:endIndex]
|
||
resp.Total = len(list)
|
||
resp.PageIndex = req.PageIndex
|
||
resp.PageSize = req.PageSize
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 将float64转换为百分比
|
||
func float64ToPercentage(value float64) string {
|
||
// 将浮点数乘以100,然后格式化为字符串
|
||
percentage := fmt.Sprintf("%.2f%%", value*100)
|
||
return percentage
|
||
}
|
||
|
||
// QueryRetailDetail 查询零售明细
|
||
func QueryRetailDetail(req *ErpOrderRetailDetailReq, c *gin.Context) (*ErpOrderRetailDetailResp, error) {
|
||
resp := &ErpOrderRetailDetailResp{}
|
||
|
||
var err error
|
||
if (req.ErpCategoryId != 0 || req.ErpCommodityName != "" || req.IMEI != "") && req.BillSn == "" { // 商品分类or商品名称不为空且订单编号为空
|
||
// 联表查询
|
||
resp, err = queryRetailDetailByJoin(req, c)
|
||
} else {
|
||
// 普通单表查询,然后补充收款数据和商品数据
|
||
resp, err = queryRetailDetailCommon(req, c)
|
||
}
|
||
if err != nil {
|
||
logger.Error("queryRetailDetailCommon err")
|
||
return nil, err
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 导出零售明细报表excel-合并单元格版本
|
||
func retailDetailExportBack(list []ErpOrder, sumData RetailDetailTotalData) (string, error) {
|
||
file := excelize.NewFile()
|
||
fSheet := "Sheet1"
|
||
|
||
url := ExportUrl
|
||
fileName := time.Now().Format(TimeFormat) + "零售明细" + ".xlsx"
|
||
fmt.Println("url fileName:", url+fileName)
|
||
|
||
title := []interface{}{"订单编号", "订单类型", "用户ID", "客户手机号", "审核时间", "店铺", "销售员", "商品分类", "商品名称",
|
||
"供应商", "是否串码", "商品串码", "是否赠送", "销售数量", "指导零售价", "零售价", "零售优惠", "会员优惠", "实际零售价/退货价",
|
||
"采购单价", "员工成本价", "销售毛利", "员工毛利", "订单总指导零售价", "订单总优惠", "订单实收", "【扫码付", "现金收款", "pos机收款",
|
||
"商场积分抵扣", "其他付款方式】", "订单总销售毛利", "订单总员工毛利", "销售毛利提成", "员工毛利提成", "销售员提成", "门店提成", "备注"}
|
||
for i, _ := range title {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||
err := file.SetCellValue(fSheet, cell, title[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
|
||
var row []interface{}
|
||
nAmount := 0.0
|
||
nExcelStartRow := 0
|
||
for i := 0; i < len(list); i++ {
|
||
var saleType string
|
||
if list[i].RetailType == RetailTypeSale {
|
||
saleType = "零售销售"
|
||
} else if list[i].RetailType == RetailTypeRejected {
|
||
saleType = "零售退货"
|
||
} else {
|
||
logger.Error("订单类型异常")
|
||
return "", errors.New("RetailMarginDataExport, 订单类型异常:" + list[i].RetailType)
|
||
}
|
||
|
||
commodityIdMap := make(map[uint32]bool)
|
||
// 先判断商品数量,确定要写几行数据
|
||
for rowId := 0; rowId < len(list[i].Commodities); rowId++ {
|
||
if list[i].RetailType == RetailTypeSale {
|
||
nAmount = list[i].Commodities[rowId].Amount
|
||
} else if list[i].RetailType == RetailTypeRejected {
|
||
nAmount = list[i].Commodities[rowId].RejectedAmount
|
||
list[i].CashierList = "" // 目前零售退货订单暂时不展示各个方式的付款金额
|
||
}
|
||
|
||
isIMEIType := "是"
|
||
if list[i].Commodities[rowId].IMEIType == 1 {
|
||
isIMEIType = "否"
|
||
}
|
||
|
||
strPresentType := "非赠送"
|
||
if list[i].Commodities[rowId].PresentType == 2 {
|
||
strPresentType = "赠送"
|
||
}
|
||
|
||
// 组合销售员名称,提成数据
|
||
salesMan := ""
|
||
strSalesProfitPer := ""
|
||
strStaffProfitPer := ""
|
||
strSalesmanPer := ""
|
||
//var salesList []ErpOrderSales
|
||
//err := json.Unmarshal([]byte(list[i].SalesmanList), &salesList)
|
||
//if err != nil {
|
||
// logger.Error("unmarshal err:", logger.Field("err", err))
|
||
//}
|
||
for j, item := range list[i].Salesman {
|
||
salesMan += item.Name
|
||
// 将浮点数转换为字符串,保留两位小数
|
||
strNumber1 := strconv.FormatFloat(item.SalesProfitPer, 'f', 2, 64)
|
||
strSalesProfitPer += strNumber1
|
||
strNumber2 := strconv.FormatFloat(item.StaffProfitPer, 'f', 2, 64)
|
||
strStaffProfitPer += strNumber2
|
||
strNumber3 := strconv.FormatFloat(item.SalesmanPer, 'f', 2, 64)
|
||
strSalesmanPer += strNumber3
|
||
|
||
if j < len(list[i].Salesman)-1 {
|
||
salesMan += "\n"
|
||
strSalesProfitPer += "\n"
|
||
strStaffProfitPer += "\n"
|
||
strSalesmanPer += "\n"
|
||
}
|
||
}
|
||
|
||
// 组合支付相关信息
|
||
var cashierData TotalCashierData
|
||
var cashiers []ErpOrderCashier
|
||
err := json.Unmarshal([]byte(list[i].CashierList), &cashiers)
|
||
if err != nil {
|
||
logger.Error("unmarshal err:", logger.Field("err", err))
|
||
}
|
||
for _, item := range cashiers {
|
||
switch item.CashierId {
|
||
case 1:
|
||
cashierData.ScanAmount = item.Amount
|
||
case 2:
|
||
cashierData.CashAmount = item.Amount
|
||
case 3:
|
||
cashierData.PosAmount = item.Amount
|
||
case 4:
|
||
cashierData.StoreVmAmount = item.Amount
|
||
default:
|
||
cashierData.OtherAmount += item.Amount
|
||
}
|
||
}
|
||
|
||
// 单个订单的汇总数据只记录一次
|
||
var temp RetailDetailTotalData
|
||
if !commodityIdMap[list[i].Commodities[rowId].ErpCommodityId] {
|
||
commodityIdMap[list[i].Commodities[rowId].ErpCommodityId] = true
|
||
temp.TotalRetailPrice = list[i].TotalRetailPrice
|
||
temp.TotalDiscount = list[i].TotalDiscount
|
||
temp.TotalAmount = list[i].TotalAmount
|
||
temp.TotalSalesProfit = list[i].TotalSalesProfit
|
||
temp.TotalStaffProfit = list[i].TotalStaffProfit
|
||
temp.StorePer = list[i].StorePer
|
||
}
|
||
|
||
row = []interface{}{
|
||
list[i].BillSn,
|
||
saleType,
|
||
list[i].Uid,
|
||
list[i].Tel,
|
||
list[i].AuditTime,
|
||
list[i].StoreName,
|
||
salesMan, //销售员
|
||
list[i].Commodities[rowId].ErpCategoryName,
|
||
list[i].Commodities[rowId].ErpCommodityName,
|
||
list[i].Commodities[rowId].ErpSupplierName, //供应商
|
||
isIMEIType,
|
||
list[i].Commodities[rowId].IMEI,
|
||
strPresentType,
|
||
list[i].Commodities[rowId].Count,
|
||
list[i].Commodities[rowId].RetailPrice,
|
||
list[i].Commodities[rowId].SalePrice,
|
||
list[i].Commodities[rowId].SaleDiscount,
|
||
list[i].Commodities[rowId].MemberDiscount,
|
||
nAmount,
|
||
list[i].Commodities[rowId].WholesalePrice,
|
||
list[i].Commodities[rowId].WholesalePrice + list[i].Commodities[rowId].StaffCostPrice,
|
||
list[i].Commodities[rowId].SalesProfit,
|
||
list[i].Commodities[rowId].StaffProfit,
|
||
temp.TotalRetailPrice,
|
||
temp.TotalDiscount,
|
||
temp.TotalAmount,
|
||
cashierData.ScanAmount, // 扫码付
|
||
cashierData.CashAmount, // 现金收款
|
||
cashierData.PosAmount, // pos机收款
|
||
cashierData.StoreVmAmount, // 商场积分抵扣
|
||
cashierData.OtherAmount, // 其他付款方式
|
||
temp.TotalSalesProfit,
|
||
temp.TotalStaffProfit,
|
||
strSalesProfitPer, // 销售毛利提成
|
||
strStaffProfitPer, // 员工毛利提成
|
||
strSalesmanPer, // 销售员提成
|
||
temp.StorePer,
|
||
list[i].Commodities[rowId].Remark,
|
||
}
|
||
|
||
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++
|
||
}
|
||
|
||
//合并单元格
|
||
nRow := len(list[i].Commodities)
|
||
if nRow > 1 {
|
||
for j := 'A'; j <= 'G'; j++ {
|
||
colName := string(j)
|
||
str1 := fmt.Sprintf("%s%d", colName, nExcelStartRow-nRow+2)
|
||
str2 := fmt.Sprintf("%s%d", colName, nExcelStartRow+1)
|
||
_ = file.MergeCell(fSheet, str1, str2)
|
||
}
|
||
|
||
for j := 'X'; j <= 'Z'; j++ {
|
||
colName := string(j)
|
||
str1 := fmt.Sprintf("%s%d", colName, nExcelStartRow-nRow+2)
|
||
str2 := fmt.Sprintf("%s%d", colName, nExcelStartRow+1)
|
||
_ = file.MergeCell(fSheet, str1, str2)
|
||
}
|
||
|
||
for j := 'A'; j <= 'L'; j++ {
|
||
colName := string(j)
|
||
str1 := fmt.Sprintf("A%s%d", colName, nExcelStartRow-nRow+2)
|
||
str2 := fmt.Sprintf("A%s%d", colName, nExcelStartRow+1)
|
||
_ = file.MergeCell(fSheet, str1, str2)
|
||
}
|
||
}
|
||
}
|
||
|
||
totalData := "订单数:" + strconv.FormatInt(int64(sumData.Count), 10)
|
||
end := []interface{}{totalData, "", "", "", "", "", "", "", "", "", "", "", "",
|
||
sumData.Count,
|
||
sumData.RetailPrice,
|
||
sumData.SalePrice,
|
||
sumData.SaleDiscount,
|
||
sumData.MemberDiscount,
|
||
sumData.Amount,
|
||
sumData.WholesalePrice,
|
||
sumData.StaffPrice,
|
||
sumData.SalesProfit,
|
||
sumData.StaffProfit,
|
||
sumData.TotalRetailPrice,
|
||
sumData.TotalDiscount,
|
||
sumData.TotalAmount,
|
||
sumData.ScanAmount, // 扫码付
|
||
sumData.CashAmount, // 现金收款
|
||
sumData.PosAmount, // pos机收款
|
||
sumData.StoreVmAmount, // 商场积分抵扣
|
||
sumData.OtherAmount, // 其他付款方式
|
||
sumData.TotalSalesProfit,
|
||
sumData.TotalStaffProfit,
|
||
sumData.TotalSalesProfitPer, // 销售毛利提成
|
||
sumData.TotalStaffProfitPer, // 员工毛利提成
|
||
sumData.SalesmanPer, // 销售员提成
|
||
sumData.StorePer,
|
||
""}
|
||
|
||
for i, _ := range end {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2)
|
||
err := file.SetCellValue(fSheet, cell, end[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
// 设置所有单元格的样式: 居中、加边框
|
||
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}]}`)
|
||
|
||
endRow := fmt.Sprintf("AL%d", nExcelStartRow+2)
|
||
// 应用样式到整个表格
|
||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||
|
||
//需要自动换行的列
|
||
endRow1 := fmt.Sprintf("G%d", nExcelStartRow+2)
|
||
endRow2 := fmt.Sprintf("AH%d", nExcelStartRow+2)
|
||
endRow3 := fmt.Sprintf("AI%d", nExcelStartRow+2)
|
||
endRow4 := fmt.Sprintf("AJ%d", nExcelStartRow+2)
|
||
_ = file.SetCellStyle("Sheet1", "A1", "AL1", style1)
|
||
_ = file.SetCellStyle("Sheet1", "G2", endRow1, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AH2", endRow2, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AI2", endRow3, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AJ2", endRow4, 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
|
||
}
|
||
|
||
// 导出零售明细报表excel-不合并
|
||
func retailDetailExport(list []ErpOrder, sumData RetailDetailTotalData) (string, error) {
|
||
file := excelize.NewFile()
|
||
fSheet := "Sheet1"
|
||
|
||
url := ExportUrl
|
||
fileName := time.Now().Format(TimeFormat) + "零售明细" + ".xlsx"
|
||
fmt.Println("url fileName:", url+fileName)
|
||
|
||
title := []interface{}{"订单编号", "订单类型", "用户ID", "客户手机号", "审核时间", "店铺", "销售员", "商品分类", "商品名称",
|
||
"供应商", "是否串码", "商品串码", "是否赠送", "销售数量", "指导零售价", "零售价", "零售优惠", "会员优惠", "实际零售价/退货价",
|
||
"采购单价", "员工成本价", "销售毛利", "员工毛利", "订单总指导零售价", "订单总优惠", "订单实收", "【扫码付", "现金收款", "pos机收款",
|
||
"商场积分抵扣", "其他付款方式】", "订单总销售毛利", "订单总员工毛利", "销售毛利提成", "员工毛利提成", "销售员提成", "门店提成", "备注"}
|
||
for i, _ := range title {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||
err := file.SetCellValue(fSheet, cell, title[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
|
||
var row []interface{}
|
||
nAmount := 0.0
|
||
nExcelStartRow := 0
|
||
for i := 0; i < len(list); i++ {
|
||
var saleType string
|
||
if list[i].RetailType == RetailTypeSale {
|
||
saleType = "零售销售"
|
||
} else if list[i].RetailType == RetailTypeRejected {
|
||
saleType = "零售退货"
|
||
} else {
|
||
logger.Error("订单类型异常")
|
||
return "", errors.New("RetailMarginDataExport, 订单类型异常:" + list[i].RetailType)
|
||
}
|
||
|
||
commodityIdMap := make(map[uint32]bool)
|
||
// 先判断商品数量,确定要写几行数据
|
||
for rowId := 0; rowId < len(list[i].Commodities); rowId++ {
|
||
if list[i].RetailType == RetailTypeSale {
|
||
nAmount = list[i].Commodities[rowId].Amount
|
||
} else if list[i].RetailType == RetailTypeRejected {
|
||
nAmount = list[i].Commodities[rowId].RejectedAmount
|
||
list[i].CashierList = "" // 目前零售退货订单暂时不展示各个方式的付款金额
|
||
}
|
||
|
||
isIMEIType := "是"
|
||
if list[i].Commodities[rowId].IMEIType == 1 {
|
||
isIMEIType = "否"
|
||
}
|
||
|
||
strPresentType := "非赠送"
|
||
if list[i].Commodities[rowId].PresentType == 2 {
|
||
strPresentType = "赠送"
|
||
}
|
||
|
||
// 组合支付相关信息
|
||
var cashierData TotalCashierData
|
||
var cashiers []ErpOrderCashier
|
||
err := json.Unmarshal([]byte(list[i].CashierList), &cashiers)
|
||
if err != nil {
|
||
logger.Error("unmarshal err:", logger.Field("err", err))
|
||
}
|
||
for _, item := range cashiers {
|
||
switch item.CashierId {
|
||
case 1:
|
||
cashierData.ScanAmount = item.Amount
|
||
case 2:
|
||
cashierData.CashAmount = item.Amount
|
||
case 3:
|
||
cashierData.PosAmount = item.Amount
|
||
case 4:
|
||
cashierData.StoreVmAmount = item.Amount
|
||
default:
|
||
cashierData.OtherAmount += item.Amount
|
||
}
|
||
}
|
||
|
||
// 单个订单的汇总数据只记录一次
|
||
if !commodityIdMap[list[i].Commodities[rowId].ErpCommodityId] {
|
||
commodityIdMap[list[i].Commodities[rowId].ErpCommodityId] = true
|
||
salesMan := ""
|
||
nSalesProfitPer := 0.0
|
||
nStaffProfitPer := 0.0
|
||
nSalesmanPer := 0.0
|
||
if len(list[i].Salesman) > 0 {
|
||
salesMan = list[i].Salesman[0].Name
|
||
nSalesProfitPer = math.Round(list[i].Salesman[0].SalesProfitPer*100) / 100
|
||
nStaffProfitPer = math.Round(list[i].Salesman[0].StaffProfitPer*100) / 100
|
||
nSalesmanPer = math.Round(list[i].Salesman[0].SalesmanPer*100) / 100
|
||
}
|
||
row = []interface{}{
|
||
list[i].BillSn,
|
||
saleType,
|
||
list[i].Uid,
|
||
list[i].Tel,
|
||
list[i].AuditTime,
|
||
list[i].StoreName,
|
||
salesMan, //销售员
|
||
list[i].Commodities[rowId].ErpCategoryName,
|
||
list[i].Commodities[rowId].ErpCommodityName,
|
||
list[i].Commodities[rowId].ErpSupplierName, //供应商
|
||
isIMEIType,
|
||
list[i].Commodities[rowId].IMEI,
|
||
strPresentType,
|
||
list[i].Commodities[rowId].Count,
|
||
list[i].Commodities[rowId].RetailPrice,
|
||
list[i].Commodities[rowId].SalePrice,
|
||
list[i].Commodities[rowId].SaleDiscount,
|
||
list[i].Commodities[rowId].MemberDiscount,
|
||
nAmount,
|
||
list[i].Commodities[rowId].WholesalePrice,
|
||
list[i].Commodities[rowId].WholesalePrice + list[i].Commodities[rowId].StaffCostPrice,
|
||
list[i].Commodities[rowId].SalesProfit,
|
||
list[i].Commodities[rowId].StaffProfit,
|
||
list[i].TotalRetailPrice,
|
||
list[i].TotalDiscount,
|
||
list[i].TotalAmount,
|
||
cashierData.ScanAmount, // 扫码付
|
||
cashierData.CashAmount, // 现金收款
|
||
cashierData.PosAmount, // pos机收款
|
||
cashierData.StoreVmAmount, // 商场积分抵扣
|
||
cashierData.OtherAmount, // 其他付款方式
|
||
list[i].TotalSalesProfit,
|
||
list[i].TotalStaffProfit,
|
||
nSalesProfitPer, // 销售毛利提成
|
||
nStaffProfitPer, // 员工毛利提成
|
||
nSalesmanPer, // 销售员提成
|
||
list[i].StorePer,
|
||
list[i].Commodities[rowId].Remark,
|
||
}
|
||
} else {
|
||
if len(list[i].Salesman) == 2 && rowId == 1 {
|
||
row = []interface{}{
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
list[i].Salesman[1].Name, //销售员
|
||
list[i].Commodities[rowId].ErpCategoryName,
|
||
list[i].Commodities[rowId].ErpCommodityName,
|
||
list[i].Commodities[rowId].ErpSupplierName, //供应商
|
||
isIMEIType,
|
||
list[i].Commodities[rowId].IMEI,
|
||
strPresentType,
|
||
list[i].Commodities[rowId].Count,
|
||
list[i].Commodities[rowId].RetailPrice,
|
||
list[i].Commodities[rowId].SalePrice,
|
||
list[i].Commodities[rowId].SaleDiscount,
|
||
list[i].Commodities[rowId].MemberDiscount,
|
||
nAmount,
|
||
list[i].Commodities[rowId].WholesalePrice,
|
||
list[i].Commodities[rowId].WholesalePrice + list[i].Commodities[rowId].StaffCostPrice,
|
||
list[i].Commodities[rowId].SalesProfit,
|
||
list[i].Commodities[rowId].StaffProfit,
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
math.Round(list[i].Salesman[1].SalesProfitPer*100) / 100, // 销售毛利提成
|
||
math.Round(list[i].Salesman[1].StaffProfitPer*100) / 100, // 员工毛利提成
|
||
math.Round(list[i].Salesman[1].SalesmanPer*100) / 100, // 销售员提成
|
||
"",
|
||
"",
|
||
}
|
||
} else {
|
||
row = []interface{}{
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"", //销售员
|
||
list[i].Commodities[rowId].ErpCategoryName,
|
||
list[i].Commodities[rowId].ErpCommodityName,
|
||
list[i].Commodities[rowId].ErpSupplierName, //供应商
|
||
isIMEIType,
|
||
list[i].Commodities[rowId].IMEI,
|
||
strPresentType,
|
||
list[i].Commodities[rowId].Count,
|
||
list[i].Commodities[rowId].RetailPrice,
|
||
list[i].Commodities[rowId].SalePrice,
|
||
list[i].Commodities[rowId].SaleDiscount,
|
||
list[i].Commodities[rowId].MemberDiscount,
|
||
nAmount,
|
||
list[i].Commodities[rowId].WholesalePrice,
|
||
list[i].Commodities[rowId].WholesalePrice + list[i].Commodities[rowId].StaffCostPrice,
|
||
list[i].Commodities[rowId].SalesProfit,
|
||
list[i].Commodities[rowId].StaffProfit,
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"", // 销售毛利提成
|
||
"", // 员工毛利提成
|
||
"", // 销售员提成
|
||
"",
|
||
"",
|
||
}
|
||
}
|
||
}
|
||
|
||
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++
|
||
|
||
if len(list[i].Commodities) == 1 && len(list[i].Salesman) == 2 {
|
||
row = []interface{}{
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
list[i].Salesman[1].Name, //销售员
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
math.Round(list[i].Salesman[1].SalesProfitPer*100) / 100, // 销售毛利提成
|
||
math.Round(list[i].Salesman[1].StaffProfitPer*100) / 100, // 员工毛利提成
|
||
math.Round(list[i].Salesman[1].SalesmanPer*100) / 100, // 销售员提成
|
||
"",
|
||
"",
|
||
}
|
||
|
||
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++
|
||
}
|
||
}
|
||
}
|
||
|
||
totalData := "订单数:" + strconv.FormatInt(int64(len(list)), 10)
|
||
end := []interface{}{totalData, "", "", "", "", "", "", "", "", "", "", "", "",
|
||
sumData.Count,
|
||
sumData.RetailPrice,
|
||
sumData.SalePrice,
|
||
sumData.SaleDiscount,
|
||
sumData.MemberDiscount,
|
||
sumData.Amount,
|
||
sumData.WholesalePrice,
|
||
sumData.StaffPrice,
|
||
sumData.SalesProfit,
|
||
sumData.StaffProfit,
|
||
sumData.TotalRetailPrice,
|
||
sumData.TotalDiscount,
|
||
sumData.TotalAmount,
|
||
sumData.ScanAmount, // 扫码付
|
||
sumData.CashAmount, // 现金收款
|
||
sumData.PosAmount, // pos机收款
|
||
sumData.StoreVmAmount, // 商场积分抵扣
|
||
sumData.OtherAmount, // 其他付款方式
|
||
sumData.TotalSalesProfit,
|
||
sumData.TotalStaffProfit,
|
||
sumData.TotalSalesProfitPer, // 销售毛利提成
|
||
sumData.TotalStaffProfitPer, // 员工毛利提成
|
||
sumData.SalesmanPer, // 销售员提成
|
||
sumData.StorePer,
|
||
""}
|
||
|
||
for i, _ := range end {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2)
|
||
err := file.SetCellValue(fSheet, cell, end[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
// 设置所有单元格的样式: 居中、加边框
|
||
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}}`)
|
||
|
||
// 设置单元格的样式: 居中、加边框、自动换行
|
||
style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}}`)
|
||
|
||
endRow := fmt.Sprintf("AL%d", nExcelStartRow+2)
|
||
// 应用样式到整个表格
|
||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||
|
||
//需要自动换行的列
|
||
endRow1 := fmt.Sprintf("G%d", nExcelStartRow+2)
|
||
endRow2 := fmt.Sprintf("AH%d", nExcelStartRow+2)
|
||
endRow3 := fmt.Sprintf("AI%d", nExcelStartRow+2)
|
||
endRow4 := fmt.Sprintf("AJ%d", nExcelStartRow+2)
|
||
_ = file.SetCellStyle("Sheet1", "A1", "AL1", style1)
|
||
_ = file.SetCellStyle("Sheet1", "G2", endRow1, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AH2", endRow2, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AI2", endRow3, style1)
|
||
_ = file.SetCellStyle("Sheet1", "AJ2", endRow4, 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
|
||
}
|
||
|
||
// RetailDetailByJoin 联表查询扫描参数
|
||
type RetailDetailByJoin struct {
|
||
ErpOrderCommodity
|
||
ErpOrder
|
||
}
|
||
|
||
// 联表查询
|
||
func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq, c *gin.Context) (*ErpOrderRetailDetailResp, error) {
|
||
showConfig, err := GetErpOrderShowConfig()
|
||
if err != nil {
|
||
logger.Errorf("List err:", err)
|
||
showConfig.ShowAll = "ON"
|
||
}
|
||
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
resp := &ErpOrderRetailDetailResp{
|
||
PageIndex: page + 1,
|
||
PageSize: req.PageSize,
|
||
}
|
||
|
||
qs := orm.Eloquent.Debug().Table("erp_order_commodity").
|
||
Select("erp_order_commodity.*, erp_order.*").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id")
|
||
|
||
es := orm.Eloquent.Debug().Table("erp_order_commodity").
|
||
Select("erp_order_commodity.*, erp_order.*").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id")
|
||
|
||
orderSumQs := orm.Eloquent.Table("erp_order_commodity AS oc").Select("oc.*, eo.*").
|
||
Joins("JOIN erp_order AS eo ON oc.erp_order_id = eo.id")
|
||
|
||
rejectedOrderSumQs := orm.Eloquent.Table("erp_order_commodity AS oc").Select("oc.*, eo.*").
|
||
Joins("JOIN erp_order AS eo ON oc.erp_order_id = eo.id")
|
||
|
||
if req.ErpCategoryId != 0 { // 商品分类
|
||
qs = qs.Where("erp_order_commodity.erp_category_id=?", req.ErpCategoryId)
|
||
es = es.Where("erp_order_commodity.erp_category_id=?", req.ErpCategoryId)
|
||
orderSumQs = orderSumQs.Where("oc.erp_category_id=?", req.ErpCategoryId)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("oc.erp_category_id=?", req.ErpCategoryId)
|
||
}
|
||
if req.ErpCommodityName != "" { // 商品名称
|
||
qs = qs.Where("erp_order_commodity.erp_commodity_name = ?", req.ErpCommodityName)
|
||
es = es.Where("erp_order_commodity.erp_commodity_name = ?", req.ErpCommodityName)
|
||
orderSumQs = orderSumQs.Where("oc.erp_commodity_name = ?", req.ErpCommodityName)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("oc.erp_commodity_name = ?", req.ErpCommodityName)
|
||
}
|
||
if req.RetailType != "" { // 销售类型
|
||
qs = qs.Where("erp_order.retail_type=?", req.RetailType)
|
||
es = es.Where("erp_order.retail_type=?", req.RetailType)
|
||
orderSumQs = orderSumQs.Where("eo.retail_type=?", req.RetailType)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.retail_type=?", req.RetailType)
|
||
}
|
||
if req.Uid != 0 { // 用户ID
|
||
qs = qs.Where("erp_order.uid=?", req.Uid)
|
||
es = es.Where("erp_order.uid=?", req.Uid)
|
||
orderSumQs = orderSumQs.Where("eo.uid=?", req.Uid)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.uid=?", req.Uid)
|
||
}
|
||
if req.Tel != "" { // 用户手机号
|
||
qs = qs.Where("erp_order.tel=?", req.Tel)
|
||
es = es.Where("erp_order.tel=?", req.Tel)
|
||
orderSumQs = orderSumQs.Where("eo.tel=?", req.Tel)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.tel=?", req.Tel)
|
||
}
|
||
if req.StoreId != 0 { // 门店ID
|
||
qs = qs.Where("erp_order.store_id=?", req.StoreId)
|
||
es = es.Where("erp_order.store_id=?", req.StoreId)
|
||
orderSumQs = orderSumQs.Where("eo.store_id=?", req.StoreId)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.store_id=?", req.StoreId)
|
||
}
|
||
if req.IMEI != "" { // 串码
|
||
qs = qs.Where("erp_order_commodity.imei=?", req.IMEI)
|
||
es = es.Where("erp_order_commodity.imei=?", req.IMEI)
|
||
orderSumQs = orderSumQs.Where("oc.imei=?", req.IMEI)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("oc.imei=?", req.IMEI)
|
||
}
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
if len(storeList) == 1 {
|
||
qs = qs.Where("erp_order.store_id = ?", storeList[0])
|
||
es = es.Where("erp_order.store_id = ?", storeList[0])
|
||
orderSumQs = orderSumQs.Where("eo.store_id = ?", storeList[0])
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.store_id = ?", storeList[0])
|
||
} else {
|
||
qs = qs.Where("erp_order.store_id IN (?)", storeList)
|
||
es = es.Where("erp_order.store_id IN (?)", storeList)
|
||
orderSumQs = orderSumQs.Where("eo.store_id IN (?)", storeList)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.store_id IN (?)", storeList)
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
if req.Salesman != 0 { // 销售员
|
||
qs = qs.Where("JSON_CONTAINS(erp_order.salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, req.Salesman))
|
||
es = es.Where("JSON_CONTAINS(erp_order.salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, req.Salesman))
|
||
orderSumQs = orderSumQs.Where("JSON_CONTAINS(eo.salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, req.Salesman))
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("JSON_CONTAINS(eo.salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, req.Salesman))
|
||
}
|
||
if req.StartTime != "" { // 审核开始时间
|
||
parse, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
qs = qs.Where("erp_order.audit_time > ?", parse)
|
||
es = es.Where("erp_order.audit_time > ?", parse)
|
||
orderSumQs = orderSumQs.Where("eo.audit_time > ?", parse)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.audit_time > ?", parse)
|
||
}
|
||
if req.EndTime != "" { // 审核结束时间
|
||
parse, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
//parse = parse.AddDate(0, 0, 1)
|
||
qs = qs.Where("erp_order.audit_time < ?", parse)
|
||
es = es.Where("erp_order.audit_time < ?", parse)
|
||
orderSumQs = orderSumQs.Where("eo.audit_time < ?", parse)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.audit_time < ?", parse)
|
||
}
|
||
if showConfig.ShowAll == "OFF" {
|
||
qs = qs.Where("erp_order.is_print = ? or erp_order.retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
es = es.Where("erp_order.is_print = ? or erp_order.retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
orderSumQs = orderSumQs.Where("eo.is_print = ? or eo.retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
rejectedOrderSumQs = rejectedOrderSumQs.Where("eo.is_print = ? or eo.retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
}
|
||
qs.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
es.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
orderSumQs.Where("eo.pay_status = ? or (eo.retail_type = ? and eo.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
rejectedOrderSumQs.Where("eo.pay_status = ? or (eo.retail_type = ? and eo.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
|
||
// 销售订单的汇总数据
|
||
var sumData RetailDetailTotalData
|
||
sumData, err = getRetailDetailTotalDataJoinErpOrderSale(orderSumQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单的汇总数据
|
||
var rejectedSumData RetailDetailTotalData
|
||
rejectedSumData, err = getRetailDetailTotalDataJoinErpOrderRejected(rejectedOrderSumQs, RetailTypeRejected)
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 计算销售订单和退货订单汇总后的销售数据
|
||
sumData = subtractRetailData(sumData, rejectedSumData)
|
||
|
||
// 销售订单提成汇总
|
||
var totalPerData TotalPerData
|
||
totalPerQs := qs
|
||
totalPerData, err = getTotalPerData(totalPerQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单提成汇总
|
||
var rejectedTotalPerData TotalPerData
|
||
rejectedTotalPerQs := qs
|
||
rejectedTotalPerData, err = getTotalPerData(rejectedTotalPerQs, RetailTypeRejected)
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 计算销售订单和退货订单汇总后的提成数据
|
||
totalPerData = subtractTotalPerData(totalPerData, rejectedTotalPerData)
|
||
|
||
// 销售订单支持汇总
|
||
var cashier TotalCashierData
|
||
cashierQs := qs
|
||
cashier, err = getTotalCashierData(cashierQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单支付汇总:目前零售退货订单暂时不展示各个方式的付款金额
|
||
var rejectedCashier TotalCashierData
|
||
//rejectedCashierQs := qs
|
||
//rejectedCashier, err = getTotalCashierData(rejectedCashierQs, RetailTypeRejected)
|
||
//if err != nil {
|
||
// logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
|
||
// return resp, err
|
||
//}
|
||
// 计算销售订单和退货订单汇总后的支付数据
|
||
cashier = subtractCashierData(cashier, rejectedCashier)
|
||
|
||
// 处理汇总数据,四舍五入保留2位小数
|
||
roundValues(&sumData, &totalPerData, &cashier)
|
||
|
||
sumData.TotalSalesProfit = 0 // 订单总销售毛利
|
||
sumData.TotalStaffProfit = 0 // 订单总员工毛利
|
||
sumData.TotalRetailPrice = 0 // 订单总指导零售价
|
||
sumData.TotalDiscount = 0 // 订单总优惠
|
||
sumData.TotalAmount = 0 // 订单实收金额
|
||
sumData.StorePer = 0 // 门店提成
|
||
|
||
sumData.ScanAmount = cashier.ScanAmount
|
||
sumData.CashAmount = cashier.CashAmount
|
||
sumData.PosAmount = cashier.PosAmount
|
||
sumData.StoreVmAmount = cashier.StoreVmAmount
|
||
sumData.OtherAmount = cashier.OtherAmount
|
||
|
||
var result []RetailDetailByJoin
|
||
|
||
if req.IsExport == 1 { //导出excel
|
||
err = qs.Order("erp_order.audit_time DESC").Find(&result).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var count int64
|
||
err = es.Count(&count).Error
|
||
if err != nil {
|
||
logger.Errorf("QueryRetailMargin count err:", err.Error())
|
||
return nil, err
|
||
}
|
||
|
||
orders := packData(result)
|
||
fileUrl, err := retailDetailExport(orders, sumData)
|
||
if err != nil {
|
||
logger.Error("retailDetailExport err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
resp.ExportUrl = fileUrl
|
||
} else {
|
||
//err = qs.Order("erp_order.audit_time DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&result).Error
|
||
err = qs.Order("erp_order.audit_time DESC").Find(&result).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var count int64
|
||
err = es.Count(&count).Error
|
||
if err != nil {
|
||
logger.Errorf("QueryRetailMargin count err:", err.Error())
|
||
return nil, err
|
||
}
|
||
|
||
orders := packData(result)
|
||
erpOrderListSetCashier(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
pagedOrders := paginate(orders, page, req.PageSize)
|
||
|
||
resp.List = pagedOrders
|
||
|
||
//跟之前保持一致
|
||
resp.Total = len(orders)
|
||
resp.PageIndex = page + 1
|
||
resp.PageSize = req.PageSize
|
||
resp.SumData = sumData
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 分页函数
|
||
func paginate(orders []ErpOrder, page int, pageSize int) []ErpOrder {
|
||
start := page * pageSize
|
||
end := start + pageSize
|
||
|
||
if start >= len(orders) {
|
||
return []ErpOrder{}
|
||
}
|
||
|
||
if end > len(orders) {
|
||
end = len(orders)
|
||
}
|
||
|
||
return orders[start:end]
|
||
}
|
||
|
||
// 组合数据
|
||
func packData(result []RetailDetailByJoin) []ErpOrder {
|
||
var orders []ErpOrder
|
||
orderIdMap := make(map[uint32]ErpOrder)
|
||
for _, item := range result {
|
||
var order ErpOrder
|
||
var commodity ErpOrderCommodity
|
||
|
||
// 判断是否有重复数据
|
||
if len(orderIdMap) != 0 && orderIdMap[item.ErpOrderId].BillSn != "" {
|
||
order = orderIdMap[item.ErpOrderId]
|
||
} else {
|
||
// 订单数据
|
||
order.CreatedAt = item.ErpOrderCommodity.CreatedAt
|
||
order.ID = item.ErpOrderId
|
||
order.BillSn = item.BillSn
|
||
order.RetailType = item.RetailType
|
||
order.Uid = item.Uid
|
||
order.Tel = item.Tel
|
||
order.StoreId = item.StoreId
|
||
order.StoreName = item.StoreName
|
||
order.MakerId = item.MakerId
|
||
order.MakerName = item.MakerName
|
||
order.MakerTime = item.MakerTime
|
||
order.AuditorId = item.AuditorId
|
||
order.AuditorName = item.AuditorName
|
||
order.AuditTime = item.AuditTime
|
||
order.CashierList = item.CashierList
|
||
order.SalesmanList = item.SalesmanList
|
||
order.MemberType = item.MemberType
|
||
order.State = item.State
|
||
order.TotalRetailPrice = item.TotalRetailPrice
|
||
order.TotalAmount = item.TotalAmount
|
||
order.TotalCount = item.TotalCount
|
||
order.TotalSalesProfit = item.TotalSalesProfit
|
||
order.TotalStaffProfit = item.TotalStaffProfit
|
||
order.VmCount = item.VmCount
|
||
order.SaleOrderId = item.SaleOrderId
|
||
order.PayStatus = item.PayStatus
|
||
order.IsPrint = item.IsPrint
|
||
order.PrintCount = item.PrintCount
|
||
order.InvoiceCode = item.InvoiceCode
|
||
order.InvoiceNumber = item.InvoiceNumber
|
||
order.RejectedTotalAmount = item.RejectedTotalAmount
|
||
order.RejectedTotalCount = item.RejectedTotalCount
|
||
|
||
if order.RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
|
||
order.TotalRetailPrice = -math.Abs(order.TotalRetailPrice)
|
||
order.TotalAmount = -math.Abs(order.TotalAmount)
|
||
order.TotalCount = -int32(math.Abs(float64(order.TotalCount)))
|
||
order.TotalSalesProfit = -order.TotalSalesProfit
|
||
order.TotalStaffProfit = -order.TotalStaffProfit
|
||
order.TotalDiscount = -math.Abs(order.TotalDiscount)
|
||
order.VmCount = -uint32(math.Abs(float64(order.VmCount)))
|
||
order.StorePer = -math.Abs(order.StorePer)
|
||
}
|
||
}
|
||
|
||
if order.RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值
|
||
item.Count = -item.Count
|
||
item.RetailPrice = -item.RetailPrice
|
||
item.SalePrice = -item.SalePrice
|
||
item.Amount = -item.Amount
|
||
item.SaleDiscount = -item.SaleDiscount
|
||
item.MemberDiscount = -item.MemberDiscount
|
||
item.VmDiscount = -item.VmDiscount
|
||
item.ReceivedAmount = -item.ReceivedAmount
|
||
item.RejectedAmount = -item.RejectedAmount
|
||
item.SalesProfit = -item.SalesProfit
|
||
item.StaffProfit = -item.StaffProfit
|
||
item.StaffCostPrice = -item.StaffCostPrice
|
||
item.WholesalePrice = -item.WholesalePrice
|
||
}
|
||
// 订单商品数据
|
||
commodity.CreatedAt = item.ErpOrderCommodity.CreatedAt
|
||
commodity.ErpOrderId = item.ErpOrderId
|
||
commodity.ErpCategoryId = item.ErpCategoryId
|
||
commodity.ErpCategoryName = item.ErpCategoryName
|
||
commodity.ErpCommodityId = item.ErpCommodityId
|
||
commodity.ErpCommodityName = item.ErpCommodityName
|
||
commodity.IMEIType = item.IMEIType
|
||
commodity.IMEI = item.IMEI
|
||
commodity.PresentType = item.PresentType
|
||
commodity.RetailPrice = item.RetailPrice
|
||
commodity.SalePrice = item.SalePrice
|
||
commodity.Count = item.Count
|
||
commodity.SaleDiscount = item.SaleDiscount
|
||
commodity.MemberDiscount = item.MemberDiscount
|
||
commodity.VmDiscount = item.VmDiscount
|
||
commodity.Amount = item.Amount
|
||
commodity.ReceivedAmount = item.ReceivedAmount
|
||
commodity.Remark = item.Remark
|
||
commodity.RejectedPrice = item.RejectedPrice
|
||
commodity.RejectedCount = item.RejectedCount
|
||
commodity.RejectedAmount = item.RejectedAmount
|
||
commodity.RejectedOrderCommodityId = item.RejectedOrderCommodityId
|
||
commodity.StaffCostPrice = item.StaffCostPrice
|
||
commodity.WholesalePrice = item.WholesalePrice
|
||
commodity.ErpSupplierId = item.ErpSupplierId
|
||
commodity.ErpSupplierName = item.ErpSupplierName
|
||
commodity.SalesProfit = item.SalesProfit
|
||
commodity.StaffProfit = item.StaffProfit
|
||
|
||
order.Commodities = append(order.Commodities, commodity)
|
||
orderIdMap[item.ErpOrderId] = order
|
||
}
|
||
|
||
for _, item := range orderIdMap {
|
||
orders = append(orders, item)
|
||
}
|
||
|
||
return orders
|
||
}
|
||
|
||
// 普通单表查询,然后补充收款数据和商品数据
|
||
func queryRetailDetailCommon(req *ErpOrderRetailDetailReq, c *gin.Context) (*ErpOrderRetailDetailResp, error) {
|
||
showConfig, err := GetErpOrderShowConfig()
|
||
if err != nil {
|
||
logger.Errorf("List err:", err)
|
||
showConfig.ShowAll = "ON"
|
||
}
|
||
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
resp := &ErpOrderRetailDetailResp{
|
||
PageIndex: page + 1,
|
||
PageSize: req.PageSize,
|
||
}
|
||
|
||
qs := orm.Eloquent.Table("erp_order")
|
||
totalPerQs := orm.Eloquent.Table("erp_order")
|
||
if showConfig.ShowAll == "OFF" {
|
||
qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
totalPerQs = totalPerQs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected)
|
||
}
|
||
if req.BillSn != "" { // 订单编号
|
||
qs = qs.Where("bill_sn=?", req.BillSn)
|
||
totalPerQs = totalPerQs.Where("bill_sn=?", req.BillSn)
|
||
} else {
|
||
if req.RetailType != "" { // 销售类型
|
||
qs = qs.Where("retail_type=?", req.RetailType)
|
||
totalPerQs = totalPerQs.Where("retail_type=?", req.RetailType)
|
||
}
|
||
if req.Uid != 0 { // 用户ID
|
||
qs = qs.Where("erp_order.uid=?", req.Uid)
|
||
totalPerQs = totalPerQs.Where("erp_order.uid=?", req.Uid)
|
||
}
|
||
if req.Tel != "" { // 用户手机号
|
||
qs = qs.Where("tel=?", req.Tel)
|
||
totalPerQs = totalPerQs.Where("tel=?", req.Tel)
|
||
}
|
||
if req.StoreId != 0 { // 门店ID
|
||
qs = qs.Where("store_id=?", req.StoreId)
|
||
totalPerQs = totalPerQs.Where("store_id=?", req.StoreId)
|
||
}
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 返回sysUser未过期的门店id列表
|
||
storeList := GetValidStoreIDs(sysUser.StoreData)
|
||
if len(storeList) > 0 {
|
||
if len(storeList) == 1 {
|
||
qs = qs.Where("store_id = ?", storeList[0])
|
||
totalPerQs = totalPerQs.Where("store_id = ?", storeList[0])
|
||
} else {
|
||
qs = qs.Where("store_id IN (?)", storeList)
|
||
totalPerQs = totalPerQs.Where("store_id IN (?)", storeList)
|
||
}
|
||
} else {
|
||
return nil, errors.New("用户未绑定门店")
|
||
}
|
||
}
|
||
if req.Salesman != 0 { // 销售员
|
||
qs = qs.Where("JSON_CONTAINS(salesman_list, ?)", fmt.Sprintf(`{"userId":%d}`, req.Salesman))
|
||
totalPerQs = totalPerQs.Where("erp_order_sales.uid = ?", req.Salesman)
|
||
}
|
||
if req.StartTime != "" { // 审核开始时间
|
||
parse, err := time.Parse(QueryTimeFormat, req.StartTime)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
qs = qs.Where("audit_time > ?", parse)
|
||
totalPerQs = totalPerQs.Where("audit_time > ?", parse)
|
||
}
|
||
if req.EndTime != "" { // 审核结束时间
|
||
parse, err := time.Parse(QueryTimeFormat, req.EndTime)
|
||
if err != nil {
|
||
logger.Errorf("err:", err)
|
||
}
|
||
//parse = parse.AddDate(0, 0, 1)
|
||
qs = qs.Where("audit_time < ?", parse)
|
||
totalPerQs = totalPerQs.Where("audit_time < ?", parse)
|
||
}
|
||
}
|
||
qs.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
totalPerQs.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)",
|
||
HavePaid, RetailTypeRejected, ErpOrderStateUnAudit)
|
||
es := qs
|
||
rejectedTotalPerQs := totalPerQs
|
||
|
||
// 销售订单的汇总数据
|
||
orderSumQs := qs
|
||
var sumData RetailDetailTotalData
|
||
sumData, err = getRetailDetailTotalDataSale(orderSumQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单的汇总数据
|
||
var rejectedSumData RetailDetailTotalData
|
||
rejectedOrderSumQs := qs
|
||
rejectedSumData, err = getRetailDetailTotalDataRejected(rejectedOrderSumQs, RetailTypeRejected)
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 计算销售订单和退货订单汇总后的销售数据
|
||
sumData = subtractRetailData(sumData, rejectedSumData)
|
||
|
||
// 销售订单提成汇总
|
||
var totalPerData TotalPerData
|
||
totalPerData, err = getTotalPerData(totalPerQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单提成汇总
|
||
var rejectedTotalPerData TotalPerData
|
||
rejectedTotalPerData, err = getTotalPerData(rejectedTotalPerQs, RetailTypeRejected)
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 计算销售订单和退货订单汇总后的提成数据
|
||
totalPerData = subtractTotalPerData(totalPerData, rejectedTotalPerData)
|
||
|
||
// 销售订单支付汇总
|
||
var cashier TotalCashierData
|
||
cashierQs := qs
|
||
cashier, err = getTotalCashierData(cashierQs, RetailTypeSale)
|
||
if err != nil {
|
||
logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
// 退货订单支付汇总:目前零售退货订单暂时不展示各个方式的付款金额
|
||
var rejectedCashier TotalCashierData
|
||
//rejectedCashierQs := qs
|
||
//rejectedCashier, err = getTotalCashierData(rejectedCashierQs, RetailTypeRejected)
|
||
//if err != nil {
|
||
// logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
|
||
// return resp, err
|
||
//}
|
||
// 计算销售订单和退货订单汇总后的支付数据
|
||
cashier = subtractCashierData(cashier, rejectedCashier)
|
||
|
||
// 处理汇总数据,四舍五入保留2位小数
|
||
roundValues(&sumData, &totalPerData, &cashier)
|
||
sumData.TotalSalesProfitPer = totalPerData.TotalSalesProfitPer
|
||
sumData.TotalStaffProfitPer = totalPerData.TotalStaffProfitPer
|
||
sumData.SalesmanPer = totalPerData.SalesmanPer
|
||
sumData.ScanAmount = cashier.ScanAmount
|
||
sumData.CashAmount = cashier.CashAmount
|
||
sumData.PosAmount = cashier.PosAmount
|
||
sumData.StoreVmAmount = cashier.StoreVmAmount
|
||
sumData.OtherAmount = cashier.OtherAmount
|
||
|
||
if req.IsExport == 1 { // 导出excel
|
||
var orders []ErpOrder
|
||
err = qs.Order("id DESC").Find(&orders).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
ErpOrderRetailDetailSetCommodity(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
|
||
fileUrl, err := retailDetailExport(orders, sumData)
|
||
if err != nil {
|
||
logger.Error("retailDetailExport err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
resp.ExportUrl = fileUrl
|
||
} else {
|
||
var count int64
|
||
err = es.Count(&count).Error
|
||
if err != nil {
|
||
logger.Error("count err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var orders []ErpOrder
|
||
err = qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error
|
||
if err != nil && err != RecordNotFound {
|
||
logger.Error("erp commodity list err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
// 添加付款、销售员、商品信息
|
||
ErpOrderRetailDetailSetCommodity(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
erpOrderListSetCashier(orders)
|
||
//erpOrderListSetSalesmanByRetailDetail(req.Salesman, orders)
|
||
|
||
resp.List = orders
|
||
|
||
//跟之前保持一致
|
||
resp.Total = int(count)
|
||
resp.PageIndex = page + 1
|
||
resp.PageSize = req.PageSize
|
||
resp.SumData = sumData
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 四舍五入保留2位小数
|
||
func roundValues(data *RetailDetailTotalData, totalPerData *TotalPerData, cashier *TotalCashierData) {
|
||
roundMap := map[*float64]*float64{
|
||
&data.StorePer: &data.StorePer,
|
||
&totalPerData.TotalSalesProfitPer: &totalPerData.TotalSalesProfitPer,
|
||
&totalPerData.TotalStaffProfitPer: &totalPerData.TotalStaffProfitPer,
|
||
&totalPerData.SalesmanPer: &totalPerData.SalesmanPer,
|
||
&cashier.ScanAmount: &cashier.ScanAmount,
|
||
&cashier.CashAmount: &cashier.CashAmount,
|
||
&cashier.PosAmount: &cashier.PosAmount,
|
||
&cashier.StoreVmAmount: &cashier.StoreVmAmount,
|
||
&cashier.OtherAmount: &cashier.OtherAmount,
|
||
}
|
||
|
||
for original, rounded := range roundMap {
|
||
*rounded = tools.RoundToTwoDecimalPlaces(*original)
|
||
}
|
||
}
|
||
|
||
// 查询零售订单的汇总数据
|
||
func getRetailDetailTotalDataSale(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) {
|
||
var sumData RetailDetailTotalData
|
||
|
||
err := qs.Debug().
|
||
Select("SUM(cs.count) as count, "+
|
||
"SUM(cs.retail_price) as retail_price, "+
|
||
"SUM(cs.sale_price) as sale_price, "+
|
||
"SUM(cs.sale_discount) as sale_discount, "+
|
||
"SUM(cs.member_discount) as member_discount, "+
|
||
"SUM(cs.amount) as Amount, "+
|
||
"SUM(cs.wholesale_price) as wholesale_price, "+
|
||
"(SUM(cs.wholesale_price) + SUM(cs.staff_cost_price)) as staff_price, "+
|
||
"(SUM(cs.amount) - SUM(cs.wholesale_price)) as sales_profit, "+
|
||
"(SUM(cs.amount) - SUM(cs.wholesale_price) - SUM(cs.staff_cost_price)) as staff_profit, "+
|
||
"SUM(erp_order.total_retail_price) as total_retail_price, "+
|
||
"(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, "+
|
||
"SUM(erp_order.total_amount) as total_amount, "+
|
||
"SUM(erp_order.total_sales_profit) as total_sales_profit, "+
|
||
"SUM(erp_order.total_staff_profit) as total_staff_profit, "+
|
||
"SUM(erp_order.store_per) as store_per").
|
||
Joins("JOIN (SELECT erp_order_id, "+
|
||
"SUM(count) as count, "+
|
||
"SUM(retail_price) as retail_price, "+
|
||
"SUM(sale_price) as sale_price, "+
|
||
"SUM(sale_discount) as sale_discount, "+
|
||
"SUM(member_discount) as member_discount, "+
|
||
"SUM(amount) as amount, "+
|
||
"SUM(wholesale_price) as wholesale_price, "+
|
||
"SUM(staff_cost_price) as staff_cost_price "+
|
||
"FROM erp_order_commodity "+
|
||
"GROUP BY erp_order_id) as cs ON cs.erp_order_id = erp_order.id").
|
||
Where("erp_order.retail_type = ?", retailType).
|
||
Scan(&sumData).Error
|
||
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return sumData, err
|
||
}
|
||
return sumData, nil
|
||
}
|
||
|
||
// 查询零售退货订单的汇总数据
|
||
func getRetailDetailTotalDataRejected(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) {
|
||
var sumData RetailDetailTotalData
|
||
|
||
err := qs.Debug().
|
||
Select("SUM(cs.count) as count, "+
|
||
"SUM(cs.retail_price) as retail_price, "+
|
||
"SUM(cs.sale_price) as sale_price, "+
|
||
"SUM(cs.sale_discount) as sale_discount, "+
|
||
"SUM(cs.member_discount) as member_discount, "+
|
||
"SUM(cs.amount) as Amount, "+
|
||
"SUM(cs.wholesale_price) as wholesale_price, "+
|
||
"(SUM(cs.wholesale_price) + SUM(cs.staff_cost_price)) as staff_price, "+
|
||
"(SUM(cs.amount) - SUM(cs.wholesale_price)) as sales_profit, "+
|
||
"(SUM(cs.amount) - SUM(cs.wholesale_price) - SUM(cs.staff_cost_price)) as staff_profit, "+
|
||
"SUM(erp_order.total_retail_price) as total_retail_price, "+
|
||
"(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, "+
|
||
"SUM(erp_order.total_amount) as total_amount, "+
|
||
"SUM(erp_order.total_sales_profit) as total_sales_profit, "+
|
||
"SUM(erp_order.total_staff_profit) as total_staff_profit, "+
|
||
"SUM(erp_order.store_per) as store_per").
|
||
Joins("JOIN (SELECT erp_order_id, "+
|
||
"SUM(count) as count, "+
|
||
"SUM(retail_price) as retail_price, "+
|
||
"SUM(sale_price) as sale_price, "+
|
||
"SUM(sale_discount) as sale_discount, "+
|
||
"SUM(member_discount) as member_discount, "+
|
||
"SUM(rejected_amount) as amount, "+
|
||
"SUM(wholesale_price) as wholesale_price, "+
|
||
"SUM(staff_cost_price) as staff_cost_price "+
|
||
"FROM erp_order_commodity "+
|
||
"GROUP BY erp_order_id) as cs ON cs.erp_order_id = erp_order.id").
|
||
Where("erp_order.retail_type = ?", retailType).
|
||
Scan(&sumData).Error
|
||
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return sumData, err
|
||
}
|
||
return sumData, nil
|
||
}
|
||
|
||
// 查询零售订单的汇总数据
|
||
func getRetailDetailTotalDataJoinErpOrderSale(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) {
|
||
var sumData RetailDetailTotalData
|
||
qs = qs.Where("eo.retail_type = ?", retailType) // 添加额外的条件
|
||
err := qs.Debug().Select("SUM(oc.count) as count, " +
|
||
"SUM(oc.retail_price) as retail_price, " +
|
||
"SUM(oc.sale_price) as sale_price, " +
|
||
"SUM(oc.sale_discount) as sale_discount, " +
|
||
"SUM(oc.member_discount) as member_discount, " +
|
||
"SUM(oc.amount) as Amount, " +
|
||
"SUM(oc.wholesale_price) as wholesale_price, " +
|
||
"(SUM(oc.wholesale_price) + SUM(oc.staff_cost_price)) as staff_price, " +
|
||
"(SUM(oc.Amount) - SUM(oc.wholesale_price)) as sales_profit, " +
|
||
"(SUM(oc.Amount) - SUM(oc.wholesale_price) - SUM(oc.staff_cost_price)) as staff_profit").
|
||
Scan(&sumData).Error
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return sumData, err
|
||
}
|
||
return sumData, nil
|
||
}
|
||
|
||
// 查询零售订单的汇总数据
|
||
func getRetailDetailTotalDataJoinErpOrderRejected(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) {
|
||
var sumData RetailDetailTotalData
|
||
qs = qs.Where("eo.retail_type = ?", retailType) // 添加额外的条件
|
||
err := qs.Debug().Select("SUM(oc.count) as count, " +
|
||
"SUM(oc.retail_price) as retail_price, " +
|
||
"SUM(oc.sale_price) as sale_price, " +
|
||
"SUM(oc.sale_discount) as sale_discount, " +
|
||
"SUM(oc.member_discount) as member_discount, " +
|
||
"SUM(oc.rejected_amount) as Amount, " +
|
||
"SUM(oc.wholesale_price) as wholesale_price, " +
|
||
"(SUM(oc.wholesale_price) + SUM(oc.staff_cost_price)) as staff_price, " +
|
||
"SUM(oc.sales_profit) as sales_profit, " +
|
||
"SUM(oc.staff_profit) as staff_profit").
|
||
Scan(&sumData).Error
|
||
if err != nil {
|
||
logger.Error("query sum data err:", logger.Field("err", err))
|
||
return sumData, err
|
||
}
|
||
return sumData, nil
|
||
}
|
||
|
||
// 查询零售订单的提成汇总数据
|
||
func getTotalPerData(qs *gorm.DB, retailType string) (TotalPerData, error) {
|
||
var totalPerData TotalPerData
|
||
err := qs.Debug().Select("SUM(erp_order_sales.sales_profit_per) as total_sales_profit_per, "+
|
||
"SUM(erp_order_sales.staff_profit_per) as total_staff_profit_per, "+
|
||
"SUM(erp_order_sales.salesman_per) as salesman_per").
|
||
Joins("JOIN erp_order_sales ON erp_order_sales.erp_order_id = erp_order.id and erp_order.retail_type = ?", retailType).
|
||
Scan(&totalPerData).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales sum data err:", logger.Field("err", err))
|
||
return totalPerData, err
|
||
}
|
||
return totalPerData, nil
|
||
}
|
||
|
||
// 查询零售订单的支付汇总数据
|
||
func getTotalCashierData(qs *gorm.DB, retailType string) (TotalCashierData, error) {
|
||
var cashier TotalCashierData
|
||
err := qs.Debug().Select(
|
||
"SUM(CASE WHEN erp_order_pay_way.cashier_id = 1 THEN erp_order_pay_way.amount ELSE 0 END) AS scan_amount,"+
|
||
"SUM(CASE WHEN erp_order_pay_way.cashier_id = 2 THEN erp_order_pay_way.amount ELSE 0 END) AS cash_amount,"+
|
||
"SUM(CASE WHEN erp_order_pay_way.cashier_id = 3 THEN erp_order_pay_way.amount ELSE 0 END) AS pos_amount,"+
|
||
"SUM(CASE WHEN erp_order_pay_way.cashier_id = 4 THEN erp_order_pay_way.amount ELSE 0 END) AS store_vm_amount,"+
|
||
"SUM(CASE WHEN erp_order_pay_way.cashier_id not in (1,2,3,4) THEN erp_order_pay_way.amount ELSE 0 END) AS other_amount").
|
||
Joins("JOIN erp_order_pay_way ON erp_order_pay_way.erp_order_id = erp_order.id and erp_order.retail_type = ?", retailType).
|
||
Scan(&cashier).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
|
||
return cashier, err
|
||
}
|
||
return cashier, nil
|
||
}
|
||
|
||
// 计算销售订单和退货订单汇总后的销售数据
|
||
func subtractRetailData(sumData, rejectedSumData RetailDetailTotalData) RetailDetailTotalData {
|
||
result := RetailDetailTotalData{
|
||
Count: sumData.Count - rejectedSumData.Count,
|
||
RetailPrice: sumData.RetailPrice - rejectedSumData.RetailPrice,
|
||
SalePrice: sumData.SalePrice - rejectedSumData.SalePrice,
|
||
SaleDiscount: sumData.SaleDiscount - rejectedSumData.SaleDiscount,
|
||
MemberDiscount: sumData.MemberDiscount - rejectedSumData.MemberDiscount,
|
||
VmDiscount: sumData.VmDiscount - rejectedSumData.VmDiscount,
|
||
Amount: sumData.Amount - rejectedSumData.Amount,
|
||
WholesalePrice: sumData.WholesalePrice - rejectedSumData.WholesalePrice,
|
||
StaffPrice: sumData.StaffPrice - rejectedSumData.StaffPrice,
|
||
SalesProfit: sumData.SalesProfit - rejectedSumData.SalesProfit,
|
||
StaffProfit: sumData.StaffProfit - rejectedSumData.StaffProfit,
|
||
TotalRetailPrice: sumData.TotalRetailPrice - rejectedSumData.TotalRetailPrice,
|
||
TotalDiscount: sumData.TotalDiscount - rejectedSumData.TotalDiscount,
|
||
TotalAmount: sumData.TotalAmount - rejectedSumData.TotalAmount,
|
||
TotalSalesProfit: sumData.TotalSalesProfit - rejectedSumData.TotalSalesProfit,
|
||
TotalStaffProfit: sumData.TotalStaffProfit - rejectedSumData.TotalStaffProfit,
|
||
StorePer: sumData.StorePer - rejectedSumData.StorePer,
|
||
}
|
||
//if sumData.TotalSalesProfit != 0 {
|
||
// result.TotalSalesProfit = sumData.TotalSalesProfit - rejectedSumData.TotalSalesProfit
|
||
//} else {
|
||
// result.TotalSalesProfit = rejectedSumData.TotalSalesProfit
|
||
//}
|
||
//if sumData.TotalStaffProfit != 0 {
|
||
// result.TotalStaffProfit = sumData.TotalStaffProfit - rejectedSumData.TotalStaffProfit
|
||
//} else {
|
||
// result.TotalStaffProfit = rejectedSumData.TotalStaffProfit
|
||
//}
|
||
|
||
return result
|
||
}
|
||
|
||
// 计算销售订单和退货订单汇总后的提成数据
|
||
func subtractTotalPerData(totalPerData, rejectedTotalPerData TotalPerData) TotalPerData {
|
||
result := TotalPerData{
|
||
TotalSalesProfitPer: totalPerData.TotalSalesProfitPer - rejectedTotalPerData.TotalSalesProfitPer,
|
||
TotalStaffProfitPer: totalPerData.TotalStaffProfitPer - rejectedTotalPerData.TotalStaffProfitPer,
|
||
SalesmanPer: totalPerData.SalesmanPer - rejectedTotalPerData.SalesmanPer,
|
||
}
|
||
return result
|
||
}
|
||
|
||
// 计算销售订单和退货订单汇总后的支付数据
|
||
func subtractCashierData(cashier, rejectedCashier TotalCashierData) TotalCashierData {
|
||
result := TotalCashierData{
|
||
ScanAmount: cashier.ScanAmount - rejectedCashier.ScanAmount,
|
||
CashAmount: cashier.CashAmount - rejectedCashier.CashAmount,
|
||
PosAmount: cashier.PosAmount - rejectedCashier.PosAmount,
|
||
StoreVmAmount: cashier.StoreVmAmount - rejectedCashier.StoreVmAmount,
|
||
OtherAmount: cashier.OtherAmount - rejectedCashier.OtherAmount,
|
||
}
|
||
return result
|
||
}
|
||
|
||
// QueryReceiptData 查询小票数据
|
||
func QueryReceiptData(req *ErpOrderDeleteReq, c *gin.Context) (*ErpOrderReceiptDataResp, error) {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
logger.Errorf("err:%#v", err)
|
||
return nil, err
|
||
}
|
||
|
||
var orders []ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("bill_sn = ?", req.BillSn).Find(&orders).Error
|
||
if err != nil {
|
||
logger.Error("erp_order find err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !CheckUserStore(orders[0].StoreId, sysUser) {
|
||
return nil, errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
if orders[0].PayStatus != HavePaid {
|
||
logger.Error("订单未支付")
|
||
return nil, errors.New("该订单未支付,不支持打印小票")
|
||
}
|
||
|
||
// 添加付款、销售员、商品信息
|
||
erpOrderListSetCommodity(orders)
|
||
erpOrderListSetCashier(orders)
|
||
erpOrderListSetSalesman(orders)
|
||
|
||
// 查询门店信息
|
||
storeInfo, err := GetStore(orders[0].StoreId)
|
||
if err != nil {
|
||
logger.Error("QueryReceiptData GetStore err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
// 记录打印信息
|
||
if orders[0].IsPrint != HavePrinted {
|
||
err = orm.Eloquent.Table("erp_order").Where("bill_sn = ?", req.BillSn).Updates(map[string]interface{}{
|
||
"is_print": HavePrinted,
|
||
}).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
err = orm.Eloquent.Model(&ErpOrder{}).
|
||
Where("bill_sn = ? ", req.BillSn).
|
||
UpdateColumn("print_count", gorm.Expr("print_count + ?", 1)).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
order := orders[0]
|
||
resp := new(ErpOrderReceiptDataResp)
|
||
resp.StoreName = order.StoreName
|
||
resp.Barcode = order.BillSn
|
||
resp.OddNum = order.BillSn
|
||
resp.Time = Now()
|
||
resp.CollectS = order.MakerName
|
||
|
||
commodityMap := make(map[string]TableData, 0)
|
||
for i, item := range order.Commodities {
|
||
var tableData TableData
|
||
tableData.Name = item.ErpCommodityName
|
||
tableData.SL = uint32(item.Count)
|
||
tableData.DJ = item.RetailPrice
|
||
tableData.JE = float64(item.Count) * item.RetailPrice
|
||
|
||
key := fmt.Sprintf("commodity_%d", i)
|
||
commodityMap[key] = tableData
|
||
|
||
resp.TotalAmount += item.SaleDiscount
|
||
resp.IntegrationAmount += item.VmDiscount
|
||
|
||
if order.MemberType != ErpOrderMemberTypeGeneral {
|
||
resp.MembersAmount += item.MemberDiscount
|
||
}
|
||
}
|
||
|
||
resp.ChandiseObj = commodityMap
|
||
resp.TotalRetailP = order.TotalRetailPrice
|
||
resp.TotalNum = uint32(order.TotalCount)
|
||
resp.ToDealWith = order.TotalAmount
|
||
|
||
cashierMap := make(map[string]ErpOrderCashier, 0)
|
||
for i, item := range order.Cashiers {
|
||
key := fmt.Sprintf("payment_%d", i)
|
||
cashierMap[key] = item
|
||
}
|
||
|
||
resp.ModeOfPayment = cashierMap
|
||
resp.ActualPayment = order.TotalAmount
|
||
resp.Tel = order.Tel
|
||
if order.MemberType != ErpOrderMemberTypeGeneral {
|
||
resp.Uid = order.Uid
|
||
}
|
||
resp.StoreTel = storeInfo.Tel
|
||
resp.StoreAddress = storeInfo.Address
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// CreateErpOrder 创建零售订单
|
||
func CreateErpOrder(req *ErpOrderCreateReq, c *gin.Context) error {
|
||
for i, _ := range req.ErpOrderCommodities {
|
||
req.ErpOrderCommodities[i].ID = 0
|
||
}
|
||
// 校验订单数据
|
||
erpOrder, err := checkOrderData(req, c)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
// 0-创建用户信息
|
||
userInfo, err := GetUserInfoByTel(req.Tel)
|
||
if err != nil {
|
||
logger.Error("checkOrderData GetUserInfoByTel err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
if userInfo.Uid == 0 {
|
||
user := UserInfo{
|
||
Uid: uint32(erpOrder.Uid),
|
||
Tel: req.Tel,
|
||
StoreId: uint64(req.StoreId),
|
||
UserType: UserTypeConsumer, // 用户
|
||
OpenMemberLevel: MemberLevelConsumer, // 普通用户
|
||
MemberLevel: MemberLevelConsumer, // 普通用户
|
||
CooperativeBusinessId: 1, // 合作商默认为1
|
||
}
|
||
err = begin.Create(&user).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("create user err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
// 1-创建零售订单
|
||
err = begin.Create(erpOrder).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("create erp_order err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 销售信息添加零售订单id
|
||
for i, _ := range req.Salesman {
|
||
req.Salesman[i].ErpOrderId = erpOrder.ID
|
||
}
|
||
// 2-创建销售员信息记录
|
||
err = begin.Create(&req.Salesman).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("Create erp_order_sales err")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 支付方式添加零售订单id
|
||
var orderPayWay ErpOrderPayWay
|
||
var orderPayWayList []ErpOrderPayWay
|
||
for _, item := range req.Cashiers {
|
||
orderPayWay.ErpOrderId = erpOrder.ID
|
||
orderPayWay.CashierId = item.CashierId
|
||
orderPayWay.Name = item.Name
|
||
orderPayWay.Amount = item.Amount
|
||
orderPayWayList = append(orderPayWayList, orderPayWay)
|
||
}
|
||
// 3-创建支付方式记录
|
||
err = begin.Create(&orderPayWayList).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("Create erp_order_pay_way err")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 订单商品表信息添加零售订单id
|
||
for i, _ := range req.ErpOrderCommodities {
|
||
req.ErpOrderCommodities[i].ErpOrderId = erpOrder.ID
|
||
}
|
||
|
||
// 4-创建商品订单信息
|
||
err = begin.Create(&req.ErpOrderCommodities).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("Create erp_order_commodity err")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("commit err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// EditErpOrder 编辑订单
|
||
func EditErpOrder(req *ErpOrderCreateReq, c *gin.Context) error {
|
||
var orderInfo ErpOrder
|
||
err := orm.Eloquent.Table("erp_order").Where("bill_sn=?", req.BillSn).Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
if orderInfo.State != ErpOrderStateUnAudit {
|
||
logger.Error("EditErpOrder err:", logger.Field("err", err))
|
||
return errors.New("订单状态不是待审核,操作失败")
|
||
}
|
||
|
||
// 校验订单数据
|
||
erpOrder, err := checkOrderData(req, c)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
erpOrder.ID = orderInfo.ID
|
||
erpOrder.BillSn = orderInfo.BillSn // 编辑的订单单据号不能改变
|
||
begin := orm.Eloquent.Begin()
|
||
// 1-更新零售订单
|
||
err = begin.Model(&ErpOrder{}).Where("id = ?", orderInfo.ID).Updates(erpOrder).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 2-更新零售订单商品信息
|
||
err = updateCommodityData(begin, orderInfo.ID, req)
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order_commodity err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 3-更新销售员信息记录
|
||
err = updateSalesData(begin, orderInfo.ID, req)
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order_sales err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 4-更新支付方式记录
|
||
err = updatePayWayData(begin, orderInfo.ID, req)
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order_pay_way err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("commit err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// CheckUserStore 校验用户门店是否包含在门店数据中且未过期
|
||
func CheckUserStore(userStoreId uint32, sysUser *SysUser) bool {
|
||
// 解析门店数据
|
||
var stores []StoreInfo
|
||
if err := json.Unmarshal([]byte(sysUser.StoreData), &stores); err != nil {
|
||
return false
|
||
}
|
||
|
||
// 查找用户门店并检查是否过期
|
||
for _, store := range stores {
|
||
if store.StoreID == int(userStoreId) {
|
||
expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime)
|
||
if err != nil {
|
||
return false
|
||
}
|
||
expireTime = expireTime.Add(24*time.Hour - time.Second)
|
||
// 如果过期时间在当前时间之后,则未过期
|
||
if expireTime.After(time.Now()) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 没有找到对应的门店
|
||
return false
|
||
}
|
||
|
||
// AuthUserStore 校验是否有某个门店的权限
|
||
func AuthUserStore(c *gin.Context, storeId uint32) error {
|
||
// 非管理员才判断所属门店
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
if !CheckUserStore(storeId, sysUser) {
|
||
return errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// checkOrderData 校验订单数据
|
||
func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
|
||
sysUser, err := GetSysUserByCtx(c)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
// 校验入参门店是否包含在用户所有门店中,是否过期
|
||
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
|
||
if !CheckUserStore(req.StoreId, sysUser) {
|
||
return nil, errors.New("操作失败:您没有该门店权限")
|
||
}
|
||
}
|
||
|
||
var rejectedOrderSaleId uint32
|
||
if req.RetailType == RetailTypeSale {
|
||
// 校验商品是否有库存,是否是对应门店库存商品
|
||
err = CheckOrderCommodityStock(req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
} else { // 零售退货单,需校验退货商品是否是本门店售卖商品,同一个退货单中只能添加同一销售订单的商品
|
||
rejectedOrderSaleId, err = checkRejectedOrderRule(req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
jCashier, err := json.Marshal(req.Cashiers)
|
||
if err != nil {
|
||
logger.Error("cashiers marshal err:", logger.Field("err", err))
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 通过手机号查询用户id,如果没有,则新建一个用户id
|
||
userInfo, err := GetUserInfoByTel(req.Tel)
|
||
if err != nil {
|
||
logger.Error("checkOrderData GetUserInfoByTel err:", logger.Field("err", err))
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
var userUid uint32
|
||
if userInfo.Uid == 0 {
|
||
userUid = CreateUid() // 没有用户则新建
|
||
} else {
|
||
userUid = userInfo.Uid
|
||
}
|
||
|
||
erpOrder := &ErpOrder{
|
||
BillSn: NewErpBillSn(),
|
||
RetailType: req.RetailType,
|
||
Uid: int(userUid),
|
||
Tel: req.Tel,
|
||
StoreId: req.StoreId,
|
||
StoreName: req.StoreName,
|
||
MakerId: uint32(sysUser.UserId),
|
||
MakerName: sysUser.NickName,
|
||
MakerTime: time.Now(),
|
||
CashierList: string(jCashier),
|
||
MemberType: req.MemberType,
|
||
State: ErpOrderStateUnAudit,
|
||
PayStatus: NoCreatePayOrder,
|
||
IsPrint: NoPrint, // 未打印
|
||
PrintCount: 0, // 打印次数
|
||
TotalRetailPrice: req.TotalRetailPrice,
|
||
VmCount: req.VmAmount,
|
||
}
|
||
|
||
if req.RetailType == RetailTypeRejected {
|
||
erpOrder.SaleOrderId = rejectedOrderSaleId
|
||
}
|
||
|
||
commodityMap := make(map[uint32]ErpStockCommodity)
|
||
imeiCommodityMap := make(map[string]ErpStockCommodity)
|
||
if req.RetailType == RetailTypeSale { // 零售订单,查商品表信息
|
||
commodityIds := make([]uint32, 0, len(req.ErpOrderCommodities)) // 非串码商品的商品id列表
|
||
imeiList := make([]string, 0, len(req.ErpOrderCommodities)) // 串码商品的串码列表
|
||
for i, _ := range req.ErpOrderCommodities {
|
||
if req.ErpOrderCommodities[i].IMEIType == 1 { // 非串码商品
|
||
commodityIds = append(commodityIds, req.ErpOrderCommodities[i].ErpCommodityId)
|
||
} else { // 串码商品
|
||
imeiList = append(imeiList, req.ErpOrderCommodities[i].IMEI)
|
||
}
|
||
}
|
||
|
||
// 商品的相关价格以库存表为准,商品表的价格除了最低零售价,其他只是参考
|
||
// 串码商品直接查询;非串码商品查询库存时间最久的商品
|
||
var commodities []ErpStockCommodity
|
||
if len(imeiList) != 0 {
|
||
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei IN (?)", imeiList).
|
||
Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("get commodities err:", logger.Field("err", err))
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
for i, _ := range commodities { // 串码
|
||
imeiCommodityMap[commodities[i].IMEI] = commodities[i]
|
||
}
|
||
}
|
||
|
||
if len(commodityIds) != 0 {
|
||
commodities = nil
|
||
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id IN (?)", commodityIds).
|
||
Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("get commodities err:", logger.Field("err", err))
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
for _, commodity := range commodities { // 非串码
|
||
v, ok := commodityMap[commodity.ErpCommodityId]
|
||
if !ok { // 没有则直接添加
|
||
commodityMap[commodity.ErpCommodityId] = commodity
|
||
} else {
|
||
// 已有则比较非串码的入库时间,添加入库时间最早的商品
|
||
if commodity.FirstStockTime.Before(v.FirstStockTime) {
|
||
commodityMap[commodity.ErpCommodityId] = commodity
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 更新用户信息表,添加首次零售订单时间
|
||
SetUserInfo(req.Tel)
|
||
}
|
||
|
||
//var orderCommodityMap map[uint32]ErpOrderCommodity
|
||
//if req.RetailType == RetailTypeRejected { // 零售退货订单,查零售商品表
|
||
// ids := make([]uint32, 0, len(req.ErpOrderCommodities))
|
||
// for i, _ := range req.ErpOrderCommodities {
|
||
// ids = append(ids, req.ErpOrderCommodities[i].ErpCommodityId)
|
||
// }
|
||
// orderCommodityMap, err = GetErpOrderCommodityMap(ids, req)
|
||
// if err != nil {
|
||
// logger.Error("order commodity map err:", logger.Field("err", err))
|
||
// return nil, err
|
||
// }
|
||
//}
|
||
|
||
bCheckFlag := false
|
||
// 校验商品相关金额是否符合要求
|
||
var respErpOrderCommodities []ErpOrderCommodity
|
||
for i, _ := range req.ErpOrderCommodities {
|
||
if req.RetailType == RetailTypeRejected { // 零售退货订单
|
||
//v, ok := orderCommodityMap[req.ErpOrderCommodities[i].ErpCommodityId]
|
||
//if ok {
|
||
// v.RejectedPrice = req.ErpOrderCommodities[i].RejectedPrice // 退货单价
|
||
// v.RejectedCount = req.ErpOrderCommodities[i].RejectedCount
|
||
// v.RejectedAmount = float64(v.RejectedCount) * v.RejectedPrice
|
||
//} else {
|
||
// logger.Error("rejected order commodity id is null")
|
||
// return nil, errors.New("rejected order commodity id is null")
|
||
//}
|
||
//v.ID = 0
|
||
//v.Remark = req.ErpOrderCommodities[i].Remark // 备注
|
||
//v.RejectedRemark = req.ErpOrderCommodities[i].RejectedRemark // 退货备注
|
||
//if v.PresentType == 1 { // 有非赠送商品
|
||
// bCheckFlag = true
|
||
//}
|
||
//req.ErpOrderCommodities[i] = v
|
||
|
||
if req.ErpOrderCommodities[i].RejectedPrice > req.ErpOrderCommodities[i].Amount { // 退货单价不能大于实际零售价
|
||
logger.Error("rejected price gt retail price ")
|
||
return nil, errors.New("退货单价大于实际零售价")
|
||
}
|
||
if int32(req.ErpOrderCommodities[i].RejectedCount) > req.ErpOrderCommodities[i].Count { // 退货数量不能大于销售数量
|
||
logger.Error("rejected count gt retail count ")
|
||
return nil, errors.New("退货数量大于销售数量")
|
||
}
|
||
|
||
// 更新订单表总退款金额和数量 备注:2024-03-12 订单表没有退款金额的字段,默认都使用订单金额字段,根据订单类型判断是零售或退款
|
||
//erpOrder.RejectedTotalAmount += req.ErpOrderCommodities[i].RejectedAmount
|
||
//erpOrder.RejectedTotalCount += req.ErpOrderCommodities[i].RejectedCount
|
||
erpOrder.TotalAmount += req.ErpOrderCommodities[i].RejectedAmount
|
||
erpOrder.TotalCount += int32(req.ErpOrderCommodities[i].Count)
|
||
|
||
// 订单总优惠
|
||
erpOrder.TotalDiscount += req.ErpOrderCommodities[i].MemberDiscount + req.ErpOrderCommodities[i].SaleDiscount
|
||
|
||
// 销售毛利:实际退货金额-采购金额(需要先取负值,然后再计算),结果等同于:采购金额-实际退货金额
|
||
//salesProfit := (-v.RejectedAmount) - (-float64(int32(v.WholesalePrice) * v.Count))
|
||
salesProfit := req.ErpOrderCommodities[i].RejectedAmount - req.ErpOrderCommodities[i].WholesalePrice*float64(req.ErpOrderCommodities[i].Count)
|
||
|
||
// 员工毛利 // todo 待测试核实
|
||
//StaffProfit := salesProfit - (-float64(int32(v.StaffCostPrice) * v.Count))
|
||
StaffProfit := salesProfit - req.ErpOrderCommodities[i].StaffCostPrice*float64(req.ErpOrderCommodities[i].Count)
|
||
|
||
req.ErpOrderCommodities[i].SalesProfit = salesProfit // 销售毛利
|
||
req.ErpOrderCommodities[i].StaffProfit = StaffProfit // 员工毛利
|
||
erpOrder.TotalSalesProfit += salesProfit
|
||
erpOrder.TotalStaffProfit += StaffProfit
|
||
|
||
// 单个商品的销售毛利
|
||
req.ErpOrderCommodities[i].SalesProfit = salesProfit / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的员工毛利
|
||
req.ErpOrderCommodities[i].StaffProfit = StaffProfit / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的零售优惠
|
||
req.ErpOrderCommodities[i].SaleDiscount = req.ErpOrderCommodities[i].SaleDiscount / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的会员优惠
|
||
req.ErpOrderCommodities[i].MemberDiscount = req.ErpOrderCommodities[i].MemberDiscount / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品实收金额
|
||
req.ErpOrderCommodities[i].ReceivedAmount = req.ErpOrderCommodities[i].ReceivedAmount / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品退货金额
|
||
req.ErpOrderCommodities[i].RejectedAmount = req.ErpOrderCommodities[i].RejectedAmount / float64(req.ErpOrderCommodities[i].Count)
|
||
|
||
for j := 0; j < int(req.ErpOrderCommodities[i].Count); j++ {
|
||
stockIdList, _ := stringToIntArray(req.ErpOrderCommodities[i].ErpStockCommodityID)
|
||
temp := req.ErpOrderCommodities[i]
|
||
temp.Count = 1
|
||
if len(stockIdList) > j {
|
||
temp.ErpStockCommodityID = fmt.Sprintf("%d", stockIdList[j])
|
||
}
|
||
respErpOrderCommodities = append(respErpOrderCommodities, temp)
|
||
}
|
||
} else if req.RetailType == RetailTypeSale { // 零售订单
|
||
var v ErpStockCommodity
|
||
var ok bool
|
||
if req.ErpOrderCommodities[i].IMEIType == 1 { // 非串码商品
|
||
v, ok = commodityMap[req.ErpOrderCommodities[i].ErpCommodityId]
|
||
if !ok {
|
||
return nil, errors.New("遍历商品信息报错")
|
||
}
|
||
} else { // 串码商品
|
||
v, ok = imeiCommodityMap[req.ErpOrderCommodities[i].IMEI]
|
||
if !ok {
|
||
return nil, errors.New("遍历商品信息报错")
|
||
}
|
||
}
|
||
|
||
// 赠送类型商品进行校验,最低零售价为0才能赠送
|
||
if req.ErpOrderCommodities[i].PresentType == 2 && v.MinRetailPrice != 0 {
|
||
logger.Error("PresentType is 2, MinRetailPrice no equal 0")
|
||
return nil, errors.New("赠送商品最低零售价不为0,不符合赠送条件,请检查")
|
||
}
|
||
if req.ErpOrderCommodities[i].SalePrice < v.MinRetailPrice { //零售价不能低于最低零售价
|
||
logger.Error("SalePrice less than MinRetailPrice")
|
||
return nil, errors.New("零售价不能低于最低零售价,请检查")
|
||
}
|
||
if req.ErpOrderCommodities[i].PresentType == 1 { // 有非赠送商品
|
||
bCheckFlag = true
|
||
}
|
||
|
||
req.ErpOrderCommodities[i].ErpCommodityId = v.ErpCommodityId // 商品id
|
||
req.ErpOrderCommodities[i].ErpCommodityName = v.ErpCommodityName // 商品名称
|
||
req.ErpOrderCommodities[i].ErpCategoryId = v.ErpCategoryId // 分类id
|
||
req.ErpOrderCommodities[i].ErpCategoryName = v.ErpCategoryName // 分类名称
|
||
req.ErpOrderCommodities[i].ErpSupplierId = v.ErpSupplierId // 供应商id
|
||
req.ErpOrderCommodities[i].ErpSupplierName = v.ErpSupplierName // 供应商名称
|
||
req.ErpOrderCommodities[i].RetailPrice = v.RetailPrice // 指导零售价
|
||
req.ErpOrderCommodities[i].StaffCostPrice = v.StaffCostPrice // 员工成本价加价
|
||
req.ErpOrderCommodities[i].WholesalePrice = v.WholesalePrice // 指导采购价
|
||
|
||
// 销售毛利 备注:产品说有亏本销售的情况,不用判断毛利是否<0
|
||
salesProfit := req.ErpOrderCommodities[i].ReceivedAmount -
|
||
req.ErpOrderCommodities[i].WholesalePrice*float64(req.ErpOrderCommodities[i].Count)
|
||
// 员工毛利
|
||
StaffProfit := salesProfit - req.ErpOrderCommodities[i].StaffCostPrice*float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的销售毛利
|
||
req.ErpOrderCommodities[i].SalesProfit = salesProfit / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的员工毛利
|
||
req.ErpOrderCommodities[i].StaffProfit = StaffProfit / float64(req.ErpOrderCommodities[i].Count)
|
||
|
||
// 订单总销售毛利
|
||
erpOrder.TotalSalesProfit += salesProfit
|
||
// 订单总员工毛利
|
||
erpOrder.TotalStaffProfit += StaffProfit
|
||
// 更新订单表总金额和数量
|
||
erpOrder.TotalAmount += req.ErpOrderCommodities[i].ReceivedAmount
|
||
erpOrder.TotalCount += int32(req.ErpOrderCommodities[i].Count)
|
||
|
||
// 单个商品的零售优惠
|
||
req.ErpOrderCommodities[i].SaleDiscount = req.ErpOrderCommodities[i].SaleDiscount / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品的会员优惠
|
||
req.ErpOrderCommodities[i].MemberDiscount = req.ErpOrderCommodities[i].MemberDiscount / float64(req.ErpOrderCommodities[i].Count)
|
||
// 单个商品实收金额
|
||
req.ErpOrderCommodities[i].ReceivedAmount = req.ErpOrderCommodities[i].ReceivedAmount / float64(req.ErpOrderCommodities[i].Count)
|
||
|
||
for j := 0; j < int(req.ErpOrderCommodities[i].Count); j++ {
|
||
temp := req.ErpOrderCommodities[i]
|
||
temp.Count = 1
|
||
respErpOrderCommodities = append(respErpOrderCommodities, temp)
|
||
}
|
||
}
|
||
}
|
||
|
||
if erpOrder.TotalAmount == 0 && bCheckFlag {
|
||
return nil, errors.New("订单包含非赠送商品,实收金额不能为0")
|
||
}
|
||
|
||
req.ErpOrderCommodities = respErpOrderCommodities
|
||
|
||
// 判断线上支付金额是否>0
|
||
if req.RetailType == RetailTypeSale {
|
||
onlinePayFlag := false
|
||
onlinePayAmount := erpOrder.TotalAmount
|
||
var nWaitPayAmount float64
|
||
for _, item := range req.Cashiers {
|
||
if item.CashierId == 1 { // 线上支付
|
||
onlinePayFlag = true
|
||
} else {
|
||
onlinePayAmount -= item.Amount
|
||
}
|
||
nWaitPayAmount += item.Amount
|
||
}
|
||
if onlinePayFlag && onlinePayAmount <= 0 { // 线上支付且金额小于0则报错
|
||
logger.Error("线上支付金额小于0")
|
||
return nil, errors.New("扫码付金额需>0")
|
||
}
|
||
if nWaitPayAmount > erpOrder.TotalAmount { // 收款金额大于订单金额
|
||
logger.Error("收款金额大于订单金额")
|
||
return nil, errors.New("收款金额大于订单金额")
|
||
}
|
||
if nWaitPayAmount < erpOrder.TotalAmount { // 收款金额小于订单金额
|
||
logger.Error("收款金额小于订单金额")
|
||
return nil, errors.New("收款金额小于订单金额")
|
||
}
|
||
}
|
||
|
||
// 添加销售员相关信息
|
||
jSalesman, err := req.GetSalesmanList()
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
erpOrder.SalesmanList = jSalesman
|
||
|
||
// 添加门店提成
|
||
store, err := GetStore(req.StoreId)
|
||
if err != nil {
|
||
return nil, errors.New("操作失败:" + err.Error())
|
||
}
|
||
erpOrder.StorePer = erpOrder.TotalStaffProfit * (store.SalesCommRate / 100)
|
||
erpOrder.StorePer = math.Round(erpOrder.StorePer*100) / 100
|
||
|
||
// 订单总优惠
|
||
if req.RetailType == RetailTypeSale {
|
||
erpOrder.TotalDiscount = erpOrder.TotalRetailPrice - erpOrder.TotalAmount
|
||
}
|
||
|
||
return erpOrder, nil
|
||
}
|
||
|
||
// CheckOrderCommodityStock 校验商品是否有库存
|
||
func CheckOrderCommodityStock(req *ErpOrderCreateReq) error {
|
||
if len(req.ErpOrderCommodities) != 0 {
|
||
// 统计串码和非串码商品信息
|
||
commodityMap := make(map[uint32]uint32) // 记录非串码商品id及其数量
|
||
imeiCommodityMap := make(map[uint32]string) // 记录串码商品id及其串码
|
||
commodityNameMap := make(map[uint32]string) // 记录商品名称
|
||
for _, commodity := range req.ErpOrderCommodities {
|
||
if commodity.IMEIType == 1 {
|
||
_, ok := commodityMap[commodity.ErpCommodityId]
|
||
if !ok { // 没有则直接添加
|
||
commodityMap[commodity.ErpCommodityId] = uint32(commodity.Count)
|
||
} else {
|
||
commodityMap[commodity.ErpCommodityId] += uint32(commodity.Count)
|
||
}
|
||
commodityNameMap[commodity.ErpCommodityId] = commodity.ErpCommodityName
|
||
} else {
|
||
imeiCommodityMap[commodity.ErpCommodityId] = commodity.IMEI
|
||
commodityNameMap[commodity.ErpCommodityId] = commodity.ErpCommodityName
|
||
}
|
||
}
|
||
|
||
// 查询库存表,确认是否有库存
|
||
if len(commodityMap) != 0 { // 查询非串码商品库存
|
||
var count int64
|
||
for commodityId, nCount := range commodityMap {
|
||
err := orm.Eloquent.Table("erp_stock_commodity").
|
||
Where("erp_commodity_id = ? and store_id = ? and state = ? and imei_type = ?",
|
||
commodityId, req.StoreId, InStock, NoIMEICommodity).
|
||
Count(&count).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if count < int64(nCount) {
|
||
// 获取商品名称
|
||
return errors.New("商品" + "[" + commodityNameMap[commodityId] + "]库存不足")
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(imeiCommodityMap) != 0 { // 查询串码商品库存
|
||
for commodityId, imei := range imeiCommodityMap {
|
||
var imeiStockCommodity ErpStockCommodity
|
||
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?", imei, InStock).
|
||
Find(&imeiStockCommodity).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if imeiStockCommodity.ID == 0 {
|
||
// 获取商品名称
|
||
return errors.New("商品" + "[" + commodityNameMap[commodityId] + "]库存不足")
|
||
}
|
||
|
||
if imeiStockCommodity.StoreId != req.StoreId {
|
||
return errors.New(commodityNameMap[commodityId] + "商品非所选门店库存,请检查")
|
||
}
|
||
}
|
||
}
|
||
|
||
} else {
|
||
return errors.New("该零售订单未添加商品")
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 退货校验
|
||
// (1)校验退货商品销售时的手机号与当前填写的手机号是否相同,不匹配报错:所退商品的历史订单手机号与当前不符。
|
||
// (2)校验商品是否是当前用户购买
|
||
// (3)校验退货商品是否是本门店售卖商品
|
||
// (4)同一个退货单中只能添加同一销售订单的商品
|
||
func checkRejectedOrderRule(req *ErpOrderCreateReq) (uint32, error) {
|
||
if req.RetailType != RetailTypeRejected {
|
||
return 0, errors.New("订单类型有误,非退货订单")
|
||
}
|
||
|
||
if len(req.ErpOrderCommodities) == 0 {
|
||
return 0, errors.New("未添加退货商品")
|
||
}
|
||
|
||
var salesId uint32
|
||
rejectOrderSalesMap := make(map[string]bool)
|
||
for _, item := range req.ErpOrderCommodities {
|
||
// 查询退货商品之前的销售情况
|
||
if item.IMEIType == NoIMEICommodity { //非串码商品
|
||
var commodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id ").
|
||
Where("erp_order_commodity.erp_commodity_id = ? and erp_order.store_id = ? "+
|
||
"and erp_order.retail_type = ? and erp_order.pay_status = ? and erp_order.tel = ?",
|
||
item.ErpCommodityId, req.StoreId, RetailTypeSale, HavePaid, req.Tel).
|
||
Find(&commodities).Order("audit_time DESC").Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_commodity err:", logger.Field("err", err))
|
||
return 0, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
if len(commodities) == 0 {
|
||
return 0, errors.New(fmt.Sprintf("未查询到商品[%s]销售情况", item.ErpCommodityName))
|
||
}
|
||
|
||
var orderInfo ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("id = ?", commodities[0].ErpOrderId).
|
||
Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order err:", logger.Field("err", err))
|
||
return 0, errors.New("操作失败:" + err.Error())
|
||
}
|
||
if orderInfo.BillSn == "" {
|
||
return 0, errors.New(fmt.Sprintf("未查询到商品[%s]销售订单", item.ErpCommodityName))
|
||
}
|
||
|
||
rejectOrderSalesMap[orderInfo.BillSn] = true
|
||
if len(rejectOrderSalesMap) > 1 {
|
||
return 0, errors.New("只可添加相同零售订单的商品")
|
||
}
|
||
salesId = orderInfo.ID
|
||
} else { // 串码商品
|
||
if item.IMEI == "" {
|
||
return 0, errors.New("退货商品串码为空")
|
||
}
|
||
var commodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id ").
|
||
Where("erp_order_commodity.imei = ? and erp_order.retail_type = ? and erp_order.pay_status = ?",
|
||
item.IMEI, RetailTypeSale, HavePaid).
|
||
Order("erp_order_id DESC").Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_commodity err:", logger.Field("err", err))
|
||
return 0, errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
if len(commodities) == 0 {
|
||
return 0, errors.New(fmt.Sprintf("未查询到商品[%s]销售情况", item.ErpCommodityName))
|
||
}
|
||
|
||
var orderInfo ErpOrder
|
||
err = orm.Eloquent.Table("erp_order").Where("id = ?", commodities[0].ErpOrderId).
|
||
Find(&orderInfo).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order err:", logger.Field("err", err))
|
||
return 0, errors.New("操作失败:" + err.Error())
|
||
}
|
||
if orderInfo.BillSn == "" {
|
||
return 0, errors.New(fmt.Sprintf("未查询到商品[%s]销售订单", item.ErpCommodityName))
|
||
}
|
||
|
||
if orderInfo.Tel != req.Tel {
|
||
return 0, errors.New(fmt.Sprintf("所退商品[%s]的历史订单手机号与当前不符", item.ErpCommodityName))
|
||
}
|
||
|
||
if orderInfo.StoreId != req.StoreId {
|
||
return 0, errors.New(fmt.Sprintf("[%s]非当前门店所售商品,需前往对应门店退货", item.ErpCommodityName))
|
||
}
|
||
|
||
rejectOrderSalesMap[orderInfo.BillSn] = true
|
||
if len(rejectOrderSalesMap) > 1 {
|
||
return 0, errors.New("只可添加相同零售订单的商品")
|
||
}
|
||
salesId = orderInfo.ID
|
||
}
|
||
}
|
||
|
||
return salesId, nil
|
||
}
|
||
|
||
// updateCommodityData 更新订单商品信息
|
||
func updateCommodityData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) error {
|
||
// 查询现有的零售订单信息
|
||
var commodities []ErpOrderCommodity
|
||
err := orm.Eloquent.Table("erp_order_commodity").Where("erp_order_id = ?", orderId).Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_commodity err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
// 1-删除所有的商品信息
|
||
if len(commodities) != 0 {
|
||
err = gdb.Delete(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("更新商品订单信息-删除 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
for i, _ := range req.ErpOrderCommodities {
|
||
req.ErpOrderCommodities[i].ID = 0
|
||
}
|
||
|
||
// 2-更新商品订单信息-新增
|
||
err = gdb.Create(&req.ErpOrderCommodities).Error
|
||
if err != nil {
|
||
logger.Error("更新商品订单信息-新增 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// updateSalesData 更新订单销售员信息
|
||
func updateSalesData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) error {
|
||
// 查询现有的零售订单销售员信息
|
||
var orderSales []ErpOrderSales
|
||
err := orm.Eloquent.Table("erp_order_sales").Where("erp_order_id = ?", orderId).Find(&orderSales).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
var newOrderSales []ErpOrderSales
|
||
var deletedOrderSales []ErpOrderSales
|
||
var matchingOrderSales []ErpOrderSales
|
||
// 找到新增的商品
|
||
for _, reqSales := range req.Salesman {
|
||
var found bool
|
||
for _, dbSales := range orderSales {
|
||
if reqSales.Uid == dbSales.Uid {
|
||
found = true
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
reqSales.ID = 0
|
||
reqSales.CreatedAt = Now()
|
||
newOrderSales = append(newOrderSales, reqSales)
|
||
}
|
||
}
|
||
|
||
// 找到删除的商品
|
||
for _, dbSales := range orderSales {
|
||
var found bool
|
||
for _, reqSales := range req.Salesman {
|
||
if reqSales.Uid == dbSales.Uid {
|
||
found = true
|
||
// 找到匹配的商品,加入匹配列表
|
||
matchingOrderSales = append(matchingOrderSales, dbSales)
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
deletedOrderSales = append(deletedOrderSales, dbSales)
|
||
}
|
||
}
|
||
|
||
// 更新
|
||
for _, orderSaleInfo := range matchingOrderSales {
|
||
if err = gdb.Model(&ErpOrderSales{}).Where("id = ?", orderSaleInfo.ID).Updates(orderSaleInfo).Error; err != nil {
|
||
logger.Error("更新订单销售员信息-更新 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
// 新增
|
||
if len(newOrderSales) != 0 {
|
||
err = gdb.Create(&newOrderSales).Error
|
||
if err != nil {
|
||
logger.Error("更新订单销售员信息-新增 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
// 删除
|
||
if len(deletedOrderSales) != 0 {
|
||
err = gdb.Delete(&deletedOrderSales).Error
|
||
if err != nil {
|
||
logger.Error("更新订单销售员信息-删除 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// updatePayWayData 更新零售订单支付方式记录表
|
||
func updatePayWayData(gdb *gorm.DB, orderId uint32, req *ErpOrderCreateReq) error {
|
||
// 查询现有的零售订单销售员信息
|
||
var orderPayWay []ErpOrderPayWay
|
||
err := orm.Eloquent.Table("erp_order_pay_way").Where("erp_order_id = ?", orderId).Find(&orderPayWay).Error
|
||
if err != nil {
|
||
logger.Error("query erp_order_sales err:", logger.Field("err", err))
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
|
||
var newOrderPayWay []ErpOrderPayWay
|
||
var deletedOrderPayWay []ErpOrderPayWay
|
||
var matchingOrderPayWay []ErpOrderPayWay
|
||
// 找到新增的商品
|
||
for _, reqPayWay := range req.Cashiers {
|
||
var found bool
|
||
for _, dbPayWay := range orderPayWay {
|
||
if reqPayWay.CashierId == dbPayWay.CashierId {
|
||
found = true
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
payWay := ErpOrderPayWay{
|
||
ErpOrderId: orderId,
|
||
CashierId: reqPayWay.CashierId,
|
||
Name: reqPayWay.Name,
|
||
Amount: reqPayWay.Amount,
|
||
}
|
||
newOrderPayWay = append(newOrderPayWay, payWay)
|
||
}
|
||
}
|
||
|
||
// 找到删除的商品
|
||
for _, dbPayWay := range orderPayWay {
|
||
var found bool
|
||
for _, reqPayWay := range req.Cashiers {
|
||
if reqPayWay.CashierId == dbPayWay.CashierId {
|
||
found = true
|
||
// 找到匹配的商品,加入匹配列表
|
||
matchingOrderPayWay = append(matchingOrderPayWay, dbPayWay)
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
deletedOrderPayWay = append(deletedOrderPayWay, dbPayWay)
|
||
}
|
||
}
|
||
|
||
// 更新
|
||
for _, orderPayWayInfo := range matchingOrderPayWay {
|
||
if err = gdb.Model(&ErpOrderPayWay{}).Where("id = ?", orderPayWayInfo.ID).Updates(orderPayWayInfo).Error; err != nil {
|
||
logger.Error("更新零售订单支付方式-更新 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
// 新增
|
||
if len(newOrderPayWay) != 0 {
|
||
err = gdb.Create(&newOrderPayWay).Error
|
||
if err != nil {
|
||
logger.Error("更新零售订单支付方式-新增 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
// 删除
|
||
if len(deletedOrderPayWay) != 0 {
|
||
err = gdb.Delete(&deletedOrderPayWay).Error
|
||
if err != nil {
|
||
logger.Error("更新零售订单支付方式-删除 error")
|
||
return errors.New("操作失败:" + err.Error())
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|