+address book service
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed

This commit is contained in:
Stephan D
2025-12-01 21:20:10 +01:00
parent c4d34c5663
commit 5e1da9617f
24 changed files with 703 additions and 2 deletions

View File

@@ -7,7 +7,9 @@ import (
mongoimpl "github.com/tech/sendico/pkg/db/internal/mongo"
"github.com/tech/sendico/pkg/db/invitation"
"github.com/tech/sendico/pkg/db/organization"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/db/refreshtokens"
"github.com/tech/sendico/pkg/db/role"
"github.com/tech/sendico/pkg/db/transaction"
@@ -23,6 +25,8 @@ type Factory interface {
NewAccountDB() (account.DB, error)
NewOrganizationDB() (organization.DB, error)
NewInvitationsDB() (invitation.DB, error)
NewRecipientsDB() (recipient.DB, error)
NewPaymentMethodsDB() (paymethod.DB, error)
NewRolesDB() (role.DB, error)
NewPoliciesDB() (policy.DB, error)

View File

@@ -15,13 +15,17 @@ import (
"github.com/tech/sendico/pkg/db/internal/mongo/confirmationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/invitationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/organizationdb"
"github.com/tech/sendico/pkg/db/internal/mongo/paymethoddb"
"github.com/tech/sendico/pkg/db/internal/mongo/policiesdb"
"github.com/tech/sendico/pkg/db/internal/mongo/recipientdb"
"github.com/tech/sendico/pkg/db/internal/mongo/refreshtokensdb"
"github.com/tech/sendico/pkg/db/internal/mongo/rolesdb"
"github.com/tech/sendico/pkg/db/internal/mongo/transactionimp"
"github.com/tech/sendico/pkg/db/invitation"
"github.com/tech/sendico/pkg/db/organization"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/db/refreshtokens"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/db/role"
@@ -201,6 +205,29 @@ func (db *DB) NewOrganizationDB() (organization.DB, error) {
return organizationDB, nil
}
func (db *DB) NewRecipientsDB() (recipient.DB, error) {
pmdb, err := db.NewPaymentMethodsDB()
if err != nil {
db.logger.Warn("Failed to create payment methods database", zap.Error(err))
return nil, err
}
create := func(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
db *mongo.Database,
) (recipient.DB, error) {
return recipientdb.Create(ctx, logger, enforcer, pdb, pmdb, db)
}
return newProtectedDB(db, create)
}
func (db *DB) NewPaymentMethodsDB() (paymethod.DB, error) {
return newProtectedDB(db, paymethoddb.Create)
}
func (db *DB) NewRefreshTokensDB() (refreshtokens.DB, error) {
return refreshtokensdb.Create(db.logger, db.db())
}

View File

@@ -0,0 +1,20 @@
package paymethoddb
import (
"context"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func (db *PaymentMethodsDB) SetArchived(ctx context.Context, accountRef, organizationRef, objectRef primitive.ObjectID, isArchived, cascade bool) error {
// Use the ArchivableDB for the main archiving logic
if err := db.ArchivableDB.SetArchived(ctx, accountRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to chnage object archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("object_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
return nil
}

View File

@@ -0,0 +1,49 @@
package paymethoddb
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/mongo"
)
type PaymentMethodsDB struct {
auth.ProtectedDBImp[*model.PaymentMethod]
auth.ArchivableDB[*model.PaymentMethod]
}
func Create(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
db *mongo.Database,
) (*PaymentMethodsDB, error) {
p, err := auth.CreateDBImp[*model.PaymentMethod](ctx, logger, pdb, enforcer, mservice.PaymentMethods, db)
if err != nil {
return nil, err
}
createEmpty := func() *model.PaymentMethod {
return &model.PaymentMethod{}
}
getArchivable := func(c *model.PaymentMethod) model.Archivable {
return &c.ArchivableBase
}
res := &PaymentMethodsDB{
ProtectedDBImp: *p,
ArchivableDB: auth.NewArchivableDB(
p.DBImp,
logger,
p.Enforcer,
createEmpty,
getArchivable,
),
}
return res, nil
}

View File

@@ -0,0 +1,28 @@
package paymethoddb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
mauth "github.com/tech/sendico/pkg/mutil/db/auth"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (db *PaymentMethodsDB) List(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, cursor *model.ViewCursor) ([]model.PaymentMethod, error) {
res, err := mauth.GetProtectedObjects[model.PaymentMethod](
ctx,
db.DBImp.Logger,
accountRef, organizationRef, model.ActionRead,
repository.OrgFilter(organizationRef).And(repository.Filter("recipientRef", recipientRef)),
cursor,
db.Enforcer,
db.DBImp.Repository,
)
if errors.Is(err, merrors.ErrNoData) {
return []model.PaymentMethod{}, nil
}
return res, err
}

View File

@@ -0,0 +1,57 @@
package recipientdb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func (db *RecipientDB) SetArchived(ctx context.Context, accountRef, organizationRef, objectRef primitive.ObjectID, isArchived, cascade bool) error {
// Use the ArchivableDB for the main archiving logic
if err := db.ArchivableDB.SetArchived(ctx, accountRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to change recipient archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("recipient_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
if cascade {
if err := db.setArchivedPaymentMethods(ctx, accountRef, organizationRef, objectRef, isArchived); err != nil {
db.DBImp.Logger.Warn("Failed to update payment methods archive status", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("organization_ref", organizationRef),
mzap.ObjRef("recipient_ref", objectRef), zap.Bool("archived", isArchived), zap.Bool("cascade", cascade))
return err
}
}
return nil
}
func (db *RecipientDB) setArchivedPaymentMethods(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, archived bool) error {
db.DBImp.Logger.Debug("Setting archived status for recipient payment methods", mzap.ObjRef("recipient_ref", recipientRef), zap.Bool("archived", archived))
db.DBImp.Logger.Debug("Applying archived status to payment methods for recipient", mzap.ObjRef("recipient_ref", recipientRef))
// Get all payMethods for the recipient
payMethods, err := db.pmdb.List(ctx, accountRef, organizationRef, recipientRef, nil)
if err != nil && !errors.Is(err, merrors.ErrNoData) {
db.DBImp.Logger.Warn("Failed to fetch payment methods for recipient", zap.Error(err), mzap.ObjRef("recipient_ref", recipientRef))
return err
}
// Archive each payment method
for _, pmethod := range payMethods {
if err := db.pmdb.SetArchived(ctx, accountRef, organizationRef, pmethod.ID, archived, true); err != nil {
db.DBImp.Logger.Warn("Failed to set archived status for payment method", zap.Error(err), mzap.ObjRef("payment_method_ref", pmethod.ID))
return err
}
}
db.DBImp.Logger.Debug("Successfully updated payment methods archived status", zap.Int("count", len(payMethods)), mzap.ObjRef("recipient_ref", recipientRef))
return nil
}

View File

@@ -0,0 +1,56 @@
package recipientdb
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/db/policy"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"go.mongodb.org/mongo-driver/mongo"
)
type RecipientDB struct {
auth.ProtectedDBImp[*model.Recipient]
auth.ArchivableDB[*model.Recipient]
pmdb paymethod.DB
paymentMethodsRepo repository.Repository
}
func Create(ctx context.Context,
logger mlogger.Logger,
enforcer auth.Enforcer,
pdb policy.DB,
pmdb paymethod.DB,
db *mongo.Database,
) (*RecipientDB, error) {
p, err := auth.CreateDBImp[*model.Recipient](ctx, logger, pdb, enforcer, mservice.Organizations, db)
if err != nil {
return nil, err
}
createEmpty := func() *model.Recipient {
return &model.Recipient{}
}
getArchivable := func(c *model.Recipient) model.Archivable {
return &c.ArchivableBase
}
res := &RecipientDB{
ProtectedDBImp: *p,
ArchivableDB: auth.NewArchivableDB(
p.DBImp,
p.DBImp.Logger,
enforcer,
createEmpty,
getArchivable,
),
paymentMethodsRepo: repository.CreateMongoRepository(db, string(mservice.PaymentMethods)),
pmdb: pmdb,
}
return res, nil
}

View File

@@ -0,0 +1,28 @@
package recipientdb
import (
"context"
"errors"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
mauth "github.com/tech/sendico/pkg/mutil/db/auth"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func (db *RecipientDB) List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Recipient, error) {
res, err := mauth.GetProtectedObjects[model.Recipient](
ctx,
db.DBImp.Logger,
accountRef, organizationRef, model.ActionRead,
repository.OrgFilter(organizationRef),
cursor,
db.Enforcer,
db.DBImp.Repository,
)
if errors.Is(err, merrors.ErrNoData) {
return []model.Recipient{}, nil
}
return res, err
}

View File

@@ -15,5 +15,5 @@ type DB interface {
Decline(ctx context.Context, invitationRef primitive.ObjectID) error
List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Invitation, error)
DeleteCascade(ctx context.Context, accountRef, statusRef primitive.ObjectID) error
SetArchived(ctx context.Context, accountRef, organizationRef, statusRef primitive.ObjectID, archived, cascade bool) error
SetArchived(ctx context.Context, accountRef, organizationRef, invitationRef primitive.ObjectID, archived, cascade bool) error
}

View File

@@ -0,0 +1,15 @@
package paymethod
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type DB interface {
auth.ProtectedDB[*model.PaymentMethod]
SetArchived(ctx context.Context, accountRef, organizationRef, methodRef primitive.ObjectID, archived, cascade bool) error
List(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, cursor *model.ViewCursor) ([]model.PaymentMethod, error)
}

View File

@@ -0,0 +1,15 @@
package recipient
import (
"context"
"github.com/tech/sendico/pkg/auth"
"github.com/tech/sendico/pkg/model"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type DB interface {
auth.ProtectedDB[*model.Recipient]
SetArchived(ctx context.Context, accountRef, organizationRef, recipientRef primitive.ObjectID, archived, cascade bool) error
List(ctx context.Context, accountRef, organizationRef, _ primitive.ObjectID, cursor *model.ViewCursor) ([]model.Recipient, error)
}

25
api/pkg/model/card.go Normal file
View File

@@ -0,0 +1,25 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type CardPaymentData struct {
Pan string `bson:"pan" json:"pan"`
FirstName string `bson:"firstName" json:"firstName"`
LastName string `bson:"lastName" json:"lastName"`
}
func (m *PaymentMethod) AsCard() (*CardPaymentData, error) {
if m.Type != PaymentTypeCard {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not card", m.Type), "type")
}
var d CardPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

26
api/pkg/model/iban.go Normal file
View File

@@ -0,0 +1,26 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type IbanPaymentData struct {
Iban string `bson:"iban" json:"iban"`
AccountHolder string `bson:"accountHolder" json:"accountHolder"`
Bic *string `bson:"bic,omitempty" json:"bic,omitempty"`
BankName *string `bson:"bankName,omitempty" json:"bankName,omitempty"`
}
func (m *PaymentMethod) AsIban() (*IbanPaymentData, error) {
if m.Type != PaymentTypeIban {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not iban", m.Type), "type")
}
var d IbanPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

66
api/pkg/model/payment.go Normal file
View File

@@ -0,0 +1,66 @@
package model
import (
"encoding/json"
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type PaymentType int
const (
PaymentTypeIban PaymentType = iota
PaymentTypeCard
PaymentTypeBankAccount
PaymentTypeWallet
)
var paymentTypeToString = map[PaymentType]string{
PaymentTypeIban: "iban",
PaymentTypeCard: "card",
PaymentTypeBankAccount: "bankAccount",
PaymentTypeWallet: "wallet",
}
var paymentTypeFromString = map[string]PaymentType{
"iban": PaymentTypeIban,
"card": PaymentTypeCard,
"bankAccount": PaymentTypeBankAccount,
"wallet": PaymentTypeWallet,
}
func (t PaymentType) String() string {
if v, ok := paymentTypeToString[t]; ok {
return v
}
return "iban"
}
func (t PaymentType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *PaymentType) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := paymentTypeFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown PaymentType: %q", val))
}
*t = v
return nil
}
type PaymentMethod struct {
PermissionBound `bson:",inline" json:",inline"`
RecipientRef primitive.ObjectID `bson:"recipientRef" json:"recipientRef"`
Type PaymentType `bson:"type" json:"type"`
IsActive bool `bson:"isActive" json:"isActive"`
Data bson.Raw `bson:"data" json:"data"`
}

31
api/pkg/model/rba.go Normal file
View File

@@ -0,0 +1,31 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type RussianBankAccountPaymentData struct {
RecipientName string `bson:"recipientName" json:"recipientName"`
Inn string `bson:"inn" json:"inn"`
Kpp string `bson:"kpp" json:"kpp"`
BankName string `bson:"bankName" json:"bankName"`
Bik string `bson:"bik" json:"bik"`
AccountNumber string `bson:"accountNumber" json:"accountNumber"`
CorrespondentAccount string `bson:"correspondentAccount" json:"correspondentAccount"`
}
func (m *PaymentMethod) AsRussianBankAccount() (*RussianBankAccountPaymentData, error) {
if m.Type != PaymentTypeBankAccount {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not bankAccount", m.Type), "type")
}
var d RussianBankAccountPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

106
api/pkg/model/recipient.go Normal file
View File

@@ -0,0 +1,106 @@
package model
import (
"encoding/json"
"fmt"
"github.com/tech/sendico/pkg/merrors"
)
type RecipientStatus int
const (
RecipientStatusReady RecipientStatus = iota
RecipientStatusRegistered
RecipientStatusNotRegistered
)
var recipientStatusToString = map[RecipientStatus]string{
RecipientStatusReady: "ready",
RecipientStatusRegistered: "registered",
RecipientStatusNotRegistered: "notRegistered",
}
var recipientStatusFromString = map[string]RecipientStatus{
"ready": RecipientStatusReady,
"registered": RecipientStatusRegistered,
"notRegistered": RecipientStatusNotRegistered,
}
func (s RecipientStatus) String() string {
if v, ok := recipientStatusToString[s]; ok {
return v
}
return "ready" // дефолт, можно поменять
}
// JSON: храним как строку ("ready" / "registered" / "notRegistered")
func (s RecipientStatus) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
func (s *RecipientStatus) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := recipientStatusFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientStatus: %q", val))
}
*s = v
return nil
}
// RecipientType { internal, external }
type RecipientType int
const (
RecipientTypeInternal RecipientType = iota
RecipientTypeExternal
)
var recipientTypeToString = map[RecipientType]string{
RecipientTypeInternal: "internal",
RecipientTypeExternal: "external",
}
var recipientTypeFromString = map[string]RecipientType{
"internal": RecipientTypeInternal,
"external": RecipientTypeExternal,
}
func (t RecipientType) String() string {
if v, ok := recipientTypeToString[t]; ok {
return v
}
return "internal"
}
func (t RecipientType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *RecipientType) UnmarshalJSON(data []byte) error {
var val string
if err := json.Unmarshal(data, &val); err != nil {
return err
}
v, ok := recipientTypeFromString[val]
if !ok {
return merrors.InvalidArgument(fmt.Sprintf("unknown RecipientType: %q", val))
}
*t = v
return nil
}
type Recipient struct {
PermissionBound `bson:",inline" json:",inline"`
Describable `bson:",inline" json:",inline"`
Email string `bson:"email" json:"email"`
AvatarURL *string `bson:"avatarUrl,omitempty" json:"avatarUrl,omitempty"`
Status RecipientStatus `bson:"status" json:"status"`
Type RecipientType `bson:"type" json:"type"`
}

25
api/pkg/model/wallet.go Normal file
View File

@@ -0,0 +1,25 @@
package model
import (
"fmt"
"github.com/tech/sendico/pkg/merrors"
"go.mongodb.org/mongo-driver/bson"
)
type WalletPaymentData struct {
WalletID string `bson:"walletId" json:"walletId"`
}
func (m *PaymentMethod) AsWallet() (*WalletPaymentData, error) {
if m.Type != PaymentTypeWallet {
return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not wallet", m.Type), "type")
}
var d WalletPaymentData
if err := bson.Unmarshal(m.Data, &d); err != nil {
return nil, err
}
return &d, nil
}

View File

@@ -33,9 +33,11 @@ const (
Notifications Type = "notifications" // Represents notifications sent to users
Organizations Type = "organizations" // Represents organizations in the system
Payments Type = "payments" // Represents payments service
PaymentMethods Type = "payment_methods" // Represents payment methods service
Permissions Type = "permissions" // Represents permissiosns service
Policies Type = "policies" // Represents access control policies
PolicyAssignements Type = "policy_assignments" // Represents policy assignments database
Recipients Type = "recipients" // Represents payment recipients
RefreshTokens Type = "refresh_tokens" // Represents refresh tokens for authentication
Roles Type = "roles" // Represents roles in access control
Storage Type = "storage" // Represents statuses of tasks or projects

View File

@@ -0,0 +1,11 @@
package paymethod
import (
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/paymethodsimp"
)
func Create(a api.API) (mservice.MicroService, error) {
return paymethodsimp.CreateAPI(a)
}

View File

@@ -0,0 +1,11 @@
package recipient
import (
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/server/interface/api"
recipientimp "github.com/tech/sendico/server/internal/server/paymethodsimp"
)
func Create(a api.API) (mservice.MicroService, error) {
return recipientimp.CreateAPI(a)
}

View File

@@ -14,12 +14,14 @@ import (
"github.com/tech/sendico/server/interface/services/account"
"github.com/tech/sendico/server/interface/services/confirmation"
"github.com/tech/sendico/server/interface/services/invitation"
"github.com/tech/sendico/server/interface/services/ledger"
"github.com/tech/sendico/server/interface/services/logo"
"github.com/tech/sendico/server/interface/services/organization"
"github.com/tech/sendico/server/interface/services/paymethod"
"github.com/tech/sendico/server/interface/services/permission"
"github.com/tech/sendico/server/interface/services/recipient"
"github.com/tech/sendico/server/interface/services/site"
"github.com/tech/sendico/server/interface/services/wallet"
"github.com/tech/sendico/server/interface/services/ledger"
"go.uber.org/zap"
)
@@ -87,6 +89,8 @@ func (a *APIImp) installServices() error {
srvf = append(srvf, site.Create)
srvf = append(srvf, wallet.Create)
srvf = append(srvf, ledger.Create)
srvf = append(srvf, recipient.Create)
srvf = append(srvf, paymethod.Create)
for _, v := range srvf {
if err := a.addMicroservice(v); err != nil {

View File

@@ -0,0 +1,46 @@
package paymethodsimp
import (
"context"
"github.com/tech/sendico/pkg/db/paymethod"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
eapi "github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/papitemplate"
"go.uber.org/zap"
)
type RecipientAPI struct {
papitemplate.ProtectedAPI[model.PaymentMethod]
db paymethod.DB
}
func (a *RecipientAPI) Name() mservice.Type {
return mservice.Recipients
}
func (a *RecipientAPI) Finish(_ context.Context) error {
return nil
}
func CreateAPI(a eapi.API) (*RecipientAPI, error) {
dbFactory := func() (papitemplate.ProtectedDB[model.PaymentMethod], error) {
return a.DBFactory().NewPaymentMethodsDB()
}
res := &RecipientAPI{}
p, err := papitemplate.CreateAPI(a, dbFactory, mservice.Recipients, mservice.PaymentMethods)
if err != nil {
return nil, err
}
res.ProtectedAPI = *p.Build()
if res.db, err = a.DBFactory().NewPaymentMethodsDB(); err != nil {
res.Logger.Warn("Failed to create payment methods database", zap.Error(err))
return nil, err
}
return res, nil
}

View File

@@ -0,0 +1,46 @@
package recipientimp
import (
"context"
"github.com/tech/sendico/pkg/db/recipient"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
eapi "github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/papitemplate"
"go.uber.org/zap"
)
type RecipientAPI struct {
papitemplate.ProtectedAPI[model.Recipient]
db recipient.DB
}
func (a *RecipientAPI) Name() mservice.Type {
return mservice.Recipients
}
func (a *RecipientAPI) Finish(_ context.Context) error {
return nil
}
func CreateAPI(a eapi.API) (*RecipientAPI, error) {
dbFactory := func() (papitemplate.ProtectedDB[model.Recipient], error) {
return a.DBFactory().NewRecipientsDB()
}
res := &RecipientAPI{}
p, err := papitemplate.CreateAPI(a, dbFactory, mservice.Organizations, mservice.Recipients)
if err != nil {
return nil, err
}
res.ProtectedAPI = *p.Build()
if res.db, err = a.DBFactory().NewRecipientsDB(); err != nil {
res.Logger.Warn("Failed to create recipients database", zap.Error(err))
return nil, err
}
return res, nil
}

View File

@@ -9,6 +9,9 @@ class Services {
static const String storage = 'storage';
static const String chainWallets = 'chain_wallets';
static const String recipients = 'recipients';
static const String paymentMethods = 'payment_methods';
static const String amplitude = 'amplitude';
static const String clients = 'clients';
static const String logo = 'logo';