作者 yangfu
... ... @@ -8,53 +8,20 @@ import (
)
type CooperationApplicationItem struct {
CooperationProject struct {
CooperationProjectID string `json:"cooperationProjectId"` //共创项目
CooperationProjectName string `json:"cooperationProjectName"` //共创名称
CooperationProjectNumber string `json:"cooperationProjectNumber"` //共创编号
} `json:"cooperationProject"`
CooperationApplicationApplicant struct {
UserId int
UserInfo struct {
UserAvatar string
UserEmail string
UserName string
UserPhone string
UserAccount string
}
} `json:"cooperationApplicationApplicant"`
CooperationApplicationAttachment []domain.Attachment `json:"cooperationApplicationAttachment"` //附件
CooperationApplicationDescription string `json:"cooperationApplicationDescription"` //描述
CooperationApplicationID string `json:"cooperationApplicationId"` //id
IsCanceled bool `json:"isCanceled"` //是否取消
CooperationApplicationVerifyDescription string `json:"cooperationApplicationVerifyDescription"` //审核描述
CooperationApplicationVerifyTime time.Time `json:"cooperationApplicationVerifyTime"` //审核时间
CooperationApplicationStatus int `json:"cooperationApplicationStatus"` //
Org struct {
OrgID string `json:"orgId"`
OrgName string `json:"orgName"`
} `json:"org"` //组织
allied_creation_cooperation.CooperationApplication
AuthFlag bool `json:"authFlag"`
}
func ToCooperationApplicationItem(param *allied_creation_cooperation.CooperationApplication) *CooperationApplicationItem {
//data := CooperationApplicationItem{
// CooperationApplicationAttachment: param.CooperationApplicationAttachment,
// CooperationApplicationDescription: param.CooperationApplicationDescription,
// CooperationApplicationID: param.CooperationApplicationID,
// IsCanceled: param.IsCanceled,
// CooperationApplicationVerifyDescription: param.CooperationApplicationVerifyDescription,
// CooperationApplicationStatus: param.CooperationApplicationStatus,
// Org: param.Org,
//}
//data.CooperationApplicationApplicant.UserName = param.CooperationApplicationApplicant.UserInfo.UserName
//data.CooperationApplicationApplicant.Phone = param.CooperationApplicationApplicant.UserInfo.UserPhone
//data.CooperationApplicationApplicant.UserCode = param.CooperationApplicationApplicant.UserInfo.UserPhone
//data.CooperationApplicationApplicant.DepartmentName = param.CooperationApplicationApplicant.Department.DepartmentName
//data.CooperationProject.CooperationProjectID = param.CooperationProject.CooperationProjectID
//data.CooperationProject.CooperationProjectName = param.CooperationProject.CooperationProjectName
//data.CooperationProject.CooperationProjectNumber = param.CooperationProject.CooperationProjectNumber
//return &data
return nil
func ToCooperationApplicationItem(param []allied_creation_cooperation.CooperationApplication, operatorOrgId int64) []CooperationApplicationItem {
listData := []CooperationApplicationItem{}
for i := range param {
item := CooperationApplicationItem{
CooperationApplication: param[i],
AuthFlag: param[i].Org.OrgID == int(operatorOrgId),
}
listData = append(listData, item)
}
return listData
}
type CooperationApplicationInfo struct {
... ...
... ... @@ -3,6 +3,7 @@ package service
import (
"github.com/linmadan/egglib-go/core/application"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/cooperationApplication/command"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/cooperationApplication/dto"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/web/cooperationApplication/query"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/allied_creation_cooperation"
)
... ... @@ -73,15 +74,12 @@ func (cooperationApplicationService *CooperationApplicationService) ListCooperat
if err != nil {
return 0, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
//var dataList []dto.CooperationApplicationItem
//for i := range result.Grid.List {
// item := dto.ToCooperationApplicationItem(&result.Grid.List[i])
// dataList = append(dataList, *item)
//}
if len(result.Grid.List) == 0 {
result.Grid.List = []allied_creation_cooperation.CooperationApplication{}
}
return int64(result.Grid.Total), result.Grid.List, nil
listData := dto.ToCooperationApplicationItem(result.Grid.List, listCooperationApplicationQuery.Operator.OrgId)
return int64(result.Grid.Total), listData, nil
}
func NewCooperationApplicationService(options map[string]interface{}) *CooperationApplicationService {
... ...
... ... @@ -22,9 +22,10 @@ type CooperationContractItem struct {
Org domain.Org `json:"org"` //组织结构
CooperationContractUndertakerType []int `json:"cooperationContractUndertakerType"` //共创合约承接对象,1员工,2共创用户,3公开
CooperationContractDescription string `json:"cooperationContractDescription"` //合约描述
AuthFlag bool `json:"authFlag"`
}
func ToCooperationContractItem(param *allied_creation_cooperation.CooperationContract) *CooperationContractItem {
func ToCooperationContractItem(param *allied_creation_cooperation.CooperationContract, operatorOrgId int64) *CooperationContractItem {
cooperationContractUndertakerType := param.CooperationContractUndertakerTypes
if len(cooperationContractUndertakerType) == 0 {
cooperationContractUndertakerType = []int{}
... ... @@ -38,6 +39,7 @@ func ToCooperationContractItem(param *allied_creation_cooperation.CooperationCon
CooperationContractNumber: param.CooperationContractNumber,
Status: param.Status,
CreateTime: int(param.CreatedAt.UnixNano() / 1e6),
AuthFlag: param.Org.OrgId == operatorOrgId,
}
data.CooperationContractSponsor.UserId = param.CooperationContractSponsor.UserId
data.CooperationContractSponsor.UserName = param.CooperationContractSponsor.UserInfo.UserName
... ... @@ -112,7 +114,7 @@ type CooperationContractInfo struct {
UndertakerTypesUncheckedAvailable []int `json:"undertakerTypesUncheckedAvailable"` // 可以去除勾选的共创项目承接对象列表
}
func ToCooperationContractInfo(param *allied_creation_cooperation.CooperationContract) *CooperationContractInfo {
func ToCooperationContractInfo(param *allied_creation_cooperation.CooperationContract, operatorOrgId int64) *CooperationContractInfo {
relevants := []Relevant{}
dividendsIncentivesRules := []DividendsIncentivesRule{}
... ... @@ -202,7 +204,7 @@ func ToCooperationContractInfo(param *allied_creation_cooperation.CooperationCon
undertakerTypesUncheckedAvailable = []int{}
}
data := CooperationContractInfo{
CooperationContract: *ToCooperationContractItem(param),
CooperationContract: *ToCooperationContractItem(param, operatorOrgId),
Relevant: relevants,
DividendsIncentivesRules: dividendsIncentivesRules,
MoneyIncentivesRules: moneyIncentivesRules,
... ...
... ... @@ -77,7 +77,8 @@ func (cooperationContractService *CooperationContractService) CreateCooperationC
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToCooperationContractInfo(&result.CooperationContract), err
return dto.ToCooperationContractInfo(&result.CooperationContract, createCooperationContractCommand.Operator.OrgId), err
}
// 暂停恢复共创合约
... ... @@ -105,13 +106,12 @@ func (cooperationContractService *CooperationContractService) GetCooperationCont
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToCooperationContractInfo(&result.CooperationContract), nil
return dto.ToCooperationContractInfo(&result.CooperationContract, getCooperationContractQuery.Operator.OrgId), nil
}
// 返回共创合约管理列表
func (cooperationContractService *CooperationContractService) ListCooperationContract(
listCooperationContractQuery *query.ListCooperationContractQuery) (int, interface{}, error) {
creationCooperationGateway := allied_creation_cooperation.NewHttplibAlliedCreationCooperation(listCooperationContractQuery.Operator)
result, err := creationCooperationGateway.CooperationContractSearch(allied_creation_cooperation.ReqCooperationContractSearch{
PageNumber: listCooperationContractQuery.PageNumber,
... ... @@ -124,7 +124,7 @@ func (cooperationContractService *CooperationContractService) ListCooperationCon
}
data := []dto.CooperationContractItem{}
for i := range result.Grid.List {
item := dto.ToCooperationContractItem(&result.Grid.List[i])
item := dto.ToCooperationContractItem(&result.Grid.List[i], listCooperationContractQuery.Operator.OrgId)
data = append(data, *item)
}
... ... @@ -194,7 +194,7 @@ func (cooperationContractService *CooperationContractService) UpdateCooperationC
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToCooperationContractInfo(&result.CooperationContract), nil
return dto.ToCooperationContractInfo(&result.CooperationContract, updateCooperationContractCommand.Operator.OrgId), nil
}
func NewCooperationContractService(options map[string]interface{}) *CooperationContractService {
... ...
... ... @@ -17,4 +17,5 @@ type CooperationModeItem struct {
// 组织名称
OrgName string `json:"orgName"`
} `json:"org"`
AuthFlag bool `json:"authFlag"`
}
... ...
... ... @@ -51,6 +51,7 @@ func (cooperationModeService *CooperationModeService) GetCooperationMode(getCoop
Status: result.Status,
CooperationModeNumber: result.CooperationModeNumber,
Org: result.Org,
AuthFlag: result.Org.OrgId == int(getCooperationModeQuery.Operator.OrgId),
}
return data, nil
}
... ... @@ -85,6 +86,7 @@ func (cooperationModeService *CooperationModeService) ListCooperationMode(listCo
Status: v.Status,
CooperationModeNumber: v.CooperationModeNumber,
Org: v.Org,
AuthFlag: v.Org.OrgId == int(listCooperationModeQuery.Operator.OrgId),
}
listData = append(listData, item)
}
... ... @@ -169,6 +171,7 @@ func (cooperationModeService *CooperationModeService) CooperationModeSelector(li
Status: v.Status,
CooperationModeNumber: v.CooperationModeNumber,
Org: v.Org,
AuthFlag: v.Org.OrgId == int(listCooperationModeQuery.Operator.OrgId),
}
listData = append(listData, item)
}
... ...
... ... @@ -124,3 +124,22 @@ func ToCooperationApplicationItem(param *allied_creation_cooperation.Cooperation
return &data
//return nil
}
type CooperationProjectSearchItem struct {
allied_creation_cooperation.DataCooperationProjectSearchItem
AuthFlag bool `json:"authFlag"` //当前用户是否可以编辑
}
func ToCooperationProjectSearchItem(items []allied_creation_cooperation.DataCooperationProjectSearchItem, operatorOrgId int) []CooperationProjectSearchItem {
listData := []CooperationProjectSearchItem{}
operatorOrgIdStr := strconv.Itoa(operatorOrgId)
for i := range items {
listItem := CooperationProjectSearchItem{
DataCooperationProjectSearchItem: items[i],
AuthFlag: operatorOrgIdStr == items[i].Org.OrgID,
}
listData = append(listData, listItem)
}
return listData
}
... ...
... ... @@ -118,7 +118,8 @@ func (cooperationProjectService *CooperationProjectService) ListCooperationProje
if len(result.List) == 0 {
result.List = []allied_creation_cooperation.DataCooperationProjectSearchItem{}
}
return int64(result.Total), result.List, nil
listData := dto.ToCooperationProjectSearchItem(result.List, int(listCooperationProjectQuery.Operator.OrgId))
return int64(result.Total), listData, nil
}
// 更新共创项目管理
... ...
... ... @@ -44,9 +44,10 @@ type CreditAccountItem struct {
UserAccount string `json:"userAccount"` // 用户账号,
} `json:"userInfo"`
} `json:"operator"`
AuthFlag bool `json:"authFlag"`
}
func ToCreditAccountItem(param *allied_creation_cooperation.CreditAccount) *CreditAccountItem {
func ToCreditAccountItem(param *allied_creation_cooperation.CreditAccount, operatorOrgId int64) *CreditAccountItem {
data := CreditAccountItem{
CreditAccountId: param.CreditAccountId,
ActuallyPaidAmount: param.ActuallyPaidAmount,
... ... @@ -62,6 +63,7 @@ func ToCreditAccountItem(param *allied_creation_cooperation.CreditAccount) *Cred
CreatedAt: param.CreatedAt.UnixNano() / 1e6, // 创建时间
UpdatedAt: param.UpdatedAt.UnixNano() / 1e6, // 更新时间
AccountDetail: param.AccountDetail,
AuthFlag: param.Org.OrgID == int(operatorOrgId),
}
if !param.PaymentTime.IsZero() {
data.PaymentTime = param.PaymentTime.UnixNano() / 1e6
... ...
... ... @@ -29,7 +29,7 @@ func (srv *CreditAccountService) ListCreditAccount(listQuery *query.ListCreditAc
}
listData := []dto.CreditAccountItem{}
for i := range result.Grid.List {
item := dto.ToCreditAccountItem(&result.Grid.List[i])
item := dto.ToCreditAccountItem(&result.Grid.List[i], listQuery.Operator.OrgId)
listData = append(listData, *item)
}
return int64(result.Grid.Total), listData, nil
... ... @@ -44,7 +44,7 @@ func (srv *CreditAccountService) GetCreditAccount(getQuery *query.GetCreditAccou
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToCreditAccountItem(&result.CreditAccount), nil
return dto.ToCreditAccountItem(&result.CreditAccount, getQuery.Operator.OrgId), nil
}
//PayCreditAccount 支付账期结算
... ...
... ... @@ -15,28 +15,29 @@ type DividendsEstimateDividendItem struct {
OrderTime int64 `json:"orderTime"` //订单/退货单日期
OriginalOrderNum string `json:"originalOrderNum"` //来源单号,源单号,订单号
RegionName string `json:"regionName"` //区域名称
AuthFlag bool `json:"authFlag"`
}
func ToDividendsEstimateDividendItem(param *allied_creation_cooperation.DataDividendsEstimateSearchDividend) []DividendsEstimateDividendItem {
listdata := []DividendsEstimateDividendItem{}
for _, v := range param.List {
item := DividendsEstimateDividendItem{
OrderGoodId: v.OrderGoodId,
OrderGoodName: v.OrderGoodName,
CooperationContractNumber: v.CooperationContractNumber,
CustomerName: v.CustomerName,
DividendsIncentivesAmount: v.OrderAmount,
OrderOrReturnedOrderNum: v.OrderNumber,
// func ToDividendsEstimateDividendItem(param *allied_creation_cooperation.DataDividendsEstimateSearchDividend) []DividendsEstimateDividendItem {
// listdata := []DividendsEstimateDividendItem{}
// for _, v := range param.List {
// item := DividendsEstimateDividendItem{
// OrderGoodId: v.OrderGoodId,
// OrderGoodName: v.OrderGoodName,
// CooperationContractNumber: v.CooperationContractNumber,
// CustomerName: v.CustomerName,
// DividendsIncentivesAmount: v.OrderAmount,
// OrderOrReturnedOrderNum: v.OrderNumber,
OriginalOrderNum: v.OriginalOrderNum,
RegionName: v.RegionName,
}
item.OrderTime = v.OrderDate.UnixNano() / 1e6
listdata = append(listdata, item)
}
// OriginalOrderNum: v.OriginalOrderNum,
// RegionName: v.RegionName,
// }
// item.OrderTime = v.OrderDate.UnixNano() / 1e6
// listdata = append(listdata, item)
// }
return listdata
}
// return listdata
// }
//金额激励列表
type DividendsEstimateMoneyItem struct {
... ... @@ -108,4 +109,5 @@ type DividendsEstimateItem struct {
OrgId int `json:"orgId,string,"` // 组织机构ID
OrgName string `json:"orgName"` // 组织名称
} `json:"org"` // 数据所属组织机构
AuthFlag bool `json:"authFlag"`
}
... ...
... ... @@ -96,6 +96,7 @@ func (dividendsEstimateService *DividendsEstimateService) SearchDividendsEstimat
CooperationContractNumber: v.CooperationContractNumber,
DividendsIncentivesStage: v.DividendsStage,
IsCanceled: v.IsCanceled,
AuthFlag: v.Org.OrgId == int(searchDividendsEstimateQuery.Operator.OrgId),
}
item.DividendsUser.Phone = v.DividendsUser.UserInfo.UserPhone
item.DividendsUser.UsersName = v.DividendsUser.UserInfo.UserName
... ... @@ -125,7 +126,22 @@ func (dividendsEstimateService *DividendsEstimateService) SearchDividendsIncenti
if err != nil {
return 0, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
listdata := dto.ToDividendsEstimateDividendItem(result)
listdata := []dto.DividendsEstimateDividendItem{}
for _, v := range result.List {
item := dto.DividendsEstimateDividendItem{
OrderGoodId: v.OrderGoodId,
OrderGoodName: v.OrderGoodName,
CooperationContractNumber: v.CooperationContractNumber,
CustomerName: v.CustomerName,
DividendsIncentivesAmount: v.OrderAmount,
OrderOrReturnedOrderNum: v.OrderNumber,
OriginalOrderNum: v.OriginalOrderNum,
RegionName: v.RegionName,
}
item.OrderTime = v.OrderDate.UnixNano() / 1e6
listdata = append(listdata, item)
}
return result.Total, listdata, nil
}
... ...
... ... @@ -29,6 +29,7 @@ type DividendsOrder struct {
Remarks string `json:"remarks"`
Goods []DividendsOrderGoods `json:"goods"`
Returned bool `json:"returned"`
AuthFlag bool `json:"authFlag"`
}
type DividendsOrderGoods struct {
... ... @@ -44,7 +45,7 @@ type DividendsOrderGoods struct {
OrderGoodDividendsStatus int32 `json:"orderGoodDividendsStatus"` // 订单产品分红状态, 1待分红,2已分红
}
func ToDividendsOrder(param *allied_creation_cooperation.DividendsOrder) *DividendsOrder {
func ToDividendsOrder(param *allied_creation_cooperation.DividendsOrder, operatorOrgId int64) *DividendsOrder {
goods := []DividendsOrderGoods{}
for _, v := range param.Goods {
good := DividendsOrderGoods{
... ... @@ -75,6 +76,7 @@ func ToDividendsOrder(param *allied_creation_cooperation.DividendsOrder) *Divide
Remarks: param.Remarks,
Goods: goods,
Returned: param.Returned,
AuthFlag: param.Org.OrgID == int(operatorOrgId),
}
return &data
... ...
... ... @@ -48,7 +48,7 @@ func (dividendsOrderService *DividendsOrderService) CreateDividendsOrder(createD
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToDividendsOrder(&result.DividendsOrder), nil
return dto.ToDividendsOrder(&result.DividendsOrder, createDividendsOrderCommand.Operator.OrgId), nil
}
// 返回分红订单实体对象
... ... @@ -61,7 +61,7 @@ func (dividendsOrderService *DividendsOrderService) GetDividendsOrder(getDividen
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToDividendsOrder(&result.DividendsOrder), nil
return dto.ToDividendsOrder(&result.DividendsOrder, getDividendsOrderQuery.Operator.OrgId), nil
}
// 移除分红订单实体对象
... ... @@ -93,7 +93,7 @@ func (dividendsOrderService *DividendsOrderService) SearchDividendsOrder(searchD
}
dataList := []dto.DividendsOrder{}
for i := range result.Grid.List {
item := dto.ToDividendsOrder(&result.Grid.List[i])
item := dto.ToDividendsOrder(&result.Grid.List[i], searchDividendsOrderQuery.Operator.OrgId)
dataList = append(dataList, *item)
}
return result.Grid.Total, dataList, nil
... ...
... ... @@ -33,10 +33,12 @@ type DividendsReturnedOrderInfo struct {
RegionName string `json:"regionName"`
RegionNumber string `json:"regionNumber"` //区域编码
} `json:"region"` //区域信息
Goods []allied_creation_cooperation.DividendsReturnedOrderGoods `json:"goods"` //货品
AuthFlag bool `json:"authFlag"`
Goods []allied_creation_cooperation.DividendsReturnedOrderGoods `json:"goods"` //货品
}
func ToDividendsReturnedOrderInfo(param *allied_creation_cooperation.DividendsReturnedOrder) *DividendsReturnedOrderInfo {
func ToDividendsReturnedOrderInfo(param *allied_creation_cooperation.DividendsReturnedOrder, operatorOrgId int64) *DividendsReturnedOrderInfo {
goods := param.Goods
if len(param.Goods) == 0 {
goods = []allied_creation_cooperation.DividendsReturnedOrderGoods{}
... ... @@ -58,6 +60,7 @@ func ToDividendsReturnedOrderInfo(param *allied_creation_cooperation.DividendsRe
DividendsReturnedOrderRefund: param.DividendsReturnedOrderRefund,
OriginalOrderNum: param.OriginalOrderNum,
Remarks: param.Remarks,
AuthFlag: param.Org.OrgID == int(operatorOrgId),
}
return &data
}
... ...
... ... @@ -44,7 +44,7 @@ func (dividendsReturnedOrderService *DividendsReturnedOrderService) CreateDivide
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToDividendsReturnedOrderInfo(&result.DividendsReturnedOrder), nil
return dto.ToDividendsReturnedOrderInfo(&result.DividendsReturnedOrder, createDividendsReturnedOrderCommand.Operator.OrgId), nil
}
// 返回分红退货单服务
... ... @@ -56,7 +56,7 @@ func (dividendsReturnedOrderService *DividendsReturnedOrderService) GetDividends
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return dto.ToDividendsReturnedOrderInfo(&result.DividendsReturnedOrder), nil
return dto.ToDividendsReturnedOrderInfo(&result.DividendsReturnedOrder, getDividendsReturnedOrderQuery.Operator.OrgId), nil
}
// 移除分红退货单服务
... ... @@ -85,7 +85,7 @@ func (dividendsReturnedOrderService *DividendsReturnedOrderService) SearchDivide
}
dataList := []dto.DividendsReturnedOrderInfo{}
for i := range result.Grid.List {
item := dto.ToDividendsReturnedOrderInfo(&result.Grid.List[i])
item := dto.ToDividendsReturnedOrderInfo(&result.Grid.List[i], searchDividendsReturnedOrderQuery.Operator.OrgId)
dataList = append(dataList, *item)
}
return result.Grid.Total, dataList, nil
... ...
... ... @@ -10,4 +10,5 @@ type NoticeSettingItem struct {
NoticeSettingID int `json:"noticeSettingId,string"`
OrgID int `json:"orgId,string"`
OrgName string `json:"orgName"`
AuthFlag bool `json:"authFlag"`
}
... ...
... ... @@ -69,6 +69,7 @@ func (noticeSettingService *NoticeSettingService) NoticeSettingList(noticeSettin
NoticeSettingID: v.NoticeSettingID,
OrgID: v.OrgID,
ModuleActionName: v.ModuleActionName,
AuthFlag: v.OrgID == int(noticeSettingListQuery.Operator.OrgId),
}
orgData, _ := creationUserGateway.OrgGet(allied_creation_user.ReqOrgGet{
OrgId: v.OrgID,
... ... @@ -163,6 +164,7 @@ func (noticeSettingService *NoticeSettingService) NoticeSettingGet(noticeSetting
ModuleAction: result.ModuleAction,
NoticeSettingID: result.NoticeSettingID,
OrgID: result.OrgID,
AuthFlag: result.OrgID == int(noticeSettingGetQuery.Operator.OrgId),
}
return data, nil
}
... ...
... ... @@ -182,10 +182,6 @@ type (
UserPhone string `json:"userPhone"`
UserAccount string `json:"userAccount"`
} `json:"userInfo"`
//UserType int `json:"userType"`
//UserName string `json:"userName"`
//UserPhone string `json:"userPhone"`
//Status int `json:"status"`
} `json:"cooperationProjectPublisher"`
CooperationProjectSponsor struct {
UserID string `json:"userId"`
... ...