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.

877 lines
27 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 after
import (
"errors"
mysql2 "git.oa00.com/go/mysql"
gorm2 "gorm.io/gorm"
"recook/internal/dbc"
"recook/internal/libs/bean"
"recook/internal/service/comFunc"
"recook/internal/v2/hook"
"recook/internal/v2/logic/pay"
"recook/internal/v2/logic/pay/alipay"
"recook/internal/v2/logic/pay/recook"
"recook/internal/v2/logic/pay/union"
"recook/internal/v2/logic/pay/wechat"
"recook/internal/v2/logic/pay/wechatH5innter"
"recook/internal/v2/logic/pay/wechatmini"
"recook/internal/v2/logic/pay/wechatweb"
after2 "recook/internal/v2/model/gys/after"
"recook/internal/v2/model/recook/after"
"recook/internal/v2/model/recook/coin"
"recook/internal/v2/model/recook/goods"
manage2 "recook/internal/v2/model/recook/manage"
manage "recook/internal/v2/model/recook/order"
user2 "recook/internal/v2/model/recook/user"
"github.com/golangkit/formatime"
"github.com/jinzhu/gorm"
"github.com/shopspring/decimal"
)
var Logic = &afterLogic{}
type afterLogic struct {
}
type AFTQueryListResp struct {
AsID uint `json:"asID"`
OrderGoodsID uint `json:"orderGoodsID"`
SkuCode string `json:"skuCode"`
GoodsName string `json:"goodName"`
UnitPrice decimal.Decimal `json:"UnitPrice"`
RefundCoin decimal.Decimal `json:"refundCoin"`
RefundAmount decimal.Decimal `json:"refundAmount"`
ExpressFee decimal.Decimal `json:"expressFee"`
Address manage.RecookOrderAddrModel `json:"address"`
Status uint `json:"status"`
CreatedAt int64 `json:"created_at"`
FinishTime int64 `json:"finishTime"`
OrderID uint `json:"orderID"`
PayMethod uint `json:"pay_method"`
PurchasePrice decimal.Decimal `json:"purchasePrice"`
Quantity uint `json:"quantity"`
SupplierPrice decimal.Decimal `json:"supplierPrice"`
}
type AFTQueryListReq struct {
bean.Page
AsID uint `json:"asID"` // 售后单号
SkuCode string `json:"skuCode"` // 商品条码
OrderSn uint `json:"orderSn"` // 主订单编号
GoodsName string `json:"goodsName"` // 商品标题
Status uint `json:"status"` // 售后状态
Receiver string `json:"receiver"` // 收货人
Phone string `json:"phone"` // 手机号
StartDate string `json:"startDate"` // 申请开始时间
EndDate string `json:"endDate"` // 申请结束时间
CStartDate string `json:"cStartDate"` // 完成开始时间
CEndDate string `json:"cEndDate"` // 完成结束时间
AssType uint `json:"assType"` // 分类
IsClosed uint `json:"isClosed"` // 是否关闭
LabelStatus uint `json:"labelStatus"` // 标签状态
}
func (o afterLogic) List(q *AFTQueryListReq) ([]AFTQueryListResp, int) {
return o.ListByVendor(q, -1)
}
func (o afterLogic) ListByVendor(q *AFTQueryListReq, vendor int) (list []AFTQueryListResp, total int) {
aft := after.RecookAfterSalesGoodsModel{}
addr := manage.RecookOrderAddrModel{}
rog := manage.RecookOrderGoodsDetailModel{}
var orderIDs []uint
if len(q.Phone) != 0 {
orderIDs = addr.FindOrderIDByMobile(q.Phone)
}
if len(q.Receiver) != 0 {
orderIDs = addr.FindOrderIDByName(q.Receiver)
}
query := aft.GetDb().Model(&aft)
if q.AssType != 0 {
query = query.Where(AssType(q.AssType).getWhere().query)
} else {
query = query.Where(AssType(ATUnshippedAfterSale).getWhere().query)
}
if vendor >= 0 {
query = query.Where("vendor_id = ?", vendor)
}
{
if q.Status != 0 {
query = query.Where("is_closed = ?", q.IsClosed)
query = query.Where("return_status=? ", q.Status)
}
if q.LabelStatus != 0 {
query = query.Where("is_closed = ?", q.IsClosed)
query = query.Where("return_status=? ", q.LabelStatus)
}
if len(orderIDs) != 0 {
query = query.Where("order_id IN (?)", orderIDs)
}
if len(q.CStartDate) != 0 {
query = query.Where("finish_time > ?", q.CStartDate)
}
if len(q.CEndDate) != 0 {
query = query.Where("finish_time < ?", q.CEndDate)
}
if len(q.StartDate) != 0 {
query = query.Where("created_at > ?", q.StartDate)
}
if len(q.EndDate) != 0 {
query = query.Where("created_at < ?", q.EndDate)
}
if len(q.GoodsName) != 0 {
query = query.Where("goods_name like ?", q.GoodsName+"%")
}
if q.OrderSn != 0 {
query = query.Where("order_id = ?", q.OrderSn)
}
if len(q.SkuCode) != 0 {
query = query.Where("sku_code = ?", q.SkuCode)
}
if q.AsID != 0 {
query = query.Where("id = ?", q.AsID)
}
}
query.Count(&total)
start := q.GetStart()
if total > start {
var temp []after.RecookAfterSalesGoodsModel
if db := query.Offset(start).Limit(q.GetLimit()).Order("id DESC").Find(&temp); db.Error != nil {
return
}
for _, v := range temp {
rog = rog.FindById(v.OrderGoodsId)
list = append(list, AFTQueryListResp{
AsID: v.Id,
OrderGoodsID: v.OrderGoodsId,
SkuCode: v.SkuCode,
GoodsName: v.GoodsName,
UnitPrice: rog.UnitPrice,
RefundAmount: v.RefundAmount,
RefundCoin: v.RefundCoin,
ExpressFee: v.ExpressFree,
Address: addr.FindByOrderId(v.OrderId),
Status: v.ReturnStatus,
CreatedAt: v.CreatedAt.Time.Unix(),
FinishTime: v.FinishTime.Time.Unix(),
OrderID: v.OrderId,
PayMethod: v.PayMethod,
PurchasePrice: rog.PurchasePrice,
Quantity: rog.Quantity,
SupplierPrice: v.SupplierPrice,
})
}
}
return
}
type AFTDetailReq struct {
AsID uint `json:"asID" binding:"required"`
}
type afterSaleResp struct {
AsID uint `json:"asID"`
OrderID uint `json:"orderID"`
OrderGoodsID uint `json:"orderGoodsID"`
GoodsName string `json:"goodsName"`
PayMethod uint `json:"payMethod"`
ApplyTime formatime.Second `json:"applyTime"`
CreatedAt formatime.Second `json:"createdAt"`
FinishTime formatime.Second `json:"finishTime"`
VendorName string `json:"vendorName"`
SkuCode string `json:"skuCode"`
Reason string `json:"reason"`
ReasonContent string `json:"reasonContent"`
ReasonType uint `json:"reasonType"`
AssType uint `json:"assType"`
ExpressName string `json:"expressName"`
RejectReason string `json:"rejectReason"`
ExpressCompName string `json:"expressCompName"`
ExpressCompCode string `json:"expressCompCode"`
ExpressNo string `json:"expressNo"`
ExpressFee decimal.Decimal `json:"expressFee"`
RefundAmount decimal.Decimal `json:"refundAmount"`
RefundCoin decimal.Decimal `json:"refundCoin"`
ReturnStatus uint `json:"returnStatus"`
OrderGoodsAmount decimal.Decimal `json:"orderGoodsAmount"`
IsClosed int `json:"isClosed"`
ReasonImg string `json:"reasonImg"`
CheckTime formatime.Second `json:"checkTime"`
SupplierPrice decimal.Decimal `json:"supplierPrice"`
}
type orderAddrResp struct {
ReceiverName string `json:"receiverName"`
Mobile string `json:"mobile"`
Province string `json:"province"`
City string `json:"city"`
District string `json:"district"`
Address string `json:"address"`
}
type orderGoodsDetailResp struct {
MainPhotoURL string `json:"mainPhotoUrl"`
GoodsName string `json:"goodsName"`
SkuName string `json:"skuName"`
PurchasePrice decimal.Decimal `json:"purchasePrice"`
UnitPrice decimal.Decimal `json:"unitPrice"`
Quantity uint `json:"quantity"`
GoodsAmount decimal.Decimal `json:"goodsAmount"`
ExpressFee decimal.Decimal `json:"expressFee"`
CoinAmount decimal.Decimal `json:"coinAmount"`
ActualAmount decimal.Decimal `json:"actualAmount"`
BuyerMessage string `json:"buyerMessage"`
NickName string `json:"nickName"`
Phone string `json:"phone"`
}
type AFTDetailResp struct {
Aft afterSaleResp `json:"aft"`
Addr orderAddrResp `json:"addr"`
OrderGoodsDetail orderGoodsDetailResp `json:"orderGoodsDetail"`
OrderExpress []manage.RecookOrderGoodsExpressModel `json:"orderExpress"`
Logs []after.RecookAfterSalesLogsModel `json:"logs"`
Proof []after.RecookAfterSalesProofModel `json:"proof"`
RtAddress after2.GysReturnAddressModel `json:"rtAddress"`
}
func (o afterLogic) Close(q *AFTDetailReq) error {
aft := after.RecookAfterSalesGoodsModel{}
aft = aft.GetAFTByID(q.AsID)
if aft.ReturnStatus > 3 {
return errors.New("该售后不符合关闭要求")
}
if err := hook.AfterHook.Close(&aft); err != nil {
return err
}
aftNew := after.RecookAfterSalesGoodsModel{
ReturnStatus: 2,
IsClosed: 1,
RefundStatus: 2,
}
order := manage.RecookOrderGoodsDetailModel{
RefundStatus: 2,
}
err := mysql2.Db.Transaction(func(tx *gorm2.DB) error {
err := tx.Table(aft.TableName()).Where("id = ?", aft.Id).Updates(&aftNew).Error
if err != nil {
return err
}
err = tx.Table(order.TableName()).Where("id=?", aft.OrderGoodsId).Updates(&order).Error
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return nil
}
func (o afterLogic) Detail(q *AFTDetailReq) (result AFTDetailResp) {
aft := after.RecookAfterSalesGoodsModel{}
aft = aft.GetAFTByID(q.AsID)
if aft.Id <= 0 {
return
}
result.Aft = afterSaleResp{
AsID: aft.Id,
OrderID: aft.OrderId,
OrderGoodsID: aft.OrderGoodsId,
GoodsName: aft.GoodsName,
PayMethod: aft.PayMethod,
ApplyTime: aft.ApplyTime,
CreatedAt: aft.CreatedAt,
FinishTime: aft.FinishTime,
VendorName: aft.VendorName,
SkuCode: aft.SkuCode,
Reason: aft.Reason,
ReasonContent: aft.ReasonContent,
ReasonType: aft.ReasonType,
AssType: aft.AssType,
ExpressName: aft.ExpressCompName,
RejectReason: aft.RejectReason,
ExpressCompName: aft.ExpressCompName,
ExpressCompCode: aft.ExpressCompCode,
ExpressNo: aft.ExpressNo,
ExpressFee: aft.ExpressFree,
RefundAmount: aft.RefundAmount,
RefundCoin: aft.RefundCoin,
ReturnStatus: aft.ReturnStatus,
OrderGoodsAmount: aft.RefundAmount.Add(aft.ExpressFree),
IsClosed: aft.IsClosed,
ReasonImg: aft.ReasonImg,
CheckTime: aft.CheckTime,
SupplierPrice: aft.SupplierPrice,
}
addr := manage.RecookOrderAddrModel{}
addr = addr.FindByOrderId(aft.OrderId)
result.Addr = orderAddrResp{
ReceiverName: addr.ReceiverName,
Mobile: addr.Mobile,
Province: addr.Province,
City: addr.City,
District: addr.District,
Address: addr.Address,
}
ogd := manage.RecookOrderGoodsDetailModel{}
ogd.GetDb().Table(ogd.TableName()).Where("id = ?", aft.OrderGoodsId).First(&ogd)
u := user2.RecookUserInfoModel{}
u = u.FindById(aft.UserId)
result.OrderGoodsDetail = orderGoodsDetailResp{
MainPhotoURL: ogd.MainPhotoURL,
GoodsName: ogd.GoodsName,
SkuName: ogd.SkuName,
PurchasePrice: ogd.PurchasePrice,
UnitPrice: ogd.UnitPrice,
Quantity: ogd.Quantity,
GoodsAmount: ogd.GoodsAmount,
ExpressFee: ogd.ExpressFee,
CoinAmount: ogd.CoinAmount,
ActualAmount: ogd.ActualAmount,
BuyerMessage: ogd.BuyerMessage,
NickName: u.Nickname,
Phone: u.Phone,
}
express := manage.RecookOrderGoodsExpressModel{}
express.GetDb().Table(express.TableName()).Where("order_id = ?", aft.OrderId).Find(&result.OrderExpress)
sub := aft.GetDb().Table(aft.TableName()+" as aft").
Select("aft.id").
Where("order_goods_id = ?", aft.OrderGoodsId).
SubQuery()
log := after.RecookAfterSalesLogsModel{}
log.GetDb().Table(log.TableName()).
Where("as_id in (?)", sub).Order("id DESC").Find(&result.Logs)
proof := after.RecookAfterSalesProofModel{}
proof.GetDb().Table(proof.TableName()).Where("as_id = ?", q.AsID).Order("id DESC").Find(&result.Proof)
g := goods.RecookGoodsInfoModel{}
gSub := g.GetDb().Table(g.TableName()).Select("return_address_id").
Where("id = ?", aft.GoodsId).SubQuery()
if aft.AssType > 1 {
rt := after2.GysReturnAddressModel{}
rt.GetDb().Table(rt.TableName()).Where("id in (?)", gSub).First(&result.RtAddress)
}
return
}
type AFTFeeUpdateReq struct {
AsID uint `json:"asID" binding:"required"`
Fee decimal.Decimal `json:"fee" binding:"required"`
URLs []string `json:"urls" binding:"required"`
}
func (o afterLogic) UpdateCompensateFee(q *AFTFeeUpdateReq) error {
aft := after.RecookAfterSalesGoodsModel{}
if err := aft.GetDb().Transaction(func(tx *gorm.DB) error {
tx.Table(aft.TableName()).Where("id = ?", q.AsID).First(&aft)
if aft.Id <= 0 {
return errors.New("未找到售后")
}
if aft.AssType != 3 {
return errors.New("该订单并不是补偿售后")
}
og := manage.RecookOrderGoodsDetailModel{}
tx.Table(og.TableName()).Where("id = ?", aft.OrderGoodsId).First(&og)
if og.Id <= 0 {
return errors.New("未查到该订单")
}
if q.Fee.GreaterThan(og.ActualAmount.Add(og.CoinAmount)) {
return errors.New("补偿超过总和")
}
if q.Fee.LessThanOrEqual(og.ActualAmount) {
aft.RefundAmount = q.Fee.Truncate(2)
aft.RefundCoin = decimal.NewFromInt(0)
}
if q.Fee.GreaterThan(og.ActualAmount) {
aft.RefundAmount = og.ActualAmount
aft.RefundCoin = q.Fee.Sub(og.ActualAmount).Truncate(2)
}
if err := tx.Save(&aft).Error; err != nil {
return err
}
if err := saveProof(tx, q.URLs, aft.Id); err != nil {
return err
}
return nil
}); err != nil {
return err
}
return nil
}
func (o afterLogic) UpdateSupplierFee(q *AFTFeeUpdateReq) error {
aft := after.RecookAfterSalesGoodsModel{}
if err := aft.GetDb().Transaction(func(tx *gorm.DB) error {
aft.GetDb().Table(aft.TableName()).Where("id = ?", q.AsID).First(&aft)
if aft.Id <= 0 {
return errors.New("未找到售后")
}
aft.SupplierPrice = q.Fee
if err := tx.Save(&aft).Error; err != nil {
return err
}
if err := saveProof(tx, q.URLs, aft.Id); err != nil {
return err
}
return nil
}); err != nil {
return err
}
return nil
}
type UpdateOrderCheckStatusReq struct {
AsID uint `json:"asID" binding:"required"`
Opinion uint `json:"opinion" binding:"required"` // 审核意见 1可以退货 2 拒绝退货
RejectReason string `json:"rejectReason"` // 拒绝理由
Need uint `json:"need"` // 1:需要 2:不需要
URLs []string `json:"urls"` // 凭证
SupplierPrice decimal.Decimal `json:"supplierPrice"` // 供应商承担价格 补偿订单必须填写
}
func refundWithType(tx *gorm.DB, asGoods after.RecookAfterSalesGoodsModel) error {
switch asGoods.PayMethod {
case manage.RecookOrderInfoPayMethodRecookPay:
if err := recook.Refund(tx, &asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodWechatPay:
if err := wechat.Refund(&asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodAlipay:
if err := alipay.Refund(tx, &asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodWechatMiniPay:
if err := wechatmini.Refund(&asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodAlipayH5:
if err := alipay.Refund(tx, &asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodWechatH5Pay:
if err := wechatweb.Refund(&asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodWechatH5Inner:
if err := wechatH5innter.Refund(&asGoods); err != nil {
return err
}
case manage.RecookOrderInfoPayMethodUnionPay:
if err := union.Refund(&asGoods); err != nil {
return err
}
}
return nil
}
func Refund(tx *gorm.DB, asGoods after.RecookAfterSalesGoodsModel, orderInfo manage.RecookOrderInfoModel, q *UpdateOrderCheckStatusReq, user manage2.RecookManageUserInfoModel) error {
condition := asGoods.IsShip == 1 && asGoods.RefundAmount.IsZero()
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 5,
RefundStatus: 1,
CheckTime: formatime.NewSecondNow(),
SupplierPrice: q.SupplierPrice,
}).Error; err != nil {
return err
}
//这里插入日志
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台同意退款",
Content: "同意买家退款平台将在24小时内处理退款。",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
Log2 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "退款成功",
Content: "退款金额<black>¥" + asGoods.RefundAmount.String() + "</black>将原路退回至您的<black>付款账户</black>,请及时关注到账情况。|退回瑞币<black>" + asGoods.RefundCoin.Add(asGoods.ExpressFree).String() + "</black>已返回至您的<black>瑞币账户</black>,请及时合适。|<gray>若3天内未收到退款/瑞币,请联系客服咨询。</gray>",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log2)
if condition {
if err := pay.SyncRefundSuccessCallback(tx, &asGoods); err != nil {
return errors.New("退款失败")
}
} else {
if err := refundWithType(tx, asGoods); err != nil {
return err
}
}
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
return err
}
return nil
}
func (o afterLogic) Review(q *UpdateOrderCheckStatusReq, user manage2.RecookManageUserInfoModel) error {
if q.Opinion == 2 && len(q.RejectReason) == 0 {
return errors.New("必须填写拒绝理由")
}
var asGoods after.RecookAfterSalesGoodsModel
if err := dbc.DB.First(&asGoods, q.AsID).Error; err != nil {
return err
}
var orderInfo manage.RecookOrderInfoModel
if err := dbc.DB.First(&orderInfo, asGoods.OrderId).Error; err != nil {
return err
}
// 0正常1等待商家审核 2审核被拒绝 3审核成功 4买家已填写退货物流信息 5收到退货确认退款完成 6退货被拒绝
if asGoods.AssType == 2 { // 退货 退款
if q.Opinion == 1 {
if q.Need == 0 {
return errors.New("请确认是否需要退货")
}
if q.Need == 1 {
tx := dbc.DB.Begin()
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 3,
CheckTime: formatime.NewSecondNow(),
}).Error; err != nil {
tx.Rollback()
return err
}
//这边增加一个让买家填写单号的通知
var userNotice = &user2.RecookUserNoticeModel{
Type: 4,
UserID: asGoods.UserId,
Content: "您的售后已通过,尽快填写退回的快递单号",
CreatTime: formatime.NewSecondNow(),
}
tx.Create(userNotice)
var gs goods.RecookGoodsInfoModel
tx.First(&gs, "id = ?", asGoods.GoodsId)
//这里插入日志
var addr after2.GysReturnAddressModel
dbc.DB.First(&addr, "id = ?", gs.ReturnAddressID)
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台同意退货",
Content: "平台同意买家退货买家须在48小时内上传物流信息否则系统将自动关闭退货请求。|<address>寄回地址:" + addr.Address + " " + " " + addr.Name + addr.Mobile + "</address>",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
}
if q.Need == 2 {
tx := dbc.DB.Begin()
if err := Refund(tx, asGoods, orderInfo, q, user); err != nil {
tx.Rollback()
return err
}
tx.Commit()
}
} else { // 拒绝的话将原来的订单商品ass_type标记下
tx := dbc.DB.Begin()
{
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 2,
RejectReason: q.RejectReason,
FinishTime: formatime.NewSecondNow(),
}).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Model(&manage.RecookOrderGoodsDetailModel{Id: asGoods.OrderGoodsId}).Updates(map[string]interface{}{
"ass_type": 0,
}).Error; err != nil {
tx.Rollback()
return err
}
}
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台拒绝退货",
Content: "拒绝买家退货申请,如有疑问,请联系客服",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
}
} else { // 只是退款
tx := dbc.DB.Begin()
{
if q.Opinion == 1 {
if err := Refund(tx, asGoods, orderInfo, q, user); err != nil {
tx.Rollback()
return err
}
tx.Commit()
} else { // 拒绝的话将原来的订单商品ass_type标记下
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 2,
RejectReason: q.RejectReason,
FinishTime: formatime.NewSecondNow(),
}).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Model(&manage.RecookOrderGoodsDetailModel{Id: asGoods.OrderGoodsId}).Updates(map[string]interface{}{
"ass_type": 0,
}).Error; err != nil {
tx.Rollback()
return err
}
//这里插入日志
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台拒绝退款",
Content: "拒绝买家退款申请,如有疑问,请联系客服",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
Log2 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "退款关闭",
Content: "系统自动关闭",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log2)
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
}
}
}
return nil
}
func (o afterLogic) ReviewReturnAfter(q *UpdateOrderCheckStatusReq, user manage2.RecookManageUserInfoModel) error {
var asGoods after.RecookAfterSalesGoodsModel
if err := dbc.DB.First(&asGoods, q.AsID).Error; err != nil {
return err
}
if asGoods.AssType == 1 {
return errors.New("该订单仅退款")
}
if asGoods.ReturnStatus != 4 {
return errors.New("订单状态不可更新")
}
var orderInfo manage.RecookOrderInfoModel
if err := dbc.DB.First(&orderInfo, asGoods.OrderId).Error; err != nil {
return err
}
if q.Opinion == 2 {
if len(q.RejectReason) == 0 {
return errors.New("没有填写拒绝原因")
}
tx := dbc.DB.Begin()
{
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 3, //让买家继续填写单号
RejectReason: q.RejectReason,
FinishTime: formatime.NewSecondNow(),
}).Error; err != nil {
tx.Rollback()
return err
}
//这边增加一个让买家填写单号的通知
var userNotice = user2.RecookUserNoticeModel{
Type: 4,
UserID: asGoods.UserId,
Content: "您的售后已通过,尽快填写退回的快递单号",
CreatTime: formatime.NewSecondNow(),
}
tx.Create(userNotice)
//这里插入日志
var addr after2.GysReturnAddressModel
dbc.DB.Last(&addr)
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台拒绝收货",
Content: "已收到买家退回商品,不符合退货条件,拒绝退款。理由:" + q.RejectReason + "|买家须在48小时内上传物流信息否则系统将自动关闭退货请求。|<address>寄回地址:" + addr.Address + " " + addr.Name + " " + addr.Mobile + "</address>",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
Log2 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "等待买家重新上传物流信息",
Content: "",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log2)
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
} else {
tx := dbc.DB.Begin()
{
if err := tx.Model(&asGoods).Updates(after.RecookAfterSalesGoodsModel{
ReturnStatus: 5,
RefundStatus: 1,
}).Error; err != nil {
tx.Rollback()
return err
}
if err := refundWithType(tx, asGoods); err != nil {
return err
}
}
Log1 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "平台确认收货",
Content: "已收到买家退回商品,符合退货条件,同意退款。|平台将在24小时内处理退款。",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log1)
Log2 := after.RecookAfterSalesLogsModel{
AsID: asGoods.Id,
Title: "退款成功",
Content: "退款金额<black>¥" + asGoods.RefundAmount.String() + "</black>将原路退回至您的<black>付款账户</black>,请及时关注到账情况。|退回瑞币<black>" + asGoods.RefundCoin.Add(asGoods.ExpressFree).String() + "</black>已返回至您的<black>瑞币账户</black>,请及时合适。|<gray>若3天内未收到退款/瑞币,请联系客服咨询。</gray>",
CTime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log2)
if err := saveProof(tx, q.URLs, asGoods.Id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
}
return nil
}
func refundRecord(tx *gorm.DB, o manage.RecookOrderInfoModel, after after.RecookAfterSalesGoodsModel) bool {
// pay success 里面已经调用 这边不需要更新
if o.PayMethod != 0 {
if o.CoinTotalAmount.GreaterThan(decimal.NewFromInt(0)) {
var orderGoods manage.RecookOrderGoodsDetailModel
if err := dbc.DB.First(&orderGoods, after.OrderGoodsId).Error; err != nil {
return false
}
var coinHistory coin.RecookCoinHistoryModel
coinHistory.UserId = o.UserId
coinHistory.CoinType = coin.RefundTypeForCoinHistory1
// coinHistory.CoinNum = orderInfo.CoinTotalAmount
coinHistory.CoinNum = orderGoods.CoinAmount
coinHistory.OrderAmount = o.GoodsTotalAmount
coinHistory.OrderId = o.Id
coinHistory.Remark = "商品退款-退回"
// beego.Info(coinHistory.CoinNum, orderInfo.CoinTotalAmount)
if err := tx.Save(&coinHistory).Error; err != nil {
comFunc.PrintErr("refundRecord save coinHistory error:", err)
return false
}
if err := coinHistory.UpdateWalletAfterCreate(tx, o.UserId); err != nil {
comFunc.PrintErr("refundRecord UpdateWalletAfterCreate error:", err)
return false
}
}
}
return true
}
func saveProof(tx *gorm.DB, urls []string, asID uint) error {
for _, v := range urls {
t := after.RecookAfterSalesProofModel{
AsID: asID,
URL: v,
CreatedAt: formatime.NewTimestampNow(),
}
if err := tx.Table(t.TableName()).FirstOrCreate(&t, "as_id = ? and url = ?", asID, v).Error; err != nil {
return err
}
}
return nil
}