This commit is contained in:
Alex Shevchuk
2025-08-18 17:12:04 +03:00
commit d84487d238
157 changed files with 160686 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
package requestmodel
import (
amqp "github.com/rabbitmq/amqp091-go"
)
// <----------- Header Argument ---------->
type HeaderArg string
const (
Command HeaderArg = "command"
)
func (h HeaderArg) String() string {
return string(h)
}
// <----------- Header Value ----------->
type HeaderValue interface {
String() string
}
// <----------- Command ----------->
type CommandType string
var _ HeaderValue = (*CommandType)(nil)
const (
GetCompanyDataAgent CommandType = "GetCompanyData"
GetCompaniesUidAgent CommandType = "GetCompaniesUid"
SetCompanyDataAgent CommandType = "SetCompanyData"
GetVacancyListAgent CommandType = "GetVacancyList"
GetSubmissionListAgent CommandType = "GetSubmissionList"
DeleteSubmissionAgent CommandType = "DeleteSubmission"
GetProfileDataAgent CommandType = "GetProfileData"
SetProfileDataAgent CommandType = "SetProfileData"
GetBalanceAgent CommandType = "GetBalance"
GetTransactionsAgent CommandType = "GetTransactions"
CreateTransactionAgent CommandType = "CreateTransaction"
GetBankAccountsAgent CommandType = "GetBankAccounts"
CreateBankAccountAgent CommandType = "CreateBankAccount"
EditBankAccountAgent CommandType = "EditBankAccount"
DeleteBankAccountAgent CommandType = "DeleteBankAccount"
GetCompanyDataDistributor CommandType = "GetCompanyData"
GetCompaniesUidDistributor CommandType = "GetCompaniesUid"
SetCompanyDataDistributor CommandType = "SetCompanyData"
GetVacancyListDistributor CommandType = "GetVacancyList"
CreateVacancyDistributor CommandType = "CreateVacancy"
EditVacancyDistributor CommandType = "EditVacancy"
DeleteVacancyDistributor CommandType = "DeleteVacancy"
SendVacancyToModerationDistributor CommandType = "SendVacancyToModeration"
GetSubmissionsForVacancyDistributor CommandType = "GetSubmissionsForVacancy"
SetSubmissionStatusDistributor CommandType = "SetSubmissionStatus"
GetProfileDataDistributor CommandType = "GetProfileData"
SetProfileDataDistributor CommandType = "SetProfileData"
GetBalanceDistributor CommandType = "GetBalance"
GetCompanyBalanceDistributor CommandType = "GetCompanyBalance"
GetTransactionsDistributor CommandType = "GetTransactions"
GetCompanyTransactionsDistributor CommandType = "GetCompanyTransactions"
CreateTransactionDistributor CommandType = "CreateTransaction"
GetBankAccountsDistributor CommandType = "GetBankAccounts"
GetCompanyBankAccountsDistributor CommandType = "GetCompanyBankAccounts"
CreateBankAccountDistributor CommandType = "CreateBankAccount"
EditBankAccountDistributor CommandType = "EditBankAccount"
DeleteBankAccountDistributor CommandType = "DeleteBankAccount"
)
func (c CommandType) String() string {
return string(c)
}
// <----------- Header ----------->
type Header map[HeaderArg]HeaderValue
func (h Header) ToTable() amqp.Table {
table := amqp.Table{}
for k, v := range h {
table[k.String()] = v.String()
}
return table
}
type CompanyId struct {
CompanyId string `json:"company_id"`
}

View File

