提交
This commit is contained in:
@@ -1789,6 +1789,7 @@ func SaveAndSendAlarmVendorSnapshot(ctx *jxcontext.Context, vendorIDs, storeIDs
|
|||||||
err = SaveStoresVendorSnapshot(db, curSnapshotAt, curSnapshotList)
|
err = SaveStoresVendorSnapshot(db, curSnapshotAt, curSnapshotList)
|
||||||
case 2:
|
case 2:
|
||||||
prevSnapshotList, err = dao.GetVendorStoreSnapshot(db, prevSnapshotAt)
|
prevSnapshotList, err = dao.GetVendorStoreSnapshot(db, prevSnapshotAt)
|
||||||
|
curSnapshotList, err = dao.GetVendorStoreSnapshot(db, curSnapshotAt) // 因为排序的原因,重新取一下
|
||||||
case 3:
|
case 3:
|
||||||
err = SendAlarmVendorSnapshot(ctx, task, prevSnapshotList, curSnapshotList)
|
err = SendAlarmVendorSnapshot(ctx, task, prevSnapshotList, curSnapshotList)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -495,3 +495,35 @@ func CreateQrOrBarCode(width, height int, codeType, srcData string) (imgBase64 s
|
|||||||
|
|
||||||
return imgBase64, err
|
return imgBase64, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 高德地图面积计算公式
|
||||||
|
// https://blog.csdn.net/zdb1314/article/details/80661602
|
||||||
|
func CalcPolygonAreaAutonavi(points [][2]float64) (area float64) {
|
||||||
|
sJ := float64(6378137)
|
||||||
|
Hq := float64(0.017453292519943295)
|
||||||
|
c := float64(sJ * Hq)
|
||||||
|
d := float64(0)
|
||||||
|
|
||||||
|
if 3 > len(points) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(points)-1; i++ {
|
||||||
|
h := points[i]
|
||||||
|
k := points[i+1]
|
||||||
|
u := h[0] * c * math.Cos(h[1]*Hq)
|
||||||
|
|
||||||
|
hhh := h[1] * c
|
||||||
|
v := k[0] * c * math.Cos(k[1]*Hq)
|
||||||
|
d = d + (u*k[1]*c - v*hhh)
|
||||||
|
}
|
||||||
|
|
||||||
|
g1 := points[len(points)-1]
|
||||||
|
point := points[0]
|
||||||
|
eee := g1[0] * c * math.Cos(g1[1]*Hq)
|
||||||
|
g2 := g1[1] * c
|
||||||
|
|
||||||
|
k := point[0] * c * math.Cos(point[1]*Hq)
|
||||||
|
d += eee*point[1]*c - k*g2
|
||||||
|
return 0.5 * math.Abs(d) / float64(1000000)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package jxutils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSplitSlice(t *testing.T) {
|
func TestSplitSlice(t *testing.T) {
|
||||||
@@ -101,3 +104,25 @@ func TestSplitStoreName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCalcPolygonAreaAutonavi(t *testing.T) {
|
||||||
|
// pointers := GetPolygonFromCircle(104.065702, 30.657488, 3000, 128)
|
||||||
|
// area := CalcPolygonAreaAutonavi(pointers)
|
||||||
|
// t.Logf("area:%f", area)
|
||||||
|
db := dao.GetDB()
|
||||||
|
storeList, err := dao.GetStoreList(db, nil, nil, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
strBuilder := &strings.Builder{}
|
||||||
|
strBuilder.WriteString("\n")
|
||||||
|
for _, v := range storeList {
|
||||||
|
if v.DeliveryRangeType == model.DeliveryRangeTypePolygon {
|
||||||
|
pointers := CoordinateStr2Points(v.DeliveryRange)
|
||||||
|
area1 := CalcPolygonAreaAutonavi(pointers)
|
||||||
|
strBuilder.WriteString(fmt.Sprintf("%d,%f\n", v.ID, area1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log(strBuilder.String())
|
||||||
|
}
|
||||||
|
|||||||
31
business/model/common.go
Normal file
31
business/model/common.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
var (
|
||||||
|
ValideMimeTypes = map[string]int{
|
||||||
|
"image/jpeg": 1,
|
||||||
|
"image/png": 1,
|
||||||
|
|
||||||
|
"video/mpeg": 1,
|
||||||
|
"video/mp4": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type DataResource struct {
|
||||||
|
ModelIDCUL
|
||||||
|
|
||||||
|
HashCode string `orm:"size(48);unique" json:"hash_code"`
|
||||||
|
ResoureType string // 资料的mime type
|
||||||
|
|
||||||
|
Name string `orm:"size(48)" json:"name"`
|
||||||
|
|
||||||
|
MainURL string
|
||||||
|
QiniuURL string
|
||||||
|
EbaiURL string
|
||||||
|
MtwmURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DataResource) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"HashCode", "ResoureType"},
|
||||||
|
}
|
||||||
|
}
|
||||||
2
business/model/dao/food_recipe.go
Normal file
2
business/model/dao/food_recipe.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
package dao
|
||||||
|
|
||||||
@@ -301,9 +301,11 @@ func FormalizeStoreStatus(db *DaoDB, storeID, storeStatus int) (err error) {
|
|||||||
|
|
||||||
func GetVendorStoreSnapshot(db *DaoDB, snapshotAt time.Time) (snapshotList []*model.VendorStoreSnapshot, err error) {
|
func GetVendorStoreSnapshot(db *DaoDB, snapshotAt time.Time) (snapshotList []*model.VendorStoreSnapshot, err error) {
|
||||||
sql := `
|
sql := `
|
||||||
SELECT *
|
SELECT t1.*
|
||||||
FROM vendor_store_snapshot t1
|
FROM vendor_store_snapshot t1
|
||||||
WHERE t1.snapshot_at = ?`
|
LEFT JOIN store t2 ON t2.id = t1.store_id
|
||||||
|
WHERE t1.snapshot_at = ?
|
||||||
|
ORDER BY t2.city_code, t1.store_id, t1.vendor_id`
|
||||||
err = GetRows(db, &snapshotList, sql, snapshotAt)
|
err = GetRows(db, &snapshotList, sql, snapshotAt)
|
||||||
return snapshotList, err
|
return snapshotList, err
|
||||||
}
|
}
|
||||||
|
|||||||
105
business/model/food_recipe.go
Normal file
105
business/model/food_recipe.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
const (
|
||||||
|
RecipeActionCollect = 1 // 收藏
|
||||||
|
RecipeActionUpvote = 2 // 顶
|
||||||
|
RecipeActionDownvote = 4 // 踩
|
||||||
|
)
|
||||||
|
|
||||||
|
type FoodRecipe struct {
|
||||||
|
ModelIDCULD
|
||||||
|
|
||||||
|
Name string `orm:"size(48)" json:"name"`
|
||||||
|
AuthorID string `orm:"size(48);column(author_id);index" json:"authorID"`
|
||||||
|
|
||||||
|
Description string `orm:"size(4096)" json:"description"`
|
||||||
|
Img string `orm:"size(48)" json:"img"`
|
||||||
|
TimeInMinute int `json:"timeInMinute"` // 大约时间(分钟)
|
||||||
|
UpvoteCount int `json:"upvoteCount"`
|
||||||
|
DownvoteCount int `json:"downvoteCount"`
|
||||||
|
Score int `json:"score"` // 分数
|
||||||
|
|
||||||
|
TagCategory string `orm:"size(48)" json:"tagCategory"` // 菜系(川,粤,鲁等等)
|
||||||
|
TagCookType string `orm:"size(48)" json:"tagCookType"` // 制作工艺(煮,炒,蒸等等)
|
||||||
|
TagTaste string `orm:"size(48)" json:"tagTaste"` // 口味(辣,麻,甜)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipe) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"Name", "AuthorID", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜谱步骤
|
||||||
|
type FoodRecipeStep struct {
|
||||||
|
ModelIDCULD
|
||||||
|
|
||||||
|
RecipeID int `orm:"column(recipe_id)" json:"recipeID"`
|
||||||
|
Index int8 `json:"index"` // 步骤序号,从1开始
|
||||||
|
|
||||||
|
Name string `orm:"size(48)" json:"name"`
|
||||||
|
Description string `orm:"size(4096)" json:"description"`
|
||||||
|
Img string `orm:"size(48)" json:"img"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipeStep) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"RecipeID", "Index", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜谱配料
|
||||||
|
type FoodRecipeItem struct {
|
||||||
|
ModelIDCULD
|
||||||
|
|
||||||
|
RecipeID int `orm:"column(recipe_id)" json:"recipeID"`
|
||||||
|
Index int8 `json:"index"` // 配料序号,从1开始
|
||||||
|
|
||||||
|
Name string `orm:"size(48)" json:"name"`
|
||||||
|
|
||||||
|
// SpecQuality float32 `json:"specQuality"`
|
||||||
|
// SpecUnit string `orm:"size(8)" json:"specUnit"` // 质量或容量
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipeItem) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"RecipeID", "Index", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜谱配料选择
|
||||||
|
type FoodRecipeItemChoice struct {
|
||||||
|
ModelIDCULD
|
||||||
|
|
||||||
|
RecipeID int `orm:"column(recipe_id)" json:"recipeID"`
|
||||||
|
Index int8 `json:"index"` // 配料序号,从1开始
|
||||||
|
SkuID int `orm:"column(sku_id)" json:"skuID"`
|
||||||
|
|
||||||
|
ChoiceIndex int8 `json:"choiceIndex"` // 选择序号,从1开始
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipeItemChoice) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"RecipeID", "Index", "SkuID", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FoodRecipeUser struct {
|
||||||
|
ModelIDCULD
|
||||||
|
|
||||||
|
RecipeID int `orm:"column(recipe_id)" json:"recipeID"`
|
||||||
|
UserID string `orm:"size(48);column(user_id)" json:"userID" compact:"userID"`
|
||||||
|
ActionType int8 `json:"actionType"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipeUser) TableUnique() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"RecipeID", "UserID", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FoodRecipeUser) TableIndex() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
[]string{"UserID", "RecipeID", "DeletedAt"},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -375,8 +375,8 @@ func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} {
|
|||||||
tel = store.Tel2
|
tel = store.Tel2
|
||||||
}
|
}
|
||||||
if tel != "" {
|
if tel != "" {
|
||||||
params["phone"] = tel
|
// params["phone"] = tel // 外卖客服联系电话,这个有时能修改,有时不能修改,暂时统一不改
|
||||||
params["ivr_phone"] = tel
|
params["ivr_phone"] = tel // 订单提醒电话
|
||||||
}
|
}
|
||||||
if store.VendorStoreID != "" {
|
if store.VendorStoreID != "" {
|
||||||
params["baidu_shop_id"] = store.VendorStoreID
|
params["baidu_shop_id"] = store.VendorStoreID
|
||||||
|
|||||||
93
business/userstore/food_recipe.go
Normal file
93
business/userstore/food_recipe.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package userstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FoodRecipeItemParam struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
SkuIDs []int `json:"skuIDs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FoodRecipeStepParam struct {
|
||||||
|
Name string `orm:"size(48)" json:"name"`
|
||||||
|
Description string `orm:"size(4096)" json:"description"`
|
||||||
|
Img string `orm:"size(48)" json:"img"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateFoodRecipe(ctx *jxcontext.Context, foodRecipe *model.FoodRecipe, itemList []*FoodRecipeItemParam, stepList []*FoodRecipeStepParam) (err error) {
|
||||||
|
db := dao.GetDB()
|
||||||
|
dao.Begin(db)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil || err != nil {
|
||||||
|
dao.Rollback(db)
|
||||||
|
if r != nil {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, foodRecipe.AuthorID = ctx.GetMobileAndUserID()
|
||||||
|
dao.WrapAddIDCULEntity(foodRecipe, ctx.GetUserName())
|
||||||
|
if err = dao.CreateEntity(db, foodRecipe); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for k, v := range itemList {
|
||||||
|
if len(v.SkuIDs) == 0 {
|
||||||
|
return fmt.Errorf("SkuIDs必须要有值")
|
||||||
|
}
|
||||||
|
skuIDs, err2 := dao.GetSkus(db, v.SkuIDs, nil, nil, nil)
|
||||||
|
if err = err2; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(v.SkuIDs) != len(skuIDs) {
|
||||||
|
return fmt.Errorf("某些SkuIDs不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
item := &model.FoodRecipeItem{
|
||||||
|
RecipeID: foodRecipe.ID,
|
||||||
|
Index: int8(k + 1),
|
||||||
|
Name: v.Name,
|
||||||
|
}
|
||||||
|
dao.WrapAddIDCULEntity(item, ctx.GetUserName())
|
||||||
|
if err = dao.CreateEntity(db, item); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for k2, v2 := range v.SkuIDs {
|
||||||
|
choice := &model.FoodRecipeItemChoice{
|
||||||
|
RecipeID: foodRecipe.ID,
|
||||||
|
Index: item.Index,
|
||||||
|
SkuID: v2,
|
||||||
|
|
||||||
|
ChoiceIndex: int8(k2 + 1),
|
||||||
|
}
|
||||||
|
dao.WrapAddIDCULEntity(choice, ctx.GetUserName())
|
||||||
|
if err = dao.CreateEntity(db, choice); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range stepList {
|
||||||
|
step := &model.FoodRecipeStep{
|
||||||
|
RecipeID: foodRecipe.ID,
|
||||||
|
Index: int8(k + 1),
|
||||||
|
Name: v.Name,
|
||||||
|
}
|
||||||
|
dao.WrapAddIDCULEntity(step, ctx.GetUserName())
|
||||||
|
if err = dao.CreateEntity(db, step); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dao.Commit(db)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateFoodRecipe(ctx *jxcontext.Context, foodRecipe *model.FoodRecipe, itemList []*FoodRecipeItemParam, stepList []*FoodRecipeStepParam) (err error) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
43
controllers/cmd_food_recipe.go
Normal file
43
controllers/cmd_food_recipe.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/userstore"
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FoodRecipeController struct {
|
||||||
|
beego.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title 创建活动
|
||||||
|
// @Description 创建活动
|
||||||
|
// @Param token header string true "认证token"
|
||||||
|
// @Param name formData string true "菜谱名"
|
||||||
|
// @Param description formData string true "菜谱描述"
|
||||||
|
// @Param img formData string true "图片""
|
||||||
|
// @Param timeInMinute formData string true "大约需要时间(分钟)"
|
||||||
|
// @Param recipeItems formData string true "菜谱配料"
|
||||||
|
// @Param recipeSteps formData string true "菜谱步骤"
|
||||||
|
// @Success 200 {object} controllers.CallResult
|
||||||
|
// @Failure 200 {object} controllers.CallResult
|
||||||
|
// @router /CreateFoodRecipe [post]
|
||||||
|
func (c *FoodRecipeController) CreateFoodRecipe() {
|
||||||
|
c.callCreateFoodRecipe(func(params *tFoodrecipeCreateFoodRecipeParams) (retVal interface{}, errCode string, err error) {
|
||||||
|
var (
|
||||||
|
foodRecipe *model.FoodRecipe
|
||||||
|
itemList []*userstore.FoodRecipeItemParam
|
||||||
|
stepList []*userstore.FoodRecipeStepParam
|
||||||
|
)
|
||||||
|
if err = jxutils.Strings2Objs(params.RecipeItems, &itemList, params.RecipeSteps, &stepList); err == nil {
|
||||||
|
foodRecipe = &model.FoodRecipe{
|
||||||
|
Name: params.Name,
|
||||||
|
Description: params.Description,
|
||||||
|
Img: params.Img,
|
||||||
|
}
|
||||||
|
err = userstore.CreateFoodRecipe(params.Ctx, foodRecipe, itemList, stepList)
|
||||||
|
}
|
||||||
|
return retVal, "", err
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -147,14 +147,12 @@ func (c *User2Controller) GetRolesUserList() {
|
|||||||
if err = jxutils.Strings2Objs(params.RoleNames, &roleNames, params.StoreIDs, &storeIDs); err == nil {
|
if err = jxutils.Strings2Objs(params.RoleNames, &roleNames, params.StoreIDs, &storeIDs); err == nil {
|
||||||
var roleList []*authz.RoleInfo
|
var roleList []*authz.RoleInfo
|
||||||
for _, roleName := range roleNames {
|
for _, roleName := range roleNames {
|
||||||
if len(storeIDs) == 0 {
|
|
||||||
roleList = append(roleList, autils.NewRole(roleName, 0))
|
|
||||||
} else {
|
|
||||||
if roleName == authz.StoreRoleBoss {
|
if roleName == authz.StoreRoleBoss {
|
||||||
for _, storeID := range storeIDs {
|
for _, storeID := range storeIDs {
|
||||||
roleList = append(roleList, autils.NewRole(roleName, storeID))
|
roleList = append(roleList, autils.NewRole(roleName, storeID))
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
roleList = append(roleList, autils.NewRole(roleName, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retVal, err = cms.GetRolesUserList(params.Ctx, roleList)
|
retVal, err = cms.GetRolesUserList(params.Ctx, roleList)
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ func Init() {
|
|||||||
orm.RegisterModel(&model.CasbinRule{})
|
orm.RegisterModel(&model.CasbinRule{})
|
||||||
orm.RegisterModel(&model.SensitiveWord{})
|
orm.RegisterModel(&model.SensitiveWord{})
|
||||||
orm.RegisterModel(&model.StoreScore{})
|
orm.RegisterModel(&model.StoreScore{})
|
||||||
|
orm.RegisterModel(&model.FoodRecipe{}, &model.FoodRecipeStep{}, &model.FoodRecipeItem{}, &model.FoodRecipeItemChoice{}, &model.FoodRecipeUser{})
|
||||||
|
|
||||||
// create table
|
// create table
|
||||||
orm.RunSyncdb("default", false, true)
|
orm.RunSyncdb("default", false, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,11 @@ func init() {
|
|||||||
&controllers.JxShopController{},
|
&controllers.JxShopController{},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
beego.NSNamespace("/foodrecipe",
|
||||||
|
beego.NSInclude(
|
||||||
|
&controllers.FoodRecipeController{},
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
beego.AddNamespace(ns)
|
beego.AddNamespace(ns)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user