初步实现门店的逻辑代码

This commit is contained in:
2025-06-05 11:43:25 +08:00
parent 8b63f72f99
commit 9d20953377
14 changed files with 167 additions and 64 deletions

13
internal/consts/redis.go Normal file
View File

@ -0,0 +1,13 @@
package consts
// Redis key 前缀
const (
// 用户相关
UserCode = "user:code:" // 用户验证码
UserToken = "user:token:" // 用户token
UserInfo = "user:info:" // 用户信息
// 系统相关
SystemConfig = "system:config" // 系统配置
SystemCache = "system:cache:" // 系统缓存
)

View File

@ -25,11 +25,13 @@ type FeedbacksColumns struct {
Title string // 反馈标题 Title string // 反馈标题
Content string // 反馈内容 Content string // 反馈内容
FeedbackType string // 反馈类型1=BUG2=建议3=投诉4=其他 FeedbackType string // 反馈类型1=BUG2=建议3=投诉4=其他
Status string // 处理状态:0=待处理,1=处理中,2=已处理,3=已驳回 Status string // 处理状态:1=待处理,2=处理中,3=已处理,4=已驳回
Reply string // 管理员回复内容 Reply string // 管理员回复内容
CreatedAt string // 反馈提交时间 CreatedAt string // 反馈提交时间
UpdatedAt string // 反馈更新时间 UpdatedAt string // 反馈更新时间
DeletedAt string // 软删除时间戳 DeletedAt string // 软删除时间戳
StoreId string // 门店唯一 id
MerchatId string // 商户唯一 id
} }
// feedbacksColumns holds the columns for the table feedbacks. // feedbacksColumns holds the columns for the table feedbacks.
@ -44,6 +46,8 @@ var feedbacksColumns = FeedbacksColumns{
CreatedAt: "created_at", CreatedAt: "created_at",
UpdatedAt: "updated_at", UpdatedAt: "updated_at",
DeletedAt: "deleted_at", DeletedAt: "deleted_at",
StoreId: "store_id",
MerchatId: "merchat_id",
} }
// NewFeedbacksDao creates and returns a new DAO object for table data access. // NewFeedbacksDao creates and returns a new DAO object for table data access.

View File