@@ -0,0 +1,71 @@
package requestmodel
type UserCredentials struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName *string `json:"middle_name"`
Email string `json:"email"`
PhoneNumber string `json:"phone"`
Password string `json:"password"`
UserType int32 `json:"user_type"`
Permissions map[string]string `json:"permissions"`
}
type RegisterResponse struct {
UUID string `json:"uid"`
}
type (
LoginUserRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
LoginUserResponse struct {
Uid string `json:"uid"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
UserType int32 `json:"user_type"`
Permissions Permissions `json:"permissions"`
EmailVerified bool `json:"email_confirmed"`
}
Permissions struct {
Balance string `json:"balance"`
Company string `json:"company"`
Employees string `json:"employees"`
Profile string `json:"profile"`
Submissions string `json:"submissions"`
Vacancies string `json:"vacancies"`
}
)
type LogoutUserRequest struct {
RefreshToken string `json:"refresh_token"`
}
type (
RefreshTokenRequest struct {
RefreshToken string `json:"refresh_token"`
}
RefreshTokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
)
type ForgotPasswordRequest struct {
Email string `json:"email"`
}
type ValidateOTPResponse struct {
IsValid bool `json:"valid"`
Token string `json:"token"`
}
type ResetPasswordRequest struct {
Email string `json:"email"`
Password string `json:"new_password"`
Token string `json:"token"`
}

View File

@@ -0,0 +1,526 @@
package requestmodel
import (
"fmt"
"net/url"
"time"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
)
type (
Balance struct {
RawBalance int64 `json:"raw_balance"`
CleanBalance int64 `json:"clean_balance"`
}
)
func (b *Balance) From(msg *dbtypes.Balance) *Balance {
if msg == nil {
return nil
}
res := &Balance{
RawBalance: msg.RawBalance,
CleanBalance: msg.CleanBalance,
}
return res
}
type (
BalanceGetRequest struct {
OwnerId string
}
BalanceGetResponse struct {
Balance *Balance `json:"balance"`
}
)
func (r *BalanceGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
return nil
}
func (r *BalanceGetResponse) From(msg *dbtypes.BalanceGetResponse) *BalanceGetResponse {
if msg == nil {
return nil
}
return &BalanceGetResponse{
Balance: new(Balance).From(msg.Balance),
}
}
type TransactionStatus string
const (
TransactionStatusNew TransactionStatus = "new"
TransactionStatusPending TransactionStatus = "pending"
TransactionStatusApproved TransactionStatus = "approved"
TransactionStatusRejected TransactionStatus = "rejected"
)
func (s *TransactionStatus) NullString() *string {
if s == nil {
return nil
}
return (*string)(s)
}
type TransactionType string
const (
TransactionTypeDeposit TransactionType = "deposit"
TransactionTypeWithdrawal TransactionType = "withdrawal"
)
func (t *TransactionType) NullString() *string {
if t == nil {
return nil
}
return (*string)(t)
}
type (
Transaction struct {
Id string `json:"id"`
OwnerInfo *TransactionOwnerInfo `json:"owner_info"`
BankAccountInfo *BankAccountInfo `json:"bank_account_info"`
Type TransactionType `json:"type"`
Status TransactionStatus `json:"status"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
CreatedAt string `json:"created_at"`
Payload *TransactionPayload `json:"payload"`
}
BankAccountInfo struct {
Id string `json:"id"`
AccountNumber string `json:"account_number"`
AccountName string `json:"account_name"`
BankName string `json:"bank_name"`
Bik string `json:"bik"`
CorrespondentAccount string `json:"correspondent_account"`
OwnerType string `json:"owner_type"`
}
TransactionOwnerInfo struct {
Id string `json:"id"`
Name string `json:"name"`
}
TransactionPayload struct {
Origin string `json:"origin"`
CompanyId string `json:"company_id"`
CompanyName string `json:"company_name"`
VacancyId string `json:"vacancy_id"`
VacancyName string `json:"vacancy_name"`
}
)
func (t *TransactionOwnerInfo) From(msg *dbtypes.TransactionOwnerInfo) *TransactionOwnerInfo {
if msg == nil {
return nil
}
res := &TransactionOwnerInfo{
Id: msg.Id,
Name: msg.Name,
}
return res
}
func (t *BankAccountInfo) From(msg *dbtypes.BankAccountInfo) *BankAccountInfo {
if msg == nil {
return nil
}
res := &BankAccountInfo{
Id: msg.Id,
AccountNumber: msg.AccountNumber,
AccountName: msg.AccountName,
BankName: msg.BankName,
Bik: msg.Bik,
CorrespondentAccount: msg.CorrespondentAccount,
OwnerType: msg.OwnerType,
}
return res
}
func (t *TransactionPayload) From(msg *dbtypes.TransactionPayload) *TransactionPayload {
if msg == nil {
return nil
}
res := &TransactionPayload{
Origin: msg.Origin,
CompanyId: msg.CompanyId,
CompanyName: msg.CompanyName,
VacancyId: msg.VacancyId,
VacancyName: msg.VacancyName,
}
return res
}
func (t *Transaction) From(msg *dbtypes.Transaction) *Transaction {
if msg == nil {
return nil
}
res := &Transaction{
Id: msg.Id,
OwnerInfo: new(TransactionOwnerInfo).From(msg.OwnerInfo),
BankAccountInfo: new(BankAccountInfo).From(msg.BankAccountInfo),
Type: TransactionType(msg.Type),
Status: TransactionStatus(msg.Status),
Amount: msg.Amount,
Currency: msg.Currency,
CreatedAt: msg.CreatedAt.Format(time.RFC3339),
Payload: new(TransactionPayload).From(msg.Payload),
}
return res
}
type (
TransactionListGetRequest struct {
OwnerId string
Filters *TransactionListFilters
Page uint64
PageSize uint64
}
TransactionListFilters struct {
Type *TransactionType
Status *TransactionStatus
BankAccountId *string
}
TransactionListGetResponse struct {
Transactions []Transaction `json:"transactions"`
}
)
func (r *TransactionListGetRequest) FromQuery(query url.Values) (*TransactionListGetRequest, error) {
if query == nil {
return nil, nil
}
var filters TransactionListFilters
if val, ok := query["type"]; ok {
typ := TransactionType(val[0])
filters.Type = &typ
}
if val, ok := query["status"]; ok {
status := TransactionStatus(val[0])
filters.Status = &status
}
if val, ok := query["bank_account_id"]; ok {
filters.BankAccountId = &val[0]
}
res := &TransactionListGetRequest{
Filters: &filters,
Page: constants.DefaultPaginationPage,
PageSize: constants.DefaultPaginationPageSize,
}
if val, ok := query["page"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page param: %w", err)
}
res.Page = intVal
}
if val, ok := query["page_size"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page_size param: %w", err)
}
res.PageSize = intVal
}
return res, nil
}
func (r *TransactionListGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
if r.Filters != nil {
if r.Filters.Type != nil && !(*r.Filters.Type == TransactionTypeDeposit ||
*r.Filters.Type == TransactionTypeWithdrawal) {
return fmt.Errorf("%w: invalid type: %v", ErrValidation, *r.Filters.Type)
}
if r.Filters.Status != nil && !(*r.Filters.Status == TransactionStatusNew ||
*r.Filters.Status == TransactionStatusPending ||
*r.Filters.Status == TransactionStatusApproved ||
*r.Filters.Status == TransactionStatusRejected) {
return fmt.Errorf("%w: invalid status: %v", ErrValidation, *r.Filters.Status)
}
}
return nil
}
func (r *TransactionListGetResponse) From(msg *dbtypes.TransactionListGetResponse) *TransactionListGetResponse {
if msg == nil {
return nil
}
res := &TransactionListGetResponse{
Transactions: make([]Transaction, len(msg.Transactions)),
}
for i, trans := range msg.Transactions {
res.Transactions[i] = *new(Transaction).From(&trans)
}
return res
}
type (
TransactionCreateRequest struct {
OwnerId string
Amount int64 `json:"amount"`
Currency string `json:"currency"`
BankAccountId *string `json:"bank_account_id"`
Payload *TransactionPayload `json:"payload"`
RequestId string `json:"request_id"`
}
TransactionCreateResponse struct {
Id string `json:"id"`
}
)
func (r *TransactionCreateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.RequestId == "" {
return fmt.Errorf("%w: RequestID is required", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
if r.Amount == 0 {
return fmt.Errorf("%w: Amount is required", ErrValidation)
}
if r.Currency == "" {
return fmt.Errorf("%w: Currency is required", ErrValidation)
}
return nil
}
func (r *TransactionCreateResponse) From(msg *dbtypes.TransactionCreateResponse) *TransactionCreateResponse {
if msg == nil {
return nil
}
return &TransactionCreateResponse{
Id: msg.Id,
}
}
type (
BankAccount struct {
Id string `json:"id"`
OwnerId string `json:"owner_id"`
AccountNumber string `json:"account_number"`
AccountName string `json:"account_name"`
BankName string `json:"bank_name"`
Bik string `json:"bik"`
CorrespondentAccount string `json:"correspondent_account"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
)
func (b *BankAccount) From(msg *dbtypes.BankAccount) *BankAccount {
if msg == nil {
return nil
}
res := &BankAccount{
Id: msg.Id,
OwnerId: msg.OwnerId,
AccountNumber: msg.AccountNumber,
AccountName: msg.AccountName,
BankName: msg.BankName,
Bik: msg.Bik,
CorrespondentAccount: msg.CorrespondentAccount,
CreatedAt: msg.CreatedAt.Format(time.RFC3339),
UpdatedAt: msg.UpdatedAt.Format(time.RFC3339),
}
return res
}
type (
BankAccountListGetRequest struct {
OwnerId string
}
BankAccountListGetResponse struct {
BankAccounts []BankAccount `json:"bank_accounts"`
}
)
func (r *BankAccountListGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
return nil
}
func (r *BankAccountListGetResponse) From(msg *dbtypes.BankAccountListGetResponse) *BankAccountListGetResponse {
if msg == nil {
return nil
}
res := &BankAccountListGetResponse{
BankAccounts: make([]BankAccount, len(msg.BankAccounts)),
}
for i, bankAccount := range msg.BankAccounts {
res.BankAccounts[i] = *new(BankAccount).From(&bankAccount)
}
return res
}
type (
BankAccountCreateRequest struct {
OwnerId string
AccountNumber *string `json:"account_number"`
AccountName *string `json:"account_name"`
BankName *string `json:"bank_name"`
Bik *string `json:"bik"`
CorrespondentAccount *string `json:"correspondent_account"`
IsPrimary *bool `json:"is_primary"`
}
BankAccountCreateResponse struct {
Id string `json:"id"`
}
)
func (r *BankAccountCreateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
return nil
}
func (r *BankAccountCreateResponse) From(msg *dbtypes.BankAccountCreateResponse) *BankAccountCreateResponse {
if msg == nil {
return nil
}
return &BankAccountCreateResponse{
Id: msg.Id,
}
}
type (
BankAccountUpdateRequest struct {
Id string
OwnerId string
AccountNumber *string `json:"account_number"`
AccountName *string `json:"account_name"`
BankName *string `json:"bank_name"`
Bik *string `json:"bik"`
CorrespondentAccount *string `json:"correspondent_account"`
IsPrimary *bool `json:"is_primary"`
}
BankAccountUpdateResponse struct{}
)
func (r *BankAccountUpdateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
if r.AccountNumber == nil && r.AccountName == nil && r.BankName == nil && r.Bik == nil && r.CorrespondentAccount == nil {
return fmt.Errorf("%w: nothing to update", ErrValidation)
}
return nil
}
type (
BankAccountDeleteRequest struct {
Id string
OwnerId string
}
BankAccountDeleteResponse struct{}
)
func (r *BankAccountDeleteRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
return nil
}

View File

@@ -0,0 +1,270 @@
package requestmodel
import (
"fmt"
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/types"
)
type AddNewAgentCompanyMemberRequest struct {
Uid string `json:"uid"`
}
type EmployeeRequest struct {
Uid string `json:"uid"`
}
type EmployeeResponse struct {
CompanyID string `json:"company_id"`
Employees []types.Employee `json:"employees"`
}
type (
Company struct {
Id string `json:"id"`
OwnerId string `json:"owner_id"`
Name *string `json:"name"`
LegalPerson *string `json:"legal_person"`
Description *string `json:"description"`
Website *string `json:"website"`
PhysicalAddress *string `json:"physical_address"`
LegalAddress *string `json:"legal_address"`
Inn *string `json:"inn"`
Kpp *string `json:"kpp"`
IsActive bool `json:"is_active"`
HasModerationTicket bool `json:"has_moderation_ticket"`
Staff []string `json:"staff"`
Metadata *string `json:"metadata"`
ExtraFieldsTemplate *string `json:"extra_fields_template"`
}
)
func (c *Company) From(msg *dbtypes.Company) *Company {
if msg == nil {
return nil
}
res := &Company{
Id: msg.Id,
OwnerId: msg.OwnerId,
Name: msg.Name,
LegalPerson: msg.LegalPerson,
Description: msg.Description,
Website: msg.Website,
PhysicalAddress: msg.PhysicalAddress,
LegalAddress: msg.LegalAddress,
Inn: msg.Inn,
Kpp: msg.Kpp,
IsActive: msg.IsActive,
HasModerationTicket: msg.HasModerationTicket,
Staff: msg.Staff,
Metadata: msg.Metadata,
ExtraFieldsTemplate: msg.ExtraFieldsTemplate,
}
return res
}
type (
CompanyListGetRequest struct {
Id string
}
CompanyListGetResponse struct {
Companies []Company `json:"companies"`
}
)
func (r *CompanyListGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}
func (r *CompanyListGetResponse) From(msg *dbtypes.CompanyListGetResponse) *CompanyListGetResponse {
if msg == nil {
return nil
}
res := &CompanyListGetResponse{
Companies: make([]Company, len(msg.Companies)),
}
for i, company := range msg.Companies {
res.Companies[i] = *new(Company).From(&company)
}
return res
}
type (
CompanyByIdGetRequest struct {
UserId string
CompanyId string
}
CompanyByIdGetResponse struct {
Company Company `json:"company"`
}
)
func (r *CompanyByIdGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.UserId == "" {
return fmt.Errorf("%w: UserID is required", ErrValidation)
}
if r.CompanyId == "" {
return fmt.Errorf("%w: CompanyID is required", ErrValidation)
}
return nil
}
func (r *CompanyByIdGetResponse) From(msg *dbtypes.CompanyByIdGetResponse) *CompanyByIdGetResponse {
if msg == nil {
return nil
}
return &CompanyByIdGetResponse{
Company: *new(Company).From(&msg.Company),
}
}
type (
CompanyCreateRequest struct {
OwnerId string
Name *string `json:"name"`
LegalPerson *string `json:"legal_person"`
Description *string `json:"description"`
Website *string `json:"website"`
PhysicalAddress *string `json:"physical_address"`
LegalAddress *string `json:"legal_address"`
Inn *string `json:"inn"`
Kpp *string `json:"kpp"`
Staff []string `json:"staff"`
Metadata *string `json:"metadata"`
ExtraFieldsTemplate *string `json:"extra_fields_template"`
}
CompanyCreateResponse struct {
Id string `json:"id"`
}
)
func (r *CompanyCreateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.OwnerId == "" {
return fmt.Errorf("%w: OwnerID is required", ErrValidation)
}
return nil
}
func (r *CompanyCreateResponse) From(msg *dbtypes.CompanyCreateResponse) *CompanyCreateResponse {
if msg == nil {
return nil
}
return &CompanyCreateResponse{
Id: msg.Id,
}
}
type (
CompanyUpdateRequest struct {
Id string
Name *string `json:"name"`
LegalPerson *string `json:"legal_person"`
Description *string `json:"description"`
Website *string `json:"website"`
PhysicalAddress *string `json:"physical_address"`
LegalAddress *string `json:"legal_address"`
Inn *string `json:"inn"`
Kpp *string `json:"kpp"`
Staff []string `json:"staff"`
Metadata *string `json:"metadata"`
ExtraFields *string `json:"extra_fields"`
}
CompanyUpdateResponse struct {
}
)
func (r *CompanyUpdateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.Name == nil && r.LegalPerson == nil && r.Description == nil && r.Website == nil &&
r.PhysicalAddress == nil && r.LegalAddress == nil && r.Inn == nil && r.Kpp == nil &&
r.Staff == nil && r.Metadata == nil && r.ExtraFields == nil {
return fmt.Errorf("%w: nothing to update", ErrValidation)
}
return nil
}
type (
AddDistributorCompanyMemberRequest struct {
Id string `json:"id"`
CompanyId string
}
AddDistributorCompanyMemberResponse struct {
}
)
func (r *AddDistributorCompanyMemberRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.CompanyId == "" {
return fmt.Errorf("%w: CompanyID is required", ErrValidation)
}
return nil
}
type (
CompanyDeleteRequest struct {
Id string
}
CompanyDeleteResponse struct {
}
)
func (r *CompanyDeleteRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}

View File

@@ -0,0 +1,7 @@
package requestmodel
import "errors"
var (
ErrValidation = errors.New("validation error")
)

View File

@@ -0,0 +1,13 @@
package integration
type (
VkusvillSaveCandidateCallbackParams struct {
CandidateId string `json:"candidate_id"`
Status int `json:"status"`
}
VkusvillSaveCandidateCallbackRequest struct {
Message string `json:"message"`
Params VkusvillSaveCandidateCallbackParams `json:"params"`
}
)

View File

@@ -0,0 +1,90 @@
package requestmodel
import (
"fmt"
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
)
type (
Profile struct {
Id string `json:"id"`
Name string `json:"name"`
PhoneNumber string `json:"phone_number"`
Email string `json:"email"`
}
)
func (p *Profile) From(msg *dbtypes.Profile) *Profile {
if msg == nil {
return nil
}
res := &Profile{
Id: msg.Id,
Name: msg.Name,
PhoneNumber: msg.PhoneNumber,
Email: msg.Email,
}
return res
}
type (
ProfileGetRequest struct {
Id string `json:"id"`
}
ProfileGetResponse struct {
Profile *Profile `json:"profile"`
}
)
func (r *ProfileGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}
func (r *ProfileGetResponse) From(msg *dbtypes.ProfileGetResponse) *ProfileGetResponse {
if msg == nil {
return nil
}
return &ProfileGetResponse{
Profile: new(Profile).From(msg.Profile),
}
}
type (
ProfileUpdateRequest struct {
Id string
Name *string `json:"name"`
PhoneNumber *string `json:"phone_number"`
Email *string `json:"email"`
}
ProfileUpdateResponse struct{}
)
func (r *ProfileUpdateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.Name == nil && r.PhoneNumber == nil && r.Email == nil {
return fmt.Errorf("%w: nothing to update", ErrValidation)
}
return nil
}

View File

@@ -0,0 +1,388 @@
package requestmodel
import (
"fmt"
"net/url"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
)
type SubmissionStatus string
const (
SubStatusUnspecified SubmissionStatus = "unspecified"
SubStatusNew SubmissionStatus = "new"
SubStatusPending SubmissionStatus = "pending"
SubStatusOnInterview SubmissionStatus = "on_interview"
SubStatusApproved SubmissionStatus = "approved"
SubStatusCancelled SubmissionStatus = "cancelled"
SubStatusRejected SubmissionStatus = "rejected"
)
func (s *SubmissionStatus) NullString() *string {
if s == nil {
return nil
}
return (*string)(s)
}
type (
Submission struct {
Id string `json:"id"`
AgentInfo *AgentInfo `json:"agent_info"`
VacancyInfo *VacancyInfo `json:"vacancy_info"`
CandidateInfo *CandidateInfo `json:"candidate_info"`
Status SubmissionStatus `json:"status"`
}
AgentInfo struct {
Id string `json:"id"`
}
VacancyInfo struct {
Id string `json:"id"`
}
CandidateInfo struct {
Id string `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName string `json:"middle_name"`
PhoneNumber string `json:"phone_number"`
Email string `json:"email"`
Birthday string `json:"birthday"`
CvLink *string `json:"cv_link"`
Resume *string `json:"resume"`
}
)
func (s *Submission) From(msg *dbtypes.Submission) *Submission {
if msg == nil {
return nil
}
res := &Submission{
Id: msg.Id,
Status: SubmissionStatus(msg.Status),
}
if msg.AgentInfo != nil {
res.AgentInfo = &AgentInfo{
Id: msg.AgentInfo.Id,
}
}
if msg.VacancyInfo != nil {
res.VacancyInfo = &VacancyInfo{
Id: msg.VacancyInfo.Id,
}
}
if msg.CandidateInfo != nil {
res.CandidateInfo = &CandidateInfo{
Id: msg.CandidateInfo.Id,
FirstName: msg.CandidateInfo.FirstName,
LastName: msg.CandidateInfo.LastName,
MiddleName: msg.CandidateInfo.MiddleName,
PhoneNumber: msg.CandidateInfo.PhoneNumber,
Email: msg.CandidateInfo.Email,
Birthday: msg.CandidateInfo.Birthday,
CvLink: msg.CandidateInfo.CvLink,
Resume: msg.CandidateInfo.Resume,
}
}
return res
}
type (
SubmissionListGetRequest struct {
AgentId string
Filters *SubmissionListGetFilters
Page uint64
PageSize uint64
}
SubmissionListGetFilters struct {
VacancyId *string
Status *SubmissionStatus
}
SubmissionListGetResponse struct {
Submissions []Submission `json:"submissions"`
}
)
func (r *SubmissionListGetRequest) FromQuery(query url.Values) (*SubmissionListGetRequest, error) {
if query == nil {
return nil, nil
}
var filters SubmissionListGetFilters
if val, ok := query["vacancy_id"]; ok {
filters.VacancyId = &val[0]
}
if val, ok := query["status"]; ok {
status := SubmissionStatus(val[0])
filters.Status = &status
}
res := &SubmissionListGetRequest{
Filters: &filters,
Page: constants.DefaultPaginationPage,
PageSize: constants.DefaultPaginationPageSize,
}
if val, ok := query["page"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page param: %w", err)
}
res.Page = intVal
}
if val, ok := query["page_size"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page_size param: %w", err)
}
res.PageSize = intVal
}
return res, nil
}
func (r *SubmissionListGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.AgentId == "" {
return fmt.Errorf("%w: AgentID is required", ErrValidation)
}
if r.Filters != nil {
if r.Filters.Status != nil && !(*r.Filters.Status == SubStatusUnspecified ||
*r.Filters.Status == SubStatusNew ||
*r.Filters.Status == SubStatusPending ||
*r.Filters.Status == SubStatusOnInterview ||
*r.Filters.Status == SubStatusApproved ||
*r.Filters.Status == SubStatusCancelled ||
*r.Filters.Status == SubStatusRejected) {
return fmt.Errorf("%w: invalid status: %v", ErrValidation, *r.Filters.Status)
}
}
return nil
}
func (r *SubmissionListGetResponse) From(msg *dbtypes.SubmissionListGetResponse) *SubmissionListGetResponse {
if msg == nil {
return nil
}
res := &SubmissionListGetResponse{
Submissions: make([]Submission, len(msg.Submissions)),
}
for i, subm := range msg.Submissions {
res.Submissions[i] = *new(Submission).From(&subm)
}
return res
}
type (
SubmissionListForVacancyGetRequest struct {
VacancyId string
Filters *SubmissionListForVacancyGetFilters
Page uint64
PageSize uint64
}
SubmissionListForVacancyGetFilters struct {
Status *SubmissionStatus
}
SubmissionListForVacancyGetResponse struct {
Submissions []Submission `json:"submissions"`
}
)
func (r *SubmissionListForVacancyGetRequest) FromQuery(query url.Values) (*SubmissionListForVacancyGetRequest, error) {
if query == nil {
return nil, nil
}
var filters SubmissionListForVacancyGetFilters
if val, ok := query["status"]; ok {
status := SubmissionStatus(val[0])
filters.Status = &status
}
res := &SubmissionListForVacancyGetRequest{
Filters: &filters,
Page: constants.DefaultPaginationPage,
PageSize: constants.DefaultPaginationPageSize,
}
if val, ok := query["page"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page param: %w", err)
}
res.Page = intVal
}
if val, ok := query["page_size"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page_size param: %w", err)
}
res.PageSize = intVal
}
return res, nil
}
func (r *SubmissionListForVacancyGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.VacancyId == "" {
return fmt.Errorf("%w: VacancyID is required", ErrValidation)
}
if r.Filters != nil {
if r.Filters.Status != nil && !(*r.Filters.Status == SubStatusUnspecified ||
*r.Filters.Status == SubStatusNew ||
*r.Filters.Status == SubStatusPending ||
*r.Filters.Status == SubStatusOnInterview ||
*r.Filters.Status == SubStatusApproved ||
*r.Filters.Status == SubStatusCancelled ||
*r.Filters.Status == SubStatusRejected) {
return fmt.Errorf("%w: invalid status: %v", ErrValidation, *r.Filters.Status)
}
}
return nil
}
func (r *SubmissionListForVacancyGetResponse) From(msg *dbtypes.SubmissionListGetResponse) *SubmissionListForVacancyGetResponse {
if msg == nil {
return nil
}
res := &SubmissionListForVacancyGetResponse{
Submissions: make([]Submission, len(msg.Submissions)),
}
for i, subm := range msg.Submissions {
res.Submissions[i] = *new(Submission).From(&subm)
}
return res
}
type (
SubmissionCreateRequest struct {
AgentId string `json:"agent_id"`
VacancyId string `json:"vacancy_id"`
CandidateInfo *CandidateInfo `json:"candidate_info"`
}
SubmissionCreateResponse struct {
Id string `json:"id"`
}
)
func (r *SubmissionCreateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.AgentId == "" {
return fmt.Errorf("%w: AgentID is required", ErrValidation)
}
if r.VacancyId == "" {
return fmt.Errorf("%w: VacancyID is required", ErrValidation)
}
if r.CandidateInfo == nil {
return fmt.Errorf("%w: CandidateInfo is required", ErrValidation)
}
return nil
}
func (r *SubmissionCreateResponse) From(msg *dbtypes.SubmissionCreateResponse) *SubmissionCreateResponse {
if msg == nil {
return nil
}
return &SubmissionCreateResponse{
Id: msg.Id,
}
}
type (
SubmissionStatusUpdateRequest struct {
Id string
Status SubmissionStatus `json:"status"`
}
SubmissionStatusUpdateResponse struct{}
)
func (r *SubmissionStatusUpdateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if !(r.Status == SubStatusUnspecified ||
r.Status == SubStatusNew ||
r.Status == SubStatusPending ||
r.Status == SubStatusOnInterview ||
r.Status == SubStatusApproved ||
r.Status == SubStatusCancelled ||
r.Status == SubStatusRejected) {
return fmt.Errorf("%w: invalid status: %v", ErrValidation, r.Status)
}
return nil
}
type (
SubmissionDeleteRequest struct {
Id string
}
SubmissionDeleteResponse struct{}
)
func (r *SubmissionDeleteRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}

