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

4 years ago
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
}
4 years ago
4 years ago
//这里插入日志
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
}