From c73978c94298c2c3fed17e4ffca3fd882ac09746 Mon Sep 17 00:00:00 2001 From: Abhishek Sah Date: Tue, 4 Aug 2026 12:56:40 +0530 Subject: [PATCH] feat(kyc): add delete of an org kyc record The org_kyc row references the organization row, and nothing could remove it, which blocked the hard delete of an organization. Co-Authored-By: Claude Fable 5 --- core/kyc/mocks/repository.go | 47 +++++++++++++++++++++++ core/kyc/service.go | 5 +++ internal/store/postgres/kyc_repository.go | 23 +++++++++++ 3 files changed, 75 insertions(+) diff --git a/core/kyc/mocks/repository.go b/core/kyc/mocks/repository.go index ec9b93e7a..d028bfa6b 100644 --- a/core/kyc/mocks/repository.go +++ b/core/kyc/mocks/repository.go @@ -22,6 +22,53 @@ func (_m *Repository) EXPECT() *Repository_Expecter { return &Repository_Expecter{mock: &_m.Mock} } +// Delete provides a mock function with given fields: _a0, _a1 +func (_m *Repository) Delete(_a0 context.Context, _a1 string) error { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Repository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type Repository_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 string +func (_e *Repository_Expecter) Delete(_a0 interface{}, _a1 interface{}) *Repository_Delete_Call { + return &Repository_Delete_Call{Call: _e.mock.On("Delete", _a0, _a1)} +} + +func (_c *Repository_Delete_Call) Run(run func(_a0 context.Context, _a1 string)) *Repository_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *Repository_Delete_Call) Return(_a0 error) *Repository_Delete_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Repository_Delete_Call) RunAndReturn(run func(context.Context, string) error) *Repository_Delete_Call { + _c.Call.Return(run) + return _c +} + // GetByOrgID provides a mock function with given fields: _a0, _a1 func (_m *Repository) GetByOrgID(_a0 context.Context, _a1 string) (kyc.KYC, error) { ret := _m.Called(_a0, _a1) diff --git a/core/kyc/service.go b/core/kyc/service.go index 47d6d2a19..01f735532 100644 --- a/core/kyc/service.go +++ b/core/kyc/service.go @@ -6,6 +6,7 @@ type Repository interface { GetByOrgID(context.Context, string) (KYC, error) List(context.Context) ([]KYC, error) Upsert(context.Context, KYC) (KYC, error) + Delete(context.Context, string) error } type Service struct { @@ -29,3 +30,7 @@ func (s Service) SetKyc(ctx context.Context, kyc KYC) (KYC, error) { func (s Service) ListKycs(ctx context.Context) ([]KYC, error) { return s.repository.List(ctx) } + +func (s Service) DeleteKyc(ctx context.Context, orgID string) error { + return s.repository.Delete(ctx, orgID) +} diff --git a/internal/store/postgres/kyc_repository.go b/internal/store/postgres/kyc_repository.go index b109497d4..55b40c8e1 100644 --- a/internal/store/postgres/kyc_repository.go +++ b/internal/store/postgres/kyc_repository.go @@ -187,6 +187,29 @@ func (r OrgKycRepository) Upsert(ctx context.Context, input kyc.KYC) (kyc.KYC, e return result.KYC.transformToKyc() } +// Delete removes the kyc record of an org. Deleting is idempotent: an org +// without a kyc record returns success. +func (r OrgKycRepository) Delete(ctx context.Context, orgID string) error { + query, params, err := dialect.Delete(TABLE_ORGANIZATIONS_KYC).Where(goqu.Ex{ + "org_id": orgID, + }).ToSQL() + if err != nil { + return fmt.Errorf("%w: %w", errQuery, err) + } + + if err = r.dbc.WithTimeout(ctx, TABLE_ORGANIZATIONS_KYC, "Delete", func(ctx context.Context) error { + _, err := r.dbc.ExecContext(ctx, query, params...) + return err + }); err != nil { + err = checkPostgresError(err) + if errors.Is(err, ErrInvalidTextRepresentation) { + return kyc.ErrInvalidUUID + } + return err + } + return nil +} + func (r OrgKycRepository) List(ctx context.Context) ([]kyc.KYC, error) { // Define table references orgs := goqu.T(TABLE_ORGANIZATIONS)