You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package wallet
import (
"errors"
"fmt"
"git.oa00.com/go/mysql"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"recook/internal/libs/bean"
"recook/internal/v2/logic/source/wallet"
finance2 "recook/internal/v2/model/finance"
"recook/internal/v2/model/gys"
"recook/internal/v2/model/gys/enterprise"
"recook/internal/v2/model/recook/goods"
manage "recook/internal/v2/model/recook/order"
"recook/tools"
"time"
)
var DepositLogic = &depositLogic{}
type depositLogic struct {
}
type depositItem struct {
Id uint `json:"id"`
Name string `json:"name"`
BillType uint `json:"bill_type"`
DepositAmount decimal.Decimal `json:"deposit_amount"`
DepositFreezeAmount decimal.Decimal `json:"deposit_freeze_amount"`
DepositBillAmount decimal.Decimal `json:"deposit_bill_amount"`
DepositTotalAmount decimal.Decimal `json:"deposit_total_amount"`
WarningAmount decimal.Decimal `json:"warning_amount"`
Status uint `json:"status"`
}
// Lists @Title 运营方预存款列表
func (d *depositLogic) Lists(sourceId uint, page bean.Page) (lists []depositItem, total int64) {
lists = []depositItem{}
sources := []gys.GysSourceModel{}
where := mysql.Db.Where("bill_type=?", 2)
if sourceId > 0 {
where = where.Where("id = ?", sourceId)
}
mysql.Db.Model(&sources).Where(where).Count(&total)
if page.HasPage(total) {
mysql.Db.Preload("Wallet").Where(where).Offset(page.GetStart()).Limit(page.GetLimit()).Find(&sources)
for _, source := range sources {
lists = append(lists, depositItem{
Id: source.Id,
Name: source.Name,
BillType: source.BillType,
Status: source.Wallet.DepositEarlyWarningStatus,
WarningAmount: source.Wallet.DepositEarlyWarningAmount,
DepositAmount: source.Wallet.DepositAmount,
DepositFreezeAmount: source.Wallet.DepositFreezeAmount,
DepositBillAmount: source.Wallet.DepositBillAmount,
DepositTotalAmount: source.Wallet.DepositTotalAmount,
})
}
}
return
}
type depositHistoryItem struct {
Id uint `json:"id"`
Type uint `json:"type"`
CreatedAt int64 `json:"created_at"`
Proof string `json:"proof"`
Amount decimal.Decimal `json:"amount"`
AfterAmount decimal.Decimal `json:"after_amount"`
}
// History @Title 预存款变动明细
func (d *depositLogic) History(sourceId, historyType uint, timeStart, timeEnd string, page bean.Page) (lists []depositHistoryItem, total int64) {
lists = []depositHistoryItem{}
depositHistories := []gys.GysSourceDepositHistory{}
where := mysql.Db.Where("source_id = ?", sourceId)
if historyType > 0 {
switch historyType {
case gys.GysSourceDepositHistoryTypeDeposit:
where = where.Where("type = ?", gys.GysSourceDepositHistoryTypeDeposit)
case gys.GysSourceDepositHistoryTypeBill:
where = where.Where("type = ?", gys.GysSourceDepositHistoryTypeDeposit)
}
}
if timeStart != "" && timeEnd != "" {
start, err := time.ParseInLocation("2006-01-02", timeStart, time.Local)
if err == nil {
end, err := time.ParseInLocation("2006-01-02 15:04:05", timeEnd+" 23:59:59", time.Local)
if err == nil {
where = where.Where("created_at between ? and ?", start, end)
}
}
}
mysql.Db.Model(&depositHistories).Where(where).Count(&total)
if page.HasPage(total) {
mysql.Db.Where(where).Offset(page.GetStart()).Limit(page.GetLimit()).Find(&depositHistories)
for _, history := range depositHistories {
lists = append(lists, depositHistoryItem{
Id: history.Id,
Type: history.Type,
CreatedAt: history.CreatedAt.Unix(),
Proof: history.Proof,
Amount: history.Amount,
AfterAmount: history.AfterAmount,
})
}
}
return
}
// Deposit @Title 充值
func (d *depositLogic) Deposit(sourceId uint, amount decimal.Decimal, proof string, status uint) error {
sourceWallet := gys.GysSourceWallet{SourceId: sourceId}
mysql.Db.Where(&sourceWallet).First(&sourceWallet)
afterAmount := decimal.Zero
if status == 1 {
//充值
afterAmount = amount.Add(sourceWallet.DepositAmount).Add(sourceWallet.DepositFreezeAmount)
} else {
//退款
afterAmount = (sourceWallet.DepositAmount).Add(sourceWallet.DepositFreezeAmount).Sub(amount)
}
return mysql.Db.Transaction(func(tx *gorm.DB) error {
typeNum := 0
if status == 1 {
typeNum = 3
} else {
typeNum = 4
}
if tx.Create(&gys.GysSourceDepositHistory{
SourceId: sourceId,
Type: uint(typeNum),
Proof: proof,
Amount: amount,
AfterAmount: afterAmount,
}).Error != nil {
return errors.New("充值失败")
}
if err := wallet.DepositLogic.Add(tx, sourceId, amount, status); err != nil {
return err
}
return nil
})
}
//// Refund 退款
//func (d *depositLogic) Refund(sourceId uint, amount decimal.Decimal, proof string) error {
// sourceWallet := gys.GysSourceWallet{SourceId: sourceId}
// mysql.Db.Where(&sourceWallet).First(&sourceWallet)
// afterAmount := amount.Mul(decimal.NewFromInt32(-1))
// if sourceWallet.Id > 0 {
// afterAmount = afterAmount.Add(sourceWallet.DepositAmount).Add(sourceWallet.DepositFreezeAmount)
// }
// return mysql.Db.Transaction(func(tx *gorm.DB) error {
// if tx.Create(&gys.GysSourceDepositHistory{
// SourceId: sourceId,
// Type: gys.GysSourceDepositHistoryTypeDeposit,
// Proof: proof,
// Amount: amount,
// AfterAmount: afterAmount,
// }).Error != nil {
// return errors.New("退款失败")
// }
// if err := wallet.DepositLogic.Sub(tx, sourceId, amount); err != nil {
// return err
// }
// return nil
// })
//}
// EarlyWarning @Title 预警配置
func (d *depositLogic) EarlyWarning(sourceId, status uint, amount decimal.Decimal) error {
sourceWallet := gys.GysSourceWallet{SourceId: sourceId}
if mysql.Db.Where(&sourceWallet).First(&sourceWallet).Error != nil {
if status == 0 {
// 关闭
sourceWallet.DepositEarlyWarningStatus = gys.GysSourceWalletDepositEarlyWarningStatusDisable
} else {
sourceWallet.DepositEarlyWarningStatus = gys.GysSourceWalletDepositEarlyWarningStatusEnable
sourceWallet.DepositEarlyWarningAmount = amount
}
if mysql.Db.Create(&sourceWallet).Error != nil {
return errors.New("配置失败")
}
} else {
if status == 0 {
// 关闭
if mysql.Db.Model(&sourceWallet).UpdateColumns(map[string]interface{}{
"deposit_early_warning_status": gys.GysSourceWalletDepositEarlyWarningStatusDisable,
}).Error != nil {
return errors.New("配置失败")
}
} else {
if mysql.Db.Model(&sourceWallet).UpdateColumns(map[string]interface{}{
"deposit_early_warning_status": gys.GysSourceWalletDepositEarlyWarningStatusEnable,
"deposit_early_warning_amount": amount,
}).Error != nil {
return errors.New("配置失败")
}
}
}
return nil
}
// EarlyWarningEmail @Title 预警邮箱
func (d *depositLogic) EarlyWarningEmail(sourceId uint, emails []string) error {
warningEmails := []gys.GysSourceDepositEarlyWarningEmail{}
for _, email := range emails {
if !tools.VerifyEmail(email) {
return errors.New("邮箱格式错误")
}
warningEmails = append(warningEmails, gys.GysSourceDepositEarlyWarningEmail{
SourceId: sourceId,
Email: email,
})
}
return mysql.Db.Transaction(func(tx *gorm.DB) error {
if tx.Where("source_id = ?", sourceId).Delete(&gys.GysSourceDepositEarlyWarningEmail{}).Error != nil {
return errors.New("设置失败")
}
if tx.Create(&warningEmails).Error != nil {
return errors.New("设置失败")
}
return nil
})
}
type ShowItem struct {
OrderStatus string `json:"order_status" xlsx:"订单状态"`
OrderId uint `json:"order_id" xlsx:"主订单编号"`
OrderGoodsId uint `json:"order_goods_id" xlsx:"订单编号"`
AssType string `json:"ass_type" xlsx:"售后类型"`
AfterId uint `json:"after_id" xlsx:"售后单号"`
PayTime string `json:"pay_time" xlsx:"订单时间"`
ExpressTime string `json:"express_time" xlsx:"发货时间"`
CompletedAt string `json:"completed_at" xlsx:"订单完结时间"`
SkuCode string `json:"sku_code" xlsx:"商品条码"`
SkuGoodsNum string `json:"sku_goods_num" xlsx:"商品编码"`
InvoiceGoodsName string `json:"invoice_goods_name" xlsx:"开票商品名称"`
SkuName string `json:"sku_name" xlsx:"规格名称"`
InvoiceUnit string `json:"invoice_unit" xlsx:"单位"`
Quantity uint `json:"quantity" xlsx:"发货数量"`
PurchasePrice decimal.Decimal `json:"purchase_price" xlsx:"结算含税单价(元)"`
ExpressFee decimal.Decimal `json:"express_fee" xlsx:"运费金额(元)"`
Amount decimal.Decimal `json:"amount" xlsx:"应结算金额(元)"`
AfterQuantity uint `json:"after_quantity" xlsx:"退货数量"`
RefundAmount decimal.Decimal `json:"refund_amount" xlsx:"退款金额(元)"`
CompensateAmount decimal.Decimal `json:"compensate_amount" xlsx:"赔偿金额(元)"`
BillQuantity uint `json:"bill_quantity" xlsx:"实际结算数量"`
BillAmount decimal.Decimal `json:"bill_amount" xlsx:"实际结算金额(元)"`
EnterpriseName string `json:"enterprise_name" xlsx:"供应商"`
}
type OperateListReq struct {
OrderId uint `json:"order_id"`
Code string `json:"code"`
InvoiceGoodsName string `json:"invoice_goods_name"`
OrderStatus uint `json:"order_status"`
RefundType uint `json:"refund_type"`
ExpressTimeStart string `json:"express_time_start"`
ExpressTimeEnd string `json:"express_time_end"`
FinishTimeStart string `json:"finish_time_start"`
FinishTimeEnd string `json:"finish_time_end"`
Export uint `json:"export"`
GysId uint `json:"gys_id"`
SourceId uint `json:"source_id"`
bean.Page
}
//运营展示采购订单list
func (d *depositLogic) OperateShowList(filter OperateListReq) (result []ShowItem, total int64) {
var bill finance2.RecookFinanceBillOrder
table := bill.TableName()
where := mysql.Db
if filter.SourceId > 0 {
//非超级管理员----传入运营方id
q := mysql.Db.Table((&enterprise.GysEnterpriseStateModel{}).TableName()).Where("source=?", filter.SourceId).Select("user_id")
where = where.Where(fmt.Sprintf("%s.supplier_id in (?)", table), q)
}
if filter.GysId > 0 {
where = where.Where(fmt.Sprintf("%s.supplier_id=?", table), filter.GysId)
}
if filter.OrderId > 0 {
where = where.Where(fmt.Sprintf("%s.order_id like ?", table), fmt.Sprintf("%%%d%%", filter.OrderId))
}
if filter.Code != "" {
where = where.Where("Sku.code like ?", fmt.Sprintf("%%%d%%", filter.OrderId))
}
if filter.InvoiceGoodsName != "" {
q := mysql.Db.Table((&goods.RecookSkuInvoiceModel{}).TableName()).Where("goodsName like ?", fmt.Sprintf("%%%s%%", filter.InvoiceGoodsName)).Select("sku_id")
where = where.Where(fmt.Sprintf("%s.sku_id in(?)", table), q)
}
if filter.OrderStatus > 0 {
switch filter.OrderStatus {
case 1: // 已发货待确认
where = where.Where("OrderGoods.express_status = ? and OrderGoods.refund_status = ?", manage.RecookOrderGoodsDetailExpressStatusTrue, manage.RecookOrderGoodsDetailRefundStatusNone)
case 2: // 售后中
where = where.Where("OrderGoods.express_status = ? and OrderGoods.refund_status = ?", manage.RecookOrderGoodsDetailExpressStatusTrue, manage.RecookOrderGoodsDetailRefundStatusIng)
case 3: // 收货已完成
where = where.Where("OrderGoods.express_status = ? and OrderGoods.refund_status = ?", manage.RecookOrderGoodsDetailExpressStatusTrue, manage.RecookOrderGoodsDetailRefundStatusSuc)
case 4: // 已完成
where = where.Where("OrderGoods.express_status = ?", manage.RecookOrderGoodsDetailExpressStatusConfirm)
}
}
if filter.RefundType > 0 {
switch filter.RefundType {
case manage.RecookOrderGoodsDetailAssTypeRejected:
where = where.Where("OrderGoods.ass_type = ?", manage.RecookOrderGoodsDetailAssTypeRejected)
case manage.RecookOrderGoodsDetailAssTypeCompensate:
where = where.Where("OrderGoods.ass_type = ?", manage.RecookOrderGoodsDetailAssTypeCompensate)
}
}
if filter.ExpressTimeStart != "" && filter.ExpressTimeEnd != "" {
start, err := time.ParseInLocation("2006-01-02", filter.ExpressTimeStart, time.Local)
if err == nil {
end, err := time.ParseInLocation("2006-01-02 15:04:05", filter.ExpressTimeEnd+" 23:59:59", time.Local)
if err == nil {
where = where.Where("OrderExpress.express_time between ? and ?", start, end)
}
fmt.Println("发货时间:", start, end)
}
}
if filter.FinishTimeStart != "" && filter.FinishTimeEnd != "" {
start, err := time.ParseInLocation("2006-01-02", filter.FinishTimeStart, time.Local)
if err == nil {
end, err := time.ParseInLocation("2006-01-02 15:04:05", filter.FinishTimeEnd+" 23:59:59", time.Local)
if err == nil {
where = where.Where("Order.completed_at between ? and ?", start, end)
}
fmt.Println("完成时间:", start, end)
}
}
query := mysql.Db.Joins("Goods").Joins("OrderExpress").Joins("Sku").Joins("OrderGoods").Joins("Supplier").Joins("Order").Model(&bill)
query.Where(where).Count(&total)
var list []finance2.RecookFinanceBillOrder
if filter.Export > 0 {
query.Preload("After").Preload("Order").Preload("OrderExpress").Preload("Sku").Preload("Sku.Invoice").Preload("OrderGoods").Preload("Supplier").Where(where).Find(&list)
} else {
query.Preload("After").Preload("OrderExpress").Preload("Order").Preload("Sku").Preload("Sku.Invoice").Preload("OrderGoods").Preload("Supplier").Where(where).Limit(filter.Page.GetLimit()).Offset(filter.Page.GetStart()).Find(&list)
}
for _, v := range list {
//订单状态:已发货待确认 售后中 已完成 售后已退款
ostr := ""
if v.OrderGoods.RefundStatus == 2 && v.OrderGoods.AssType > 0 {
ostr = "售后已退款"
} else if v.OrderGoods.RefundStatus == 1 && v.OrderGoods.AssType > 0 {
ostr = "售后中"
}
if v.OrderGoods.PayStatus > 0 && v.OrderGoods.ExpressStatus > 0 {
ostr = "已发货待确认"
}
if v.OrderGoods.Status == 1 {
ostr = "已完成"
}
//fmt.Println(ostr)
//fmt.Println("订单详情:", v.OrderGoods)
ast := ""
//售后类型:正常,退货退款,订单补偿
if v.OrderGoods.RefundStatus > 0 && v.OrderGoods.AssType == 2 {
ast = "退货退款"
} else if v.OrderGoods.AssType == 3 {
ast = "订单补偿"
}
if v.OrderGoods.AssType == 0 {
ast = "正常"
}
fmt.Println(ast)
amount := v.OrderGoods.PurchasePrice.Mul(decimal.NewFromInt(int64(v.OrderGoods.Quantity))).Add(v.OrderGoods.ExpressFee)
one := ShowItem{
OrderStatus: ostr,
OrderId: v.OrderId,
OrderGoodsId: v.OrderGoodsId,
AssType: ast,
AfterId: v.AfterId,
PayTime: v.Order.PayTime.Time.Format("2006-01-02 15:04:05"),
ExpressTime: v.OrderExpress.ExpressTime.Time.Format("2006-01-02 15:04:05"),
CompletedAt: v.Order.CompletedAt.Time.Format("2006-01-02 15:04:05"),
SkuCode: v.Sku.Code,
SkuGoodsNum: v.Sku.GoodsNum,
InvoiceGoodsName: v.Sku.Invoice.GoodsName,
SkuName: v.Sku.Name,
InvoiceUnit: v.Sku.Invoice.Unit,
Quantity: v.OrderGoods.Quantity,
PurchasePrice: v.OrderGoods.PurchasePrice,
ExpressFee: v.OrderGoods.ExpressFee,
Amount: amount,
AfterQuantity: v.After.Quantity,
RefundAmount: v.After.RefundAmount,
CompensateAmount: v.After.SupplierPrice,
BillQuantity: v.OrderGoods.Quantity - v.After.Quantity,
BillAmount: amount.Sub(v.After.RefundAmount).Sub(v.After.SupplierPrice),
EnterpriseName: v.Supplier.EnterpriseName,
}
//fmt.Println(one)
result = append(result, one)
}
fmt.Println(len(result))
return result, total
}