操作日志记录(beta)-门店商品
This commit is contained in:
@@ -143,6 +143,7 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
|
||||
"supplementType": model.SupplementTypeName,
|
||||
"operateType": model.OperateTypeName,
|
||||
"thingType": model.ThingTypeName,
|
||||
"apiFunctionName": model.ApiFunctionName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals/refutil"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
@@ -1037,7 +1039,7 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
|
||||
if tmpStatus := getSkuSaleStatus(inSkuBind, skuBindInfo); tmpStatus != model.StoreSkuBindStatusNA {
|
||||
skuBind.Status = tmpStatus
|
||||
}
|
||||
// err = AddEventDetail(model.OperateAdd, v.RealSkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), "", "")
|
||||
err = AddEventDetail(model.OperateAdd, v.RealSkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), "", "")
|
||||
setStoreSkuBindStatus(skuBind, model.SyncFlagNewMask)
|
||||
dao.WrapAddIDCULDEntity(skuBind, userName)
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(skuBind, false))
|
||||
@@ -1061,9 +1063,10 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
|
||||
}
|
||||
}
|
||||
} else {
|
||||
beforeMsg := *v
|
||||
skuBind = &v.StoreSkuBind
|
||||
if skuBindInfo.IsFocus == -1 && isCanChangePrice {
|
||||
// err = AddEventDetail(model.OperateDelete, skuBind.SkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), "", "")
|
||||
err = AddEventDetail(model.OperateDelete, skuBind.SkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), "", "")
|
||||
if num, err = dao.DeleteEntityLogically(db, skuBind, map[string]interface{}{
|
||||
model.FieldStatus: model.StoreSkuBindStatusDeleted,
|
||||
model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
|
||||
@@ -1117,12 +1120,13 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
|
||||
skuBind.StatusSaleEnd = skuBindInfo.StatusSaleEnd
|
||||
}
|
||||
}
|
||||
// if updateFieldMap != nil {
|
||||
// afterData := utils.MustMarshal(updateFieldMap)
|
||||
// mapresult := refutil.FindMapAndStructMixed(updateFieldMap, skuBind)
|
||||
// beforeData := utils.MustMarshal(mapresult)
|
||||
// AddEventDetail(model.OperateUpdate, v.RealSkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), string(beforeData), string(afterData))
|
||||
// }
|
||||
if len(updateFieldMap) > 0 {
|
||||
mapAfter := refutil.FindMapAndStructMixed(updateFieldMap, skuBind)
|
||||
afterData := utils.MustMarshal(mapAfter)
|
||||
mapBefore := refutil.FindMapAndStructMixed(updateFieldMap, beforeMsg)
|
||||
beforeData := utils.MustMarshal(mapBefore)
|
||||
err = AddEventDetail(model.OperateUpdate, v.RealSkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), string(beforeData), string(afterData))
|
||||
}
|
||||
if len(updateFieldMap) > 0 {
|
||||
updateFieldMap[model.FieldJdSyncStatus] = 1
|
||||
updateFieldMap[model.FieldEbaiSyncStatus] = 1
|
||||
@@ -1225,6 +1229,7 @@ func updateStoreSkusSaleWithoutSync(ctx *jxcontext.Context, storeID int, skuBind
|
||||
for _, skuBind := range storeSkuList {
|
||||
if v := skuBindSkuInfosMap[skuBind.SkuID]; v != nil && v.IsSale != 0 {
|
||||
if !(!utils.IsTimeZero(autoSaleTime) && ignoreDontSale && skuBind.Status == model.StoreSkuBindStatusDontSale) {
|
||||
statusResult := skuBind.Status
|
||||
if v.IsSale == -1 || !utils.IsTimeZero(autoSaleTime) {
|
||||
skuBind.Status = model.StoreSkuBindStatusDontSale
|
||||
} else if v.IsSale == 1 {
|
||||
@@ -1243,6 +1248,21 @@ func updateStoreSkusSaleWithoutSync(ctx *jxcontext.Context, storeID int, skuBind
|
||||
} else {
|
||||
kvs["AutoSaleAt"] = autoSaleTime
|
||||
}
|
||||
var status int
|
||||
if v.IsSale == -1 {
|
||||
status = model.StoreSkuBindStatusDontSale
|
||||
} else {
|
||||
status = model.StoreSkuBindStatusNormal
|
||||
}
|
||||
if status != statusResult {
|
||||
mapAfter := make(map[string]interface{})
|
||||
mapAfter["Status"] = status
|
||||
afterData := utils.MustMarshal(mapAfter)
|
||||
mapBefore := make(map[string]interface{})
|
||||
mapBefore["Status"] = statusResult
|
||||
beforeData := utils.MustMarshal(mapBefore)
|
||||
err = AddEventDetail(model.OperateUpdate, v.SkuID, model.ThingTypeSku, storeID, ctx.GetTrackInfo(), string(beforeData), string(afterData))
|
||||
}
|
||||
if num, err = dao.UpdateEntityLogically(db, skuBind, kvs, userName, nil); err != nil {
|
||||
dao.Rollback(db)
|
||||
return nil, err
|
||||
@@ -1300,7 +1320,6 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co
|
||||
if copyMode != CopyStoreSkuModeFresh && copyMode != CopyStoreSkuModeUpdate && copyMode != CopyStoreSkuModeUpdatePrice {
|
||||
return 0, fmt.Errorf("不支持的拷贝模式:%s", copyMode)
|
||||
}
|
||||
|
||||
db := dao.GetDB()
|
||||
fromStore, err := checkStoreExisting(db, fromStoreID)
|
||||
if err != nil {
|
||||
@@ -1559,6 +1578,15 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co
|
||||
globals.SugarLogger.Debugf("CopyStoreSkus fromStoreID:%d, toStoreID:%d, trackInfo:%s num3:%d", fromStoreID, toStoreID, ctx.GetTrackInfo(), num2)
|
||||
dao.Commit(db)
|
||||
}
|
||||
mapAfter := make(map[string]interface{})
|
||||
mapAfter["ToStoreIDs"] = toStoreIDs
|
||||
mapAfter["CopyMode"] = copyMode
|
||||
mapAfter["IsScale"] = isScale
|
||||
afterData := utils.MustMarshal(mapAfter)
|
||||
mapBefore := make(map[string]interface{})
|
||||
mapBefore["FromStoreID"] = fromStoreID
|
||||
beforeData := utils.MustMarshal(mapBefore)
|
||||
err = AddEventDetail(model.OperateCopyStoreSkus, 0, model.ThingTypeSku, fromStoreID, ctx.GetTrackInfo(), string(beforeData), string(afterData))
|
||||
return num, errList.GetErrListAsOne()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
@@ -52,3 +55,43 @@ func AddOperateEventDetail(operateEventDetail *model.OperateEventDetail) (err er
|
||||
dao.Commit(db)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteOperateEventAndDetail(ctx *jxcontext.Context, deleteTime time.Time) (err error) {
|
||||
db := dao.GetDB()
|
||||
dao.Begin(db)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
dao.Rollback(db)
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
dao.DeleteOperateEventDetail(db, deleteTime)
|
||||
dao.DeleteOperateEvent(db, deleteTime)
|
||||
dao.Commit(db)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetOperateEvents(ctx *jxcontext.Context, apiFunction, name string, operateType int, skuIDs, storeIDs []int, fromTime, toTime string, offset, pageSize int) (pageInfo *model.PagedInfo, err error) {
|
||||
var (
|
||||
fromTimeP time.Time
|
||||
toTimeP time.Time
|
||||
)
|
||||
db := dao.GetDB()
|
||||
if fromTime != "" {
|
||||
fromTimeP = utils.Str2Time(fromTime)
|
||||
}
|
||||
if toTime != "" {
|
||||
toTimeP = utils.Str2Time(toTime)
|
||||
}
|
||||
pageSize = jxutils.FormalizePageSize(pageSize)
|
||||
offset = jxutils.FormalizePageOffset(offset)
|
||||
operateEventExt, totalCount, err := dao.GetOperateEvents(db, apiFunction, name, operateType, skuIDs, storeIDs, fromTimeP, toTimeP, offset, pageSize)
|
||||
if err != nil {
|
||||
return pageInfo, err
|
||||
}
|
||||
pageInfo = &model.PagedInfo{
|
||||
Data: operateEventExt,
|
||||
TotalCount: totalCount,
|
||||
}
|
||||
return pageInfo, err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/report"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
@@ -226,6 +228,8 @@ func doDailyWork() {
|
||||
orderman.RefreshOrdersWithoutJxStoreID(jxcontext.AdminCtx, "", "", true, true)
|
||||
//刷新京东门店的等级
|
||||
cms.RefreshJdLevel(jxcontext.AdminCtx)
|
||||
//删除操作日志
|
||||
event.DeleteOperateEventAndDetail(jxcontext.AdminCtx, time.Now().AddDate(0, 0, -7))
|
||||
}
|
||||
|
||||
func RefreshRealMobile(ctx *jxcontext.Context, vendorID int, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
|
||||
@@ -106,9 +106,10 @@ var (
|
||||
}
|
||||
|
||||
OperateTypeName = map[int]string{
|
||||
OperateAdd: "新增",
|
||||
OperateUpdate: "修改",
|
||||
OperateDelete: "删除",
|
||||
OperateAdd: "新增",
|
||||
OperateUpdate: "修改",
|
||||
OperateDelete: "删除",
|
||||
OperateCopyStoreSkus: "复制门店商品",
|
||||
}
|
||||
|
||||
ThingTypeName = map[int]string{
|
||||
@@ -118,6 +119,12 @@ var (
|
||||
ThingTypeStore: "门店",
|
||||
}
|
||||
|
||||
ApiFunctionName = map[string]string{
|
||||
"UpdateStoresSkus": "门店商品管理",
|
||||
"UpdateStoresSkusSale": "门店商品可售状态修改",
|
||||
"CopyStoreSkus": "京西门店商品复制到京西",
|
||||
}
|
||||
|
||||
MultiStoresVendorMap = map[int]int{
|
||||
VendorIDJD: 1,
|
||||
VendorIDMTWM: 0,
|
||||
@@ -255,9 +262,10 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
OperateAdd = 1 //新增操作
|
||||
OperateUpdate = 2 //修改操作
|
||||
OperateDelete = 4 //删除操作
|
||||
OperateAdd = 2 //新增操作
|
||||
OperateUpdate = 1 //修改操作
|
||||
OperateDelete = 4 //删除操作
|
||||
OperateCopyStoreSkus = 3 //复制门店商品
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
101
business/model/dao/event.go
Normal file
101
business/model/dao/event.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
type OperateEventExt struct {
|
||||
model.OperateEvent
|
||||
Detail []*model.OperateEventDetail
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func DeleteOperateEventDetail(db *DaoDB, deleteTime time.Time) (err error) {
|
||||
sql := `
|
||||
DELETE FROM a
|
||||
USING operate_event_detail a,operate_event b
|
||||
WHERE a.access_uuid = b.access_uuid
|
||||
AND b.created_at < ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
deleteTime,
|
||||
}
|
||||
_, err = ExecuteSQL(db, sql, sqlParams...)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteOperateEvent(db *DaoDB, deleteTime time.Time) (err error) {
|
||||
sql := `
|
||||
DELETE FROM operate_event
|
||||
WHERE created_at < ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
deleteTime,
|
||||
}
|
||||
_, err = ExecuteSQL(db, sql, sqlParams...)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetOperateEvents(db *DaoDB, apiFunction, name string, operateType int, skuIDs, storeIDs []int, fromTime, toTime time.Time, offset, pageSize int) (operateEventExt []*OperateEventExt, totalCount int, err error) {
|
||||
sql := `
|
||||
SELECT SQL_CALC_FOUND_ROWS DISTINCT a.*, c.name
|
||||
FROM operate_event a
|
||||
LEFT JOIN operate_event_detail b ON a.access_uuid = b.access_uuid
|
||||
LEFT JOIN user c ON c.user_id = a.user_id
|
||||
WHERE 1=1
|
||||
`
|
||||
sqlParams := []interface{}{}
|
||||
if name != "" {
|
||||
sql += " AND c.name LIKE ?"
|
||||
sqlParams = append(sqlParams, "%"+name+"%")
|
||||
}
|
||||
if !utils.IsTimeZero(fromTime) {
|
||||
sql += " AND a.created_at >= ?"
|
||||
sqlParams = append(sqlParams, fromTime)
|
||||
}
|
||||
if !utils.IsTimeZero(toTime) {
|
||||
sql += " AND a.created_at <= ?"
|
||||
sqlParams = append(sqlParams, toTime)
|
||||
}
|
||||
if apiFunction != "" {
|
||||
sql += " AND a.api_function = ?"
|
||||
sqlParams = append(sqlParams, apiFunction)
|
||||
}
|
||||
if operateType != 0 {
|
||||
sql += " AND b.operate_type = ?"
|
||||
sqlParams = append(sqlParams, operateType)
|
||||
}
|
||||
if len(skuIDs) > 0 {
|
||||
sql += " AND b.thing_id IN (" + GenQuestionMarks(len(skuIDs)) + ")"
|
||||
sqlParams = append(sqlParams, skuIDs)
|
||||
}
|
||||
if len(storeIDs) > 0 {
|
||||
sql += " AND b.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
|
||||
sqlParams = append(sqlParams, storeIDs)
|
||||
}
|
||||
sql += " LIMIT ? OFFSET ?"
|
||||
sqlParams = append(sqlParams, pageSize, offset)
|
||||
Begin(db)
|
||||
defer Commit(db)
|
||||
if err = GetRows(db, &operateEventExt, sql, sqlParams...); err == nil {
|
||||
totalCount = GetLastTotalRowCount(db)
|
||||
}
|
||||
for _, v := range operateEventExt {
|
||||
var details []*model.OperateEventDetail
|
||||
sql := `
|
||||
SELECT *
|
||||
FROM operate_event_detail
|
||||
WHERE access_uuid = ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
v.AccessUUID,
|
||||
}
|
||||
err = GetRows(db, &details, sql, sqlParams...)
|
||||
v.Detail = details
|
||||
}
|
||||
return operateEventExt, totalCount, err
|
||||
}
|
||||
@@ -24,8 +24,8 @@ type OperateEventDetail struct {
|
||||
ThingType int `json:"thingType"` //各字段类型
|
||||
StoreID int `orm:"column(store_id)" json:"storeID"`
|
||||
AccessUUID string `orm:"column(access_uuid)" json:"accessUUID"`
|
||||
BeforeData string `orm:"size(255)" json:"beforeData"`
|
||||
AfterData string `orm:"size(255)" json:"afterData"`
|
||||
BeforeData string `orm:"size(3200)" json:"beforeData"`
|
||||
AfterData string `orm:"size(3200)" json:"afterData"`
|
||||
}
|
||||
|
||||
func (v *OperateEventDetail) TableIndex() [][]string {
|
||||
|
||||
37
controllers/event.go
Normal file
37
controllers/event.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
// 操作事件明细相关API
|
||||
type EventController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// @Title 查询操作日志事件明细
|
||||
// @Description 查询操作日志事件明细
|
||||
// @Param token header string true "认证token"
|
||||
// @Param apiFunction query string false "功能名"
|
||||
// @Param name query string false "操作人姓名,支持模糊查询"
|
||||
// @Param operateType query int false "操作类型,1为修改,2为新增,4为删除"
|
||||
// @Param skuIDs query string false "商品ID列表"
|
||||
// @Param storeIDs query string false "门店ID列表"
|
||||
// @Param fromTime query string false "开始日期(包含),格式(2006-01-02 00:00:00)"
|
||||
// @Param toTime query string false "结束日期(包含),格式(2006-01-02 00:00:00)"
|
||||
// @Param offset query int false "门店列表起始序号(以0开始,缺省为0)"
|
||||
// @Param pageSize query int false "门店列表页大小(缺省为30)"
|
||||
// @Success 200 {object} controllers.CallResult
|
||||
// @Failure 200 {object} controllers.CallResult
|
||||
// @router /GetOperateEvents [get]
|
||||
func (c *EventController) GetOperateEvents() {
|
||||
var storeIDList, skuIDList []int
|
||||
c.callGetOperateEvents(func(params *tEventGetOperateEventsParams) (retVal interface{}, errCode string, err error) {
|
||||
if jxutils.Strings2Objs(params.StoreIDs, &storeIDList, params.SkuIDs, &skuIDList); err == nil {
|
||||
retVal, err = event.GetOperateEvents(params.Ctx, params.ApiFunction, params.Name, params.OperateType, skuIDList, storeIDList, params.FromTime, params.ToTime, params.Offset, params.PageSize)
|
||||
}
|
||||
return retVal, "", err
|
||||
})
|
||||
}
|
||||
@@ -394,6 +394,15 @@ func init() {
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetOperateEvents",
|
||||
Router: `/GetOperateEvents`,
|
||||
AllowHTTPMethods: []string{"get"},
|
||||
MethodParams: param.Make(),
|
||||
Filters: nil,
|
||||
Params: nil})
|
||||
|
||||
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:FinancialController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:FinancialController"],
|
||||
beego.ControllerComments{
|
||||
Method: "GetOrdersFinancial",
|
||||
|
||||
@@ -136,6 +136,11 @@ func init() {
|
||||
&controllers.YongHuiController{},
|
||||
),
|
||||
),
|
||||
beego.NSNamespace("/event",
|
||||
beego.NSInclude(
|
||||
&controllers.EventController{},
|
||||
),
|
||||
),
|
||||
)
|
||||
beego.AddNamespace(ns)
|
||||
|
||||
@@ -149,6 +154,7 @@ func init() {
|
||||
beego.AutoRouter(&controllers.WeixinController{})
|
||||
beego.AutoRouter(&controllers.DingDingController{})
|
||||
beego.AutoRouter(&controllers.WXPayController{})
|
||||
beego.AutoRouter(&controllers.EventController{})
|
||||
|
||||
// 如下都是用于检测存活的空接口
|
||||
beego.Any("/", func(ctx *beecontext.Context) {
|
||||
|
||||
Reference in New Issue
Block a user