From eea7891fc4eabe719b24d52306809d2b3ae796ca Mon Sep 17 00:00:00 2001 From: optclblast Date: Tue, 14 May 2024 01:26:58 +0300 Subject: [PATCH] tmp org repo commit --- .../rest/presenters/organizations.go | 8 +- backend/internal/pkg/models/organization.go | 8 +- backend/internal/pkg/models/user.go | 55 ++++++ .../interactors/organizations/interactor.go | 4 +- .../repository/organizations/repository.go | 164 +++++++++++++++--- backend/migrations/blockd.sql | 1 + 6 files changed, 206 insertions(+), 34 deletions(-) diff --git a/backend/internal/interface/rest/presenters/organizations.go b/backend/internal/interface/rest/presenters/organizations.go index 841c297..6b24f3e 100644 --- a/backend/internal/interface/rest/presenters/organizations.go +++ b/backend/internal/interface/rest/presenters/organizations.go @@ -10,8 +10,8 @@ import ( type OrganizationsPresenter interface { ResponseCreate(organization *models.Organization) ([]byte, error) - ResponseList(orgs []models.Organization, nextCursor string) ([]byte, error) - Organizations(orgs []models.Organization) []domain.Organization + ResponseList(orgs []*models.Organization, nextCursor string) ([]byte, error) + Organizations(orgs []*models.Organization) []domain.Organization } type organizationsPresenter struct { @@ -40,7 +40,7 @@ func (p *organizationsPresenter) ResponseCreate(o *models.Organization) ([]byte, return out, nil } -func (p *organizationsPresenter) ResponseList(orgs []models.Organization, nextCursor string) ([]byte, error) { +func (p *organizationsPresenter) ResponseList(orgs []*models.Organization, nextCursor string) ([]byte, error) { resp := &domain.ListOrganizationsResponse{ Collection: domain.Collection[domain.Organization]{ Items: p.Organizations(orgs), @@ -59,7 +59,7 @@ func (p *organizationsPresenter) ResponseList(orgs []models.Organization, nextCu return out, nil } -func (p *organizationsPresenter) Organizations(orgs []models.Organization) []domain.Organization { +func (p *organizationsPresenter) Organizations(orgs []*models.Organization) []domain.Organization { out := make([]domain.Organization, len(orgs)) for i, o := range orgs { diff --git a/backend/internal/pkg/models/organization.go b/backend/internal/pkg/models/organization.go index 414eb4a..dc2b744 100644 --- a/backend/internal/pkg/models/organization.go +++ b/backend/internal/pkg/models/organization.go @@ -7,6 +7,12 @@ import ( "github.com/google/uuid" ) +type Organizations []*Organization + +func (i *Organizations) MarshalBinary() ([]byte, error) { + return json.Marshal(i) +} + type Organization struct { ID uuid.UUID `json:"id"` Name string `json:"name"` @@ -16,6 +22,6 @@ type Organization struct { UpdatedAt time.Time `json:"updated_at"` } -func (i Organization) MarshalBinary() ([]byte, error) { +func (i *Organization) MarshalBinary() ([]byte, error) { return json.Marshal(i) } diff --git a/backend/internal/pkg/models/user.go b/backend/internal/pkg/models/user.go index d1556fa..61e28a6 100644 --- a/backend/internal/pkg/models/user.go +++ b/backend/internal/pkg/models/user.go @@ -21,6 +21,7 @@ type User struct { Bip39Seed []byte Activated bool CreatedAt time.Time + UpdatedAt time.Time } type UserCredentials struct { @@ -51,9 +52,21 @@ func (u *User) Seed() []byte { return u.Bip39Seed } +type OrganizationParticipantType int + +const ( + OrganizationParticipantTypeUser OrganizationParticipantType = iota + OrganizationParticipantTypeEmployee +) + type OrganizationParticipant interface { UserIdentity + Type() OrganizationParticipantType + + GetUser() *OrganizationUser + GetEmployee() *Employee + IsAdmin() bool Position() string } @@ -63,6 +76,20 @@ type OrganizationUser struct { OrgPosition string Admin bool + + Employee *Employee +} + +func (u *OrganizationUser) Type() OrganizationParticipantType { + return OrganizationParticipantTypeUser +} + +func (u *OrganizationUser) GetUser() *OrganizationUser { + return u +} + +func (u *OrganizationUser) GetEmployee() *Employee { + return u.Employee } func (u *OrganizationUser) IsAdmin() bool { @@ -72,3 +99,31 @@ func (u *OrganizationUser) IsAdmin() bool { func (u *OrganizationUser) Position() string { return u.OrgPosition } + +type Employee struct { + ID uuid.UUID + OrganizationId uuid.UUID + WalletAddress []byte + CreatedAt time.Time + UpdatedAt time.Time +} + +func (u *Employee) Type() OrganizationParticipantType { + return OrganizationParticipantTypeEmployee +} + +func (u *Employee) GetUser() *OrganizationUser { + return nil +} + +func (u *Employee) GetEmployee() *Employee { + return u +} + +func (u *Employee) IsAdmin() bool { + return false +} + +func (u *Employee) Position() string { + return "" // todo +} diff --git a/backend/internal/usecase/interactors/organizations/interactor.go b/backend/internal/usecase/interactors/organizations/interactor.go index f956a0f..59019ff 100644 --- a/backend/internal/usecase/interactors/organizations/interactor.go +++ b/backend/internal/usecase/interactors/organizations/interactor.go @@ -101,8 +101,8 @@ func (c *organizationsListCursor) decode(s string) error { } type ListResponse struct { - Organizations []models.Organization `json:"Organizations"` - NextCursor string `json:"NextCursor"` + Organizations models.Organizations + NextCursor string } func (i ListResponse) MarshalBinary() ([]byte, error) { diff --git a/backend/internal/usecase/repository/organizations/repository.go b/backend/internal/usecase/repository/organizations/repository.go index ca9c877..3a0cbb5 100644 --- a/backend/internal/usecase/repository/organizations/repository.go +++ b/backend/internal/usecase/repository/organizations/repository.go @@ -22,6 +22,16 @@ type GetParams struct { Limit int64 } +type ParticipantsParams struct { + OrganizationId uuid.UUID + Ids uuid.UUIDs + + // Filters + UsersOnly bool + ActiveOnly bool + EmployeesOnly bool +} + type AddParticipantParams struct { OrganizationId uuid.UUID UserId uuid.UUID @@ -29,13 +39,20 @@ type AddParticipantParams struct { IsAdmin bool } +type DeleteParticipantParams struct { + OrganizationId uuid.UUID + UserId uuid.UUID + EmployeeId uuid.UUID +} + type Repository interface { Create(ctx context.Context, org models.Organization) error - Get(ctx context.Context, params GetParams) ([]models.Organization, error) + Get(ctx context.Context, params GetParams) ([]*models.Organization, error) Update(ctx context.Context, org models.Organization) error Delete(ctx context.Context, id uuid.UUID) error AddParticipant(ctx context.Context, params AddParticipantParams) error CreateAndAdd(ctx context.Context, org models.Organization, user *models.User) error + DeleteParticipant(ctx context.Context, params DeleteParticipantParams) error } type repositorySQL struct { @@ -86,8 +103,8 @@ func (r *repositorySQL) Create(ctx context.Context, org models.Organization) err return nil } -func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]models.Organization, error) { - organizations := make([]models.Organization, 0, params.Limit) +func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]*models.Organization, error) { + organizations := make([]*models.Organization, 0, params.Limit) if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { query := sq.Select( @@ -158,7 +175,7 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]models.Org return fmt.Errorf("error scan row. %w", err) } - organizations = append(organizations, models.Organization{ + organizations = append(organizations, &models.Organization{ ID: id, Name: name, Address: address, @@ -177,37 +194,42 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]models.Org } func (r *repositorySQL) Update(ctx context.Context, org models.Organization) error { - panic("implement me!") + if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { + query := sq.Update("organizations as o"). + SetMap(sq.Eq{ + "o.name": org.Name, + "o.address": org.Address, + "o.wallet_seed": org.WalletSeed, + "o.created_at": org.CreatedAt, + "o.updated_at": org.UpdatedAt, + }). + Where(sq.Eq{ + "o.id": org.ID, + }). + PlaceholderFormat(sq.Dollar) + + if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil { + return fmt.Errorf("error update organization. %w", err) + } + + return nil + }); err != nil { + return fmt.Errorf("error execute transactional operation. %w", err) + } return nil } func (r *repositorySQL) Delete(ctx context.Context, id uuid.UUID) error { - panic("implement me!") - - return nil -} - -func (r *repositorySQL) AddParticipant(ctx context.Context, params AddParticipantParams) error { if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { - query := sq.Insert("organizations_users").Columns( - "organization_id", - "user_id", - "employee_id", - "added_at", - "updated_at", - "is_admin", - ).Values( - params.OrganizationId, - params.UserId, - params.EmployeeId, - time.Now(), - time.Now(), - params.IsAdmin, - ).PlaceholderFormat(sq.Dollar) + query := sq.Delete("organizations as o"). + Where(sq.Eq{ + "o.id": id, + }). + PlaceholderFormat(sq.Dollar) if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil { - return fmt.Errorf("error add new participant to organization. %w", err) + return fmt.Errorf("error delete organization. %w", err) } return nil @@ -239,3 +261,91 @@ func (r *repositorySQL) CreateAndAdd(ctx context.Context, org models.Organizatio return nil } + +func (r *repositorySQL) Participants( + ctx context.Context, + params ParticipantsParams, +) ([]models.OrganizationParticipant, error) { + participants := make([]models.OrganizationParticipant, 0, len(params.Ids)) + + if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { + + return nil + }); err != nil { + + } + + return participants, nil +} + +func (r *repositorySQL) AddParticipant(ctx context.Context, params AddParticipantParams) error { + if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { + query := sq.Insert("organizations_users"). + Columns( + "organization_id", + "user_id", + "employee_id", + "added_at", + "updated_at", + "is_admin", + ). + Values( + params.OrganizationId, + params.UserId, + params.EmployeeId, + time.Now(), + time.Now(), + params.IsAdmin, + ). + PlaceholderFormat(sq.Dollar) + + if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil { + return fmt.Errorf("error add new participant to organization. %w", err) + } + + return nil + }); err != nil { + return fmt.Errorf("error execute transactional operation. %w", err) + } + + return nil +} + +func (r *repositorySQL) DeleteParticipant(ctx context.Context, params DeleteParticipantParams) error { + if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) (err error) { + deletedAt := time.Now() + + query := sq.Update("organizations_users as ou"). + SetMap(sq.Eq{ + "updated_at": deletedAt, + "deleted_at": deletedAt, + "is_admin": false, + }). + Where(sq.Eq{ + "ou.organization_id": params.OrganizationId, + }). + PlaceholderFormat(sq.Dollar) + + if params.EmployeeId != uuid.Nil { + query = query.Where(sq.Eq{ + "ou.employee_id": params.EmployeeId, + }) + } + + if params.UserId != uuid.Nil { + query = query.Where(sq.Eq{ + "ou.user_id": params.UserId, + }) + } + + if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil { + return fmt.Errorf("error delete participant from organization. %w", err) + } + + return nil + }); err != nil { + return fmt.Errorf("error execute transactional operation. %w", err) + } + + return nil +} diff --git a/backend/migrations/blockd.sql b/backend/migrations/blockd.sql index 3d48ea4..faf8349 100644 --- a/backend/migrations/blockd.sql +++ b/backend/migrations/blockd.sql @@ -55,6 +55,7 @@ create table organizations_users ( organization_id uuid not null references organizations(id), user_id uuid not null references users(id), employee_id uuid default null, + position varchar(300), added_at timestamp default current_timestamp, updated_at timestamp default current_timestamp, deleted_at timestamp default null,