bilibili-backup/app/service/openplatform/ticket-item/dao/venue.go
2019-04-22 02:59:20 +00:00

450 lines
13 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Package dao venue
场馆venue=>场地place=>区域area的三级层次均为一对多
venue表冗余place_num表示场地数
place表通过ID对应place_polygon存有area的地理位置信息
*/
package dao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/service/openplatform/ticket-item/model"
"go-common/library/cache/redis"
"go-common/library/database/elastic"
"go-common/library/ecode"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
// RawVenues 批量获取场馆
func (d *Dao) RawVenues(c context.Context, ids []int64) (vl map[int64]*model.Venue, err error) {
vrows, err := d.db.Model(&model.Venue{}).Where("id in (?)", ids).Rows()
vl = make(map[int64]*model.Venue)
if err != nil {
log.Error("RawVenues(%v) error(%v)", ids, err)
return
}
defer vrows.Close()
for vrows.Next() {
var v model.Venue
err = d.db.ScanRows(vrows, &v)
vl[v.ID] = &v
}
return
}
// CacheVenues 缓存批量获取场馆
func (d *Dao) CacheVenues(c context.Context, ids []int64) (vl map[int64]*model.Venue, err error) {
var keys []interface{}
keyVidMap := make(map[string]int64, len(ids))
for _, id := range ids {
key := keyVenue(id)
if _, ok := keyVidMap[key]; !ok {
// duplicate pid
keyVidMap[key] = id
keys = append(keys, key)
}
}
conn := d.redis.Get(c)
defer conn.Close()
var data [][]byte
log.Info("MGET %v", model.JSONEncode(keys))
if data, err = redis.ByteSlices((conn.Do("MGET", keys))); err != nil {
log.Error("VenueList MGET %v ERR: %v", model.JSONEncode(keys), err)
return
}
vl = make(map[int64]*model.Venue)
for _, d := range data {
if d != nil {
var v *model.Venue
vl[v.ID] = v
json.Unmarshal(d, &v)
}
}
return
}
// AddCacheVenues 缓存场馆信息
func (d *Dao) AddCacheVenues(c context.Context, vl map[int64]*model.Venue) (err error) {
conn := d.redis.Get(c)
defer func() {
conn.Flush()
conn.Close()
}()
var data []interface{}
var keys []string
for k, v := range vl {
b, _ := json.Marshal(v)
key := keyVenue(k)
keys = append(keys, key)
data = append(data, key, b)
}
log.Info("MSET %v", keys)
if err = conn.Send("MSET", data...); err != nil {
return
}
for i := 0; i < len(data); i += 2 {
conn.Send("EXPIRE", data[i], CacheTimeout)
}
return
}
// VenueSearch 场馆搜索
func (d *Dao) VenueSearch(c context.Context, req *model.VenueSearchParam) (venues *model.VenueSearchList, err error) {
r := d.es.NewRequest("ticket_venue").Index("ticket_venue")
if req.ID > 0 {
r.WhereEq("id", req.ID)
} else if req.Name != "" {
r.WhereLike([]string{"name"}, []string{req.Name}, false, elastic.LikeLevelLow)
}
if req.ProvinceID > 0 {
r.WhereEq("province", req.ProvinceID)
}
if req.CityID > 0 {
r.WhereEq("city", req.CityID)
}
r.Order("ctime", elastic.OrderDesc).Ps(req.Ps).Pn(req.Pn)
log.Info(fmt.Sprintf("%s/x/admin/search/query?%s", d.c.URL.ElasticHost, r.Params()))
venues = new(model.VenueSearchList)
if err = r.Scan(c, venues); err != nil {
log.Error("VenueSearch(%v) r.Query(%s) error(%s)", req, r.Params(), err)
}
return
}
// AddVenue 添加场馆信息
func (d *Dao) AddVenue(c context.Context, venue *model.Venue) (err error) {
if err = d.db.Create(venue).Error; err != nil {
log.Error("添加场馆信息失败:%s", err)
err = ecode.NotModified
return
}
return
}
// UpdateVenue 编辑场馆信息
func (d *Dao) UpdateVenue(c context.Context, venue *model.Venue) (err error) {
// update venue with new info (using map can update the column with empty string)
if err = d.db.Table("venue").Where("id = ?", venue.ID).Updates(
map[string]interface{}{
"name": venue.Name,
"city": venue.City,
"province": venue.Province,
"district": venue.District,
"address_detail": venue.AddressDetail,
"status": venue.Status,
"traffic": venue.Traffic,
}).Error; err != nil {
log.Error("更新场馆信息失败:%s", err)
err = ecode.NotModified
return
}
return
}
// TxIncPlaceNum 增加场馆的场地数(事务)
func (d *Dao) TxIncPlaceNum(c context.Context, tx *gorm.DB, venueID int64) (err error) {
var oriVenue model.Venue
if err = tx.First(&oriVenue, venueID).Error; err != nil {
log.Error("查找对应的场馆信息ID:%d失败:%s", venueID, err)
err = ecode.NotModified
return
}
if err = tx.Model(&oriVenue).Updates(
map[string]interface{}{
"place_num": oriVenue.PlaceNum + 1,
}).Error; err != nil {
log.Error("更新场馆信息ID:%d失败:%s", venueID, err)
err = ecode.NotModified
return
}
return
}
// TxDecPlaceNum 减少场馆的场地数(事务)
func (d *Dao) TxDecPlaceNum(c context.Context, tx *gorm.DB, venueID int64) (err error) {
var oriVenue model.Venue
if err = tx.First(&oriVenue, venueID).Error; err != nil {
log.Error("查找对应的场馆信息ID:%d失败:%s", venueID, err)
err = ecode.NotModified
return
}
if oriVenue.PlaceNum < 1 {
log.Error("更新场馆信息ID:%d失败:场地数小于1", venueID)
err = ecode.NotModified
return
}
if err = tx.Model(&oriVenue).Updates(
map[string]interface{}{
"place_num": oriVenue.PlaceNum - 1,
}).Error; err != nil {
log.Error("更新场馆信息ID:%d失败:%s", venueID, err)
err = ecode.NotModified
return
}
return
}
// RawPlace 获取场地
func (d *Dao) RawPlace(c context.Context, id int64) (place *model.Place, err error) {
place = new(model.Place)
err = d.db.Model(&model.Place{}).First(&place, id).Scan(&place).Error
if err != nil {
log.Error("RawPlace(%v) error(%v)", id, err)
}
return
}
// RawPlacePolygon 获取场地坐标
func (d *Dao) RawPlacePolygon(c context.Context, id int64) (placePolygon *model.PlacePolygon, err error) {
placePolygon = new(model.PlacePolygon)
err = d.db.Model(&model.PlacePolygon{}).First(&placePolygon, id).Scan(&placePolygon).Error
if err != nil {
log.Error("RawPlacePolygon(%v) error(%v)", id, err)
}
return
}
// TxRawPlace 获取场地(事务)
func (d *Dao) TxRawPlace(c context.Context, tx *gorm.DB, id int64) (place *model.Place, err error) {
place = new(model.Place)
err = tx.Model(&model.Place{}).First(&place, id).Scan(&place).Error
if err != nil {
log.Error("TxRawPlace(%v) error(%v)", id, err)
}
return
}
// CachePlace 缓存获取场地
func (d *Dao) CachePlace(c context.Context, id int64) (place *model.Place, err error) {
var data []byte
key := keyPlace(id)
conn := d.redis.Get(c)
defer conn.Close()
log.Info("GET %v", key)
if data, err = redis.Bytes((conn.Do("GET", key))); err != nil {
if err == redis.ErrNil {
err = nil
}
return
}
json.Unmarshal(data, &place)
return
}
// AddCachePlace 缓存场地信息
func (d *Dao) AddCachePlace(c context.Context, id int64, place *model.Place) (err error) {
conn := d.redis.Get(c)
defer func() {
conn.Flush()
conn.Close()
}()
var data []interface{}
key := keyPlace(id)
data = append(data, key, place)
log.Info("SET %v", key)
if err = conn.Send("SET", data...); err != nil {
return
}
conn.Send("EXPIRE", data[0], CacheTimeout)
return
}
// TxAddPlace 添加场地信息(事务)
func (d *Dao) TxAddPlace(c context.Context, tx *gorm.DB, place *model.Place) (err error) {
if err = tx.Create(place).Error; err != nil {
log.Error("添加场地信息失败:%s", err)
err = ecode.NotModified
return
}
return
}
// TxUpdatePlace 编辑场地信息(事务)
func (d *Dao) TxUpdatePlace(c context.Context, tx *gorm.DB, place *model.Place) (err error) {
// find original place with id
if err = tx.Table("place").Where("id = ?", place.ID).Update(
map[string]interface{}{
"name": place.Name,
"base_pic": place.BasePic,
"status": place.Status,
"venue": place.Venue,
"d_width": place.DWidth,
"d_height": place.DHeight,
}).Error; err != nil {
log.Error("更新场地信息ID:%d失败:%s", place.ID, err)
err = ecode.NotModified
return
}
return
}
// TxAddOrUpdateAreaPolygon 添加或更新区域的场地坐标信息(事务)
func (d *Dao) TxAddOrUpdateAreaPolygon(c context.Context, tx *gorm.DB, place int64, area int64, coordinate *string) (err error) {
var (
oriPlacePolygon model.PlacePolygon
coordinates map[int64]string
found bool
)
if res := tx.First(&oriPlacePolygon, place); res.Error != nil {
if !res.RecordNotFound() {
log.Error("查找对应的场地坐标信息ID:%d失败:%s", place, res.Error)
err = ecode.NotModified
return
}
coordinates = make(map[int64]string)
oriPlacePolygon.ID = place
found = false
} else {
// 反序列化出coordinate字段
if err = json.Unmarshal([]byte(oriPlacePolygon.Coordinate), &coordinates); err != nil {
log.Error("数据库中的场地坐标信息ID:%d反序列化失败:%s", place, err)
err = ecode.NotModified
return
}
found = true
}
// 添加新的coordinate并序列化
coordinates[area] = *coordinate
b, _ := json.Marshal(coordinates)
oriPlacePolygon.Coordinate = string(b)
if found {
if err = tx.Model(&oriPlacePolygon).Updates(
map[string]interface{}{
"coordinate": oriPlacePolygon.Coordinate,
}).Error; err != nil {
log.Error("更新场地坐标信息ID:%d失败:%s", place, err)
err = ecode.NotModified
return
}
} else {
if err = tx.Create(oriPlacePolygon).Error; err != nil {
log.Error("创建场地坐标信息ID:%d失败:%s", place, err)
err = ecode.NotModified
return
}
}
*coordinate = oriPlacePolygon.Coordinate
return
}
// TxDelAreaPolygon 删除区域的场地坐标信息(事务)
func (d *Dao) TxDelAreaPolygon(c context.Context, tx *gorm.DB, place int64, area int64) (err error) {
var (
oriPlacePolygon model.PlacePolygon
coordinates map[int64]string
)
if err = tx.First(&oriPlacePolygon, place).Error; err != nil {
log.Error("查找对应的场地坐标信息ID:%d失败:%s", place, err)
err = ecode.NotModified
return
}
if oriPlacePolygon.Coordinate != "" {
if err = json.Unmarshal([]byte(oriPlacePolygon.Coordinate), &coordinates); err != nil {
log.Error("数据库中的场地坐标信息ID:%d反序列化失败:%s", place, err)
err = ecode.NotModified
return
}
} else {
coordinates = make(map[int64]string)
}
// 添加新的coordinate并序列化
if _, ok := coordinates[area]; !ok {
log.Error("数据库中的场地坐标信息ID:%d并未包含该区域ID:%d删除失败", place, area)
err = ecode.NotModified
return
}
delete(coordinates, area)
b, _ := json.Marshal(coordinates)
oriPlacePolygon.Coordinate = string(b)
if err = tx.Model(&oriPlacePolygon).Updates(
map[string]interface{}{
"coordinate": oriPlacePolygon.Coordinate,
}).Error; err != nil {
log.Error("创建场地坐标信息ID:%d失败:%s", place, err)
err = ecode.NotModified
return
}
return
}
// RawArea 获取区域
func (d *Dao) RawArea(c context.Context, id int64) (area *model.Area, err error) {
area = new(model.Area)
if err = d.db.Where("deleted_status = 0").First(&area, id).Error; err != nil {
log.Error("RawArea(%v) error(%v)", id, err)
}
return
}
// TxRawArea 获取区域
func (d *Dao) TxRawArea(c context.Context, tx *gorm.DB, id int64) (area *model.Area, err error) {
area = new(model.Area)
if err = tx.Where("deleted_status = 0").First(&area, id).Error; err != nil {
log.Error("TxRawArea(%v) error(%v)", id, err)
}
return
}
// TxRawDeletedAreaByAID 通过场地ID和自定义区域编号获取已删除的区域
func (d *Dao) TxRawDeletedAreaByAID(c context.Context, tx *gorm.DB, aid string, place int64) (area *model.Area, err error) {
area = new(model.Area)
if res := tx.Where("deleted_status = 1").Where("a_id = ? AND place = ?", aid, place).First(&area); res.Error != nil {
if res.RecordNotFound() {
return nil, nil
}
err = res.Error
log.Error("TxRawAreaByAID(%v, %v) error(%v)", aid, place, err)
}
return
}
// TxAddArea 添加区域信息(事务)
func (d *Dao) TxAddArea(c context.Context, tx *gorm.DB, area *model.Area) (err error) {
if res := tx.Create(area); res.Error != nil {
log.Error("添加区域信息失败:%s", res.Error)
err = ecode.NotModified
return
}
return
}
// TxUpdateArea 编辑区域信息(事务)
func (d *Dao) TxUpdateArea(c context.Context, tx *gorm.DB, area *model.Area) (err error) {
if err = tx.Table("area").Where("id = ?", area.ID).Updates(
map[string]interface{}{
"a_id": area.AID,
"name": area.Name,
"place": area.Place,
"deleted_status": area.DeletedStatus,
}).Error; err != nil {
log.Error("更新区域信息ID:%d失败:%s", area.ID, err)
err = ecode.NotModified
return
}
return
}
// TxDelArea 软删除区域(事务)
func (d *Dao) TxDelArea(c context.Context, tx *gorm.DB, id int64) (err error) {
if err = tx.Table("area").Where("id = ?", id).Updates(
map[string]interface{}{
"deleted_status": 1,
}).Error; err != nil {
log.Error("删除区域信息失败:%s", err)
err = ecode.NotModified
return
}
return
}