237 lines
8.1 KiB
Go
237 lines
8.1 KiB
Go
package userclient
|
||
|
||
import (
|
||
"context"
|
||
|
||
userv1 "hyapp.local/api/proto/user/v1"
|
||
)
|
||
|
||
// Country 是 admin-server 暴露给后台前端的国家主数据 DTO。
|
||
// 这里不引用 user-service 的 domain/storage 包,避免后台服务和用户服务代码结构耦合。
|
||
type Country struct {
|
||
// CountryID 是 user-service 生成的国家主键,后台增删改查都以它定位记录。
|
||
CountryID int64 `json:"countryId"`
|
||
// CountryName 是稳定英文或拼音名称,例如 China、United States。
|
||
CountryName string `json:"countryName"`
|
||
// CountryCode 是 App 和用户链路使用的 canonical 国家码,创建后不可变。
|
||
CountryCode string `json:"countryCode"`
|
||
// CountryDisplayName 是后台和 App 注册页展示用中文名。
|
||
CountryDisplayName string `json:"countryDisplayName"`
|
||
// SortOrder 控制 App 注册页和后台列表的默认排序。
|
||
SortOrder int32 `json:"sortOrder"`
|
||
// CreatedAtMs 直接透传 user-service 的毫秒时间戳,避免跨服务时区转换。
|
||
CreatedAtMs int64 `json:"createdAtMs"`
|
||
// UpdatedAtMs 直接透传 user-service 的毫秒时间戳,便于后台做新旧数据判断。
|
||
UpdatedAtMs int64 `json:"updatedAtMs"`
|
||
// ISOAlpha3 是 ISO 3166-1 alpha-3 或明确的 user-assigned code。
|
||
ISOAlpha3 string `json:"isoAlpha3"`
|
||
// ISONumeric 必须保持字符串,避免 020 这类前导零被破坏。
|
||
ISONumeric string `json:"isoNumeric"`
|
||
// PhoneCountryCode 是 E.164 国家呼叫码,例如 +86。
|
||
PhoneCountryCode string `json:"phoneCountryCode"`
|
||
// Enabled 表示该国家是否允许 App 注册和用户改国家选择。
|
||
Enabled bool `json:"enabled"`
|
||
// Flag 是展示字段,不参与国家唯一性、区域归属或权限判断。
|
||
Flag string `json:"flag"`
|
||
}
|
||
|
||
// Region 是 user-service 区域主数据投影;countries 只包含当前 active 国家码。
|
||
type Region struct {
|
||
// RegionID 是区域主键,BD Leader/BD/Agency 后续都围绕它建立组织关系。
|
||
RegionID int64 `json:"regionId"`
|
||
// RegionCode 是稳定业务编码;后台修改时仍由 user-service 做唯一性校验。
|
||
RegionCode string `json:"regionCode"`
|
||
// Name 是后台展示名。
|
||
Name string `json:"name"`
|
||
// Status 当前只由 user-service 约束为 active 或 disabled。
|
||
Status string `json:"status"`
|
||
// Countries 是 active 映射国家码列表;一个国家不能同时属于多个 active 区域。
|
||
Countries []string `json:"countries"`
|
||
// SortOrder 控制后台和业务选择器排序。
|
||
SortOrder int32 `json:"sortOrder"`
|
||
// CreatedAtMs 直接透传 user-service 的毫秒时间戳。
|
||
CreatedAtMs int64 `json:"createdAtMs"`
|
||
// UpdatedAtMs 直接透传 user-service 的毫秒时间戳。
|
||
UpdatedAtMs int64 `json:"updatedAtMs"`
|
||
}
|
||
|
||
// ListCountriesRequest 支持 enabled 三态过滤:nil 表示全部,true/false 表示显式筛选。
|
||
type ListCountriesRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
Enabled *bool
|
||
}
|
||
|
||
// UpdateCountryRequest 只允许修改展示和辅助字段,不允许修改 country_code。
|
||
type UpdateCountryRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
CountryID int64
|
||
CountryName string
|
||
CountryDisplayName string
|
||
SortOrder int32
|
||
OperatorUserID int64
|
||
ISOAlpha3 string
|
||
ISONumeric string
|
||
PhoneCountryCode string
|
||
Flag string
|
||
}
|
||
|
||
// ListRegionsRequest 支持 status 过滤;空字符串表示全部。
|
||
type ListRegionsRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
Status string
|
||
}
|
||
|
||
// GetRegionRequest 按区域主键查询单个区域及 active 国家码。
|
||
type GetRegionRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
RegionID int64
|
||
}
|
||
|
||
// UpdateRegionRequest 只修改区域展示字段,不替换国家归属。
|
||
type UpdateRegionRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
RegionID int64
|
||
RegionCode string
|
||
Name string
|
||
SortOrder int32
|
||
OperatorUserID int64
|
||
}
|
||
|
||
// ReplaceRegionCountriesRequest 原子替换区域国家归属,并由 user-service 创建用户区域重算任务。
|
||
type ReplaceRegionCountriesRequest struct {
|
||
RequestID string
|
||
Caller string
|
||
RegionID int64
|
||
Countries []string
|
||
OperatorUserID int64
|
||
}
|
||
|
||
func (c *GRPCClient) ListCountries(ctx context.Context, req ListCountriesRequest) ([]*Country, error) {
|
||
resp, err := c.countryClient.ListCountries(ctx, &userv1.ListCountriesRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
Enabled: req.Enabled,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
items := make([]*Country, 0, len(resp.GetCountries()))
|
||
for _, country := range resp.GetCountries() {
|
||
items = append(items, fromProtoCountry(country))
|
||
}
|
||
return items, nil
|
||
}
|
||
|
||
func (c *GRPCClient) UpdateCountry(ctx context.Context, req UpdateCountryRequest) (*Country, error) {
|
||
resp, err := c.countryClient.UpdateCountry(ctx, &userv1.UpdateCountryRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
CountryId: req.CountryID,
|
||
CountryName: req.CountryName,
|
||
CountryDisplayName: req.CountryDisplayName,
|
||
SortOrder: req.SortOrder,
|
||
OperatorUserId: req.OperatorUserID,
|
||
IsoAlpha3: req.ISOAlpha3,
|
||
IsoNumeric: req.ISONumeric,
|
||
PhoneCountryCode: req.PhoneCountryCode,
|
||
Flag: req.Flag,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return fromProtoCountry(resp.GetCountry()), nil
|
||
}
|
||
|
||
func (c *GRPCClient) ListRegions(ctx context.Context, req ListRegionsRequest) ([]*Region, error) {
|
||
resp, err := c.regionClient.ListRegions(ctx, &userv1.ListRegionsRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
Status: req.Status,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
items := make([]*Region, 0, len(resp.GetRegions()))
|
||
for _, region := range resp.GetRegions() {
|
||
items = append(items, fromProtoRegion(region))
|
||
}
|
||
return items, nil
|
||
}
|
||
|
||
func (c *GRPCClient) GetRegion(ctx context.Context, req GetRegionRequest) (*Region, error) {
|
||
resp, err := c.regionClient.GetRegion(ctx, &userv1.GetRegionRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
RegionId: req.RegionID,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return fromProtoRegion(resp.GetRegion()), nil
|
||
}
|
||
|
||
func (c *GRPCClient) UpdateRegion(ctx context.Context, req UpdateRegionRequest) (*Region, error) {
|
||
resp, err := c.regionClient.UpdateRegion(ctx, &userv1.UpdateRegionRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
RegionId: req.RegionID,
|
||
RegionCode: req.RegionCode,
|
||
Name: req.Name,
|
||
SortOrder: req.SortOrder,
|
||
OperatorUserId: req.OperatorUserID,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return fromProtoRegion(resp.GetRegion()), nil
|
||
}
|
||
|
||
func (c *GRPCClient) ReplaceRegionCountries(ctx context.Context, req ReplaceRegionCountriesRequest) (*Region, error) {
|
||
resp, err := c.regionClient.ReplaceRegionCountries(ctx, &userv1.ReplaceRegionCountriesRequest{
|
||
Meta: requestMeta(ctx, req.RequestID, req.Caller),
|
||
RegionId: req.RegionID,
|
||
Countries: append([]string(nil), req.Countries...),
|
||
OperatorUserId: req.OperatorUserID,
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return fromProtoRegion(resp.GetRegion()), nil
|
||
}
|
||
|
||
func fromProtoCountry(country *userv1.Country) *Country {
|
||
if country == nil {
|
||
return nil
|
||
}
|
||
return &Country{
|
||
CountryID: country.GetCountryId(),
|
||
CountryName: country.GetCountryName(),
|
||
CountryCode: country.GetCountryCode(),
|
||
CountryDisplayName: country.GetCountryDisplayName(),
|
||
SortOrder: country.GetSortOrder(),
|
||
CreatedAtMs: country.GetCreatedAtMs(),
|
||
UpdatedAtMs: country.GetUpdatedAtMs(),
|
||
ISOAlpha3: country.GetIsoAlpha3(),
|
||
ISONumeric: country.GetIsoNumeric(),
|
||
PhoneCountryCode: country.GetPhoneCountryCode(),
|
||
Enabled: country.GetEnabled(),
|
||
Flag: country.GetFlag(),
|
||
}
|
||
}
|
||
|
||
func fromProtoRegion(region *userv1.Region) *Region {
|
||
if region == nil {
|
||
return nil
|
||
}
|
||
return &Region{
|
||
RegionID: region.GetRegionId(),
|
||
RegionCode: region.GetRegionCode(),
|
||
Name: region.GetName(),
|
||
Status: region.GetStatus(),
|
||
Countries: append([]string{}, region.GetCountries()...),
|
||
SortOrder: region.GetSortOrder(),
|
||
CreatedAtMs: region.GetCreatedAtMs(),
|
||
UpdatedAtMs: region.GetUpdatedAtMs(),
|
||
}
|
||
}
|