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.
412 lines
11 KiB
412 lines
11 KiB
package service |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"encoding/json" |
|
"net/http" |
|
"strconv" |
|
"time" |
|
|
|
"go-common/app/admin/main/tv/model" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
|
|
"github.com/jinzhu/gorm" |
|
) |
|
|
|
const ( |
|
_configTableName = "tv_price_config" |
|
_valid = 0 |
|
_invalid = 1 |
|
_noPid = 0 |
|
_orderField = "ctime" |
|
_vip = 10 |
|
_online = 0 |
|
_delete = 2 |
|
) |
|
|
|
// PanelInfo select panel info by id |
|
func (s *Service) PanelInfo(id int64) (panelInfo *model.TvPriceConfigResp, err error) { |
|
if panelInfo, err = s.dao.GetById(id); err != nil { |
|
if err == gorm.ErrRecordNotFound { |
|
return nil, nil |
|
} |
|
log.Error("PanelInfo (%v) error(%v)", panelInfo, err) |
|
return |
|
} |
|
|
|
if panelInfo != nil { |
|
panelInfo.OriginPrice = panelInfo.Price |
|
hasDiscount, price, discountInfos := s.hasDiscount(nil, panelInfo.ID) |
|
if hasDiscount { |
|
panelInfo.Price = price |
|
} |
|
panelInfo.Items = discountInfos |
|
} |
|
return |
|
} |
|
|
|
// PanelStatus change panel status by id |
|
func (s *Service) PanelStatus(id, status int64) (err error) { |
|
var ( |
|
flag bool |
|
panelInfo *model.TvPriceConfigResp |
|
) |
|
if panelInfo, err = s.dao.GetById(id); err != nil { |
|
log.Error("PanelInfo (%v) error(%v)", panelInfo, err) |
|
} |
|
if status == _online && panelInfo.SuitType == _vip { |
|
if flag, err = s.hasOnlineUpgradeVipProduct(); err != nil { |
|
log.Error("GetValidUpgradeVipProduct Err %v", err) |
|
return |
|
} |
|
if flag { |
|
err = ecode.TVVipSuitTypeConflict |
|
return err |
|
} |
|
} |
|
|
|
if panelInfo.PID == 0 && status == _delete { |
|
if err = s.dao.DB.Table(_configTableName).Where("pid = ?", id).Update("status", _delete).Error; err != nil { |
|
log.Error("PanelStatus discount (%v) error(%v)", id, err) |
|
} |
|
} |
|
|
|
if err = s.dao.PanelStatus(id, status); err != nil { |
|
log.Error("PanelStatus (%v) error(%v)", id, err) |
|
} |
|
|
|
return |
|
} |
|
|
|
// SavePanel add or update panel info |
|
func (s *Service) SavePanel(c context.Context, panel *model.TvPriceConfig) (err error) { |
|
opType := s.c.YSTParam.Update |
|
//start tx |
|
tx := s.DB.Begin() |
|
|
|
if panel.PID != 0 { |
|
_, _, discounts := s.hasDiscount(nil, panel.PID) |
|
if flag := checkDisCountTime(discounts, panel); !flag { |
|
err = ecode.TvPriceTimeConflict |
|
return err |
|
} |
|
s.copyParentExtraField(panel) |
|
} |
|
|
|
if panel.ID != 0 && panel.PID == 0 { |
|
if err = tx.Table(_configTableName).Where("pid = ?", panel.ID). |
|
Update(map[string]interface{}{ |
|
"suit_type": panel.SuitType, |
|
"sub_type": panel.SubType, |
|
"selected": panel.Selected, |
|
"superscript": panel.Superscript, |
|
"month": panel.Month, |
|
}).Error; err != nil { |
|
log.Error("Update discount failed while update panel, Err %v", err) |
|
tx.Rollback() |
|
return |
|
} |
|
_, _, discounts := s.hasDiscount(tx, panel.ID) |
|
for _, discount := range discounts { |
|
if err = s.syncPanels(c, opType, &discount); err != nil { |
|
err = ecode.TvVipProdSyncErr |
|
tx.Rollback() |
|
return err |
|
} |
|
} |
|
} |
|
|
|
if panel.ID == 0 { |
|
opType = s.c.YSTParam.Insert |
|
|
|
if panel.PID == 0 { |
|
panel.Status = _invalid |
|
} else { |
|
s.copyParentExtraField(panel) |
|
} |
|
if flag := s.dao.ExistProduct(panel.ProductID); flag { |
|
err = ecode.TvVipProductExit |
|
return err |
|
} |
|
} |
|
|
|
if err = tx.Save(panel).Error; err != nil { |
|
log.Error("SavePanel %s, Err %v", panel, err) |
|
return err |
|
} |
|
if err = s.syncPanels(c, opType, panel); err != nil { |
|
err = ecode.TvVipProdSyncErr |
|
tx.Rollback() |
|
return err |
|
} |
|
tx.Commit() |
|
|
|
return |
|
} |
|
|
|
// PanelList get panle list |
|
func (s *Service) PanelList(platform, month, subType, suitType int64) (panels []*model.TvPriceConfigListResp, err error) { |
|
var ( |
|
db = s.dao.DB.Model(&model.TvPriceConfigListResp{}).Where("pid = ? and status in (?, ?)", _noPid, _valid, _invalid) |
|
) |
|
|
|
if platform != 0 { |
|
db = db.Where("platform = ?", platform) |
|
} |
|
if month != 0 { |
|
db = db.Where("month = ?", month) |
|
} |
|
if subType != -1 { |
|
db = db.Where("sub_type = ?", subType) |
|
} |
|
if suitType != -1 { |
|
db = db.Where("suit_type = ?", suitType) |
|
} |
|
|
|
if err = db.Order("suit_type, sub_type desc, month desc").Find(&panels).Error; err != nil { |
|
log.Error("OrderList %v, Err %v", panels, err) |
|
return panels, err |
|
} |
|
|
|
for _, panel := range panels { |
|
hasDiscount, price, _ := s.hasDiscount(nil, panel.ID) |
|
panel.OriginPrice = panel.Price |
|
|
|
if hasDiscount { |
|
panel.Price = price |
|
} |
|
} |
|
|
|
return |
|
} |
|
|
|
// HasDiscount Judge whether there is a discount |
|
func (s *Service) hasDiscount(tx *gorm.DB, id int64) (hasDiscount bool, price int64, panels []model.TvPriceConfig) { |
|
if tx == nil { |
|
tx = s.dao.DB |
|
} |
|
if err := tx.Table(_configTableName).Where("pid = ? and status = ?", id, _valid).Find(&panels).Error; err != nil { |
|
log.Error("HasDiscount %v, Err %v", id, err) |
|
return |
|
} |
|
nowTime := time.Now().Unix() |
|
|
|
for _, panel := range panels { |
|
if int64(panel.Stime) < nowTime && nowTime < int64(panel.Etime) { |
|
hasDiscount = true |
|
price = panel.Price |
|
return |
|
} |
|
} |
|
|
|
return |
|
} |
|
|
|
// checkDisCountTime check discount time conflict |
|
func checkDisCountTime(discounts []model.TvPriceConfig, panel *model.TvPriceConfig) (flag bool) { |
|
var ( |
|
startTime = panel.Stime |
|
endTime = panel.Etime |
|
) |
|
|
|
for _, discount := range discounts { |
|
// do not compare with self |
|
if panel.ID != discount.ID { |
|
if discount.Stime < startTime && startTime < discount.Etime { |
|
return false |
|
} |
|
|
|
if discount.Stime < endTime && endTime < discount.Etime { |
|
return false |
|
} |
|
|
|
if discount.Stime > startTime && endTime > discount.Etime { |
|
return false |
|
} |
|
} |
|
} |
|
|
|
return true |
|
} |
|
|
|
// checkRemotePanel check YST panel |
|
func (s *Service) checkRemotePanel(c context.Context) { |
|
var ( |
|
panels []*model.TvPriceConfigListResp |
|
) |
|
if err := s.dao.DB.Table(_configTableName).Order(_orderField).Find(&panels).Error; err != nil { |
|
log.Error("CheckRemotePanel Err %v", err) |
|
return |
|
} |
|
res, _ := s.getRemotePanels(c) |
|
remotePanels := res.Product |
|
|
|
panelMap := make(map[string]*model.TvPriceConfigListResp, len(panels)) |
|
remotePaneMap := make(map[string]model.Product, len(remotePanels)) |
|
for i := 0; i < len(panels); i++ { |
|
panelMap[panels[i].ProductID] = panels[i] |
|
} |
|
for i := 0; i < len(remotePanels); i++ { |
|
remotePaneMap[remotePanels[i].ID] = remotePanels[i] |
|
} |
|
|
|
for i := 0; i < len(panels); i++ { |
|
rp, exists := remotePaneMap[panels[i].ProductID] |
|
if exists { |
|
s.compareFiled(rp, panels[i]) |
|
} else { |
|
log.Error("Our panel not exists in YST, panel id is (%v)", panels[i].ProductID) |
|
} |
|
} |
|
|
|
for i := 0; i < len(remotePanels); i++ { |
|
p, exists := panelMap[remotePanels[i].ID] |
|
if exists { |
|
s.compareFiled(remotePanels[i], p) |
|
} else { |
|
log.Error("YST panel not exists in our db, panel id is (%v)", remotePanels[i].ID) |
|
} |
|
} |
|
} |
|
|
|
// getRemotePanels get YST panel |
|
func (s *Service) getRemotePanels(c context.Context) (res *model.RemotePanel, err error) { |
|
var ( |
|
req *http.Request |
|
) |
|
res = &model.RemotePanel{} |
|
params := map[string]string{ |
|
"vod_type": s.c.YSTParam.QueryPanelType, |
|
"source": s.c.YSTParam.Source, |
|
} |
|
reqBody, _ := json.Marshal(params) |
|
getRemotePanelUrl := s.c.URLConf.GetRemotePanelUrl |
|
if req, err = http.NewRequest(http.MethodPost, getRemotePanelUrl, bytes.NewReader(reqBody)); err != nil { |
|
log.Error("MerakNotify NewRequest Err %v, Url %v", err, getRemotePanelUrl) |
|
return |
|
} |
|
req.Header.Set("Content-Type", "application/json; charset=utf-8") |
|
if err = s.client.Do(c, req, &res); err != nil { |
|
log.Error("MergeUpInfo http req failed ,err:%v", err) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// compareFiled compare our panel field with YST |
|
func (s *Service) compareFiled(remotePanel model.Product, panel *model.TvPriceConfigListResp) { |
|
rpid := remotePanel.ID |
|
prodiuctId := panel.ProductID |
|
if rpid != prodiuctId { |
|
log.Error("PanelInfo id different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId) |
|
} |
|
if remotePanel.Price != panel.Price { |
|
log.Error("PanelInfo price different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId) |
|
} |
|
if remotePanel.Contract != strconv.Itoa(int(panel.SubType)) { |
|
log.Error("PanelInfo subType different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId) |
|
} |
|
if remotePanel.SuitType != panel.SuitType { |
|
log.Error("PanelInfo suitType different, Remote panel id is (%v), Our panel id is (%v)", rpid, prodiuctId) |
|
} |
|
if remotePanel.ProductDuration != strconv.FormatInt(panel.Month*31, 10) { |
|
log.Error("PanelInfo months different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId) |
|
} |
|
if remotePanel.Title != panel.ProductName { |
|
log.Error("PanelInfo productName different, Remote panel prodiuctId is (%v), Our panel id prodiuctId (%v)", rpid, prodiuctId) |
|
} |
|
if panel.PID != 0 { |
|
parentPanel, err := s.dao.GetById(panel.PID) |
|
if err != nil { |
|
log.Error("PanelInfo (%v) error(%v)", parentPanel, err) |
|
} |
|
if remotePanel.ComboPkgID != parentPanel.ProductID { |
|
log.Error("PanelInfo pid different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId) |
|
} |
|
} |
|
} |
|
|
|
// syncPanels send our panel to YST |
|
func (s *Service) syncPanels(c context.Context, opType string, panel *model.TvPriceConfig) (err error) { |
|
var ( |
|
req *http.Request |
|
res struct { |
|
Result string `json:"result"` |
|
Message string `json:"message"` |
|
} |
|
params struct { |
|
OpType string `json:"optype"` |
|
Source string `json:"source"` |
|
Product model.Product `json:"product"` |
|
} |
|
) |
|
params.OpType = opType |
|
params.Source = s.c.YSTParam.Source |
|
params.Product.ID = panel.ProductID |
|
params.Product.VodType = s.c.YSTParam.InsertPanelType |
|
params.Product.Title = panel.ProductName |
|
params.Product.ProductDuration = strconv.FormatInt(31*panel.Month, 10) |
|
params.Product.Description = panel.Remark |
|
params.Product.Contract = strconv.Itoa(int(panel.SubType)) |
|
if panel.PID != 0 { |
|
parentPanel, _ := s.dao.GetById(panel.PID) |
|
if parentPanel != nil { |
|
params.Product.ComboPkgID = parentPanel.ProductID |
|
params.Product.ComboDes = parentPanel.Remark |
|
} else { |
|
log.Error("Prarent PanelInfo not found, pid =(%v)", panel.PID) |
|
err = ecode.NothingFound |
|
return err |
|
} |
|
|
|
} |
|
params.Product.Price = panel.Price |
|
params.Product.SuitType = panel.SuitType |
|
|
|
reqBody, _ := json.Marshal(params) |
|
|
|
SyncPanelUrl := s.c.URLConf.SyncPanelUrl |
|
if req, err = http.NewRequest(http.MethodPost, SyncPanelUrl, bytes.NewReader(reqBody)); err != nil { |
|
log.Error("MerakNotify NewRequest Err %v, Url %v", err, SyncPanelUrl) |
|
return err |
|
} |
|
req.Header.Set("Content-Type", "application/json; charset=utf-8") |
|
if err = s.client.Do(c, req, &res); err != nil { |
|
log.Error("MergeUpInfo http req failed ,err:%v", err) |
|
return err |
|
} |
|
|
|
if res.Result != "SUCCESS" { |
|
err = ecode.TvVipProdSyncErr |
|
log.Info("Sync panel To YST Fail,err:%v", res.Message) |
|
return err |
|
} |
|
|
|
return |
|
} |
|
|
|
func (s *Service) hasOnlineUpgradeVipProduct() (flag bool, err error) { |
|
var ( |
|
panels []*model.TvPriceConfig |
|
) |
|
if err = s.dao.DB.Table(_configTableName).Where("suit_type = ? and status = ? and pid = ?", _vip, _valid, _noPid).Find(&panels).Error; err != nil { |
|
log.Error("GetValidUpgradeVipProduct Err %v", err) |
|
return |
|
} |
|
flag = !(len(panels) == 0) |
|
|
|
return |
|
} |
|
|
|
func (s *Service) copyParentExtraField(panel *model.TvPriceConfig) { |
|
parentPanel, _ := s.dao.GetById(panel.PID) |
|
if parentPanel != nil { |
|
panel.SuitType = parentPanel.SuitType |
|
panel.SubType = parentPanel.SubType |
|
panel.Selected = parentPanel.Selected |
|
panel.Superscript = parentPanel.Superscript |
|
panel.Month = parentPanel.Month |
|
} |
|
}
|
|
|