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.

343 lines
9.2 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 aftersales
import (
"fmt"
"recook/internal/back"
"recook/internal/dbc"
"recook/internal/libs/snow"
"recook/internal/model/aftersales"
"recook/internal/model/goods"
"recook/internal/model/order"
"recook/internal/v2/hook"
"recook/internal/v2/lib/common"
"recook/internal/v2/lib/jcook"
"recook/internal/v2/model/recook/after"
"recook/tools"
"time"
"github.com/gin-gonic/gin"
"github.com/golangkit/formatime"
"github.com/shopspring/decimal"
)
type applyRefundParam struct {
UserID uint `json:"userId"`
OrderGoodsIDs []uint `json:"orderGoodsIds"`
Coin decimal.Decimal `json:"coin"` //允许发货订单发起仅退款的数字,
ReasonContent string `json:"reasonContent"` //如果是已发货的话,必须填写申请理由
ReasonImg string `json:"reasonImg"`
}
// RefundOrder 退款
//
//标记订单有售后痕迹
//生成退款记录
//
//钱包支付;退回商品用过的的余额
//退回优惠券
//退回运费
func RefundOrder(c *gin.Context) {
var p applyRefundParam
err := tools.ParseParams(&p, c)
if err != nil {
back.Fail(c, err.Error())
return
}
if len(p.OrderGoodsIDs) == 0 {
back.Fail(c, "参数不完整")
return
}
var temp order.GoodsDetail
err = dbc.DB.First(&temp, p.OrderGoodsIDs[0]).Error
if err != nil {
back.Fail(c, err.Error())
return
}
var orderTemp order.Information
err = dbc.DB.First(&orderTemp, temp.OrderID).Error
if err != nil {
back.Fail(c, err.Error())
return
}
if (orderTemp.Kind == 1 || orderTemp.Kind == 2) && orderTemp.JCookStatus == 0 {
var ogs []order.GoodsDetail
err = dbc.DB.Find(&ogs, "order_id = ?", orderTemp.ID).Error
if err != nil {
back.Fail(c, err.Error())
return
}
ids := make([]uint, 0)
for _, v := range ogs {
ids = append(ids, v.ID)
}
p.OrderGoodsIDs = ids
}
orderGoodsList := make([]order.GoodsDetail, 0, 0)
for _, v := range p.OrderGoodsIDs {
var one order.GoodsDetail
err = dbc.DB.First(&one, v).Error
if err != nil {
back.Fail(c, err.Error())
return
}
var count uint
dbc.DB.Table((&aftersales.Goods{}).TableName()).Where(aftersales.Goods{
OrderGoodsID: v,
}).Count(&count)
if count >= 3 {
back.Fail(c, one.GoodsName+"已超过三次售后申请,不可再次申请")
return
}
orderGoodsList = append(orderGoodsList, one)
}
var orderInfo order.Information
if err = dbc.DB.First(&orderInfo, orderGoodsList[0].OrderID).Error; err != nil {
back.Fail(c, err.Error())
return
}
if orderInfo.Status == 4 {
back.Fail(c, "已超过售后期限")
return
}
if time.Now().Unix() >= orderInfo.CreatedAt.Time.AddDate(0, 0, 18).Unix() {
back.Fail(c, "关账时间已过,无法发起售后")
return
}
var asCount uint
dbc.DB.Table((&aftersales.Goods{}).TableName()).Where("order_id = ?", orderInfo.ID).Count(&asCount)
if asCount > 20 {
back.Fail(c, "单笔订单售后次数最多20次您已经超过上线")
return
}
for _, v := range orderGoodsList {
if v.PayStatus == 0 {
back.Fail(c, "当前订单未支付")
return
}
if v.AssType != 0 {
back.Fail(c, "请勿重复申请")
return
}
if v.GoodsAmount.LessThan(p.Coin) {
back.Err(c, "计算错误!!! 退款金额大于总金额")
return
}
//如果是已经发货的
if v.ExpressStatus == 1 {
if len(p.ReasonContent) == 0 {
back.Fail(c, "请填写申请理由")
return
}
if p.Coin.LessThanOrEqual(decimal.NewFromInt(0)) {
back.Fail(c, "申请补偿订单必须大于0")
return
}
}
}
var goodsIds []uint
for _, detail := range orderGoodsList {
goodsIds = append(goodsIds, detail.GoodsID)
}
var goodsInfos []goods.Information
dbc.DB.Model(&goods.Information{}).Find(&goodsInfos, "id in (?)", goodsIds)
goodsInfoMap := map[uint]goods.Information{}
for _, info := range goodsInfos {
goodsInfoMap[info.ID] = info
}
var ids []uint
for i, v := range orderGoodsList {
goodsDetail := orderGoodsList[i]
asGoods := aftersales.Goods{
AncestorID: v.AncestorID,
ParentID: v.ParentID,
SharerID: orderInfo.SharerID,
UserID: v.UserID,
UserRole: orderInfo.UserRole,
OrderID: v.OrderID,
OrderGoodsID: v.ID,
VendorID: v.VendorID,
VendorName: v.VendorName,
BrandName: v.BrandName,
CategoryName: v.CategoryName,
GoodsID: v.GoodsID,
GoodsName: v.GoodsName,
SkuName: v.SkuName,
SkuCode: v.SkuCode,
MainPhotoURL: v.MainPhotoURL,
Quantity: v.Quantity,
OrderTime: v.OrderTime,
OrderTotalAmount: orderInfo.ActualTotalAmount,
RefundAmount: v.ActualAmount, //这个就是最后实际支付的价格
RefundCoin: v.CoinAmount,
TradeNo: orderInfo.TradeNo,
PayMethod: orderInfo.PayMethod,
ThirdPartyType: goodsInfoMap[v.GoodsID].ThirdPartyType,
IsShip: v.ExpressStatus,
AssType: 1,
ReturnStatus: 1,
ApplyTime: formatime.NewSecondNow(),
ReasonImg: p.ReasonImg,
ReasonContent: p.ReasonContent,
RefundNo: fmt.Sprintf("%d_%vA%d", time.Now().Unix(), orderInfo.TradeNo, goodsDetail.ID),
}
//如果是已经发货的订单需要在售后里面把实际支付改成功0将瑞币改成提交过来的数字
if asGoods.IsShip == 1 {
// 认为是补偿订单
asGoods.AssType = 3
if p.Coin.GreaterThan(v.ActualAmount.Add(v.CoinAmount)) {
back.Fail(c, "补偿金额超过最大金额")
return
}
if p.Coin.GreaterThan(v.ActualAmount) && p.Coin.LessThanOrEqual(v.ActualAmount.Add(v.CoinAmount)) {
asGoods.RefundAmount = v.ActualAmount.Truncate(2)
asGoods.RefundCoin = p.Coin.Sub(v.ActualAmount).Truncate(2)
}
if p.Coin.LessThan(v.ActualAmount) {
asGoods.RefundAmount = p.Coin.Truncate(2)
asGoods.RefundCoin = decimal.NewFromInt(0)
}
}
tx := dbc.DB.Begin()
{
lastID, e := snow.GetAfsWorker().NextID()
if e != nil {
back.Err(c, "网络异常,请稍后重试")
tx.Rollback()
return
}
asGoods.ID = uint(lastID)
if asGoods.IsShip == 1 {
tx.Model(&goodsDetail).Updates(order.GoodsDetail{
AssType: 3,
})
} else {
tx.Model(&goodsDetail).Updates(order.GoodsDetail{
AssType: 1,
})
}
if err = tx.Create(&asGoods).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
ids = append(ids, asGoods.ID)
if err := hook.AfterHook.Create(&goodsDetail, &asGoods); err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
//这里插入日志
user, _ := common.GetManageUser(c)
Log := aftersales.AftersalesLog{
AsId: uint(lastID),
Title: "买家申请仅退款",
Content: "退款原因:" + p.ReasonContent + "|退款金额:" + (asGoods.RefundAmount).String() + "|退回瑞币:" + asGoods.RefundCoin.String(),
Ctime: formatime.NewSecondNow(),
User: user.Name,
UserId: user.Id,
}
tx.Create(&Log)
if (orderInfo.Kind == 1 || orderInfo.Kind == 2) && orderInfo.ApplyStatus != 11 && orderInfo.ApplyStatus != 12 && orderInfo.JCookStatus == 0 {
client := jcook.GetClient()
req := jcook.OrderCancelReq{
OrderID: orderInfo.JCookOrderID,
CancelReasonCode: 100,
}
var resp jcook.OrderCancelResp
if err = client.Exec(req, &resp); err != nil {
tx.Rollback()
back.Suc(c, "申请失败", nil)
return
}
if resp.CancelStatus == 1 {
tx.Model(orderInfo).Update("apply_status", 12) // 取消申请失败
} else {
tx.Model(orderInfo).Update("apply_status", 11) // 取消申请成功
}
}
}
tx.Commit()
}
c.Set("status", "AfterApply")
c.Set("id", ids)
back.Suc(c, "申请成功,请等待商家审核", nil)
}
type CannelAfterOrderPem struct {
ID uint `json:"orderGoodsId"`
}
//撤销售后的申请
//有售后,且售后未完结,才能撤销
//refund_status=1,express_status=1ass_type=0才能申请撤销退款
func CannelAfterOrder(c *gin.Context) {
var p CannelAfterOrderPem
err := tools.ParseParams(&p, c)
if err != nil {
back.Fail(c, err.Error())
return
}
userlog, _ := common.GetManageUser(c)
var orderGoodsDea order.GoodsDetail
dbc.DB.First(&orderGoodsDea, "id=? and express_status=1 and ass_type!=0", p.ID)
if orderGoodsDea.ID <= 0 {
back.Fail(c, "该订单无法撤销售后")
return
}
//去撤销售后
dbc.DB.Table("recook_order_goods_detail").Where("id=?", p.ID).Update(map[string]interface{}{
"ass_type": 0,
})
var idlist []uint
var afterOrder after.RecookAfterSalesGoodsModel
dbc.DB.Order("id desc").First(&afterOrder, "order_goods_id=?", p.ID)
if afterOrder.Id > 0 {
dbc.DB.Model(&afterOrder).Updates(aftersales.Goods{
ReturnStatus: 6,
RejectReason: "买家主动撤销",
FinishTime: formatime.NewSecondNow(),
IsClosed: 1,
})
hook.AfterHook.Close(&afterOrder)
aftersalesLog := aftersales.AftersalesLog{
AsId: afterOrder.Id,
Title: "主动撤销",
Content: "买家主动撤销售后",
Ctime: formatime.NewSecondNow(),
User: userlog.Name,
UserId: userlog.Id,
}
dbc.DB.Create(&aftersalesLog)
}
idlist = append(idlist, afterOrder.Id)
c.Set("status", "AfterApply")
c.Set("id", idlist)
back.Suc(c, "", nil)
}