diff --git a/api/admin.crm.api b/api/admin.crm.api index 50237c84..74f79174 100644 --- a/api/admin.crm.api +++ b/api/admin.crm.api @@ -1,6 +1,7 @@ import "admin/crm/customerdomain/lead.api" import "admin/crm/customerdomain/customer.api" import "admin/crm/customerdomain/registercode.api" +import "admin/crm/membership/membership.api" import "admin/crm/market/media.api" import "admin/crm/market/store.api" import "admin/crm/market/mgm.api" diff --git a/api/admin/crm/customerdomain/customer.api b/api/admin/crm/customerdomain/customer.api index 81d2a93e..208bb986 100644 --- a/api/admin/crm/customerdomain/customer.api +++ b/api/admin/crm/customerdomain/customer.api @@ -17,7 +17,7 @@ info( service PowerX { @doc "查询客户" @handler GetCustomer - get /customers/:id (GetCustomerReqeuest) returns (GetCustomerReply) + get /customers/:id (GetCustomerRequest) returns (GetCustomerReply) @doc "获取客户分页列表" @handler ListCustomersPage @@ -78,7 +78,7 @@ type ( ) type ( - GetCustomerReqeuest { + GetCustomerRequest { Id int64 `path:"id"` } diff --git a/api/admin/crm/customerdomain/lead.api b/api/admin/crm/customerdomain/lead.api index bcc3f177..c786c8d6 100644 --- a/api/admin/crm/customerdomain/lead.api +++ b/api/admin/crm/customerdomain/lead.api @@ -17,7 +17,7 @@ info( service PowerX { @doc "查询线索" @handler GetLead - get /leads/:id (GetLeadReqeuest) returns (GetLeadReply) + get /leads/:id (GetLeadRequest) returns (GetLeadReply) @doc "获取线索分页列表" @handler ListLeadsPage @@ -76,7 +76,7 @@ type ( ) type ( - GetLeadReqeuest { + GetLeadRequest { Id int64 `path:"id"` } diff --git a/api/admin/crm/customerdomain/registercode.api b/api/admin/crm/customerdomain/registercode.api index 064bd3f6..abde10ff 100644 --- a/api/admin/crm/customerdomain/registercode.api +++ b/api/admin/crm/customerdomain/registercode.api @@ -17,7 +17,7 @@ info( service PowerX { @doc "查询注册码" @handler GetRegisterCode - get /register-codes/:id (GetRegisterCodeReqeuest) returns (GetRegisterCodeReply) + get /register-codes/:id (GetRegisterCodeRequest) returns (GetRegisterCodeReply) @doc "获取注册码分页列表" @handler ListRegisterCodesPage @@ -57,7 +57,7 @@ type ( ) type ( - GetRegisterCodeReqeuest { + GetRegisterCodeRequest { Id int64 `path:"id"` } diff --git a/api/admin/crm/market/brandstory.api b/api/admin/crm/market/brandstory.api new file mode 100644 index 00000000..3b0fbd8c --- /dev/null +++ b/api/admin/crm/market/brandstory.api @@ -0,0 +1,161 @@ +syntax = "v1" + +info( + title: "品牌故事" + desc: "品牌故事" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + +@server( + group: admin/crm/market/brandstory + prefix: /api/v1/admin/market + middleware: EmployeeJWTAuth +) + +service PowerX { + @doc "查询品牌故事列表" + @handler ListStoresPage + get /brand-stories/page-list (ListStoresPageRequest) returns (ListStoresPageReply) + + @doc "查询品牌故事详情" + @handler GetStore + get /brand-stories/:id (GetStoreRequest) returns (GetStoreReply) + + + @doc "创建品牌故事" + @handler CreateStore + post /brand-stories (CreateStoreRequest) returns (CreateStoreReply) + + + @doc "全量品牌故事" + @handler PutStore + put /brand-stories/:id (PutStoreRequest) returns (PutStoreReply) + + + @doc "删除品牌故事" + @handler DeleteStore + delete /brand-stories/:id (DeleteStoreRequest) returns (DeleteStoreReply) + + +} + +type ( + StoreArtisanSpecific { + ArtisanId int64 `json:"artisanId,optional"` + } + + + + StoreArtisan { + EmployeeId int64 `json:"employeeId,optional"` + Name string `json:"name,optional"` + Level int8 `json:"level,optional"` + Gender bool `json:"gender,optional"` + birthday string `json:"birthday,optional"` + PhoneNumber string `json:"phoneNumber,optional"` + CoverURL string `json:"coverURL,optional"` + WorkNo string `json:"workNo,optional"` + Email string `json:"email,optional"` + Experience string `json:"experience,optional"` + Specialty string `json:"specialty,optional"` + Certificate string `json:"certificate,optional"` + Address string `json:"address,optional"` + ArtisanSpecific StoreArtisanSpecific `json:"artisanSpecific,optional"` + } + + Store { + Id int64 `json:"id,optional"` + Name string `json:"name"` + StoreEmployeeId int64 `json:"storeEmployeeId,optional"` + ContactNumber string `json:"contactNumber"` + Email string `json:"email,optional"` + Address string `json:"address"` + Description string `json:"description,optional"` + Longitude float32 `json:"longitude,optional"` + Latitude float32 `json:"latitude,optional"` + StartWork string `json:"startWork,optional"` + EndWork string `json:"endWork,optional"` + Artisans []*StoreArtisan `json:"artisans,optional"` + CreatedAt string `json:"createdAt,optional"` + + CoverImageId int64 `json:"coverImageId,optional"` + CoverImage *MediaResource `json:"coverImage,optional"` + DetailImageIds []int64 `json:"detailImageIds,optional"` + DetailImages []*MediaResource `json:"detailImages,optional"` + } +) +type ( + ListStoresPageRequest struct { + Ids []int64 `form:"ids,optional"` + LikeName string `form:"likeName,optional"` + OrderBy string `form:"orderBy,optional"` + PageIndex int `form:"pageIndex,optional"` + PageSize int `form:"pageSize,optional"` + } + + + ListStoresPageReply struct { + List []*Store `json:"list"` + PageIndex int `json:"pageIndex"` + PageSize int `json:"pageSize"` + Total int64 `json:"total"` + } +) + +type ( + CreateStoreRequest struct { + Store + } + + CreateStoreReply struct { + StoreId int64 `json:"id"` + } +) + +type ( + GetStoreRequest struct { + StoreId int64 `path:"id"` + } + + GetStoreReply struct { + *Store + } +) + + +type ( + PutStoreRequest struct { + StoreId int64 `path:"id"` + Store + } + + PutStoreReply struct { + *Store + } +) + + +type ( + DeleteStoreRequest struct { + StoreId int64 `path:"id"` + } + + DeleteStoreReply struct { + StoreId int64 `json:"id"` + } +) + + +type ( + AssignStoreManagerRequest { + Id int64 `path:"id"` + EmployeeId int64 `json:"employeeId"` + } + + AssignStoreManagerReply { + Store + } +) diff --git a/api/admin/crm/market/store.api b/api/admin/crm/market/store.api index cb462ac8..dc94db7d 100644 --- a/api/admin/crm/market/store.api +++ b/api/admin/crm/market/store.api @@ -49,17 +49,6 @@ type ( ArtisanId int64 `json:"artisanId,optional"` } -// StoreImage { -// Id int64 `json:"id,optional"` -// Filename string `json:"filename,optional"` -// Size int64 `json:"size,optional"` -// Url string `json:"url,optional"` -// BucketName string `json:"bucketName,optional"` -// IsLocalStored bool `json:"isLocalStored,optional"` -// ContentType string `json:"contentType,optional"` -// ResourceType string `json:"resourceType,optional"` -// } - StoreArtisan { EmployeeId int64 `json:"employeeId,optional"` Name string `json:"name,optional"` diff --git a/api/admin/crm/membership/membership.api b/api/admin/crm/membership/membership.api new file mode 100644 index 00000000..47552eef --- /dev/null +++ b/api/admin/crm/membership/membership.api @@ -0,0 +1,49 @@ +syntax = "v1" + +info( + title: "会籍管理" + desc: "会籍管理" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + +@server( + group: admin/crm/membership + prefix: /api/v1/admin/membership + middleware: EmployeeJWTAuth +) + +service PowerX { + @doc "查询会籍" + @handler GetCustomer + get /customers/:id (GetMembershipRequest) returns (GetMembershipReply) +} + +type ( + Membership { + Id int64 `json:"id,optional"` + + Name string `json:"name,optional"` + MainMembershipId int64 `json:"mainMembershipId,optional"` + OrderId int64 `json:"orderId,optional"` + OrderItemId int64 `json:"orderItemId,optional"` + CustomerId int64 `json:"customerId,optional"` + ProductId int64 `json:"productId,optional"` + StartDate string `json:"startDate,optional"` + EndDate string `json:"endDate,optional"` + Status int `json:"status,optional"` + Type int `json:"type,optional"` + ExtendPeriod bool `json:"extendPeriod,optional"` + Plan int `json:"plan,optional"` + + } + + GetMembershipRequest{ + Id int64 `path:"id"` + } + + GetMembershipReply { + *Membership + } +) \ No newline at end of file diff --git a/api/mp.api b/api/mp.api index cc839d8c..55458fee 100644 --- a/api/mp.api +++ b/api/mp.api @@ -1,5 +1,7 @@ import "mp/dictionary.api" import "mp/customerdomain/authcustomer.api" +import "mp/customerdomain/customer.api" +import "mp/membership/membership.api" import "mp/market/store.api" import "mp/market/media.api" import "mp/product/artisan.api" @@ -12,3 +14,5 @@ import "mp/trade/shippingaddress.api" import "mp/trade/deliveryaddress.api" import "mp/trade/billingaddress.api" import "mp/trade/payment.api" +import "mp/trade/token.api" +import "mp/infoorganization/category.api" diff --git a/api/mp/customerdomain/authcustomer.api b/api/mp/customerdomain/authcustomer.api index 49759a0f..3ac8cd53 100644 --- a/api/mp/customerdomain/authcustomer.api +++ b/api/mp/customerdomain/authcustomer.api @@ -16,6 +16,10 @@ info( service PowerX { + @doc "微信小程序Token验证" + @handler ValidToken + get /validToken (MPValidTokenRequest) returns (MPValidTokenReply) + @doc "微信小程序登录" @handler Login post /login (MPCustomerLoginRequest) returns (MPCustomerLoginAuthReply) @@ -32,6 +36,14 @@ service PowerX { type ( + MPValidTokenRequest { + Token string `form:"token"` + } + MPValidTokenReply { + Valid bool `json:"valid"` + Reason string `json:"reason"` + } + MPCustomerLoginRequest { Code string `json:"code"` } diff --git a/api/mp/customerdomain/customer.api b/api/mp/customerdomain/customer.api new file mode 100644 index 00000000..a16ce179 --- /dev/null +++ b/api/mp/customerdomain/customer.api @@ -0,0 +1,26 @@ +syntax = "v1" + +info( + title: "客户服务" + desc: "客户服务" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + +@server( + group: mp/crm/customer + prefix: /api/v1/mp/customer + middleware: MPCustomerJWTAuth, MPCustomerGet +) + +service PowerX { + @doc "获取用户信息" + @handler GetUserInfo + get /user-info returns (GetUserInfoReplyForMP) +} + +type GetUserInfoReplyForMP{ + *Customer +} \ No newline at end of file diff --git a/api/mp/infoorganization/category.api b/api/mp/infoorganization/category.api new file mode 100644 index 00000000..0c1afa2a --- /dev/null +++ b/api/mp/infoorganization/category.api @@ -0,0 +1,47 @@ +syntax = "v1" + +info( + title: "类别" + desc: "类别" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + +@server( + group: mp/infoorganization/category + prefix: /api/v1/mp/info-organization +) + +service PowerX { + @doc "查询类别列表" + @handler ListCategoryTree + get /category-tree (ListCategoryTreeRequest) returns (ListCategoryTreeReply) + + @doc "查询类别详情" + @handler GetCategory + get /categories/:id (GetCategoryRequest) returns (GetCategoryReply) + + + @doc "创新类别" + @handler CreateCategory + post /categories (CreateCategoryRequest) returns (CreateCategoryReply) + + @doc "修改类别" + @handler UpdateCategory + put /categories/:id (UpdateCategoryRequest) returns (UpdateCategoryReply) + + + @doc "修改类别父级" + @handler PatchCategory + patch /categories/:id (PatchCategoryRequest) returns (PatchCategoryReply) + + + @doc "删除类别" + @handler DeleteCategory + delete /categories/:id (DeleteCategoryRequest) returns (DeleteCategoryReply) +} + + + + diff --git a/api/mp/infoorganization/label.api b/api/mp/infoorganization/label.api new file mode 100644 index 00000000..6dfa6fce --- /dev/null +++ b/api/mp/infoorganization/label.api @@ -0,0 +1,47 @@ +syntax = "v1" + +info( + title: "框架标签" + desc: "框架标签" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + + +@server( + group: web/infoorganization/label + prefix: /api/v1/web/info-organization + middleware: WebCustomerJWTAuth +) + +service PowerX { + @doc "查询框架标签列表" + @handler ListLabelTree + get /label-tree (ListLabelTreeRequest) returns (ListLabelTreeReply) + + @doc "查询框架标签详情" + @handler GetLabel + get /labels/:id (GetLabelRequest) returns (GetLabelReply) + + + @doc "创新框架标签" + @handler CreateLabel + post /labels (CreateLabelRequest) returns (CreateLabelReply) + + @doc "修改框架标签" + @handler UpdateLabel + put /labels/:id (UpdateLabelRequest) returns (UpdateLabelReply) + + + @doc "修改框架标签父级" + @handler PatchLabel + patch /labels/:id (PatchLabelRequest) returns (PatchLabelReply) + + + @doc "删除框架标签" + @handler DeleteLabel + delete /labels/:id (DeleteLabelRequest) returns (DeleteLabelReply) +} + diff --git a/api/mp/infoorganization/tag.api b/api/mp/infoorganization/tag.api new file mode 100644 index 00000000..a20ecfc8 --- /dev/null +++ b/api/mp/infoorganization/tag.api @@ -0,0 +1,45 @@ +syntax = "v1" + +info( + title: "碎片标签" + desc: "碎片标签" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + +@server( + group: web/infoorganization/tag + prefix: /api/v1/web/info-organization + middleware: WebCustomerJWTAuth +) + +service PowerX { + @doc "查询碎片标签列表" + @handler ListTagTree + get /tag-tree (ListTagTreeRequest) returns (ListTagTreeReply) + + @doc "查询碎片标签详情" + @handler GetTag + get /tags/:id (GetTagRequest) returns (GetTagReply) + + + @doc "创新碎片标签" + @handler CreateTag + post /tags (CreateTagRequest) returns (CreateTagReply) + + @doc "修改碎片标签" + @handler UpdateTag + put /tags/:id (UpdateTagRequest) returns (UpdateTagReply) + + + @doc "修改碎片标签父级" + @handler PatchTag + patch /tags/:id (PatchTagRequest) returns (PatchTagReply) + + + @doc "删除碎片标签" + @handler DeleteTag + delete /tags/:id (DeleteTagRequest) returns (DeleteTagReply) +} diff --git a/api/mp/membership/membership.api b/api/mp/membership/membership.api new file mode 100644 index 00000000..a3d1673b --- /dev/null +++ b/api/mp/membership/membership.api @@ -0,0 +1,36 @@ +syntax = "v1" + +info( + title: "会籍管理" + desc: "会籍管理" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + +@server( + group: mp/crm/membership + prefix: /api/v1/mp/membership + middleware: MPCustomerJWTAuth, MPCustomerGet +) + +service PowerX { + @doc "查询会籍" + @handler GetCustomerMembership + get /customer (GetCustomerMembershipByTypeRequest) returns (GetCustomerMembershipByTypeReply) + + @doc "查询会籍" + @handler GetMembership + get /:id (GetMembershipRequest) returns (GetMembershipReply) +} + +type ( + GetCustomerMembershipByTypeRequest { + TypeId int64 `form:"typeId"` + } + + GetCustomerMembershipByTypeReply { + *Membership + } +) \ No newline at end of file diff --git a/api/mp/trade/token.api b/api/mp/trade/token.api new file mode 100644 index 00000000..eec490eb --- /dev/null +++ b/api/mp/trade/token.api @@ -0,0 +1,37 @@ +syntax = "v1" + +info( + title: "代币管理" + desc: "代币管理" + author: "MichaelHu" + email: "matrix-x@artisan-cloud.com" + version: "v1" +) + + +@server( + group: mp/crm/trade/token + prefix: /api/v1/mp/trade/token + middleware: MPCustomerJWTAuth, MPCustomerGet +) + +service PowerX { + @doc "查询代币" + @handler GetCustomerTokenBalance + get /balance returns (GetCustomerBalanceReply) +} + +type ( + TokenBalance { + Id int64 `json:"id,optional" desc:"代币ID"` + + Balance float64 `json:"balance" desc:"代币余额"` + Usage float64 `json:"usage" desc:"使用代币"` + UnusedTicketsCount int64 `json:"unusedTicketsCount" desc:"可继续使用的ticket"` + ReservedToken float64 `json:"reservedToken" desc:"预扣代币"` + } + + GetCustomerBalanceReply { + *TokenBalance + } +) \ No newline at end of file diff --git a/api/web/customerdomain/customer.api b/api/web/customerdomain/customer.api index 95ef1099..a9272c55 100644 --- a/api/web/customerdomain/customer.api +++ b/api/web/customerdomain/customer.api @@ -26,7 +26,7 @@ service PowerX { @doc "获取用户信息" @handler GetUserInfo - get /user-info returns (GetUserInfoReplyToWeb) + get /user-info returns (GetUserInfoReplyForWeb) } @@ -59,7 +59,7 @@ type ( } - GetUserInfoReplyToWeb { + GetUserInfoReplyForWeb { *Customer } ) \ No newline at end of file diff --git a/cmd/ctl/database/migrate/powerx.go b/cmd/ctl/database/migrate/powerx.go index 2281dfa7..80b213fa 100644 --- a/cmd/ctl/database/migrate/powerx.go +++ b/cmd/ctl/database/migrate/powerx.go @@ -6,7 +6,6 @@ import ( "PowerX/internal/model" "PowerX/internal/model/crm/customerdomain" "PowerX/internal/model/crm/market" - "PowerX/internal/model/crm/membership" "PowerX/internal/model/crm/product" "PowerX/internal/model/crm/trade" infoorganizatoin "PowerX/internal/model/infoorganization" @@ -60,7 +59,7 @@ func (m *PowerMigrator) AutoMigrate() { // customer domain _ = m.db.AutoMigrate( &customerdomain.Lead{}, &customerdomain.Contact{}, customerdomain.RegisterCode{}, - &customerdomain.Customer{}, &membership.Membership{}, + &customerdomain.Customer{}, &operation.Membership{}, ) _ = m.db.AutoMigrate(&wechat.WechatOACustomer{}, &wechat.WechatMPCustomer{}, &wechat.WeWorkExternalContact{}) _ = m.db.AutoMigrate( @@ -87,7 +86,10 @@ func (m *PowerMigrator) AutoMigrate() { _ = m.db.AutoMigrate(&trade.OrderStatusTransition{}, &trade.PivotOrderToInventoryLog{}) _ = m.db.AutoMigrate(&trade.Payment{}, &trade.PaymentItem{}) _ = m.db.AutoMigrate(&trade.RefundOrder{}, &trade.RefundOrderItem{}) - _ = m.db.AutoMigrate(&trade.TokenBalance{}, &trade.TokenExchangeRatio{}, &trade.TokenExchangeRecord{}) + _ = m.db.AutoMigrate(&trade.TokenBalance{}, + &trade.TokenExchangeRatio{}, &trade.TokenExchangeRecord{}, + trade.TokenReservation{}, trade.TokenTransaction{}, + ) // custom migrate.AutoMigrateCustom(m.db) diff --git a/cmd/ctl/database/seed/datadictionary/datadictionary.go b/cmd/ctl/database/seed/datadictionary/datadictionary.go index 94fce59d..6f979d28 100644 --- a/cmd/ctl/database/seed/datadictionary/datadictionary.go +++ b/cmd/ctl/database/seed/datadictionary/datadictionary.go @@ -50,7 +50,10 @@ func DefaultDataDictionary() (data []*model.DataDictionaryType) { defaultPaymentTypeDataDictionary(), defaultPaymentStatusDataDictionary(), defaultTokenCategoryDataDictionary(), + defaultTokenTransactionDataDictionary(), defaultMGMDataDictionary(), + defaultMembershipTypeDataDictionary(), + defaultMembershipStatusDataDictionary(), } return data diff --git a/cmd/ctl/database/seed/datadictionary/membershipstatus.go b/cmd/ctl/database/seed/datadictionary/membershipstatus.go new file mode 100644 index 00000000..be7ef0d1 --- /dev/null +++ b/cmd/ctl/database/seed/datadictionary/membershipstatus.go @@ -0,0 +1,43 @@ +package datadictionary + +import ( + "PowerX/internal/model" +) + +func defaultMembershipStatusDataDictionary() *model.DataDictionaryType { + return &model.DataDictionaryType{ + Items: []*model.DataDictionaryItem{ + &model.DataDictionaryItem{ + Key: operation.MembershipStatusActive, + Type: operation.TypeMembershipStatus, + Name: "活跃状态", + Value: operation.MembershipStatusActive, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipStatusInactive, + Type: operation.TypeMembershipStatus, + Name: "非活跃状态", + Value: operation.MembershipStatusInactive, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipStatusExpired, + Type: operation.TypeMembershipStatus, + Name: "已过期", + Value: operation.MembershipStatusExpired, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipStatusCancelled, + Type: operation.TypeMembershipStatus, + Name: "已取消", + Value: operation.MembershipStatusCancelled, + Sort: 0, + }, + }, + Type: operation.TypeMembershipStatus, + Name: "会籍状态", + Description: "会籍状态区分", + } +} diff --git a/cmd/ctl/database/seed/datadictionary/membershiptype.go b/cmd/ctl/database/seed/datadictionary/membershiptype.go new file mode 100644 index 00000000..bda2eef4 --- /dev/null +++ b/cmd/ctl/database/seed/datadictionary/membershiptype.go @@ -0,0 +1,51 @@ +package datadictionary + +import ( + "PowerX/internal/model" +) + +func defaultMembershipTypeDataDictionary() *model.DataDictionaryType { + return &model.DataDictionaryType{ + Items: []*model.DataDictionaryItem{ + &model.DataDictionaryItem{ + Key: operation.MembershipTypeBase, + Type: operation.TypeMembershipType, + Name: "基本会籍", + Value: operation.MembershipTypeBase, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipTypeNormal, + Type: operation.TypeMembershipType, + Name: "普通会籍", + Value: operation.MembershipTypeNormal, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipTypePremium, + Type: operation.TypeMembershipType, + Name: "高级会籍", + Value: operation.MembershipTypePremium, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipTypeVIP, + Type: operation.TypeMembershipType, + Name: "VIP会籍", + Value: operation.MembershipTypeVIP, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: operation.MembershipTypeCustom, + Type: operation.TypeMembershipType, + Name: "定制会籍", + Value: operation.MembershipTypeCustom, + Sort: 0, + }, + }, + Type: operation.TypeMembershipType, + Name: "会籍类型", + Description: "会籍的类型区分", + } + +} diff --git a/cmd/ctl/database/seed/datadictionary/token.go b/cmd/ctl/database/seed/datadictionary/token.go index f3c268bc..99e6e678 100644 --- a/cmd/ctl/database/seed/datadictionary/token.go +++ b/cmd/ctl/database/seed/datadictionary/token.go @@ -64,3 +64,83 @@ func defaultTokenCategoryDataDictionary() *model.DataDictionaryType { } } + +func defaultTokenTransactionDataDictionary() *model.DataDictionaryType { + return &model.DataDictionaryType{ + Items: []*model.DataDictionaryItem{ + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypePurchase, + Type: trade.TypeTokenTransactionType, + Name: "购买", + Value: trade.TokenTransactionTypePurchase, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeReward, + Type: trade.TypeTokenTransactionType, + Name: "奖励", + Value: trade.TokenTransactionTypeReward, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeExchange, + Type: trade.TypeTokenTransactionType, + Name: "兑换", + Value: trade.TokenTransactionTypeExchange, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeSpending, + Type: trade.TypeTokenTransactionType, + Name: "消费", + Value: trade.TokenTransactionTypeSpending, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeRefund, + Type: trade.TypeTokenTransactionType, + Name: "退款", + Value: trade.TokenTransactionTypeRefund, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeExpired, + Type: trade.TypeTokenTransactionType, + Name: "过期", + Value: trade.TokenTransactionTypeExpired, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeGift, + Type: trade.TypeTokenTransactionType, + Name: "赠送", + Value: trade.TokenTransactionTypeGift, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeInterest, + Type: trade.TypeTokenTransactionType, + Name: "利息", + Value: trade.TokenTransactionTypeInterest, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeInvest, + Type: trade.TypeTokenTransactionType, + Name: "投资", + Value: trade.TokenTransactionTypeInvest, + Sort: 0, + }, + &model.DataDictionaryItem{ + Key: trade.TokenTransactionTypeOther, + Type: trade.TypeTokenTransactionType, + Name: "其他", + Value: trade.TokenTransactionTypeOther, + Sort: 0, + }, + }, + Type: trade.TypeTokenTransactionType, + Name: "代币的流水", + Description: "代币的使用交易流水记录", + } +} diff --git a/cmd/ctl/database/seed/token.go b/cmd/ctl/database/seed/token.go index 6961f6b8..5b45f2cd 100644 --- a/cmd/ctl/database/seed/token.go +++ b/cmd/ctl/database/seed/token.go @@ -36,5 +36,4 @@ func DefaultExchangeRecord(db *gorm.DB) []*trade.TokenExchangeRatio { Ratio: 1, }, } - } diff --git a/go.mod b/go.mod index 4942bb38..b0003a89 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ go 1.21 require ( github.com/ArtisanCloud/PowerLibs/v3 v3.0.16 github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 - github.com/ArtisanCloud/PowerWeChat/v3 v3.1.13 + github.com/ArtisanCloud/PowerWeChat/v3 v3.1.15 github.com/Blank-Xu/sql-adapter v0.0.0-20210714092925-0bdd0d548758 github.com/brianvoe/gofakeit/v6 v6.21.0 github.com/casbin/casbin/v2 v2.60.0 diff --git a/go.sum b/go.sum index 15aaadca..4ba2ade4 100644 --- a/go.sum +++ b/go.sum @@ -389,8 +389,8 @@ github.com/ArtisanCloud/PowerLibs/v3 v3.0.16 h1:LBgAuPIkNKGh0fL/HK4HHSqWuoMIbRtf github.com/ArtisanCloud/PowerLibs/v3 v3.0.16/go.mod h1:nuUJGlLNKhBmo5nLBqJOuKD2+oDoJkWaqzxxhkLPo5s= github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 h1:P+erNlErr+X2v7Et+yTWaTfIRhw+HfpAPdvNIEwk9Gw= github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7/go.mod h1:VZQNCvcK/rldF3QaExiSl1gJEAkyc5/I8RLOd3WFZq4= -github.com/ArtisanCloud/PowerWeChat/v3 v3.1.13 h1:AwIrC2ICmdzyCrI2blvVRD6SU98b1c1oJSzqVD1d2iU= -github.com/ArtisanCloud/PowerWeChat/v3 v3.1.13/go.mod h1:i4quVLQxrTJ4Yg5A5ZKvmkH+P+8VP6+2VzJPc3B6qTo= +github.com/ArtisanCloud/PowerWeChat/v3 v3.1.15 h1:QK8/v5pNyzgiYx6A7BJcoNxLIPkNUVnOQvVfTKG9j9c= +github.com/ArtisanCloud/PowerWeChat/v3 v3.1.15/go.mod h1:i4quVLQxrTJ4Yg5A5ZKvmkH+P+8VP6+2VzJPc3B6qTo= github.com/Blank-Xu/sql-adapter v0.0.0-20210714092925-0bdd0d548758 h1:L4iwZiJYTNirz4Er7Bw2+AVzW8VCpCGYc8luHc3y5lU= github.com/Blank-Xu/sql-adapter v0.0.0-20210714092925-0bdd0d548758/go.mod h1:GlBcPpgzETyqz83HIUFEMobVY38h1fOFXgwpy7T64xE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= diff --git a/internal/config/config.go b/internal/config/config.go index 07cb02a1..c5c7bce1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -16,8 +16,10 @@ type Database struct { } type RedisBase struct { - Host string + Host string + //Username string Password string + //DB int } type WeWork struct { diff --git a/internal/handler/admin/crm/customerdomain/customer/getcustomerhandler.go b/internal/handler/admin/crm/customerdomain/customer/getcustomerhandler.go index 1a4c291b..8fe7241e 100644 --- a/internal/handler/admin/crm/customerdomain/customer/getcustomerhandler.go +++ b/internal/handler/admin/crm/customerdomain/customer/getcustomerhandler.go @@ -11,7 +11,7 @@ import ( func GetCustomerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.GetCustomerReqeuest + var req types.GetCustomerRequest if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/handler/admin/crm/customerdomain/leader/getleadhandler.go b/internal/handler/admin/crm/customerdomain/leader/getleadhandler.go index 2160d985..3acc7faa 100644 --- a/internal/handler/admin/crm/customerdomain/leader/getleadhandler.go +++ b/internal/handler/admin/crm/customerdomain/leader/getleadhandler.go @@ -11,7 +11,7 @@ import ( func GetLeadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.GetLeadReqeuest + var req types.GetLeadRequest if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/handler/admin/crm/customerdomain/registercode/getregistercodehandler.go b/internal/handler/admin/crm/customerdomain/registercode/getregistercodehandler.go index 4edf45ea..80eada06 100644 --- a/internal/handler/admin/crm/customerdomain/registercode/getregistercodehandler.go +++ b/internal/handler/admin/crm/customerdomain/registercode/getregistercodehandler.go @@ -11,7 +11,7 @@ import ( func GetRegisterCodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.GetRegisterCodeReqeuest + var req types.GetRegisterCodeRequest if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/handler/admin/crm/membership/getcustomerhandler.go b/internal/handler/admin/crm/membership/getcustomerhandler.go new file mode 100644 index 00000000..15c286b5 --- /dev/null +++ b/internal/handler/admin/crm/membership/getcustomerhandler.go @@ -0,0 +1,28 @@ +package membership + +import ( + "net/http" + + "PowerX/internal/logic/admin/crm/membership" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetCustomerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetMembershipRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := membership.NewGetCustomerLogic(r.Context(), svcCtx) + resp, err := l.GetCustomer(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/admin/customerdomain/customer/getcustomerhandler.go b/internal/handler/admin/customerdomain/customer/getcustomerhandler.go index be03cecb..4e5d7310 100644 --- a/internal/handler/admin/customerdomain/customer/getcustomerhandler.go +++ b/internal/handler/admin/customerdomain/customer/getcustomerhandler.go @@ -11,7 +11,7 @@ import ( func GetCustomerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.GetCustomerReqeuest + var req types.GetCustomerRequest if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/handler/admin/customerdomain/leader/getleadhandler.go b/internal/handler/admin/customerdomain/leader/getleadhandler.go index b7ff1a94..1fd9883b 100644 --- a/internal/handler/admin/customerdomain/leader/getleadhandler.go +++ b/internal/handler/admin/customerdomain/leader/getleadhandler.go @@ -11,7 +11,7 @@ import ( func GetLeadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.GetLeadReqeuest + var req types.GetLeadRequest if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/handler/mp/crm/customer/auth/validtokenhandler.go b/internal/handler/mp/crm/customer/auth/validtokenhandler.go new file mode 100644 index 00000000..2674de5e --- /dev/null +++ b/internal/handler/mp/crm/customer/auth/validtokenhandler.go @@ -0,0 +1,28 @@ +package auth + +import ( + "net/http" + + "PowerX/internal/logic/mp/crm/customer/auth" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func ValidTokenHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.MPValidTokenRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := auth.NewValidTokenLogic(r.Context(), svcCtx) + resp, err := l.ValidToken(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/crm/customer/getuserinfohandler.go b/internal/handler/mp/crm/customer/getuserinfohandler.go new file mode 100644 index 00000000..20faff01 --- /dev/null +++ b/internal/handler/mp/crm/customer/getuserinfohandler.go @@ -0,0 +1,21 @@ +package customer + +import ( + "net/http" + + "PowerX/internal/logic/mp/crm/customer" + "PowerX/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetUserInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := customer.NewGetUserInfoLogic(r.Context(), svcCtx) + resp, err := l.GetUserInfo() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/crm/membership/getcustomermembershiphandler.go b/internal/handler/mp/crm/membership/getcustomermembershiphandler.go new file mode 100644 index 00000000..f4ce7d6d --- /dev/null +++ b/internal/handler/mp/crm/membership/getcustomermembershiphandler.go @@ -0,0 +1,28 @@ +package membership + +import ( + "net/http" + + "PowerX/internal/logic/mp/crm/membership" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetCustomerMembershipHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetCustomerMembershipByTypeRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := membership.NewGetCustomerMembershipLogic(r.Context(), svcCtx) + resp, err := l.GetCustomerMembership(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/crm/membership/getmembershiphandler.go b/internal/handler/mp/crm/membership/getmembershiphandler.go new file mode 100644 index 00000000..18792d74 --- /dev/null +++ b/internal/handler/mp/crm/membership/getmembershiphandler.go @@ -0,0 +1,28 @@ +package membership + +import ( + "net/http" + + "PowerX/internal/logic/mp/crm/membership" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetMembershipHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetMembershipRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := membership.NewGetMembershipLogic(r.Context(), svcCtx) + resp, err := l.GetMembership(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/crm/trade/token/getcustomertokenbalancehandler.go b/internal/handler/mp/crm/trade/token/getcustomertokenbalancehandler.go new file mode 100644 index 00000000..78d6e427 --- /dev/null +++ b/internal/handler/mp/crm/trade/token/getcustomertokenbalancehandler.go @@ -0,0 +1,21 @@ +package token + +import ( + "net/http" + + "PowerX/internal/logic/mp/crm/trade/token" + "PowerX/internal/svc" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetCustomerTokenBalanceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := token.NewGetCustomerTokenBalanceLogic(r.Context(), svcCtx) + resp, err := l.GetCustomerTokenBalance() + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/createcategoryhandler.go b/internal/handler/mp/infoorganization/category/createcategoryhandler.go new file mode 100644 index 00000000..63f7ad4a --- /dev/null +++ b/internal/handler/mp/infoorganization/category/createcategoryhandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func CreateCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.CreateCategoryRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewCreateCategoryLogic(r.Context(), svcCtx) + resp, err := l.CreateCategory(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/deletecategoryhandler.go b/internal/handler/mp/infoorganization/category/deletecategoryhandler.go new file mode 100644 index 00000000..e648753e --- /dev/null +++ b/internal/handler/mp/infoorganization/category/deletecategoryhandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func DeleteCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.DeleteCategoryRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewDeleteCategoryLogic(r.Context(), svcCtx) + resp, err := l.DeleteCategory(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/getcategoryhandler.go b/internal/handler/mp/infoorganization/category/getcategoryhandler.go new file mode 100644 index 00000000..63a1a33e --- /dev/null +++ b/internal/handler/mp/infoorganization/category/getcategoryhandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func GetCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.GetCategoryRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewGetCategoryLogic(r.Context(), svcCtx) + resp, err := l.GetCategory(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/listcategorytreehandler.go b/internal/handler/mp/infoorganization/category/listcategorytreehandler.go new file mode 100644 index 00000000..d6dd856e --- /dev/null +++ b/internal/handler/mp/infoorganization/category/listcategorytreehandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func ListCategoryTreeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.ListCategoryTreeRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewListCategoryTreeLogic(r.Context(), svcCtx) + resp, err := l.ListCategoryTree(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/patchcategoryhandler.go b/internal/handler/mp/infoorganization/category/patchcategoryhandler.go new file mode 100644 index 00000000..a2be1ba4 --- /dev/null +++ b/internal/handler/mp/infoorganization/category/patchcategoryhandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func PatchCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.PatchCategoryRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewPatchCategoryLogic(r.Context(), svcCtx) + resp, err := l.PatchCategory(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/mp/infoorganization/category/updatecategoryhandler.go b/internal/handler/mp/infoorganization/category/updatecategoryhandler.go new file mode 100644 index 00000000..83307cdb --- /dev/null +++ b/internal/handler/mp/infoorganization/category/updatecategoryhandler.go @@ -0,0 +1,28 @@ +package category + +import ( + "net/http" + + "PowerX/internal/logic/mp/infoorganization/category" + "PowerX/internal/svc" + "PowerX/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func UpdateCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.UpdateCategoryRequest + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := category.NewUpdateCategoryLogic(r.Context(), svcCtx) + resp, err := l.UpdateCategory(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} diff --git a/internal/handler/routes.go b/internal/handler/routes.go index b83fe09d..c80c3170 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -13,6 +13,7 @@ import ( admincrmmarketmedia "PowerX/internal/handler/admin/crm/market/media" admincrmmarketmgm "PowerX/internal/handler/admin/crm/market/mgm" admincrmmarketstore "PowerX/internal/handler/admin/crm/market/store" + admincrmmembership "PowerX/internal/handler/admin/crm/membership" admincrmproduct "PowerX/internal/handler/admin/crm/product" admincrmproductartisan "PowerX/internal/handler/admin/crm/product/artisan" admincrmproductcategory "PowerX/internal/handler/admin/crm/product/category" @@ -47,9 +48,11 @@ import ( adminuserinfo "PowerX/internal/handler/admin/userinfo" adminwechatofficialaccountmedia "PowerX/internal/handler/admin/wechat/officialaccount/media" adminwechatofficialaccountmenu "PowerX/internal/handler/admin/wechat/officialaccount/menu" + mpcrmcustomer "PowerX/internal/handler/mp/crm/customer" mpcrmcustomerauth "PowerX/internal/handler/mp/crm/customer/auth" mpcrmmarketmedia "PowerX/internal/handler/mp/crm/market/media" mpcrmmarketstore "PowerX/internal/handler/mp/crm/market/store" + mpcrmmembership "PowerX/internal/handler/mp/crm/membership" mpcrmproduct "PowerX/internal/handler/mp/crm/product" mpcrmproductartisan "PowerX/internal/handler/mp/crm/product/artisan" mpcrmproductproductstatistics "PowerX/internal/handler/mp/crm/product/productstatistics" @@ -59,7 +62,9 @@ import ( mpcrmtradecart "PowerX/internal/handler/mp/crm/trade/cart" mpcrmtradeorder "PowerX/internal/handler/mp/crm/trade/order" mpcrmtradepayment "PowerX/internal/handler/mp/crm/trade/payment" + mpcrmtradetoken "PowerX/internal/handler/mp/crm/trade/token" mpdictionary "PowerX/internal/handler/mp/dictionary" + mpinfoorganizationcategory "PowerX/internal/handler/mp/infoorganization/category" plugin "PowerX/internal/handler/plugin" systemhealth "PowerX/internal/handler/system/health" webcustomerauth "PowerX/internal/handler/web/customer/auth" @@ -591,6 +596,20 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { rest.WithPrefix("/api/v1/admin/customerdomain"), ) + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.EmployeeJWTAuth}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/customers/:id", + Handler: admincrmmembership.GetCustomerHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/admin/membership"), + ) + server.AddRoutes( rest.WithMiddlewares( []rest.Middleware{serverCtx.EmployeeJWTAuth}, @@ -1643,6 +1662,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ + { + Method: http.MethodGet, + Path: "/validToken", + Handler: mpcrmcustomerauth.ValidTokenHandler(serverCtx), + }, { Method: http.MethodPost, Path: "/login", @@ -1662,6 +1686,39 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { rest.WithPrefix("/api/v1/mp/customer"), ) + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.MPCustomerJWTAuth, serverCtx.MPCustomerGet}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/user-info", + Handler: mpcrmcustomer.GetUserInfoHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/mp/customer"), + ) + + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.MPCustomerJWTAuth, serverCtx.MPCustomerGet}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/customer", + Handler: mpcrmmembership.GetCustomerMembershipHandler(serverCtx), + }, + { + Method: http.MethodGet, + Path: "/:id", + Handler: mpcrmmembership.GetMembershipHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/mp/membership"), + ) + server.AddRoutes( []rest.Route{ { @@ -2092,6 +2149,56 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { rest.WithPrefix("/api/v1/mp/trade"), ) + server.AddRoutes( + rest.WithMiddlewares( + []rest.Middleware{serverCtx.MPCustomerJWTAuth, serverCtx.MPCustomerGet}, + []rest.Route{ + { + Method: http.MethodGet, + Path: "/balance", + Handler: mpcrmtradetoken.GetCustomerTokenBalanceHandler(serverCtx), + }, + }..., + ), + rest.WithPrefix("/api/v1/mp/trade/token"), + ) + + server.AddRoutes( + []rest.Route{ + { + Method: http.MethodGet, + Path: "/category-tree", + Handler: mpinfoorganizationcategory.ListCategoryTreeHandler(serverCtx), + }, + { + Method: http.MethodGet, + Path: "/categories/:id", + Handler: mpinfoorganizationcategory.GetCategoryHandler(serverCtx), + }, + { + Method: http.MethodPost, + Path: "/categories", + Handler: mpinfoorganizationcategory.CreateCategoryHandler(serverCtx), + }, + { + Method: http.MethodPut, + Path: "/categories/:id", + Handler: mpinfoorganizationcategory.UpdateCategoryHandler(serverCtx), + }, + { + Method: http.MethodPatch, + Path: "/categories/:id", + Handler: mpinfoorganizationcategory.PatchCategoryHandler(serverCtx), + }, + { + Method: http.MethodDelete, + Path: "/categories/:id", + Handler: mpinfoorganizationcategory.DeleteCategoryHandler(serverCtx), + }, + }, + rest.WithPrefix("/api/v1/mp/info-organization"), + ) + server.AddRoutes( rest.WithMiddlewares( []rest.Middleware{serverCtx.WebCustomerJWTAuth}, diff --git a/internal/logic/admin/crm/customerdomain/customer/getcustomerlogic.go b/internal/logic/admin/crm/customerdomain/customer/getcustomerlogic.go index 39d98506..8855852f 100644 --- a/internal/logic/admin/crm/customerdomain/customer/getcustomerlogic.go +++ b/internal/logic/admin/crm/customerdomain/customer/getcustomerlogic.go @@ -25,7 +25,7 @@ func NewGetCustomerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCu } } -func (l *GetCustomerLogic) GetCustomer(req *types.GetCustomerReqeuest) (resp *types.GetCustomerReply, err error) { +func (l *GetCustomerLogic) GetCustomer(req *types.GetCustomerRequest) (resp *types.GetCustomerReply, err error) { mdlCustomer, err := l.svcCtx.PowerX.Customer.GetCustomer(l.ctx, req.Id) if err != nil { diff --git a/internal/logic/admin/crm/customerdomain/leader/getleadlogic.go b/internal/logic/admin/crm/customerdomain/leader/getleadlogic.go index 2e90b849..27253124 100644 --- a/internal/logic/admin/crm/customerdomain/leader/getleadlogic.go +++ b/internal/logic/admin/crm/customerdomain/leader/getleadlogic.go @@ -26,7 +26,7 @@ func NewGetLeadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLeadLo } } -func (l *GetLeadLogic) GetLead(req *types.GetLeadReqeuest) (resp *types.GetLeadReply, err error) { +func (l *GetLeadLogic) GetLead(req *types.GetLeadRequest) (resp *types.GetLeadReply, err error) { mdlLead, err := l.svcCtx.PowerX.Lead.GetLead(l.ctx, req.Id) if err != nil { diff --git a/internal/logic/admin/crm/customerdomain/registercode/getregistercodelogic.go b/internal/logic/admin/crm/customerdomain/registercode/getregistercodelogic.go index 349794ca..3720e377 100644 --- a/internal/logic/admin/crm/customerdomain/registercode/getregistercodelogic.go +++ b/internal/logic/admin/crm/customerdomain/registercode/getregistercodelogic.go @@ -23,7 +23,7 @@ func NewGetRegisterCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G } } -func (l *GetRegisterCodeLogic) GetRegisterCode(req *types.GetRegisterCodeReqeuest) (resp *types.GetRegisterCodeReply, err error) { +func (l *GetRegisterCodeLogic) GetRegisterCode(req *types.GetRegisterCodeRequest) (resp *types.GetRegisterCodeReply, err error) { // todo: add your logic here and delete this line return diff --git a/internal/logic/admin/crm/membership/getcustomerlogic.go b/internal/logic/admin/crm/membership/getcustomerlogic.go new file mode 100644 index 00000000..9a2867cf --- /dev/null +++ b/internal/logic/admin/crm/membership/getcustomerlogic.go @@ -0,0 +1,30 @@ +package membership + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetCustomerLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetCustomerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCustomerLogic { + return &GetCustomerLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetCustomerLogic) GetCustomer(req *types.GetMembershipRequest) (resp *types.GetMembershipReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/admin/mediaresource/createmediaresourcebybase64logic.go b/internal/logic/admin/mediaresource/createmediaresourcebybase64logic.go index 45b0ef6e..4c431122 100644 --- a/internal/logic/admin/mediaresource/createmediaresourcebybase64logic.go +++ b/internal/logic/admin/mediaresource/createmediaresourcebybase64logic.go @@ -26,7 +26,7 @@ func NewCreateMediaResourceByBase64Logic(ctx context.Context, svcCtx *svc.Servic func (l *CreateMediaResourceByBase64Logic) CreateMediaResourceByBase64(req *types.CreateMediaResourceByBase64Request) (resp *types.CreateMediaResourceReply, err error) { - resource, err := l.svcCtx.PowerX.MediaResource.MakeOSSResourceByBase64(l.ctx, req.BucketName, req.Base64Data) + resource, err := l.svcCtx.PowerX.MediaResource.MakeOSSResourceByBase64String(l.ctx, req.BucketName, req.Base64Data) if err != nil { return nil, errorx.WithCause(errorx.ErrBadRequest, err.Error()) } diff --git a/internal/logic/mp/crm/customer/auth/authbyphonelogic.go b/internal/logic/mp/crm/customer/auth/authbyphonelogic.go index 2f59da34..67fba0ca 100644 --- a/internal/logic/mp/crm/customer/auth/authbyphonelogic.go +++ b/internal/logic/mp/crm/customer/auth/authbyphonelogic.go @@ -3,14 +3,18 @@ package auth import ( "PowerX/internal/model" "PowerX/internal/model/crm/customerdomain" + "PowerX/internal/model/crm/operation" + "PowerX/internal/model/crm/trade" "PowerX/internal/model/wechat" "PowerX/internal/svc" "PowerX/internal/types" + "PowerX/internal/types/errorx" customerdomain2 "PowerX/internal/uc/powerx/crm/customerdomain" + fmt2 "PowerX/pkg/printx" "context" + "encoding/json" "errors" "fmt" - "github.com/ArtisanCloud/PowerLibs/v3/object" "github.com/zeromicro/go-zero/core/logx" ) @@ -39,33 +43,25 @@ func (l *AuthByPhoneLogic) AuthByPhone(req *types.MPCustomerAuthRequest) (resp * if rs.ErrCode != 0 { return nil, errors.New(rs.ErrMsg) } - //fmt2.DD(rs) - //req = &types.MPCustomerAuthRequest{ - // IV: "aggABXMAyD1TQa1OS5pjzA==", - // EncryptedData: "VMkaPGYIWUdCwO+MxEBoY6jUs9Ib2uJEQPiDGWnEum9eSHiBEYbGpY+sJn6gPh4PrkyhOMaLH0CuwasVVbaKUS1NHmjEd0Z6pf9W7OyAX4Z3bC8UsEm8PX0YvUPnYnRSMpGdouyOUJu1ie9XCIaqU6j39AZqJfs7bB3aksGN3YHk4EryVIeli9HmrIul9gaa433P/SVJA/34dASdjltv0w==", - //} - //rs := &response.ResponseCode2Session{ - // OpenID: "o1IFX5A8sfi5nbkXwOzNLLLiL0OA", - // SessionKey: "+CG6t0FMK1QMLP4IKWNPUw==", - //} - - //fmt2.Dump(rs, req) + + fmt2.Dump(rs, req) // 解码手机授权信息 msgData, errEncrypt := l.svcCtx.PowerX.WechatMP.App.Encryptor.DecryptData(req.EncryptedData, rs.SessionKey, req.IV) if errEncrypt != nil { return nil, errors.New(errEncrypt.ErrMsg) } - //println(string(msgData)) // 解析手机信息 mpPhoneInfo := &wechat.MPPhoneInfo{} - err = object.JsonDecode(msgData, mpPhoneInfo) + err = json.Unmarshal(msgData, mpPhoneInfo) if err != nil { panic(err.Error()) return } + fmt2.Dump(mpPhoneInfo) + mpCustomer := &wechat.WechatMPCustomer{ OpenId: rs.OpenID, SessionKey: rs.SessionKey, @@ -117,6 +113,38 @@ func (l *AuthByPhoneLogic) AuthByPhone(req *types.MPCustomerAuthRequest) (resp * token := l.svcCtx.PowerX.CustomerAuthorization.SignMPToken(mpCustomer, l.svcCtx.Config.JWT.MPJWTSecret) + // 创建一个默认的客户会籍 + ddBaseMembershipType := l.svcCtx.PowerX.DataDictionary.GetCachedDD(l.ctx, operation.TypeMembershipType, operation.MembershipTypeBase) + normalMembership, err := l.svcCtx.PowerX.Membership.GetMembershipBy(l.ctx, customer, ddBaseMembershipType.Id) + if err != nil { + return nil, errorx.WithCause(errorx.ErrRecordNotFound, err.Error()) + } + if normalMembership == nil { + normalMembership = &operation.Membership{ + CustomerId: customer.Id, + Type: int(ddBaseMembershipType.Id), + } + err = l.svcCtx.PowerX.Membership.CreateMembership(l.ctx, normalMembership) + if err != nil { + return nil, errorx.WithCause(errorx.ErrCreateObject, "创建默认会籍发生错误") + } + + // 如果是第一次有会籍,创建一个虚拟代币账号 + err = l.svcCtx.PowerX.Token.CreateTokenBalance(l.ctx, &trade.TokenBalance{ + CustomerId: customer.Id, + Balance: 1, + }) + if err != nil { + return nil, errorx.WithCause(errorx.ErrCreateObject, "创建默认代币账户发生错误") + } + // 赠送1元代币 + err = l.svcCtx.PowerX.Token.CreateTokenExchangeRecord(l.ctx, &trade.TokenExchangeRecord{ + CustomerId: customer.Id, + TokenAmount: 1, + }) + + } + return &types.MPCustomerLoginAuthReply{ OpenId: mpCustomer.OpenId, UnionId: mpCustomer.UnionId, diff --git a/internal/logic/mp/crm/customer/auth/validtokenlogic.go b/internal/logic/mp/crm/customer/auth/validtokenlogic.go new file mode 100644 index 00000000..5fea1857 --- /dev/null +++ b/internal/logic/mp/crm/customer/auth/validtokenlogic.go @@ -0,0 +1,95 @@ +package auth + +import ( + "PowerX/internal/svc" + "PowerX/internal/types" + "PowerX/internal/uc/powerx/crm/customerdomain" + "PowerX/internal/uc/powerx/wechat" + "context" + "github.com/golang-jwt/jwt/v4" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" +) + +type ValidTokenLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewValidTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ValidTokenLogic { + return &ValidTokenLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *ValidTokenLogic) ValidToken(req *types.MPValidTokenRequest) (resp *types.MPValidTokenReply, err error) { + res := &types.MPValidTokenReply{ + Valid: true, + Reason: "", + } + tokenString := req.Token + + secret := l.svcCtx.Config.JWT.MPJWTSecret + + var claims types.TokenClaims + token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) { + return []byte(secret), nil + }) + if err != nil || !token.Valid { + if errors.Is(err, jwt.ErrTokenMalformed) { + res.Valid = false + res.Reason = "token malformed" + } else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) { + res.Valid = false + res.Reason = "token expired" + } else { + res.Valid = false + res.Reason = "违规Token" + + } + return res, nil + } + + // 获取小程序授权的openid + payload, err := customerdomain.GetPayloadFromToken(token.Raw) + if err != nil { + res.Valid = false + res.Reason = "无效客户信息" + return res, nil + } + vOpenId := payload[customerdomain.AuthCustomerOpenIdKey] + + if vOpenId == nil { + res.Valid = false + res.Reason = "无效授权客户OpenId" + return res, nil + } + openId := vOpenId.(string) + if openId == "" { + res.Valid = false + res.Reason = "授权客户OpenId为空" + return res, nil + } + + // 小程序的客户记录是否存在 + authMPCustomer, err := l.svcCtx.PowerX.WechatMP.FindOneMPCustomer(l.ctx, &wechat.FindMPCustomerOption{ + OpenIds: []string{openId}, + }) + if err != nil { + res.Valid = false + res.Reason = "无效微信小程序客户" + return res, nil + } + + // 小程序的客户记录是否存在 + if authMPCustomer.Customer == nil { + res.Valid = false + res.Reason = "无效客户记录" + return res, nil + } + + return res, nil +} diff --git a/internal/logic/mp/crm/customer/getuserinfologic.go b/internal/logic/mp/crm/customer/getuserinfologic.go new file mode 100644 index 00000000..d91e0a65 --- /dev/null +++ b/internal/logic/mp/crm/customer/getuserinfologic.go @@ -0,0 +1,30 @@ +package customer + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetUserInfoLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic { + return &GetUserInfoLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetUserInfoLogic) GetUserInfo() (resp *types.GetUserInfoReplyForMP, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/crm/membership/getcustomermembershiplogic.go b/internal/logic/mp/crm/membership/getcustomermembershiplogic.go new file mode 100644 index 00000000..d324da7a --- /dev/null +++ b/internal/logic/mp/crm/membership/getcustomermembershiplogic.go @@ -0,0 +1,30 @@ +package membership + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetCustomerMembershipLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetCustomerMembershipLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCustomerMembershipLogic { + return &GetCustomerMembershipLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetCustomerMembershipLogic) GetCustomerMembership(req *types.GetCustomerMembershipByTypeRequest) (resp *types.GetCustomerMembershipByTypeReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/crm/membership/getmembershiplogic.go b/internal/logic/mp/crm/membership/getmembershiplogic.go new file mode 100644 index 00000000..b53c2261 --- /dev/null +++ b/internal/logic/mp/crm/membership/getmembershiplogic.go @@ -0,0 +1,30 @@ +package membership + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetMembershipLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetMembershipLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMembershipLogic { + return &GetMembershipLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetMembershipLogic) GetMembership(req *types.GetMembershipRequest) (resp *types.GetMembershipReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/crm/trade/token/getcustomertokenbalancelogic.go b/internal/logic/mp/crm/trade/token/getcustomertokenbalancelogic.go new file mode 100644 index 00000000..7c20e87e --- /dev/null +++ b/internal/logic/mp/crm/trade/token/getcustomertokenbalancelogic.go @@ -0,0 +1,49 @@ +package token + +import ( + customerdomain2 "PowerX/internal/model/crm/customerdomain" + "PowerX/internal/model/crm/trade" + "PowerX/internal/svc" + "PowerX/internal/types" + "PowerX/internal/uc/powerx/crm/customerdomain" + "context" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetCustomerTokenBalanceLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetCustomerTokenBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCustomerTokenBalanceLogic { + return &GetCustomerTokenBalanceLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetCustomerTokenBalanceLogic) GetCustomerTokenBalance() (resp *types.GetCustomerBalanceReply, err error) { + vAuthCustomer := l.ctx.Value(customerdomain.AuthCustomerKey) + authCustomer := vAuthCustomer.(*customerdomain2.Customer) + + balance, unusedTicketsCount, err := l.svcCtx.PowerX.Token.CheckTokenBalanceIsEnough(l.ctx, authCustomer) + if err != nil { + return nil, err + } + balanceReply := TransformBalanceToReplyForMP(balance) + balanceReply.UnusedTicketsCount = unusedTicketsCount + return &types.GetCustomerBalanceReply{ + TokenBalance: balanceReply, + }, nil +} + +func TransformBalanceToReplyForMP(balance *trade.TokenBalance) *types.TokenBalance { + return &types.TokenBalance{ + Id: balance.Id, + Balance: balance.Balance, + Usage: balance.Usage, + } +} diff --git a/internal/logic/mp/infoorganization/category/createcategorylogic.go b/internal/logic/mp/infoorganization/category/createcategorylogic.go new file mode 100644 index 00000000..aefcc02c --- /dev/null +++ b/internal/logic/mp/infoorganization/category/createcategorylogic.go @@ -0,0 +1,30 @@ +package category + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type CreateCategoryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCreateCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateCategoryLogic { + return &CreateCategoryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *CreateCategoryLogic) CreateCategory(req *types.CreateCategoryRequest) (resp *types.CreateCategoryReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/infoorganization/category/deletecategorylogic.go b/internal/logic/mp/infoorganization/category/deletecategorylogic.go new file mode 100644 index 00000000..d940689a --- /dev/null +++ b/internal/logic/mp/infoorganization/category/deletecategorylogic.go @@ -0,0 +1,30 @@ +package category + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DeleteCategoryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDeleteCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCategoryLogic { + return &DeleteCategoryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *DeleteCategoryLogic) DeleteCategory(req *types.DeleteCategoryRequest) (resp *types.DeleteCategoryReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/infoorganization/category/getcategorylogic.go b/internal/logic/mp/infoorganization/category/getcategorylogic.go new file mode 100644 index 00000000..1cfcef2c --- /dev/null +++ b/internal/logic/mp/infoorganization/category/getcategorylogic.go @@ -0,0 +1,66 @@ +package category + +import ( + "PowerX/internal/logic/admin/mediaresource" + infoorganizatoin "PowerX/internal/model/infoorganization" + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type GetCategoryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewGetCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCategoryLogic { + return &GetCategoryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *GetCategoryLogic) GetCategory(req *types.GetCategoryRequest) (resp *types.GetCategoryReply, err error) { + // 获取模型类型的列表 + productCategoryTree, err := l.svcCtx.PowerX.Category.GetCategory(l.ctx, req.CategoryId) + if err != nil { + return nil, err + } + + // 转化返回类别 + categoryReply := TransformCategoryToReplyForMP(productCategoryTree) + + return &types.GetCategoryReply{ + Category: categoryReply, + }, nil +} + +func TransformCategoryToReplyForMP(category *infoorganizatoin.Category) *types.Category { + + node := &types.Category{ + Id: category.Id, + PId: category.PId, + Name: category.Name, + Sort: category.Sort, + ViceName: category.ViceName, + Description: category.Description, + CreatedAt: category.CreatedAt.String(), + CoverImage: mediaresource.TransformMediaResourceToReply(category.CoverImage), + ImageAbleInfo: types.ImageAbleInfo{ + Icon: category.Icon, + BackgroundColor: category.BackgroundColor, + }, + Children: nil, + } + if len(category.Children) > 0 { + node.Children = TransformCategoriesToReplyForMP(category.Children) + + } + + return node +} diff --git a/internal/logic/mp/infoorganization/category/listcategorytreelogic.go b/internal/logic/mp/infoorganization/category/listcategorytreelogic.go new file mode 100644 index 00000000..3efc4ba1 --- /dev/null +++ b/internal/logic/mp/infoorganization/category/listcategorytreelogic.go @@ -0,0 +1,63 @@ +package category + +import ( + "PowerX/internal/logic/admin/infoorganization/category" + infoorganizatoin "PowerX/internal/model/infoorganization" + "PowerX/internal/uc/powerx/crm/infoorganization" + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type ListCategoryTreeLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewListCategoryTreeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListCategoryTreeLogic { + return &ListCategoryTreeLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *ListCategoryTreeLogic) ListCategoryTree(req *types.ListCategoryTreeRequest) (resp *types.ListCategoryTreeReply, err error) { + option := infoorganization.FindCategoryOption{ + Names: req.Names, + OrderBy: req.OrderBy, + } + + // 获取模型类型的列表 + productCategoryTree := l.svcCtx.PowerX.Category.ListCategoryTree(l.ctx, &option, 0) + + // 转化返回类型的列表 + productCategoryReplyList := category.TransformProductCategoriesToReply(productCategoryTree) + + return &types.ListCategoryTreeReply{ + ProductCategories: productCategoryReplyList, + }, nil +} + +func TransformCategoriesToReplyForMP(productCategoryList []*infoorganizatoin.Category) []*types.Category { + uniqueIds := make(map[int64]bool) + var productCategoryReplyList []*types.Category + for _, category := range productCategoryList { + if !uniqueIds[category.Id] { + node := TransformCategoryToReplyForMP(category) + if len(category.Children) > 0 { + node.Children = TransformCategoriesToReplyForMP(category.Children) + } + + productCategoryReplyList = append(productCategoryReplyList, node) + uniqueIds[category.Id] = true + + } + } + + return productCategoryReplyList +} diff --git a/internal/logic/mp/infoorganization/category/patchcategorylogic.go b/internal/logic/mp/infoorganization/category/patchcategorylogic.go new file mode 100644 index 00000000..462f146e --- /dev/null +++ b/internal/logic/mp/infoorganization/category/patchcategorylogic.go @@ -0,0 +1,30 @@ +package category + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type PatchCategoryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewPatchCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PatchCategoryLogic { + return &PatchCategoryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *PatchCategoryLogic) PatchCategory(req *types.PatchCategoryRequest) (resp *types.PatchCategoryReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/mp/infoorganization/category/updatecategorylogic.go b/internal/logic/mp/infoorganization/category/updatecategorylogic.go new file mode 100644 index 00000000..6922d469 --- /dev/null +++ b/internal/logic/mp/infoorganization/category/updatecategorylogic.go @@ -0,0 +1,30 @@ +package category + +import ( + "context" + + "PowerX/internal/svc" + "PowerX/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UpdateCategoryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUpdateCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateCategoryLogic { + return &UpdateCategoryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *UpdateCategoryLogic) UpdateCategory(req *types.UpdateCategoryRequest) (resp *types.UpdateCategoryReply, err error) { + // todo: add your logic here and delete this line + + return +} diff --git a/internal/logic/web/customer/auth/getuserinfologic.go b/internal/logic/web/customer/auth/getuserinfologic.go index f81353ed..2b6c246d 100644 --- a/internal/logic/web/customer/auth/getuserinfologic.go +++ b/internal/logic/web/customer/auth/getuserinfologic.go @@ -26,14 +26,14 @@ func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUs } } -func (l *GetUserInfoLogic) GetUserInfo() (resp *types.GetUserInfoReplyToWeb, err error) { +func (l *GetUserInfoLogic) GetUserInfo() (resp *types.GetUserInfoReplyForWeb, err error) { vAuthCustomer := l.ctx.Value(customerdomain.AuthCustomerKey) authCustomer := vAuthCustomer.(*customerdomain2.Customer) customer := customer.TransformCustomerToReply(l.svcCtx, authCustomer) customer.AccountId = fmt.Sprintf("%d", customer.Id) - return &types.GetUserInfoReplyToWeb{ + return &types.GetUserInfoReplyForWeb{ Customer: customer, }, nil } diff --git a/internal/logic/web/infoorganization/category/getcategorylogic.go b/internal/logic/web/infoorganization/category/getcategorylogic.go index 6eeba22f..a135e15e 100644 --- a/internal/logic/web/infoorganization/category/getcategorylogic.go +++ b/internal/logic/web/infoorganization/category/getcategorylogic.go @@ -1,6 +1,8 @@ package category import ( + "PowerX/internal/logic/admin/mediaresource" + infoorganizatoin "PowerX/internal/model/infoorganization" "context" "PowerX/internal/svc" @@ -24,7 +26,42 @@ func NewGetCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCa } func (l *GetCategoryLogic) GetCategory(req *types.GetCategoryRequest) (resp *types.GetCategoryReply, err error) { - // todo: add your logic here and delete this line - return + // 获取模型类型的列表 + productCategoryTree, err := l.svcCtx.PowerX.Category.GetCategory(l.ctx, req.CategoryId) + if err != nil { + return nil, err + } + + // 转化返回类别 + categoryReply := TransformCategoryToReplyForWeb(productCategoryTree) + + return &types.GetCategoryReply{ + Category: categoryReply, + }, nil +} + +func TransformCategoryToReplyForWeb(category *infoorganizatoin.Category) *types.Category { + + node := &types.Category{ + Id: category.Id, + PId: category.PId, + Name: category.Name, + Sort: category.Sort, + ViceName: category.ViceName, + Description: category.Description, + CreatedAt: category.CreatedAt.String(), + CoverImage: mediaresource.TransformMediaResourceToReply(category.CoverImage), + ImageAbleInfo: types.ImageAbleInfo{ + Icon: category.Icon, + BackgroundColor: category.BackgroundColor, + }, + Children: nil, + } + if len(category.Children) > 0 { + node.Children = TransformCategoriesToReplyForWeb(category.Children) + + } + + return node } diff --git a/internal/logic/web/infoorganization/category/listcategorytreelogic.go b/internal/logic/web/infoorganization/category/listcategorytreelogic.go index 2a51b66d..c49eff4f 100644 --- a/internal/logic/web/infoorganization/category/listcategorytreelogic.go +++ b/internal/logic/web/infoorganization/category/listcategorytreelogic.go @@ -2,6 +2,7 @@ package category import ( "PowerX/internal/logic/admin/infoorganization/category" + infoorganizatoin "PowerX/internal/model/infoorganization" "PowerX/internal/uc/powerx/crm/infoorganization" "context" @@ -41,3 +42,22 @@ func (l *ListCategoryTreeLogic) ListCategoryTree(req *types.ListCategoryTreeRequ ProductCategories: productCategoryReplyList, }, nil } + +func TransformCategoriesToReplyForWeb(productCategoryList []*infoorganizatoin.Category) []*types.Category { + uniqueIds := make(map[int64]bool) + var productCategoryReplyList []*types.Category + for _, category := range productCategoryList { + if !uniqueIds[category.Id] { + node := TransformCategoryToReplyForWeb(category) + if len(category.Children) > 0 { + node.Children = TransformCategoriesToReplyForWeb(category.Children) + } + + productCategoryReplyList = append(productCategoryReplyList, node) + uniqueIds[category.Id] = true + + } + } + + return productCategoryReplyList +} diff --git a/internal/middleware/mpmembershipgetmiddleware.go b/internal/middleware/mpmembershipgetmiddleware.go new file mode 100644 index 00000000..eb3dbeb5 --- /dev/null +++ b/internal/middleware/mpmembershipgetmiddleware.go @@ -0,0 +1,19 @@ +package middleware + +import "net/http" + +type MPMembershipGetMiddleware struct { +} + +func NewMPMembershipGetMiddleware() *MPMembershipGetMiddleware { + return &MPMembershipGetMiddleware{} +} + +func (m *MPMembershipGetMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // TODO generate middleware implement function, delete after code implementation + + // Passthrough to next handler if need + next(w, r) + } +} diff --git a/internal/middleware/mpmembershipjwtauthmiddleware.go b/internal/middleware/mpmembershipjwtauthmiddleware.go new file mode 100644 index 00000000..d15a3c23 --- /dev/null +++ b/internal/middleware/mpmembershipjwtauthmiddleware.go @@ -0,0 +1,19 @@ +package middleware + +import "net/http" + +type MPMembershipJWTAuthMiddleware struct { +} + +func NewMPMembershipJWTAuthMiddleware() *MPMembershipJWTAuthMiddleware { + return &MPMembershipJWTAuthMiddleware{} +} + +func (m *MPMembershipJWTAuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // TODO generate middleware implement function, delete after code implementation + + // Passthrough to next handler if need + next(w, r) + } +} diff --git a/internal/model/crm/membership/membership.go b/internal/model/crm/membership/membership.go deleted file mode 100644 index 806caa01..00000000 --- a/internal/model/crm/membership/membership.go +++ /dev/null @@ -1,29 +0,0 @@ -package membership - -import ( - "PowerX/internal/model/crm/customerdomain" - "PowerX/internal/model/powermodel" - "time" -) - -type Membership struct { - Customer *customerdomain.Customer `gorm:"foreignKey:CustomerId;references:id"` - - MainMembership *Membership `gorm:"foreignKey:MainMembershipId;references:id"` - SubMemberships []*Membership `gorm:"foreignKey:MainMembershipId;references:id"` - - powermodel.PowerModel - - Name string `gorm:"comment:会籍名称" json:"name"` - MainMembershipId string `gorm:"comment:主会籍Id" json:"mainMembershipId"` - OrderId string `gorm:"comment:订单Id" json:"orderId"` - OrderItemId string `gorm:"comment:订单项Id" json:"orderItemId"` - CustomerId string `gorm:"comment:客户Id" json:"accountId"` - ProductId string `gorm:"comment:产品Id" json:"productId"` - StartDate time.Time `gorm:"comment:开始时间" json:"startDate"` - EndDate time.Time `gorm:"comment:结束时间" json:"endDate"` - Status int `gorm:"comment:会籍状态" json:"status"` - ExtendPeriod bool `gorm:"comment:是否延续" json:"extendPeriod"` - Level int `gorm:"comment:级别" json:"level"` - Plan int `gorm:"comment:计划" json:"plan"` -} diff --git a/internal/model/crm/operation/membership.go b/internal/model/crm/operation/membership.go new file mode 100644 index 00000000..1ace41cb --- /dev/null +++ b/internal/model/crm/operation/membership.go @@ -0,0 +1,50 @@ +package operation + +import ( + "PowerX/internal/model/crm/customerdomain" + "PowerX/internal/model/powermodel" + "time" +) + +type Membership struct { + Customer *customerdomain.Customer `gorm:"foreignKey:CustomerId;references:id"` + + MainMembership *Membership `gorm:"foreignKey:MainMembershipId;references:id"` + SubMemberships []*Membership `gorm:"foreignKey:MainMembershipId;references:id"` + + powermodel.PowerModel + + Name string `gorm:"comment:会籍名称" json:"name"` + MainMembershipId int64 `gorm:"comment:主会籍Id" json:"mainMembershipId"` + OrderId int64 `gorm:"comment:订单Id" json:"orderId"` + OrderItemId int64 `gorm:"comment:订单项Id" json:"orderItemId"` + CustomerId int64 `gorm:"comment:客户Id" json:"accountId"` + ProductId int64 `gorm:"comment:产品Id" json:"productId"` + StartDate time.Time `gorm:"comment:开始时间" json:"startDate"` + EndDate time.Time `gorm:"comment:结束时间" json:"endDate"` + Status int `gorm:"comment:会籍状态" json:"status"` + Type int `gorm:"comment:计划" json:"type"` + ExtendPeriod bool `gorm:"comment:是否延续" json:"extendPeriod"` + Plan int `gorm:"comment:计划" json:"plan"` +} + +const MembershipUniqueId = powermodel.UniqueId + +const TypeMembershipType = "_membership_type" +const TypeMembershipStatus = "_membership_status" + +const ( + MembershipStatusActive = "_active" // 活跃状态 + MembershipStatusInactive = "_inactive" // 非活跃状态 + MembershipStatusExpired = "_expired" // 已过期 + MembershipStatusCancelled = "_cancelled" // 已取消 + // 添加其他状态... +) + +const ( + MembershipTypeBase = "_base" // 基础会籍 + MembershipTypeNormal = "_normal" // 普通会籍 + MembershipTypePremium = "_premium" // 高级会籍 + MembershipTypeVIP = "_vip" // VIP会籍 + MembershipTypeCustom = "_custom" // 定制会籍 +) diff --git a/internal/model/crm/operation/ticket.go b/internal/model/crm/operation/ticket.go new file mode 100644 index 00000000..e9548a16 --- /dev/null +++ b/internal/model/crm/operation/ticket.go @@ -0,0 +1,28 @@ +package operation + +import ( + "PowerX/internal/model/powermodel" +) + +type TicketRecord struct { + powermodel.PowerModel + + CustomerId int64 `gorm:"comment:客户Id; index" json:"customerId"` + TemplateId int64 `gorm:"comment:模板Id" json:"templateId"` + JobID string `gorm:"comment:作业ID" json:"jobID"` + Count int `gorm:"comment:作业生图数量" json:"count"` + DeductedTokenAmount float64 `gorm:"comment:使用代币金额" json:"deductedAmount"` + IsUsed bool `gorm:"comment:是否使用" json:"isUsed"` +} + +func (mdl *TicketRecord) GetTableName(needFull bool) string { + tableName := TableNameTicketRecord + if needFull { + tableName = "public." + tableName + } + return tableName +} + +const TableNameTicketRecord = "ticket_record" + +const TicketRecordUniqueId = powermodel.UniqueId diff --git a/internal/model/crm/trade/order.go b/internal/model/crm/trade/order.go index a53fae0e..c06d6d72 100644 --- a/internal/model/crm/trade/order.go +++ b/internal/model/crm/trade/order.go @@ -29,6 +29,7 @@ type Order struct { PaymentType int `gorm:"comment:支付方式" json:"paymentType"` Type int `gorm:"comment:订单类型" json:"type"` Status int `gorm:"comment:订单状态" json:"status"` + IsVerified bool `gorm:"comment:在产生支付完整后,有使用窗口期,是否被核销" json:"isVerified"` OrderNumber string `gorm:"comment:订单号; index;unique" json:"orderNumber"` UnitPrice float64 `gorm:"type:decimal(10,2); comment:是实际交易价格" json:"unitPrice"` ListPrice float64 `gorm:"type:decimal(10,2); comment:是订单价格" json:"listPrice"` @@ -36,6 +37,7 @@ type Order struct { Comment string `gorm:"comment:备注" json:"comment"` CompletedAt time.Time `gorm:"comment:订单完成时间" json:"completedAt"` CancelledAt time.Time `gorm:"comment:订单取消时间" json:"cancelledAt"` + VerifiedAt time.Time `gorm:"comment:订单核销时间" json:"verifiedAt"` ShippingMethod string `gorm:"comment:物流方式" json:"shippingMethod"` } @@ -58,8 +60,6 @@ const ( OrderStatusReturned = "_returned" // 已退货 ) -type OrderType int - const ( OrderTypeNormal = "_normal" // 普通订单 OrderTypePreorder = "_preorder" // 预定订单 diff --git a/internal/model/crm/trade/token.go b/internal/model/crm/trade/token.go index 0cb8d3b1..6e1e4894 100644 --- a/internal/model/crm/trade/token.go +++ b/internal/model/crm/trade/token.go @@ -3,34 +3,39 @@ package trade import ( "PowerX/internal/model/crm/customerdomain" "PowerX/internal/model/powermodel" - "github.com/ArtisanCloud/PowerLibs/v3/database" ) type TokenExchangeRatio struct { - database.PowerModel + powermodel.PowerModel FromCategory int `gorm:"comment:要兑换的代币种类" json:"fromCategory"` Ratio float64 `gorm:"comment:兑换比例" json:"ratio"` } type TokenBalance struct { - database.PowerModel + powermodel.PowerModel Customer *customerdomain.Customer `gorm:"foreignKey:CustomerId;references:Id" json:"customer"` CustomerId int64 `gorm:"comment:客户Id; index" json:"customerId"` - Balance float64 `gorm:"comment:代币余额; index" json:"balance"` + Balance float64 `gorm:"comment:代币余额" json:"balance"` + Usage float64 `gorm:"comment:使用代币 " json:"usage"` } const TokenBalanceUniqueId = powermodel.UniqueId +const TokenExchangeRecordId = powermodel.UniqueId type TokenExchangeRecord struct { - database.PowerModel + powermodel.PowerModel CustomerId int64 `gorm:"comment:客户Id; index" json:"customerId"` + ProductId int64 `gorm:"comment:产品Id" json:"productId"` + OrderId int64 `gorm:"comment:订单Id" json:"orderId"` SourceCategory int `gorm:"comment:原品种; index" json:"sourceCategory"` - SourceAmount float64 `gorm:"comment:原金额; index" json:"sourceAmount"` - TokenAmount float64 `gorm:"comment:换代币金额; index" json:"tokenAmount"` + SourceAmount float64 `gorm:"comment:原金额" json:"sourceAmount"` + TokenAmount float64 `gorm:"comment:换代币金额" json:"tokenAmount"` + ExchangeRateId int64 `gorm:"comment:兑换比例Id" json:"exchangeRateId"` + ExchangeRate float64 `gorm:"comment:兑换比例" json:"exchangeRate"` } // TokenCategory 代表代币的种类 @@ -47,6 +52,44 @@ const ( // 添加其他种类... ) +// 定义预扣记录对象 +type TokenReservation struct { + powermodel.PowerModel + CustomerId int64 `gorm:"comment:客户ID; index" json:"customerId"` + Amount float64 `gorm:"comment:预扣金额" json:"amount"` + SourceType string `gorm:"column:source_type; not null;index:idx_src_type;comment:来源对象表名称" json:"sourceOwner"` + SourceID int64 `gorm:"column:source_id; not null;index:idx_src_id;comment:对象Id" json:"sourceId"` + IsConfirmed bool `gorm:"comment:是否已确认" json:"isConfirmed"` +} + +// 定义交易记录对象 +type TokenTransaction struct { + powermodel.PowerModel + + CustomerId int64 `gorm:"comment:客户ID; index" json:"customerId"` + Amount float64 `gorm:"comment:交易金额" json:"amount"` + Type int `gorm:"comment:交易类型(增加或减少)" json:"transactionType"` + SourceType string `gorm:"column:source_type; not null;index:idx_src_type;comment:来源对象表名称" json:"sourceOwner"` + SourceID int64 `gorm:"column:source_id; not null;index:idx_src_id;comment:对象Id" json:"sourceId"` +} + +const TokenTransactionId = powermodel.UniqueId + +const TypeTokenTransactionType = "_token_transaction_type" + +const ( + TokenTransactionTypePurchase = "_purchase" // 购买 + TokenTransactionTypeReward = "_reward" // 奖励 + TokenTransactionTypeExchange = "_exchange" // 兑换 + TokenTransactionTypeSpending = "_spending" // 消费 + TokenTransactionTypeRefund = "_refund" // 退款 + TokenTransactionTypeExpired = "_expired" // 过期 + TokenTransactionTypeGift = "_gift" // 赠送 + TokenTransactionTypeInterest = "_interest" // 利息 + TokenTransactionTypeInvest = "_invest" // 投资 + TokenTransactionTypeOther = "_other" // 其他 +) + func ConvertTokens(fromCategory, amount float64) float64 { return 0.0 diff --git a/internal/model/origanzation/employee_test.go b/internal/model/origanzation/employee_test.go new file mode 100644 index 00000000..d3cbdd09 --- /dev/null +++ b/internal/model/origanzation/employee_test.go @@ -0,0 +1,16 @@ +package origanzation + +import ( + fmt "PowerX/pkg/printx" + "github.com/stretchr/testify/assert" + "testing" +) + +func Test_HashPassword(t *testing.T) { + pwd := "root" + encodedPassword, _ := HashPassword(pwd) + fmt.Dump(encodedPassword) + + result := VerifyPassword("$2a$04$G68CjMtt1qCkD9.heW.d4ul7uER7SZIGP3gQJJzHgir4pJW1Mksre", pwd) + assert.EqualValues(t, true, result) +} diff --git a/internal/types/errorx/errors.go b/internal/types/errorx/errors.go index a984c9a0..20e12baa 100644 --- a/internal/types/errorx/errors.go +++ b/internal/types/errorx/errors.go @@ -25,3 +25,5 @@ var ErrDeleteObjectNotFound = NewError(400, "OBJECT_NOT_FOUND", "未找到删除 var ErrNotFoundStandardPriceBook = NewError(400, "STANDARD_PRICE_BOOK_NOT_FOUND", "标准价格手册未找到") var ErrOneStandardPriceBookOnly = NewError(400, "STANDARD_PRICE_BOOK_ONLY_ONE", "标准价格手册只能有一本") var ErrCanNotDeleteStandardPrice = NewError(400, "CAN_NOT_DELETE_STANDARD_PRICE_BOOK", "不能删除标准价格手册") +var ErrNotEnoughBalance = NewError(400, "NOT_ENOUGH_BALANCE", "余额不足,请充值") +var ErrNotEnoughTicket = NewError(400, "NOT_ENOUGH_TICKET", "没有多余券,请充值购买") diff --git a/internal/types/types.go b/internal/types/types.go index 9587f343..e6ebaeec 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -787,7 +787,7 @@ type Lead struct { *LeadExternalId } -type GetLeadReqeuest struct { +type GetLeadRequest struct { Id int64 `path:"id"` } @@ -889,7 +889,7 @@ type Customer struct { *CustomerExternalId } -type GetCustomerReqeuest struct { +type GetCustomerRequest struct { Id int64 `path:"id"` } @@ -970,7 +970,7 @@ type RegisterCode struct { CreatedAt string `json:"createdAt,optional"` } -type GetRegisterCodeReqeuest struct { +type GetRegisterCodeRequest struct { Id int64 `path:"id"` } @@ -1051,6 +1051,30 @@ type AssignRegisterCodeToEmployeeReply struct { RegisterCodeId int64 `json:"customerId"` } +type Membership struct { + Id int64 `json:"id,optional"` + Name string `json:"name,optional"` + MainMembershipId int64 `json:"mainMembershipId,optional"` + OrderId int64 `json:"orderId,optional"` + OrderItemId int64 `json:"orderItemId,optional"` + CustomerId int64 `json:"customerId,optional"` + ProductId int64 `json:"productId,optional"` + StartDate string `json:"startDate,optional"` + EndDate string `json:"endDate,optional"` + Status int `json:"status,optional"` + Type int `json:"type,optional"` + ExtendPeriod bool `json:"extendPeriod,optional"` + Plan int `json:"plan,optional"` +} + +type GetMembershipRequest struct { + Id int64 `path:"id"` +} + +type GetMembershipReply struct { + *Membership +} + type ListMediasPageRequest struct { MediaTypes []int8 `form:"mediaTypes,optional"` Keys []string `form:"keys,optional"` @@ -3043,6 +3067,15 @@ type DeleteOAMediaReply struct { Data interface{} `json:"data"` } +type MPValidTokenRequest struct { + Token string `form:"token"` +} + +type MPValidTokenReply struct { + Valid bool `json:"valid"` + Reason string `json:"reason"` +} + type MPCustomerLoginRequest struct { Code string `json:"code"` } @@ -3070,6 +3103,18 @@ type MPToken struct { RefreshToken string `json:"refreshToken"` } +type GetUserInfoReplyForMP struct { + *Customer +} + +type GetCustomerMembershipByTypeRequest struct { + TypeId int64 `form:"typeId"` +} + +type GetCustomerMembershipByTypeReply struct { + *Membership +} + type ListProductCategoriesRequest struct { CategoryPId int `form:"categoryPId,optional"` NeedChildren bool `form:"needChildren,optional"` @@ -3494,6 +3539,18 @@ type UpdatePaymentReply struct { *Payment } +type TokenBalance struct { + Id int64 `json:"id,optional" desc:"代币ID"` + Balance float64 `json:"balance" desc:"代币余额"` + Usage float64 `json:"usage" desc:"使用代币"` + UnusedTicketsCount int64 `json:"unusedTicketsCount" desc:"可继续使用的ticket"` + ReservedToken float64 `json:"reservedToken" desc:"预扣代币"` +} + +type GetCustomerBalanceReply struct { + *TokenBalance +} + type CustomerLoginRequest struct { Account string `json:"account"` Password string `json:"password"` @@ -3555,7 +3612,7 @@ type WebToken struct { RefreshToken string `json:"refreshToken"` } -type GetUserInfoReplyToWeb struct { +type GetUserInfoReplyForWeb struct { *Customer } diff --git a/internal/uc/powerx.go b/internal/uc/powerx.go index a2cf77fd..8cc4576f 100644 --- a/internal/uc/powerx.go +++ b/internal/uc/powerx.go @@ -6,10 +6,13 @@ import ( customerDomainUC "PowerX/internal/uc/powerx/crm/customerdomain" "PowerX/internal/uc/powerx/crm/infoorganization" "PowerX/internal/uc/powerx/crm/market" + "PowerX/internal/uc/powerx/crm/operation" productUC "PowerX/internal/uc/powerx/crm/product" tradeUC "PowerX/internal/uc/powerx/crm/trade" "PowerX/internal/uc/powerx/scrm" "PowerX/internal/uc/powerx/wechat" + "github.com/ArtisanCloud/PowerLibs/v3/cache" + "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel" "github.com/pkg/errors" "github.com/robfig/cron/v3" "github.com/zeromicro/go-zero/core/stores/redis" @@ -21,6 +24,7 @@ import ( type PowerXUseCase struct { db *gorm.DB redis *redis.Redis + Cache cache.CacheInterface DataDictionary *powerx.DataDictionaryUseCase AdminAuthorization *powerx.AdminPermsUseCase @@ -34,6 +38,7 @@ type PowerXUseCase struct { Customer *customerDomainUC.CustomerUseCase Lead *customerDomainUC.LeadUseCase RegisterCode *customerDomainUC.RegisterCodeUseCase + Membership *operation.MembershipUseCase Product *productUC.ProductUseCase ProductStatistics *productUC.ProductStatisticsUseCase ProductSpecific *productUC.ProductSpecificUseCase @@ -50,6 +55,7 @@ type PowerXUseCase struct { Payment *tradeUC.PaymentUseCase Logistics *tradeUC.LogisticsUseCase RefundOrder *tradeUC.RefundOrderUseCase + Token *tradeUC.TokenUseCase WechatMP *wechat.WechatMiniProgramUseCase WechatOA *wechat.WechatOfficialAccountUseCase //WeWork *powerx.WeWorkUseCase @@ -90,6 +96,16 @@ func NewPowerXUseCase(conf *config.Config) (uc *PowerXUseCase, clean func()) { r.Pass = conf.RedisBase.Password }), } + + // 加载Cache对象 + cacheOption := &kernel.RedisOptions{ + Addr: conf.RedisBase.Host, + //Username: conf.RedisBase.Username, + Password: conf.RedisBase.Password, + //DB: conf.RedisBase.DB, + } + uc.Cache = kernel.NewRedisClient(cacheOption) + // 加载基础UseCase uc.DataDictionary = powerx.NewDataDictionaryUseCase(db) @@ -108,6 +124,9 @@ func NewPowerXUseCase(conf *config.Config) (uc *PowerXUseCase, clean func()) { uc.Lead = customerDomainUC.NewLeadUseCase(db) uc.RegisterCode = customerDomainUC.NewRegisterCodeUseCase(db) + // 会籍权益 + uc.Membership = operation.NewMembershipUseCase(db) + // 加载产品服务UseCase uc.ProductSpecific = productUC.NewProductSpecificUseCase(db) uc.ProductStatistics = productUC.NewProductStatisticsUseCase(db) @@ -126,6 +145,7 @@ func NewPowerXUseCase(conf *config.Config) (uc *PowerXUseCase, clean func()) { uc.Payment = tradeUC.NewPaymentUseCase(db, conf) uc.RefundOrder = tradeUC.NewRefundOrderUseCase(db) uc.Logistics = tradeUC.NewLogisticsUseCase(db) + uc.Token = tradeUC.NewTokenUseCase(db) // 加载微信UseCase //uc.WeWork = powerx.NewWeWorkUseCase(db, conf) @@ -151,3 +171,7 @@ func NewPowerXUseCase(conf *config.Config) (uc *PowerXUseCase, clean func()) { _ = sqlDB.Close() } } + +func GetRedis() { + +} diff --git a/internal/uc/powerx/crm/customerdomain/customer.go b/internal/uc/powerx/crm/customerdomain/customer.go index 32f586e5..fcb7d357 100644 --- a/internal/uc/powerx/crm/customerdomain/customer.go +++ b/internal/uc/powerx/crm/customerdomain/customer.go @@ -153,7 +153,7 @@ func (uc *CustomerUseCase) UpsertCustomers(ctx context.Context, customers []*cus func (uc *CustomerUseCase) UpdateCustomer(ctx context.Context, id int64, customer *customerdomain.Customer) error { //fmt.Dump(customer) err := uc.db.WithContext(ctx).Model(&customerdomain.Customer{}). - Debug(). + //Debug(). Where(id).Updates(&customer).Error return err diff --git a/internal/uc/powerx/crm/infoorganization/category.go b/internal/uc/powerx/crm/infoorganization/category.go index 2f6c0f06..5af23498 100644 --- a/internal/uc/powerx/crm/infoorganization/category.go +++ b/internal/uc/powerx/crm/infoorganization/category.go @@ -113,6 +113,7 @@ func (uc *CategoryUseCase) FindAllCategories(ctx context.Context, opt *FindCateg query = uc.buildFindQueryNoPage(query, opt) if err := query. + //Debug(). Find(&categories).Error; err != nil { panic(errors.Wrap(err, "find all categories failed")) } @@ -212,3 +213,30 @@ func (uc *CategoryUseCase) DeleteCategory(ctx context.Context, id int64) error { } return nil } + +func (uc *CategoryUseCase) UpsertCategoriesToObjectByObject(ctx context.Context, obj powermodel.ModelInterface, categories []*infoorganizatoin.Category) error { + + err := uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + + // 创建Pivot + pivotCategoryToObjects, err := (&infoorganizatoin.PivotCategoryToObject{}).MakeMorphPivotsFromObjectToCategories(obj, categories) + if err != nil { + return err + } + + // 清除之前的Pivot + err = tx. + //Debug(). + Delete(&infoorganizatoin.PivotCategoryToObject{}, "object_type = ? and object_id = ?", obj.GetTableName(false), obj.GetForeignReferValue()).Error + if err != nil { + return err + } + + // 创建新的Pivots + err = tx.Create(pivotCategoryToObjects).Error + + return err + }) + + return err +} diff --git a/internal/uc/powerx/crm/operation/membership.go b/internal/uc/powerx/crm/operation/membership.go new file mode 100644 index 00000000..2d65305d --- /dev/null +++ b/internal/uc/powerx/crm/operation/membership.go @@ -0,0 +1,176 @@ +package operation + +import ( + "PowerX/internal/model/crm/customerdomain" + "PowerX/internal/model/crm/operation" + "PowerX/internal/model/powermodel" + "PowerX/internal/types" + "PowerX/internal/types/errorx" + "context" + "github.com/pkg/errors" + "gorm.io/gorm" + "strings" +) + +type MembershipUseCase struct { + DB *gorm.DB +} + +func NewMembershipUseCase(db *gorm.DB) *MembershipUseCase { + return &MembershipUseCase{ + DB: db, + } +} + +type FindManyMembershipsOption struct { + LikeName string + LikeMobile string + Mobile string + Statuses []int + Sources []int + OrderBy string + types.PageEmbedOption +} + +func (uc *MembershipUseCase) buildFindQueryNoPage(db *gorm.DB, opt *FindManyMembershipsOption) *gorm.DB { + if opt.LikeName != "" { + db = db.Where("name LIKE ?", "%"+opt.LikeName+"%") + } + + if len(opt.Statuses) > 0 { + db = db.Where("status IN ?", opt.Statuses) + } + + orderBy := "id desc" + if opt.OrderBy != "" { + orderBy = opt.OrderBy + "," + orderBy + } + db.Order(orderBy) + + return db +} + +func (uc *MembershipUseCase) FindManyMemberships(ctx context.Context, opt *FindManyMembershipsOption) (pageList types.Page[*operation.Membership], err error) { + var memberships []*operation.Membership + db := uc.DB.WithContext(ctx).Model(&operation.Membership{}) + + db = uc.buildFindQueryNoPage(db, opt) + + var count int64 + if err := db.Count(&count).Error; err != nil { + panic(err) + } + + opt.DefaultPageIfNotSet() + if opt.PageIndex != 0 && opt.PageSize != 0 { + db.Offset((opt.PageIndex - 1) * opt.PageSize).Limit(opt.PageSize) + } + + if err := db. + //Debug(). + Find(&memberships).Error; err != nil { + panic(err) + } + + return types.Page[*operation.Membership]{ + List: memberships, + PageIndex: opt.PageIndex, + PageSize: opt.PageSize, + Total: count, + }, nil +} + +func (uc *MembershipUseCase) CreateMembership(ctx context.Context, membership *operation.Membership) error { + if err := uc.DB.WithContext(ctx).Create(&membership).Error; err != nil { + if strings.Contains(err.Error(), "duplicate key value violates unique constraint") { + return errorx.WithCause(errorx.ErrDuplicatedInsert, "该对象不能重复创建") + } + panic(err) + } + return nil +} + +func (uc *MembershipUseCase) UpsertMembership(ctx context.Context, m *operation.Membership) (*operation.Membership, error) { + + arrayMembership := []*operation.Membership{m} + + err := uc.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + err := powermodel.UpsertModelsOnUniqueID(tx, &operation.Membership{}, operation.MembershipUniqueId, arrayMembership, nil, false) + + if err != nil { + panic(errors.Wrap(err, "upsert membershipdomain failed")) + } + + return err + }) + + return m, err +} + +func (uc *MembershipUseCase) UpsertMemberships(ctx context.Context, memberships []*operation.Membership) ([]*operation.Membership, error) { + + err := powermodel.UpsertModelsOnUniqueID(uc.DB.WithContext(ctx), &operation.Membership{}, operation.MembershipUniqueId, memberships, nil, false) + + if err != nil { + panic(errors.Wrap(err, "batch upsert memberships failed")) + } + + return memberships, err +} + +func (uc *MembershipUseCase) UpdateMembership(ctx context.Context, id int64, m *operation.Membership) error { + //fmt.Dump(membership) + err := uc.DB.WithContext(ctx).Model(&operation.Membership{}). + //Debug(). + Where(id).Updates(m).Error + + return err +} + +func (uc *MembershipUseCase) GetMembership(ctx context.Context, id int64) (*operation.Membership, error) { + var membership operation.Membership + if err := uc.DB.WithContext(ctx).First(&membership, id).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, errorx.WithCause(errorx.ErrBadRequest, "未找到会籍") + } + panic(err) + } + return &membership, nil +} + +func (uc *MembershipUseCase) GetMembershipBy(ctx context.Context, customer *customerdomain.Customer, membershipTypeId int64) (*operation.Membership, error) { + var membership operation.Membership + if err := uc.DB.WithContext(ctx). + Where("customer_id = ? and type =?", customer.Id, membershipTypeId). + First(&membership).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + panic(err) + } + return &membership, nil + +} +func (uc *MembershipUseCase) GetMembershipByOrderId(ctx context.Context, inviteCode string) (*operation.Membership, error) { + var membership operation.Membership + if err := uc.DB.WithContext(ctx). + Where("order_id", inviteCode). + First(&membership).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, errorx.WithCause(errorx.ErrBadRequest, "未找到会籍") + } + panic(err) + } + return &membership, nil +} + +func (uc *MembershipUseCase) DeleteMembership(ctx context.Context, id int64) error { + result := uc.DB.WithContext(ctx).Delete(&operation.Membership{}, id) + if err := result.Error; err != nil { + panic(err) + } + if result.RowsAffected == 0 { + return errorx.WithCause(errorx.ErrBadRequest, "未找到会籍") + } + return nil +} diff --git a/internal/uc/powerx/crm/operation/ticket.go b/internal/uc/powerx/crm/operation/ticket.go new file mode 100644 index 00000000..986bf55c --- /dev/null +++ b/internal/uc/powerx/crm/operation/ticket.go @@ -0,0 +1,68 @@ +package operation + +import ( + "PowerX/internal/model/crm/operation" + "context" + "gorm.io/gorm" +) + +type TicketUseCase struct { + db *gorm.DB +} + +func NewTicketUseCase(db *gorm.DB) *TicketUseCase { + return &TicketUseCase{db: db} +} + +func (uc *TicketUseCase) CreateTicket(ctx context.Context, ticket *operation.TicketRecord) error { + result := uc.db.WithContext(ctx).Create(ticket) + if result.Error != nil { + return result.Error + } + return nil +} + +func (uc *TicketUseCase) GetTicketByJobID(ctx context.Context, jobId string) (*operation.TicketRecord, error) { + ticket := &operation.TicketRecord{} + result := uc.db.WithContext(ctx). + //Debug(). + First(ticket, "job_id", jobId) + if result.Error != nil { + return nil, result.Error + } + return ticket, nil +} + +func (uc *TicketUseCase) GetTicketByID(ctx context.Context, id int64) (*operation.TicketRecord, error) { + ticket := &operation.TicketRecord{} + result := uc.db.WithContext(ctx).First(ticket, id) + if result.Error != nil { + return nil, result.Error + } + return ticket, nil +} + +func (uc *TicketUseCase) UpdateTicketById(ctx context.Context, id int64, ticket *operation.TicketRecord) error { + result := uc.db.WithContext(ctx).Model(&operation.TicketRecord{}).Where("id = ?", id).Updates(ticket) + if result.Error != nil { + return result.Error + } + return nil +} + +func (uc *TicketUseCase) UpdateTicketUsage(ctx context.Context, id int64, isUsed bool) error { + result := uc.db.WithContext(ctx).Model(&operation.TicketRecord{}).Where("id = ?", id).Update("is_used", isUsed) + if result.Error != nil { + return result.Error + } + return nil +} + +func (uc *TicketUseCase) GetTicketsByStatus(ctx context.Context, customerId int64, isUsed bool) ([]*operation.TicketRecord, error) { + tickets := []*operation.TicketRecord{} + result := uc.db.WithContext(ctx).Find(&tickets, "customer_id = ? AND is_used = ?", customerId, isUsed) + if result.Error != nil { + return nil, result.Error + } + return tickets, nil +} diff --git a/internal/uc/powerx/crm/product/product.go b/internal/uc/powerx/crm/product/product.go index 89ea9c02..e763dd12 100644 --- a/internal/uc/powerx/crm/product/product.go +++ b/internal/uc/powerx/crm/product/product.go @@ -203,7 +203,7 @@ func (uc *ProductUseCase) PatchProduct(ctx context.Context, id int64, product in if err := uc.db.WithContext(ctx). Model(&model.Product{}). Where(id). - Debug(). + //Debug(). Updates(product). Error; err != nil { panic(err) diff --git a/internal/uc/powerx/crm/product/productstatistics.go b/internal/uc/powerx/crm/product/productstatistics.go index 357d2ac2..21f228c0 100644 --- a/internal/uc/powerx/crm/product/productstatistics.go +++ b/internal/uc/powerx/crm/product/productstatistics.go @@ -148,7 +148,7 @@ func (uc *ProductStatisticsUseCase) GetProductStatisticsByProductId(ctx context. var ProductStatistics product.ProductStatistics if err := uc.db.WithContext(ctx). Where("product_id", productId). - Debug(). + //Debug(). FirstOrCreate(&ProductStatistics). Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { diff --git a/internal/uc/powerx/crm/trade/order.go b/internal/uc/powerx/crm/trade/order.go index 9cc56208..9d34907c 100644 --- a/internal/uc/powerx/crm/trade/order.go +++ b/internal/uc/powerx/crm/trade/order.go @@ -18,12 +18,12 @@ import ( ) type OrderUseCase struct { - db *gorm.DB + DB *gorm.DB } func NewOrderUseCase(db *gorm.DB) *OrderUseCase { return &OrderUseCase{ - db: db, + DB: db, } } @@ -88,7 +88,7 @@ func (uc *OrderUseCase) PreloadItems(db *gorm.DB) *gorm.DB { } func (uc *OrderUseCase) FindAllOrders(ctx context.Context, opt *FindManyOrdersOption) (orders []*trade.Order, err error) { - query := uc.db.WithContext(ctx).Model(&trade.Order{}) + query := uc.DB.WithContext(ctx).Model(&trade.Order{}) query = uc.buildFindQueryNoPage(query, opt) query = uc.PreloadItems(query) @@ -103,7 +103,7 @@ func (uc *OrderUseCase) FindAllOrders(ctx context.Context, opt *FindManyOrdersOp func (uc *OrderUseCase) FindManyOrders(ctx context.Context, opt *FindManyOrdersOption) (pageList types.Page[*trade.Order], err error) { opt.DefaultPageIfNotSet() var orders []*trade.Order - db := uc.db.WithContext(ctx).Model(&trade.Order{}) + db := uc.DB.WithContext(ctx).Model(&trade.Order{}) db = uc.buildFindQueryNoPage(db, opt) @@ -134,7 +134,7 @@ func (uc *OrderUseCase) FindManyOrders(ctx context.Context, opt *FindManyOrdersO func (uc *OrderUseCase) CreateOrder(ctx context.Context, order *trade.Order) error { - if err := uc.db.WithContext(ctx). + if err := uc.DB.WithContext(ctx). //Debug(). Create(&order).Error; err != nil { if strings.Contains(err.Error(), "duplicate key value violates unique constraint") { @@ -153,7 +153,7 @@ func (uc *OrderUseCase) CreateOrderByPriceBookEntries(ctx context.Context, comment string, ) (*trade.Order, error) { order := &trade.Order{} - db := uc.db.WithContext(ctx) + db := uc.DB.WithContext(ctx) // 创建订单,类型为 普通订单 orderTypeId := uc.GetOrderTypeId(ctx, trade.OrderTypeNormal) @@ -214,7 +214,7 @@ func (uc *OrderUseCase) CreateOrderByCartItems(ctx context.Context, cart := &trade.Cart{ CustomerId: customer.Id, } - db := uc.db.WithContext(ctx) + db := uc.DB.WithContext(ctx) err := db.Transaction(func(tx *gorm.DB) error { var err error @@ -372,7 +372,7 @@ func (uc *OrderUseCase) MakeOrderItemFromCartItem( func (uc *OrderUseCase) UpsertOrderWithLogistic(ctx context.Context, order *trade.Order) (*trade.Order, error) { orders := []*trade.Order{order} - err := uc.db.Transaction(func(tx *gorm.DB) error { + err := uc.DB.Transaction(func(tx *gorm.DB) error { // 更新产品对象主体 _, err := uc.UpsertOrders(ctx, orders) @@ -392,7 +392,7 @@ func (uc *OrderUseCase) UpsertOrder(ctx context.Context, order *trade.Order) (*t orders := []*trade.Order{order} - err := uc.db.Transaction(func(tx *gorm.DB) error { + err := uc.DB.Transaction(func(tx *gorm.DB) error { // 删除产品的相关联对象 _, err := uc.ClearAssociations(tx, order) if err != nil { @@ -413,7 +413,7 @@ func (uc *OrderUseCase) UpsertOrder(ctx context.Context, order *trade.Order) (*t func (uc *OrderUseCase) UpsertOrders(ctx context.Context, orders []*trade.Order) ([]*trade.Order, error) { - err := powermodel.UpsertModelsOnUniqueID(uc.db.WithContext(ctx), &trade.Order{}, trade.OrderUniqueId, orders, nil, false) + err := powermodel.UpsertModelsOnUniqueID(uc.DB.WithContext(ctx), &trade.Order{}, trade.OrderUniqueId, orders, nil, false) if err != nil { panic(errors.Wrap(err, "batch upsert orders failed")) @@ -423,7 +423,7 @@ func (uc *OrderUseCase) UpsertOrders(ctx context.Context, orders []*trade.Order) } func (uc *OrderUseCase) PatchOrder(ctx context.Context, id int64, order *trade.Order) { - if err := uc.db.WithContext(ctx).Model(&trade.Order{}). + if err := uc.DB.WithContext(ctx).Model(&trade.Order{}). Where(id).Updates(&order).Error; err != nil { panic(err) } @@ -431,7 +431,7 @@ func (uc *OrderUseCase) PatchOrder(ctx context.Context, id int64, order *trade.O func (uc *OrderUseCase) GetOrder(ctx context.Context, id int64) (*trade.Order, error) { var order = &trade.Order{} - db := uc.db.WithContext(ctx) + db := uc.DB.WithContext(ctx) db = uc.PreloadItems(db) if err := db. //Debug(). @@ -453,7 +453,7 @@ func (uc *OrderUseCase) DeleteOrder(ctx context.Context, id int64) error { return errorx.ErrNotFoundObject } - err = uc.db.Transaction(func(tx *gorm.DB) error { + err = uc.DB.Transaction(func(tx *gorm.DB) error { // 删除产品相关项 _, err = uc.ClearAssociations(tx, order) if err != nil { @@ -488,12 +488,12 @@ func (uc *OrderUseCase) ChangeOrderStatusFromTo(ctx context.Context, order *trad fromStatus string, toStatus string, ) (*trade.Order, error) { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) orderStatusId := ucDD.GetCachedDDId(ctx, trade.TypeOrderStatus, fromStatus) toStatusId := ucDD.GetCachedDDId(ctx, trade.TypeOrderStatus, toStatus) - err := uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + err := uc.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error { // 修改订单的支付状态记录 order.Status = toStatusId @@ -516,7 +516,7 @@ func (uc *OrderUseCase) ChangeOrderStatusFromTo(ctx context.Context, order *trad } func (uc *OrderUseCase) CanOrderCancel(ctx context.Context, order *trade.Order) bool { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) ddOrderStatus := ucDD.GetCachedDDById(ctx, order.Status) availableStatus := []string{ trade.OrderStatusPending, @@ -531,26 +531,26 @@ func (uc *OrderUseCase) CanOrderCancel(ctx context.Context, order *trade.Order) } func (uc *OrderUseCase) IsOrderTypeSameAs(ctx context.Context, order *trade.Order, orderType string) bool { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) return order.Type == ucDD.GetCachedDDId(ctx, trade.TypeOrderType, orderType) } func (uc *OrderUseCase) IsOrderStatusSameAs(ctx context.Context, order *trade.Order, orderStatus string) bool { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) return order.Status == ucDD.GetCachedDDId(ctx, trade.TypeOrderStatus, orderStatus) } func (uc *OrderUseCase) GetOrderTypeId(ctx context.Context, orderType string) (orderTypeId int) { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) orderTypeId = ucDD.GetCachedDDId(ctx, trade.TypeOrderType, orderType) return orderTypeId } func (uc *OrderUseCase) GetOrderStatusId(ctx context.Context, orderStatus string) (orderStatusId int) { - ucDD := powerx.NewDataDictionaryUseCase(uc.db) + ucDD := powerx.NewDataDictionaryUseCase(uc.DB) orderStatusId = ucDD.GetCachedDDId(ctx, trade.TypeOrderStatus, orderStatus) return orderStatusId } diff --git a/internal/uc/powerx/crm/trade/token.go b/internal/uc/powerx/crm/trade/token.go index 4812495a..7b12d6b1 100644 --- a/internal/uc/powerx/crm/trade/token.go +++ b/internal/uc/powerx/crm/trade/token.go @@ -1,6 +1,8 @@ package trade import ( + "PowerX/internal/model/crm/customerdomain" + "PowerX/internal/model/crm/operation" "PowerX/internal/model/crm/trade" "PowerX/internal/model/powermodel" "PowerX/internal/types" @@ -49,23 +51,29 @@ func (uc *TokenUseCase) PreloadItems(db *gorm.DB) *gorm.DB { return db } -func (uc *TokenUseCase) FindAllTokenBalances(ctx context.Context, opt *FindManyTokensOption) (tokenBalances []*trade.TokenBalance, err error) { - query := uc.db.WithContext(ctx).Model(&trade.TokenBalance{}) +// -----------------------------// + +// Token Exchange Record + +// -----------------------------// + +func (uc *TokenUseCase) FindAllTokenExchangeRecords(ctx context.Context, opt *FindManyTokensOption) (records []*trade.TokenExchangeRecord, err error) { + query := uc.db.WithContext(ctx).Model(&trade.TokenExchangeRecord{}) query = uc.buildFindQueryNoPage(query, opt) query = uc.PreloadItems(query) if err := query. //Debug(). - Find(&tokenBalances).Error; err != nil { + Find(&records).Error; err != nil { panic(errors.Wrap(err, "find all tokenBalances failed")) } - return tokenBalances, err + return records, err } -func (uc *TokenUseCase) FindManyTokens(ctx context.Context, opt *FindManyTokensOption) (pageList types.Page[*trade.TokenBalance], err error) { +func (uc *TokenUseCase) FindManyTokensExchangeRecords(ctx context.Context, opt *FindManyTokensOption) (pageList types.Page[*trade.TokenExchangeRecord], err error) { opt.DefaultPageIfNotSet() - var tokens []*trade.TokenBalance - db := uc.db.WithContext(ctx).Model(&trade.TokenBalance{}) + var tokens []*trade.TokenExchangeRecord + db := uc.db.WithContext(ctx).Model(&trade.TokenExchangeRecord{}) db = uc.buildFindQueryNoPage(db, opt) @@ -86,7 +94,7 @@ func (uc *TokenUseCase) FindManyTokens(ctx context.Context, opt *FindManyTokensO panic(err) } - return types.Page[*trade.TokenBalance]{ + return types.Page[*trade.TokenExchangeRecord]{ List: tokens, PageIndex: opt.PageIndex, PageSize: opt.PageSize, @@ -94,11 +102,11 @@ func (uc *TokenUseCase) FindManyTokens(ctx context.Context, opt *FindManyTokensO }, nil } -func (uc *TokenUseCase) CreateToken(ctx context.Context, order *trade.TokenBalance) error { +func (uc *TokenUseCase) CreateTokenExchangeRecord(ctx context.Context, record *trade.TokenExchangeRecord) error { if err := uc.db.WithContext(ctx). //Debug(). - Create(&order).Error; err != nil { + Create(&record).Error; err != nil { if strings.Contains(err.Error(), "duplicate key value violates unique constraint") { return errorx.WithCause(errorx.ErrDuplicatedInsert, "该对象不能重复创建") } @@ -107,64 +115,360 @@ func (uc *TokenUseCase) CreateToken(ctx context.Context, order *trade.TokenBalan return nil } -func (uc *TokenUseCase) UpsertToken(ctx context.Context, order *trade.TokenBalance) (*trade.TokenBalance, error) { +func (uc *TokenUseCase) UpsertTokenExchangeRecord(ctx context.Context, record *trade.TokenExchangeRecord) (*trade.TokenExchangeRecord, error) { - tokens := []*trade.TokenBalance{order} + records := []*trade.TokenExchangeRecord{record} err := uc.db.Transaction(func(tx *gorm.DB) error { // 删除产品的相关联对象 - _, err := uc.ClearAssociations(tx, order) - if err != nil { - return err - } + //_, err := uc.ClearAssociations(tx, records) + //if err != nil { + // return err + //} // 更新产品对象主体 - _, err = uc.UpsertTokens(ctx, tokens) + _, err := uc.UpsertTokenExchangeRecords(ctx, records) if err != nil { - return errors.Wrap(err, "upsert order failed") + return errors.Wrap(err, "upsert records failed") } return err }) - return order, err + return record, err } -func (uc *TokenUseCase) UpsertTokens(ctx context.Context, tokens []*trade.TokenBalance) ([]*trade.TokenBalance, error) { +func (uc *TokenUseCase) UpsertTokenExchangeRecords(ctx context.Context, records []*trade.TokenExchangeRecord) ([]*trade.TokenExchangeRecord, error) { - err := powermodel.UpsertModelsOnUniqueID(uc.db.WithContext(ctx), &trade.TokenBalance{}, trade.TokenBalanceUniqueId, tokens, nil, false) + err := powermodel.UpsertModelsOnUniqueID(uc.db.WithContext(ctx), &trade.TokenExchangeRecord{}, trade.TokenExchangeRecordId, records, nil, false) if err != nil { panic(errors.Wrap(err, "batch upsert tokens failed")) } - return tokens, err + return records, err } -func (uc *TokenUseCase) PatchToken(ctx context.Context, id int64, order *trade.TokenBalance) { +func (uc *TokenUseCase) PatchTokenExchangeRecords(ctx context.Context, id int64, record *trade.TokenExchangeRecord) { if err := uc.db.WithContext(ctx).Model(&trade.TokenBalance{}). - Where(id).Updates(&order).Error; err != nil { + Where(id).Updates(&record).Error; err != nil { + panic(err) + } +} + +func (uc *TokenUseCase) AddTokenByOrder(ctx context.Context, ticket *operation.TicketRecord, tokenTransactionTypeId int) (*trade.TokenTransaction, error) { + var err error + + transaction := &trade.TokenTransaction{ + CustomerId: ticket.CustomerId, + Amount: ticket.DeductedTokenAmount, + Type: tokenTransactionTypeId, + SourceType: (&operation.TicketRecord{}).GetTableName(false), + SourceID: ticket.Id, + } + + err = uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + + // 更新Token预约单状态 + err = tx.Model(&trade.TokenReservation{}). + //Debug(). + Where("source_type =? AND source_id = ?", ticket.GetTableName(false), ticket.Id). + Update("is_confirmed", true).Error + + // 修改ticket状态为已经完成 + ticket.IsUsed = true + err = tx.Save(ticket).Error + if err != nil { + return err + } + + // 创建一条代币事务记录 + err = tx. + //Debug(). + Create(transaction).Error + if err != nil { + return err + } + + return err + }) + + return transaction, err + +} + +func (uc *TokenUseCase) DeductTokenByTicket(ctx context.Context, ticket *operation.TicketRecord, tokenTransactionTypeId int) (*trade.TokenTransaction, error) { + var err error + + transaction := &trade.TokenTransaction{ + CustomerId: ticket.CustomerId, + Amount: ticket.DeductedTokenAmount, + Type: tokenTransactionTypeId, + SourceType: (&operation.TicketRecord{}).GetTableName(false), + SourceID: ticket.Id, + } + + err = uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + + // 更新Token预约单状态 + err = tx.Model(&trade.TokenReservation{}). + //Debug(). + Where("source_type =? AND source_id = ?", ticket.GetTableName(false), ticket.Id). + Update("is_confirmed", true).Error + + // 修改ticket状态为已经完成 + ticket.IsUsed = true + err = tx.Save(ticket).Error + if err != nil { + return err + } + + // 创建一条代币事务记录 + err = tx. + //Debug(). + Create(transaction).Error + if err != nil { + return err + } + + return err + }) + + return transaction, err + +} + +// -----------------------------// + +// Token Balance + +// -----------------------------// + +func (uc *TokenUseCase) CreateTokenBalance(ctx context.Context, balance *trade.TokenBalance) error { + + if err := uc.db.WithContext(ctx). + //Debug(). + Create(&balance).Error; err != nil { + if strings.Contains(err.Error(), "duplicate key value violates unique constraint") { + return errorx.WithCause(errorx.ErrDuplicatedInsert, "该对象不能重复创建") + } panic(err) } + return nil } -func (uc *TokenUseCase) GetTokenBalance(ctx context.Context, id int64) (*trade.TokenBalance, error) { - var order = &trade.TokenBalance{} +func (uc *TokenUseCase) GetTokenBalance(ctx context.Context, customerId int64) (*trade.TokenBalance, error) { + var balance = &trade.TokenBalance{} db := uc.db.WithContext(ctx) db = uc.PreloadItems(db) if err := db. //Debug(). - First(order, id).Error; err != nil { + Where("customer_id = ?", customerId). + First(balance).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errorx.WithCause(errorx.ErrBadRequest, "未找到产品") } - panic(err) + return nil, err + } + + return balance, nil +} + +func (uc *TokenUseCase) UpsertTokenBalance(ctx context.Context, record *trade.TokenExchangeRecord) (*trade.TokenExchangeRecord, error) { + + records := []*trade.TokenExchangeRecord{record} + + err := uc.db.Transaction(func(tx *gorm.DB) error { + // 删除产品的相关联对象 + //_, err := uc.ClearAssociations(tx, records) + //if err != nil { + // return err + //} + + // 更新产品对象主体 + _, err := uc.UpsertTokenExchangeRecords(ctx, records) + if err != nil { + return errors.Wrap(err, "upsert records failed") + } + + return err + }) + + return record, err +} + +func (uc *TokenUseCase) UpsertTokenBalances(ctx context.Context, records []*trade.TokenExchangeRecord) ([]*trade.TokenExchangeRecord, error) { + + err := powermodel.UpsertModelsOnUniqueID(uc.db.WithContext(ctx), &trade.TokenExchangeRecord{}, trade.TokenBalanceUniqueId, records, nil, false) + + if err != nil { + panic(errors.Wrap(err, "batch upsert tokens failed")) + } + + return records, err +} + +// -----------------------------// + +// Token Reservation + +// -----------------------------// + +func (uc *TokenUseCase) CheckTokenBalanceIsEnough(ctx context.Context, customer *customerdomain.Customer) (*trade.TokenBalance, int64, error) { + // 当前余额 + balance, err := uc.GetTokenBalance(ctx, customer.Id) + if err != nil { + return nil, 0, err + } + // 使用代币状态 + usedToken, err := uc.GetUsedTokens(ctx, customer.Id) + if err != nil { + return nil, 0, err + } + balance.Usage = usedToken + + // 预扣款代币状态 + var unusedTicketsCount int64 + if err := uc.db.WithContext(ctx).Model(&operation.TicketRecord{}). + //Debug(). + Select("count(ticket_records.id) as unused_tickets_count"). + Where("ticket_records.customer_id = ? AND ticket_records.is_used = ?", customer.Id, false). + Joins("LEFT JOIN robot_tasks ON ticket_records.job_id = robot_tasks.job_id"). + Where("ticket_records.is_used = ?", false). + Count(&unusedTicketsCount). + Error; err != nil { + return nil, 0, err + } + + if balance.Balance < 1 && unusedTicketsCount < 1 { + if balance.Balance < 1 { + return balance, unusedTicketsCount, errorx.ErrNotEnoughBalance + } + if unusedTicketsCount < 1 { + return balance, unusedTicketsCount, errorx.ErrNotEnoughTicket + } + } + + return balance, unusedTicketsCount, nil +} + +func (uc *TokenUseCase) CreateReservedTokenByTicket(ctx context.Context, + ticket *operation.TicketRecord, balance *trade.TokenBalance, +) error { + err := uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // 创建一条Ticket + err := tx.Create(ticket).Error + if err != nil { + return err + } + + // 同时预扣款Token + err = tx.Create(&trade.TokenReservation{ + CustomerId: ticket.CustomerId, + Amount: ticket.DeductedTokenAmount, + SourceType: ticket.GetTableName(false), + SourceID: ticket.Id, + IsConfirmed: false, + }).Error + if err != nil { + return err + } + + // 扣除余额,并且保存 + balance.Balance = balance.Balance - ticket.DeductedTokenAmount + err = tx.Save(balance).Error + + return err + }) + + return err +} + +func (uc *TokenUseCase) ReuseTicketForTask(ctx context.Context, + customer *customerdomain.Customer, + oldTicket *operation.TicketRecord, newTicket *operation.TicketRecord, + reservedToken *trade.TokenReservation, balance *trade.TokenBalance, +) error { + err := uc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // 之前对应的Ticket,需要被作废,delete + err := tx.Delete(&operation.TicketRecord{}, oldTicket.Id).Error + if err != nil { + return err + } + + // 创建一条Ticket + err = tx.Create(newTicket).Error + if err != nil { + return err + } + + // 同时Token预扣记录更新 + reservedToken.SourceType = newTicket.GetTableName(false) + reservedToken.SourceID = newTicket.Id + err = tx.Save(reservedToken).Error + if err != nil { + return err + } + + return err + }) + + return err + +} + +func (uc *TokenUseCase) GetUsedTokens(ctx context.Context, customerId int64) (float64, error) { + type result struct { + Total float64 `gorm:"column:amount_used"` + } + var tokenReserved = &result{} + db := uc.db.WithContext(ctx) + if err := db.Model(&trade.TokenReservation{}). + Select("customer_id, sum(amount) as amount_used"). + //Debug(). + Where("customer_id = ? AND is_confirmed = ?", customerId, true). + Group("customer_id"). + Limit(1). + Scan(tokenReserved).Error; err != nil { + return 0, err + } + + return tokenReserved.Total, nil +} + +func (uc *TokenUseCase) GetReservedTokenByTicket(ctx context.Context, ticket *operation.TicketRecord) (*trade.TokenReservation, error) { + + reservation := &trade.TokenReservation{} + err := uc.db.WithContext(ctx).Model(&trade.TokenReservation{}). + Debug(). + Where("source_type =? AND source_id = ?", ticket.GetTableName(false), ticket.Id). + First(reservation).Error + if err != nil { + return nil, err + } + return reservation, nil +} + +func (uc *TokenUseCase) GetReservedTokens(ctx context.Context, customerId int64) (float64, error) { + type result struct { + Total float64 `gorm:"column:amount_reserved"` + } + var tokenReserved = &result{} + db := uc.db.WithContext(ctx) + if err := db.Model(&trade.TokenReservation{}). + Select("customer_id, sum(amount) as amount_reserved"). + //Debug(). + Where("customer_id = ? AND is_confirmed = ?", customerId, false). + Group("customer_id"). + Limit(1). + Scan(tokenReserved).Error; err != nil { + return 0, err } - return order, nil + return tokenReserved.Total, nil } -func (uc *TokenUseCase) ClearAssociations(db *gorm.DB, order *trade.TokenBalance) (*trade.TokenBalance, error) { +func (uc *TokenUseCase) ClearAssociations(db *gorm.DB, balance *trade.TokenBalance) (*trade.TokenBalance, error) { var err error // 清除订单的关联 //err = order.ClearArtisans(db) @@ -172,5 +476,5 @@ func (uc *TokenUseCase) ClearAssociations(db *gorm.DB, order *trade.TokenBalance // return nil, err //} - return order, err + return balance, err } diff --git a/internal/uc/powerx/mediaresource.go b/internal/uc/powerx/mediaresource.go index 92db15cb..d477c5c0 100644 --- a/internal/uc/powerx/mediaresource.go +++ b/internal/uc/powerx/mediaresource.go @@ -10,11 +10,14 @@ import ( "context" "encoding/base64" "fmt" + "github.com/ArtisanCloud/PowerLibs/v3/cache" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/pkg/errors" "gorm.io/gorm" + "io" "mime/multipart" + "net/http" "os" "path/filepath" "time" @@ -204,6 +207,24 @@ func (uc *MediaResourceUseCase) MakeLocalResource(ctx context.Context, bucket st return resource, nil } +func (uc *MediaResourceUseCase) GetOSSResourceURL(bucket string, key string) (string, error) { + + uri, err := uc.GetOSSResourceURI(bucket, key) + if err != nil { + return "", nil + } + endpoint := uc.OSSClient.EndpointURL() + url := endpoint.String() + uri + + return url, err +} + +func (uc *MediaResourceUseCase) GetOSSResourceURI(bucket string, key string) (string, error) { + endpoint := uc.OSSClient.EndpointURL() + url, err := httpx.AppendURIs(endpoint.String(), bucket, key) + return url, err +} + func (uc *MediaResourceUseCase) MakeOSSResource(ctx context.Context, bucket string, handle *multipart.FileHeader) (resource *media.MediaResource, err error) { err = uc.CheckBucketExits(ctx, bucket) @@ -219,7 +240,7 @@ func (uc *MediaResourceUseCase) MakeOSSResource(ctx context.Context, bucket stri info, err := uc.OSSClient.PutObject(ctx, bucket, objectName, filePath, handle.Size, minio.PutObjectOptions{ContentType: contentType}) //fmt2.Dump(info) - url, _ := httpx.AppendURIs(uc.OSSClient.EndpointURL().String(), bucket, info.Key) + url, _ := uc.GetOSSResourceURI(bucket, info.Key) resource = &media.MediaResource{ BucketName: bucket, @@ -233,17 +254,53 @@ func (uc *MediaResourceUseCase) MakeOSSResource(ctx context.Context, bucket stri return resource, err } -func (uc *MediaResourceUseCase) MakeOSSResourceByBase64(ctx context.Context, bucket string, base64Data string) (resource *media.MediaResource, err error) { +func (uc *MediaResourceUseCase) MakeOSSResourceByBase64String(ctx context.Context, bucket string, base64Data string) (resource *media.MediaResource, err error) { + // 解码base64数据 + data, err := base64.StdEncoding.DecodeString(base64Data) + if err != nil { + return nil, fmt.Errorf("base64数据解码失败:%w", err) + } - err = uc.CheckBucketExits(ctx, bucket) + return uc.MakeOSSResourceByBase64Data(ctx, bucket, data) + +} + +func (m *MediaResourceUseCase) GetBase64DataFromMedia(ctx context.Context, media *media.MediaResource) (string, error) { + // 从OSS中获取图片数据 + url, err := m.GetOSSResourceURL(media.BucketName, media.Filename) if err != nil { - return nil, err + return "", err } - // 解码base64数据 - data, err := base64.StdEncoding.DecodeString(base64Data) + // 加载图片,转变成base64 + // 通过HTTP GET请求获取图片数据 + resp, err := http.Get(url) if err != nil { - return nil, fmt.Errorf("base64数据解码失败:%w", err) + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", errors.New("failed to fetch media data") + } + + // 读取图片数据 + data, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + // 将图片数据转换为Base64 + base64Data := base64.StdEncoding.EncodeToString(data) + + return base64Data, err +} + +func (uc *MediaResourceUseCase) MakeOSSResourceByBase64Data(ctx context.Context, bucket string, data []byte) (resource *media.MediaResource, err error) { + + err = uc.CheckBucketExits(ctx, bucket) + if err != nil { + return nil, err } // 创建一个新的MinIO对象,并使用随机名称 @@ -251,7 +308,9 @@ func (uc *MediaResourceUseCase) MakeOSSResourceByBase64(ctx context.Context, buc // 准备对象元数据(可选) objectMetadata := make(map[string]string) - objectMetadata["Content-Type"] = "image/jpeg" // 替换为实际内容类型 + objectMetadata["Content-Type"] = "image/png" // 替换为实际内容类型 + //objectMetadata["Content-Type"] = "image/jpeg" // 替换为实际内容类型 + //objectMetadata["Content-Type"] = "image/webp" // 替换为实际内容类型 // 上传对象到MinIO contentType := objectMetadata["Content-Type"] @@ -308,3 +367,18 @@ func (uc *MediaResourceUseCase) CheckBucketExits(ctx context.Context, bucket str return nil } + +func (uc *MediaResourceUseCase) GetCachedBase64DataFromMedia(ctx context.Context, cache cache.CacheInterface, media *media.MediaResource) (string, error) { + // 从缓存中获取图片数据 + data, err := cache.Remember(media.Filename, 3600*time.Hour, func() (interface{}, error) { + // 将url图片转换成Base64 + //fmt2.Dump("get data from oss", media.Filename) + return uc.GetBase64DataFromMedia(ctx, media) + + }) + if err != nil { + return "", err + } + + return data.(string), err +} diff --git a/pkg/filex/filex.go b/pkg/filex/filex.go index 7ed1c79b..0535f5de 100644 --- a/pkg/filex/filex.go +++ b/pkg/filex/filex.go @@ -49,6 +49,12 @@ func GetTempFilePath(fileName string) (string, error) { return filePath, nil } +// 判断文件是否为图片文件(可根据实际情况修改) +func IsImageFile(fileName string) bool { + ext := strings.ToLower(filepath.Ext(fileName)) + return ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" +} + func GetFileExtension(filename string) string { ext := filepath.Ext(filename) // 去掉后缀中的点号 diff --git a/swagger/customer.json b/swagger/customer.json index e2785faa..fd86c1b9 100644 --- a/swagger/customer.json +++ b/swagger/customer.json @@ -431,14 +431,14 @@ "customer" ] }, - "GetCustomerReqeuest": { + "GetCustomerRequest": { "type": "object", "properties": { "id": { "type": "string" } }, - "title": "GetCustomerReqeuest", + "title": "GetCustomerRequest", "required": [ "id" ]