- Remove backend Medusa.js (TypeScript) e substitui pelo backend Go (saveinmed-performance-core) - Corrige testes auth.test.ts: alinha paths de API (v1/ sem barra inicial) e campo access_token - Corrige GroupedProductCard.test.tsx: ajusta distância formatada (toFixed) e troca userEvent por fireEvent com fakeTimers - Corrige AuthContext.test.tsx: usa vi.hoisted() para mocks e corrige parênteses no waitFor Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
99 lines
3.9 KiB
Go
99 lines
3.9 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
"github.com/saveinmed/backend-go/internal/domain"
|
|
)
|
|
|
|
// CreateDocument persists a KYC document.
|
|
func (r *Repository) CreateDocument(ctx context.Context, doc *domain.CompanyDocument) error {
|
|
now := time.Now().UTC()
|
|
doc.CreatedAt = now
|
|
doc.UpdatedAt = now
|
|
|
|
query := `INSERT INTO company_documents (id, company_id, type, url, status, rejection_reason, created_at, updated_at)
|
|
VALUES (:id, :company_id, :type, :url, :status, :rejection_reason, :created_at, :updated_at)`
|
|
|
|
_, err := r.db.NamedExecContext(ctx, query, doc)
|
|
return err
|
|
}
|
|
|
|
// ListDocuments retrieves documents for a company.
|
|
func (r *Repository) ListDocuments(ctx context.Context, companyID uuid.UUID) ([]domain.CompanyDocument, error) {
|
|
var docs []domain.CompanyDocument
|
|
query := `SELECT id, company_id, type, url, status, rejection_reason, created_at, updated_at FROM company_documents WHERE company_id = $1 ORDER BY created_at DESC`
|
|
if err := r.db.SelectContext(ctx, &docs, query, companyID); err != nil {
|
|
return nil, err
|
|
}
|
|
return docs, nil
|
|
}
|
|
|
|
// RecordLedgerEntry inserts an immutable financial record.
|
|
func (r *Repository) RecordLedgerEntry(ctx context.Context, entry *domain.LedgerEntry) error {
|
|
entry.CreatedAt = time.Now().UTC()
|
|
query := `INSERT INTO ledger_entries (id, company_id, amount_cents, type, description, reference_id, created_at)
|
|
VALUES (:id, :company_id, :amount_cents, :type, :description, :reference_id, :created_at)`
|
|
|
|
_, err := r.db.NamedExecContext(ctx, query, entry)
|
|
return err
|
|
}
|
|
|
|
// GetLedger returns transaction history for a company.
|
|
func (r *Repository) GetLedger(ctx context.Context, companyID uuid.UUID, limit, offset int) ([]domain.LedgerEntry, int64, error) {
|
|
var entries []domain.LedgerEntry
|
|
|
|
// Get total count
|
|
var total int64
|
|
if err := r.db.GetContext(ctx, &total, "SELECT count(*) FROM ledger_entries WHERE company_id = $1", companyID); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
// Get paginated entries
|
|
query := `SELECT id, company_id, amount_cents, type, description, reference_id, created_at FROM ledger_entries WHERE company_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`
|
|
if err := r.db.SelectContext(ctx, &entries, query, companyID, limit, offset); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return entries, total, nil
|
|
}
|
|
|
|
// GetBalance calculates the current balance based on ledger entries.
|
|
func (r *Repository) GetBalance(ctx context.Context, companyID uuid.UUID) (int64, error) {
|
|
var balance int64
|
|
// COALESCE to handle case with no entries returning NULL
|
|
query := `SELECT COALESCE(SUM(amount_cents), 0) FROM ledger_entries WHERE company_id = $1`
|
|
if err := r.db.GetContext(ctx, &balance, query, companyID); err != nil {
|
|
return 0, err
|
|
}
|
|
return balance, nil
|
|
}
|
|
|
|
// CreateWithdrawal requests a payout.
|
|
func (r *Repository) CreateWithdrawal(ctx context.Context, withdrawal *domain.Withdrawal) error {
|
|
now := time.Now().UTC()
|
|
withdrawal.CreatedAt = now
|
|
withdrawal.UpdatedAt = now
|
|
|
|
// Transaction to ensure balance check?
|
|
// In a real system, we reserved balance via ledger entry first.
|
|
// The Service layer should call RecordLedgerEntry(WITHDRAWAL) before calling CreateWithdrawal.
|
|
// So here we just insert the request.
|
|
|
|
query := `INSERT INTO withdrawals (id, company_id, amount_cents, status, bank_account_info, created_at, updated_at)
|
|
VALUES (:id, :company_id, :amount_cents, :status, :bank_account_info, :created_at, :updated_at)`
|
|
|
|
_, err := r.db.NamedExecContext(ctx, query, withdrawal)
|
|
return err
|
|
}
|
|
|
|
// ListWithdrawals retrieves payout requests.
|
|
func (r *Repository) ListWithdrawals(ctx context.Context, companyID uuid.UUID) ([]domain.Withdrawal, error) {
|
|
var list []domain.Withdrawal
|
|
query := `SELECT id, company_id, amount_cents, status, bank_account_info, transaction_id, rejection_reason, created_at, updated_at FROM withdrawals WHERE company_id = $1 ORDER BY created_at DESC`
|
|
if err := r.db.SelectContext(ctx, &list, query, companyID); err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|