Files
shop-go/internal/repository/order.go
T

198 lines
5.3 KiB
Go

package repository
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"shop/internal/models"
)
const orderSelect = `
SELECT id, user_id, guest_name, guest_email, guest_phone, address, total, status,
COALESCE(payment_method, 'cod'), COALESCE(heleket_uuid, ''), COALESCE(heleket_order_id, ''),
COALESCE(heleket_payment_url, ''), COALESCE(heleket_payment_status, ''), created_at
FROM orders
`
type OrderRepository struct {
pool *pgxpool.Pool
}
func NewOrderRepository(pool *pgxpool.Pool) *OrderRepository {
return &OrderRepository{pool: pool}
}
func scanOrder(row pgx.Row) (models.Order, error) {
var o models.Order
err := row.Scan(
&o.ID, &o.UserID, &o.GuestName, &o.GuestEmail, &o.GuestPhone, &o.Address, &o.Total, &o.Status,
&o.PaymentMethod, &o.HeleketUUID, &o.HeleketOrderID, &o.HeleketPaymentURL, &o.HeleketPaymentStatus, &o.CreatedAt,
)
return o, err
}
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)
status := order.Status
if status == "" {
status = "pending"
}
paymentMethod := order.PaymentMethod
if paymentMethod == "" {
paymentMethod = "cod"
}
err = tx.QueryRow(ctx, `
INSERT INTO orders (user_id, guest_name, guest_email, guest_phone, address, total, status, payment_method)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id, created_at
`, order.UserID, order.GuestName, order.GuestEmail, order.GuestPhone, order.Address, order.Total, status, paymentMethod,
).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) UpdateHeleketPayment(ctx context.Context, orderID int, uuid, externalID, paymentURL, paymentStatus string) error {
_, err := r.pool.Exec(ctx, `
UPDATE orders SET
heleket_uuid = $1,
heleket_order_id = $2,
heleket_payment_url = $3,
heleket_payment_status = $4
WHERE id = $5
`, uuid, externalID, paymentURL, paymentStatus, orderID)
return err
}
func (r *OrderRepository) UpdateHeleketStatus(ctx context.Context, orderID int, paymentStatus, orderStatus string) error {
_, err := r.pool.Exec(ctx, `
UPDATE orders SET heleket_payment_status = $1, status = $2 WHERE id = $3
`, paymentStatus, orderStatus, orderID)
return err
}
func (r *OrderRepository) GetByHeleketOrderID(ctx context.Context, externalID string) (models.Order, error) {
row := r.pool.QueryRow(ctx, orderSelect+` WHERE heleket_order_id = $1`, externalID)
o, err := scanOrder(row)
if err != nil {
return models.Order{}, err
}
o.Items, err = r.items(ctx, o.ID)
return o, err
}
func (r *OrderRepository) ByUser(ctx context.Context, userID int) ([]models.Order, error) {
rows, err := r.pool.Query(ctx, orderSelect+` 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() {
o, err := scanOrder(rows)
if 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, orderSelect+` 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) {
row := r.pool.QueryRow(ctx, orderSelect+` WHERE id = $1`, id)
o, err := scanOrder(row)
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() {
o, err := scanOrder(rows)
if 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()
}