154 lines
4.2 KiB
Go
154 lines
4.2 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"shop/internal/models"
|
|
)
|
|
|
|
type OrderRepository struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewOrderRepository(pool *pgxpool.Pool) *OrderRepository {
|
|
return &OrderRepository{pool: pool}
|
|
}
|
|
|
|
func (r *OrderRepository) Create(ctx context.Context, order *models.Order, items []models.CartItem) error {
|
|
tx, err := r.pool.Begin(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
|
|
err = tx.QueryRow(ctx, `
|
|
INSERT INTO orders (user_id, guest_name, guest_email, guest_phone, address, total, status)
|
|
VALUES ($1, $2, $3, $4, $5, $6, 'pending')
|
|
RETURNING id, created_at
|
|
`, order.UserID, order.GuestName, order.GuestEmail, order.GuestPhone, order.Address, order.Total,
|
|
).Scan(&order.ID, &order.CreatedAt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, item := range items {
|
|
_, err = tx.Exec(ctx, `
|
|
INSERT INTO order_items (order_id, product_id, product_name, price, quantity)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
`, order.ID, item.ProductID, item.Product.Name, item.Product.EffectivePrice(), item.Quantity)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return tx.Commit(ctx)
|
|
}
|
|
|
|
func (r *OrderRepository) ByUser(ctx context.Context, userID int) ([]models.Order, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT id, user_id, guest_name, guest_email, guest_phone, address, total, status, created_at
|
|
FROM orders WHERE user_id = $1 ORDER BY created_at DESC
|
|
`, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var orders []models.Order
|
|
for rows.Next() {
|
|
var o models.Order
|
|
if err := rows.Scan(&o.ID, &o.UserID, &o.GuestName, &o.GuestEmail, &o.GuestPhone, &o.Address, &o.Total, &o.Status, &o.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
o.Items, err = r.items(ctx, o.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
orders = append(orders, o)
|
|
}
|
|
return orders, rows.Err()
|
|
}
|
|
|
|
func (r *OrderRepository) items(ctx context.Context, orderID int) ([]models.OrderItem, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT id, order_id, product_id, product_name, price, quantity
|
|
FROM order_items WHERE order_id = $1
|
|
`, orderID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var items []models.OrderItem
|
|
for rows.Next() {
|
|
var i models.OrderItem
|
|
if err := rows.Scan(&i.ID, &i.OrderID, &i.ProductID, &i.ProductName, &i.Price, &i.Quantity); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
return items, rows.Err()
|
|
}
|
|
|
|
func (r *OrderRepository) All(ctx context.Context, limit int) ([]models.Order, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT id, user_id, guest_name, guest_email, guest_phone, address, total, status, created_at
|
|
FROM orders ORDER BY created_at DESC LIMIT $1
|
|
`, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
return r.collectOrders(ctx, rows)
|
|
}
|
|
|
|
func (r *OrderRepository) GetByID(ctx context.Context, id int) (models.Order, error) {
|
|
var o models.Order
|
|
err := r.pool.QueryRow(ctx, `
|
|
SELECT id, user_id, guest_name, guest_email, guest_phone, address, total, status, created_at
|
|
FROM orders WHERE id = $1
|
|
`, id).Scan(&o.ID, &o.UserID, &o.GuestName, &o.GuestEmail, &o.GuestPhone, &o.Address, &o.Total, &o.Status, &o.CreatedAt)
|
|
if err != nil {
|
|
return models.Order{}, err
|
|
}
|
|
o.Items, err = r.items(ctx, o.ID)
|
|
return o, err
|
|
}
|
|
|
|
func (r *OrderRepository) UpdateStatus(ctx context.Context, id int, status string) error {
|
|
tag, err := r.pool.Exec(ctx, `UPDATE orders SET status = $1 WHERE id = $2`, status, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if tag.RowsAffected() == 0 {
|
|
return pgx.ErrNoRows
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *OrderRepository) Count(ctx context.Context) (int, error) {
|
|
var n int
|
|
err := r.pool.QueryRow(ctx, `SELECT COUNT(*) FROM orders`).Scan(&n)
|
|
return n, err
|
|
}
|
|
|
|
func (r *OrderRepository) collectOrders(ctx context.Context, rows pgx.Rows) ([]models.Order, error) {
|
|
var orders []models.Order
|
|
for rows.Next() {
|
|
var o models.Order
|
|
if err := rows.Scan(&o.ID, &o.UserID, &o.GuestName, &o.GuestEmail, &o.GuestPhone, &o.Address, &o.Total, &o.Status, &o.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
var err error
|
|
o.Items, err = r.items(ctx, o.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
orders = append(orders, o)
|
|
}
|
|
return orders, rows.Err()
|
|
}
|