+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
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:
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
20
api/pkg/db/internal/mongo/paymethoddb/archived.go
Normal file
20
api/pkg/db/internal/mongo/paymethoddb/archived.go
Normal 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
|
||||
}
|
||||
49
api/pkg/db/internal/mongo/paymethoddb/db.go
Normal file
49
api/pkg/db/internal/mongo/paymethoddb/db.go
Normal 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
|
||||
}
|
||||
28
api/pkg/db/internal/mongo/paymethoddb/list.go
Normal file
28
api/pkg/db/internal/mongo/paymethoddb/list.go
Normal 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
|
||||
}
|
||||
57
api/pkg/db/internal/mongo/recipientdb/archived.go
Normal file
57
api/pkg/db/internal/mongo/recipientdb/archived.go
Normal 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
|
||||
}
|
||||
56
api/pkg/db/internal/mongo/recipientdb/db.go
Normal file
56
api/pkg/db/internal/mongo/recipientdb/db.go
Normal 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
|
||||
}
|
||||
28
api/pkg/db/internal/mongo/recipientdb/list.go
Normal file
28
api/pkg/db/internal/mongo/recipientdb/list.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
15
api/pkg/db/paymethod/db.go
Normal file
15
api/pkg/db/paymethod/db.go
Normal 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)
|
||||
}
|
||||
15
api/pkg/db/recipient/db.go
Normal file
15
api/pkg/db/recipient/db.go
Normal 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
25
api/pkg/model/card.go
Normal 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
26
api/pkg/model/iban.go
Normal 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
66
api/pkg/model/payment.go
Normal 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
31
api/pkg/model/rba.go
Normal 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
106
api/pkg/model/recipient.go
Normal 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
25
api/pkg/model/wallet.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
11
api/server/interface/services/paymethod/paymethod.go
Normal file
11
api/server/interface/services/paymethod/paymethod.go
Normal 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)
|
||||
}
|
||||
11
api/server/interface/services/recipient/recipient.go
Normal file
11
api/server/interface/services/recipient/recipient.go
Normal 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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
46
api/server/internal/server/paymethodsimp/service.go
Normal file
46
api/server/internal/server/paymethodsimp/service.go
Normal 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
|
||||
}
|
||||
46
api/server/internal/server/recipientimp/service.go
Normal file
46
api/server/internal/server/recipientimp/service.go
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user