@ -27,7 +27,7 @@ type StoreAdminsColumns struct {
RealName string // 真实姓名 RealName string // 真实姓名
Phone string // 手机号 Phone string // 手机号
Email string // 邮箱 Email string // 邮箱
Role string // 角色1=店长2=收银员3=网管 IsPrimary string // 是否为主账号1=是0=否)
Status string // 状态1=正常2=禁用 Status string // 状态1=正常2=禁用
LastLoginAt string // 最后登录时间 LastLoginAt string // 最后登录时间
CreatedAt string // 创建时间 CreatedAt string // 创建时间
@ -45,7 +45,7 @@ var storeAdminsColumns = StoreAdminsColumns{
RealName: "real_name", RealName: "real_name",
Phone: "phone", Phone: "phone",
Email: "email", Email: "email",
Role: "role", IsPrimary: "is_primary",
Status: "status", Status: "status",
LastLoginAt: "last_login_at", LastLoginAt: "last_login_at",
CreatedAt: "created_at", CreatedAt: "created_at",

View File

@ -27,7 +27,7 @@ type StoresColumns struct {
Address string // 门店地址 Address string // 门店地址
ContactName string // 联系人姓名 ContactName string // 联系人姓名
ContactPhone string // 联系人电话 ContactPhone string // 联系人电话
Status string // 状态1=正常营业2=暂停营业3=已关闭 Status string // 状态1=正常营业2=暂停营业
CreatedAt string // 创建时间 CreatedAt string // 创建时间
UpdatedAt string // 更新时间 UpdatedAt string // 更新时间
DeletedAt string // 软删除时间戳 DeletedAt string // 软删除时间戳

View File

@ -2,13 +2,13 @@ package store
import ( import (
"context" "context"
"github.com/gogf/gf/v2/database/gdb"
"server/internal/consts"
"server/internal/dao" "server/internal/dao"
"server/internal/model" "server/internal/model"
"server/internal/model/do" "server/internal/model/do"
"server/internal/service" "server/internal/service"
"server/utility/ecode" "server/utility/ecode"
"github.com/gogf/gf/v2/database/gdb"
) )
type sStore struct { type sStore struct {
@ -26,6 +26,7 @@ func (s *sStore) List(ctx context.Context, in *model.StoreListIn) (out *model.St
} }
func (s *sStore) Create(ctx context.Context, in *model.StoreCreateIn) (out *model.CreateOut, err error) { func (s *sStore) Create(ctx context.Context, in *model.StoreCreateIn) (out *model.CreateOut, err error) {
out = &model.CreateOut{}
// 1. 检查门店名称是否重复 // 1. 检查门店名称是否重复
exist, err := dao.Stores.Ctx(ctx).Where(do.Stores{Name: in.Name}).Exist() exist, err := dao.Stores.Ctx(ctx).Where(do.Stores{Name: in.Name}).Exist()
if err != nil { if err != nil {
@ -36,11 +37,31 @@ func (s *sStore) Create(ctx context.Context, in *model.StoreCreateIn) (out *mode
} }
// 2. 使用事务处理数据插入 // 2. 使用事务处理数据插入
if err = dao.Stores.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { if err = dao.Stores.Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
// 2.1 生成唯一的门店编号 // 2.1 根据商户 id 获取所属的商户
// 2.2 插入门店基本信息 value, err := dao.MerchantAdmins.Ctx(ctx).WherePri(in.MerchantAdminId).Fields(dao.MerchantAdmins.Columns().MerchantId).Value()
// 2.3 创建门店管理员账号 if err != nil {
// 2.4 初始化门店配置 return ecode.Fail.Sub("获取商户ID出现异常")
}
// 2,2 生成门店的相关信息
// 2.3 插入门店数据
id, err := tx.Model(dao.Stores.Table()).Data(do.Stores{
MerchantId: value.Int64(),
}).InsertAndGetId()
if err != nil {
return ecode.Fail.Sub("新增门店出现异常")
}
//2.4 生成门店主管理账号
// 2.5 插入门店管理员数据
_, err = tx.Model(dao.StoreAdmins.Table()).Data(do.StoreAdmins{
StoreId: id,
}).Insert()
if err != nil {
return ecode.Fail.Sub("新增门店管理员出现异常")
}
return nil return nil
}); err != nil { }); err != nil {
return nil, err return nil, err
@ -48,30 +69,69 @@ func (s *sStore) Create(ctx context.Context, in *model.StoreCreateIn) (out *mode
return return
} }
func (s *sStore) Update(ctx context.Context, in *model.StoreUpdateIn) (out *model.UpdateOut, err error) { func (s *sStore) Update(ctx context.Context, in *model.StoreUpdateIn) (out *model.UpdateOut, err error) {
// 1. 验证门店是否存在 exist, err := dao.Stores.Ctx(ctx).WherePri(in.Id).Exist()
// 2. 验证操作权限(商户管理员或门店管理员) if err != nil {
// 3. 检查更新后的门店名称是否重复 return nil, ecode.Fail.Sub("查询门店出现异常")
// 4. 使用事务更新门店信息 }
// 5. 记录操作日志 if !exist {
return return nil, ecode.Params.Sub("门店不存在")
}
if in.OperatorId == 0 || (in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode) {
return nil, ecode.InvalidOperation.Sub("无权限操作")
}
if in.Name != "" {
exist, err = dao.Stores.Ctx(ctx).Where(dao.Stores.Columns().Name, in.Name).WhereNot(dao.Stores.Columns().Id, in.Id).Exist()
if err != nil {
return nil, ecode.Fail.Sub("检查门店名称出现异常")
}
if exist {
return nil, ecode.Params.Sub("门店名称已存在")
}
}
_, err = dao.Stores.Ctx(ctx).WherePri(in.Id).Data(do.Stores{
Name: in.Name,
Address: in.Address,
ContactName: in.ContactName,
ContactPhone: in.ContactPhone, // TODO暂定可以直接修改后续可能需要验证手机号
Status: in.Status,
}).Update()
if err != nil {
return nil, ecode.Fail.Sub("更新门店出现异常")
}
return &model.UpdateOut{Success: true}, nil
} }
func (s *sStore) Delete(ctx context.Context, in *model.StoreDeleteIn) (out *model.DeleteOut, err error) { func (s *sStore) Delete(ctx context.Context, in *model.StoreDeleteIn) (out *model.DeleteOut, err error) {
// 1. 验证门店是否存在 exist, err := dao.Stores.Ctx(ctx).WherePri(in.Id).Exist()
// 2. 验证操作权限(仅允许商户管理员) if err != nil {
// 3. 检查门店状态(是否有关联数据) return nil, ecode.Fail.Sub("查询门店出现异常")
// 4. 使用事务处理删除操作 }
// 5. 清理相关数据 if !exist {
// 6. 记录操作日志 return nil, ecode.Params.Sub("门店不存在")
return }
if in.OperatorId == 0 || (in.OperatorRole != consts.MerchantRoleCode) {
return nil, ecode.InvalidOperation.Sub("无权限操作")
}
// TODO: 是否需要检查门店下存在未发放奖励等
return &model.DeleteOut{Success: true}, nil
} }
func (s *sStore) Info(ctx context.Context, in *model.StoreInfoIn) (out *model.StoreInfoOut, err error) { func (s *sStore) Info(ctx context.Context, in *model.StoreInfoIn) (out *model.StoreInfoOut, err error) {
// 1. 验证门店是否存在 exist, err := dao.Stores.Ctx(ctx).Where(do.Stores{Id: in.Id}).Exist()
// 2. 验证访问权限 if err != nil {
// 3. 获取门店基本信息 return nil, ecode.Fail.Sub("查询门店出现异常")
// 4. 获取门店配置信息 }
// 5. 获取门店管理员信息 if !exist {
// 6. 获取门店统计信息 return nil, ecode.Params.Sub("门店不存在")
// 7. 处理敏感信息 }
// TODO 获取门店信息等相关信息
return return
} }

View File

@ -117,14 +117,19 @@ func (s *sUser) Info(ctx context.Context, in *model.UserInfoIn) (out *model.User
return return
} }
func (s *sUser) Code(ctx context.Context, in *model.UserCodeIn) (out *model.UserCodeOut, err error) {
return
}
func (s *sUser) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) { func (s *sUser) Update(ctx context.Context, in *model.UserUpdateIn) (out *model.UpdateOut, err error) {
return return
} }
func (s *sUser) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error) { func (s *sUser) BindPhone(ctx context.Context, in *model.UserBindPhoneIn) (out *model.UpdateOut, err error) {
// 绑定手机号,需要验证入参和缓存中的验证码时候相同
return return
} }
func (s *sUser) List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error) { func (s *sUser) List(ctx context.Context, in *model.UserListIn) (out *model.UserListOut, err error) {
// 用于系统管理员、商户、门店查看用户列表, 展示用户最近的相关信息
return return
} }

