omnix-sopiga/services/template-service/repository/orders.go
2026-08-07 12:21:42 +07:00

104 lines
2.5 KiB
Go

package repository
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/yourorg/go-dw-platform/services/template-service/entity"
)
type Filter struct {
StartDate time.Time
EndDate time.Time
Limit int
}
type Repository struct {
pool *pgxpool.Pool
}
func New(pool *pgxpool.Pool) *Repository {
return &Repository{pool: pool}
}
func (r *Repository) ExistsByKey(ctx context.Context, naturalKey string) (bool, error) {
var exists bool
err := r.pool.QueryRow(ctx,
`SELECT EXISTS(SELECT 1 FROM orders WHERE natural_key = $1)`,
naturalKey,
).Scan(&exists)
if err != nil {
return false, fmt.Errorf("exists by key: %w", err)
}
return exists, nil
}
func (r *Repository) InsertBatch(ctx context.Context, entities []*entity.Order) (int64, error) {
tx, err := r.pool.Begin(ctx)
if err != nil {
return 0, fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback(ctx)
stmt := `INSERT INTO orders (order_id, customer_id, amount, natural_key, created_at)
VALUES ($1, $2, $3, $4, $5)`
batch := &pgx.Batch{}
for _, e := range entities {
naturalKey := fmt.Sprintf("%s_%s_%d", e.OrderID, e.CustomerID, e.CreatedAt.Unix())
batch.Queue(stmt, e.OrderID, e.CustomerID, e.Amount, naturalKey, e.CreatedAt)
}
results := tx.SendBatch(ctx, batch)
var rowsInserted int64
for i := 0; i < len(entities); i++ {
tag, err := results.Exec()
if err != nil {
results.Close()
return 0, fmt.Errorf("exec batch: %w", err)
}
rowsInserted += tag.RowsAffected()
}
if err := results.Close(); err != nil {
return 0, fmt.Errorf("close batch results: %w", err)
}
if err := tx.Commit(ctx); err != nil {
return 0, fmt.Errorf("commit: %w", err)
}
return rowsInserted, nil
}
func (r *Repository) FindByFilters(ctx context.Context, filter *Filter) ([]*entity.Order, error) {
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
query := `SELECT order_id, customer_id, amount, created_at
FROM orders
WHERE created_at >= $1 AND created_at <= $2
LIMIT $3`
rows, err := r.pool.Query(ctx, query, filter.StartDate, filter.EndDate, filter.Limit)
if err != nil {
return nil, fmt.Errorf("query: %w", err)
}
defer rows.Close()
var orders []*entity.Order
for rows.Next() {
var o entity.Order
if err := rows.Scan(&o.OrderID, &o.CustomerID, &o.Amount, &o.CreatedAt); err != nil {
return nil, fmt.Errorf("scan: %w", err)
}
orders = append(orders, &o)
}
return orders, rows.Err()
}