View File

@@ -0,0 +1,467 @@
package requestmodel
import (
"fmt"
"math"
"net/url"
"strconv"
"time"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
)
type VacancyStatus string
const (
VacUnspecified VacancyStatus = "unspecified"
VacNew VacancyStatus = "new"
VacPending VacancyStatus = "pending"
VacApproved VacancyStatus = "approved"
VacRejected VacancyStatus = "rejected"
)
func (s *VacancyStatus) NullString() *string {
if s == nil {
return nil
}
return (*string)(s)
}
type (
// TODO: remove extra fields for agent
Vacancy struct {
Id string `json:"id"`
Company VacancyCompanyInfo `json:"company"`
Name string `json:"name"`
Address string `json:"address"`
WorkFormat string `json:"work_format"`
AgentReward *int32 `json:"agent_reward"`
SalaryTop int32 `json:"salary_top"`
SalaryBottom int32 `json:"salary_bottom"`
Requirements *string `json:"requirements"`
Responsibilities *string `json:"responsibilities"`
ExtraInfo *string `json:"extra_info"`
Region string `json:"region"`
IsArchived bool `json:"is_archived"`
TargetAction VacancyTargetAction `json:"target_action"`
Moderation VacancyModeration `json:"moderation"`
RequiredCandidates int32 `json:"required_candidates"`
CurrentCandidates int32 `json:"current_candidates"`
ExtraFields *string `json:"extra_fields"`
CreatedAt string `json:"created_at"`
}
VacancyCompanyInfo struct {
Id string `json:"id"`
Name string `json:"name"`
LogoLink *string `json:"logo_link"`
}
VacancyTargetAction struct {
Action string `json:"action"`
Duration int32 `json:"duration"`
}
VacancyModeration struct {
Status VacancyStatus `json:"status"`
DescriptionHistory []VacancyModerationDescription `json:"description_history"`
}
VacancyModerationDescription struct {
Description *string `json:"description"`
CreatedAt string `json:"created_at"`
}
)
func (m *VacancyModeration) From(msg *dbtypes.VacancyModeration) *VacancyModeration {
if msg == nil {
return nil
}
res := &VacancyModeration{
Status: VacancyStatus(msg.Status),
DescriptionHistory: make([]VacancyModerationDescription, len(msg.DescriptionHistory)),
}
for i, desc := range msg.DescriptionHistory {
res.DescriptionHistory[i] = VacancyModerationDescription{
Description: desc.Description,
CreatedAt: desc.CreatedAt.Format(time.DateOnly),
}
}
return res
}
func (v *Vacancy) From(msg *dbtypes.Vacancy) *Vacancy {
if msg == nil {
return nil
}
res := &Vacancy{
Id: msg.Id,
Company: VacancyCompanyInfo{
Id: msg.Company.Id,
Name: msg.Company.Name,
},
Name: msg.Name,
Address: msg.Address,
WorkFormat: msg.WorkFormat,
AgentReward: msg.AgentReward,
SalaryTop: msg.SalaryTop,
SalaryBottom: msg.SalaryBottom,
Requirements: msg.Requirements,
Responsibilities: msg.Responsibilities,
ExtraInfo: msg.ExtraInfo,
Region: msg.Region,
IsArchived: msg.IsArchived,
TargetAction: VacancyTargetAction{
Action: msg.TargetAction.Action,
Duration: msg.TargetAction.Duration,
},
Moderation: *new(VacancyModeration).From(&msg.Moderation),
RequiredCandidates: msg.RequiredCandidates,
CurrentCandidates: msg.CurrentCandidates,
ExtraFields: msg.ExtraFields,
CreatedAt: msg.CreatedAt.Format(time.DateOnly),
}
return res
}
type (
VacancyListGetRequest struct {
Filters *VacancyListFilters
Page uint64
PageSize uint64
}
VacancyListFilters struct {
DistributorId *string
CompanyId *string
VacancyId *string
Region *string
SalaryBottom *int32
SalaryTop *int32
IsArchived *bool
Status *VacancyStatus
}
VacancyListGetResponse struct {
Vacancies []Vacancy `json:"vacancies"`
}
)
func (f *VacancyListGetRequest) FromQuery(query url.Values) (*VacancyListGetRequest, error) {
if query == nil {
return nil, nil
}
var filters VacancyListFilters
if val, ok := query["distributor_id"]; ok {
filters.DistributorId = &val[0]
}
if val, ok := query["company_id"]; ok {
filters.CompanyId = &val[0]
}
if val, ok := query["vacancy_id"]; ok {
filters.VacancyId = &val[0]
}
if val, ok := query["region"]; ok {
filters.Region = &val[0]
}
if val, ok := query["salary_bottom"]; ok {
intVal, err := parseInt32(val[0])
if err != nil {
return nil, fmt.Errorf("invalid salary_bottom param: %w", err)
}
filters.SalaryBottom = &intVal
}
if val, ok := query["salary_top"]; ok {
intVal, err := parseInt32(val[0])
if err != nil {
return nil, fmt.Errorf("invalid salary_top param: %w", err)
}
filters.SalaryTop = &intVal
}
if val, ok := query["is_archived"]; ok {
flag := val[0] == "true" || val[0] == "1"
filters.IsArchived = &flag
}
if val, ok := query["status"]; ok {
status := VacancyStatus(val[0])
filters.Status = &status
}
res := &VacancyListGetRequest{
Filters: &filters,
Page: constants.DefaultPaginationPage,
PageSize: constants.DefaultPaginationPageSize,
}
if val, ok := query["page"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page param: %w", err)
}
res.Page = intVal
}
if val, ok := query["page_size"]; ok {
intVal, err := parseUint64(val[0])
if err != nil {
return nil, fmt.Errorf("invalid page_size param: %w", err)
}
res.PageSize = intVal
}
return res, nil
}
func (r *VacancyListGetRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Filters != nil {
if r.Filters.Status != nil && !(*r.Filters.Status == VacUnspecified ||
*r.Filters.Status == VacNew ||
*r.Filters.Status == VacPending ||
*r.Filters.Status == VacApproved ||
*r.Filters.Status == VacRejected) {
return fmt.Errorf("%w: invalid status: %v", ErrValidation, *r.Filters.Status)
}
}
return nil
}
func (r *VacancyListGetResponse) From(msg *dbtypes.VacancyListGetResponse) *VacancyListGetResponse {
if msg == nil {
return nil
}
res := &VacancyListGetResponse{
Vacancies: make([]Vacancy, len(msg.Vacancies)),
}
for i, vacancy := range msg.Vacancies {
res.Vacancies[i] = *new(Vacancy).From(&vacancy)
}
return res
}
type (
VacancyCreateRequest struct {
CompanyId string `json:"company_id"`
Name string `json:"name"`
Address string `json:"address"`
WorkFormat string `json:"work_format"`
AgentReward *int32 `json:"agent_reward"`
SalaryTop int32 `json:"salary_top"`
SalaryBottom int32 `json:"salary_bottom"`
Requirements *string `json:"requirements"`
Responsibilities *string `json:"responsibilities"`
ExtraInfo *string `json:"extra_info"`
Region string `json:"region"`
TargetAction VacancyTargetAction `json:"target_action"`
RequiredCandidates int32 `json:"required_candidates"`
CurrentCandidates int32 `json:"current_candidates"`
ExtraFields *string `json:"extra_fields"`
}
VacancyCreateResponse struct {
Id string `json:"id"`
}
)
func (r *VacancyCreateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.CompanyId == "" {
return fmt.Errorf("%w: CompanyID is required", ErrValidation)
}
if r.Name == "" {
return fmt.Errorf("%w: Name is required", ErrValidation)
}
if r.Address == "" {
return fmt.Errorf("%w: Address is required", ErrValidation)
}
if r.WorkFormat == "" {
return fmt.Errorf("%w: WorkFormat is required", ErrValidation)
}
if r.Region == "" {
return fmt.Errorf("%w: Region is required", ErrValidation)
}
if r.TargetAction.Action == "" {
return fmt.Errorf("%w: TargetAction.Action is required", ErrValidation)
}
if r.TargetAction.Duration == 0 {
return fmt.Errorf("%w: TargetAction.Duration is required", ErrValidation)
}
return nil
}
func (r *VacancyCreateResponse) From(msg *dbtypes.VacancyCreateResponse) *VacancyCreateResponse {
if msg == nil {
return nil
}
return &VacancyCreateResponse{
Id: msg.Id,
}
}
type (
VacancyUpdateRequest struct {
Id string
Name *string `json:"name"`
Address *string `json:"address"`
WorkFormat *string `json:"work_format"`
AgentReward *int32 `json:"agent_reward"`
SalaryTop *int32 `json:"salary_top"`
SalaryBottom *int32 `json:"salary_bottom"`
Requirements *string `json:"requirements"`
Responsibilities *string `json:"responsibilities"`
ExtraInfo *string `json:"extra_info"`
Region *string `json:"region"`
TargetAction VacancyTargetActionForUpdate `json:"target_action"`
RequiredCandidates *int32 `json:"required_candidates"`
ExtraFields *string `json:"extra_fields"`
}
VacancyTargetActionForUpdate struct {
Action *string `json:"action"`
Duration *int32 `json:"duration"`
}
VacancyUpdateResponse struct {
}
)
func (r *VacancyUpdateRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
if r.Name == nil && r.Address == nil && r.WorkFormat == nil && r.AgentReward == nil &&
r.SalaryTop == nil && r.SalaryBottom == nil && r.Requirements == nil && r.Responsibilities == nil &&
r.ExtraInfo == nil && r.Region == nil && r.TargetAction.Action == nil && r.TargetAction.Duration == nil &&
r.RequiredCandidates == nil && r.ExtraFields == nil {
return fmt.Errorf("%w: nothing to update", ErrValidation)
}
return nil
}
func (r *VacancyUpdateResponse) From(msg *dbtypes.VacancyUpdateResponse) *VacancyUpdateResponse {
if msg == nil {
return nil
}
return &VacancyUpdateResponse{}
}
type (
VacancyDeleteRequest struct {
Id string
}
VacancyDeleteResponse struct {
}
)
func (r *VacancyDeleteRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}
func (r *VacancyDeleteResponse) From(msg *dbtypes.VacancyDeleteResponse) *VacancyDeleteResponse {
if msg == nil {
return nil
}
return &VacancyDeleteResponse{}
}
type (
SendVacancyToModerationRequest struct {
Id string
}
SendVacancyToModerationResponse struct {
}
)
func (r *SendVacancyToModerationRequest) Validate() error {
if r == nil {
return fmt.Errorf("%w: request is nil", ErrValidation)
}
if r.Id == "" {
return fmt.Errorf("%w: ID is required", ErrValidation)
}
return nil
}
func parseInt32(val string) (int32, error) {
intVal, err := strconv.Atoi(val)
if err != nil {
return 0, err
}
// Check overflow int32
if intVal < int(math.MinInt32) || intVal > int(math.MaxInt32) {
return 0, constants.ErrIntOutOfRange
}
//nolint:gosec // ignore integer overflow check for Atoi conversion to int32
int32Val := int32(intVal)
return int32Val, nil
}
func parseUint64(val string) (uint64, error) {
uintVal, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return 0, err
}
return uintVal, nil
}