View File

@ -17,9 +17,11 @@ type Feedbacks struct {
Title interface{} // 反馈标题 Title interface{} // 反馈标题
Content interface{} // 反馈内容 Content interface{} // 反馈内容
FeedbackType interface{} // 反馈类型1=BUG2=建议3=投诉4=其他 FeedbackType interface{} // 反馈类型1=BUG2=建议3=投诉4=其他
Status interface{} // 处理状态:0=待处理,1=处理中,2=已处理,3=已驳回 Status interface{} // 处理状态:1=待处理,2=处理中,3=已处理,4=已驳回
Reply interface{} // 管理员回复内容 Reply interface{} // 管理员回复内容
CreatedAt *gtime.Time // 反馈提交时间 CreatedAt *gtime.Time // 反馈提交时间
UpdatedAt *gtime.Time // 反馈更新时间 UpdatedAt *gtime.Time // 反馈更新时间
DeletedAt *gtime.Time // 软删除时间戳 DeletedAt *gtime.Time // 软删除时间戳
StoreId interface{} // 门店唯一 id
MerchatId interface{} // 商户唯一 id
} }

View File

@ -19,7 +19,7 @@ type StoreAdmins struct {
RealName interface{} // 真实姓名 RealName interface{} // 真实姓名
Phone interface{} // 手机号 Phone interface{} // 手机号
Email interface{} // 邮箱 Email interface{} // 邮箱
Role interface{} // 角色1=店长2=收银员3=网管 IsPrimary interface{} // 是否为主账号1=是0=否)
Status interface{} // 状态1=正常2=禁用 Status interface{} // 状态1=正常2=禁用
LastLoginAt *gtime.Time // 最后登录时间 LastLoginAt *gtime.Time // 最后登录时间
CreatedAt *gtime.Time // 创建时间 CreatedAt *gtime.Time // 创建时间

View File

@ -19,7 +19,7 @@ type Stores struct {
Address interface{} // 门店地址 Address interface{} // 门店地址
ContactName interface{} // 联系人姓名 ContactName interface{} // 联系人姓名
ContactPhone interface{} // 联系人电话 ContactPhone interface{} // 联系人电话
Status interface{} // 状态1=正常营业2=暂停营业3=已关闭 Status interface{} // 状态1=正常营业2=暂停营业
CreatedAt *gtime.Time // 创建时间 CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 更新时间 UpdatedAt *gtime.Time // 更新时间
DeletedAt *gtime.Time // 软删除时间戳 DeletedAt *gtime.Time // 软删除时间戳

View File

@ -15,9 +15,11 @@ type Feedbacks struct {
Title string `json:"title" orm:"title" description:"反馈标题"` // 反馈标题 Title string `json:"title" orm:"title" description:"反馈标题"` // 反馈标题
Content string `json:"content" orm:"content" description:"反馈内容"` // 反馈内容 Content string `json:"content" orm:"content" description:"反馈内容"` // 反馈内容
FeedbackType int `json:"feedbackType" orm:"feedback_type" description:"反馈类型1=BUG2=建议3=投诉4=其他"` // 反馈类型1=BUG2=建议3=投诉4=其他 FeedbackType int `json:"feedbackType" orm:"feedback_type" description:"反馈类型1=BUG2=建议3=投诉4=其他"` // 反馈类型1=BUG2=建议3=投诉4=其他
Status int `json:"status" orm:"status" description:"处理状态:0=待处理,1=处理中,2=已处理,3=已驳回"` // 处理状态:0=待处理,1=处理中,2=已处理,3=已驳回 Status int `json:"status" orm:"status" description:"处理状态:1=待处理,2=处理中,3=已处理,4=已驳回"` // 处理状态:1=待处理,2=处理中,3=已处理,4=已驳回
Reply string `json:"reply" orm:"reply" description:"管理员回复内容"` // 管理员回复内容 Reply string `json:"reply" orm:"reply" description:"管理员回复内容"` // 管理员回复内容
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"反馈提交时间"` // 反馈提交时间 CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"反馈提交时间"` // 反馈提交时间
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"反馈更新时间"` // 反馈更新时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"反馈更新时间"` // 反馈更新时间
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳
StoreId int64 `json:"storeId" orm:"store_id" description:"门店唯一 id"` // 门店唯一 id
MerchatId int64 `json:"merchatId" orm:"merchat_id" description:"商户唯一 id"` // 商户唯一 id
} }

View File

@ -17,7 +17,7 @@ type StoreAdmins struct {
RealName string `json:"realName" orm:"real_name" description:"真实姓名"` // 真实姓名 RealName string `json:"realName" orm:"real_name" description:"真实姓名"` // 真实姓名
Phone string `json:"phone" orm:"phone" description:"手机号"` // 手机号 Phone string `json:"phone" orm:"phone" description:"手机号"` // 手机号
Email string `json:"email" orm:"email" description:"邮箱"` // 邮箱 Email string `json:"email" orm:"email" description:"邮箱"` // 邮箱
Role int `json:"role" orm:"role" description:"角色1=店长2=收银员3=网管"` // 角色1=店长2=收银员3=网管 IsPrimary bool `json:"isPrimary" orm:"is_primary" description:"是否为主账号1=是0=否)"` // 是否为主账号1=是0=否)
Status int `json:"status" orm:"status" description:"状态1=正常2=禁用"` // 状态1=正常2=禁用 Status int `json:"status" orm:"status" description:"状态1=正常2=禁用"` // 状态1=正常2=禁用
LastLoginAt *gtime.Time `json:"lastLoginAt" orm:"last_login_at" description:"最后登录时间"` // 最后登录时间 LastLoginAt *gtime.Time `json:"lastLoginAt" orm:"last_login_at" description:"最后登录时间"` // 最后登录时间
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间

View File

@ -17,7 +17,7 @@ type Stores struct {
Address string `json:"address" orm:"address" description:"门店地址"` // 门店地址 Address string `json:"address" orm:"address" description:"门店地址"` // 门店地址
ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名 ContactName string `json:"contactName" orm:"contact_name" description:"联系人姓名"` // 联系人姓名
ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话 ContactPhone string `json:"contactPhone" orm:"contact_phone" description:"联系人电话"` // 联系人电话
Status int `json:"status" orm:"status" description:"状态1=正常营业2=暂停营业3=已关闭"` // 状态1=正常营业2=暂停营业3=已关闭 Status int `json:"status" orm:"status" description:"状态1=正常营业2=暂停营业"` // 状态1=正常营业2=暂停营业
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间
DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳

View File

@ -17,12 +17,19 @@ type Store struct {
} }
type StoreCreateIn struct { type StoreCreateIn struct {
MerchantAdminId int64
Name string Name string
} }
type StoreUpdateIn struct { type StoreUpdateIn struct {
OperatorId int64
OperatorRole string
Id int Id int
Name string Name string
Address string
ContactPhone string
ContactName string
Status int
} }
type StoreListIn struct { type StoreListIn struct {
@ -44,4 +51,6 @@ type StoreInfoOut struct {
type StoreDeleteIn struct { type StoreDeleteIn struct {
Id int Id int
OperatorId int
OperatorRole string
} }

View File

@ -84,3 +84,11 @@ type UserListOut struct {
List []User List []User
Total int Total int
} }
type UserCodeIn struct {
UserId int // 绑定手机号时需要使用该字段
Phone string
}
type UserCodeOut struct {
}