mirror of
https://github.com/3ybactuk/marketplace-go-service-project.git
synced 2025-10-30 22:13:44 +03:00
[hw-4] add postgres db
This commit is contained in:
32
loms/internal/domain/repository/orders/sqlc/db.go
Normal file
32
loms/internal/domain/repository/orders/sqlc/db.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
5
loms/internal/domain/repository/orders/sqlc/models.go
Normal file
5
loms/internal/domain/repository/orders/sqlc/models.go
Normal file
@@ -0,0 +1,5 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
18
loms/internal/domain/repository/orders/sqlc/querier.go
Normal file
18
loms/internal/domain/repository/orders/sqlc/querier.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
OrderAddItem(ctx context.Context, arg *OrderAddItemParams) error
|
||||
OrderCreate(ctx context.Context, arg *OrderCreateParams) (int64, error)
|
||||
OrderGetByID(ctx context.Context, id int64) ([]*OrderGetByIDRow, error)
|
||||
OrderSetStatus(ctx context.Context, arg *OrderSetStatusParams) (int64, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
||||
25
loms/internal/domain/repository/orders/sqlc/query.sql
Normal file
25
loms/internal/domain/repository/orders/sqlc/query.sql
Normal file
@@ -0,0 +1,25 @@
|
||||
-- name: OrderCreate :one
|
||||
insert into orders (status_name, user_id)
|
||||
values ($1, $2)
|
||||
returning id;
|
||||
|
||||
-- name: OrderAddItem :exec
|
||||
insert into order_items (order_id, sku, count)
|
||||
select $1, $2, $3;
|
||||
|
||||
-- name: OrderSetStatus :execrows
|
||||
update orders
|
||||
set status_name = $2
|
||||
where id = $1;
|
||||
|
||||
-- name: OrderGetByID :many
|
||||
select
|
||||
o.id as order_id,
|
||||
o.status_name as status,
|
||||
o.user_id,
|
||||
oi.sku,
|
||||
oi.count
|
||||
from orders o
|
||||
left join order_items oi on oi.order_id = o.id
|
||||
where o.id = $1
|
||||
order by oi.id;
|
||||
110
loms/internal/domain/repository/orders/sqlc/query.sql.go
Normal file
110
loms/internal/domain/repository/orders/sqlc/query.sql.go
Normal file
@@ -0,0 +1,110 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
// source: query.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const orderAddItem = `-- name: OrderAddItem :exec
|
||||
insert into order_items (order_id, sku, count)
|
||||
select $1, $2, $3
|
||||
`
|
||||
|
||||
type OrderAddItemParams struct {
|
||||
OrderID int64
|
||||
Sku int64
|
||||
Count int64
|
||||
}
|
||||
|
||||
func (q *Queries) OrderAddItem(ctx context.Context, arg *OrderAddItemParams) error {
|
||||
_, err := q.db.Exec(ctx, orderAddItem, arg.OrderID, arg.Sku, arg.Count)
|
||||
return err
|
||||
}
|
||||
|
||||
const orderCreate = `-- name: OrderCreate :one
|
||||
insert into orders (status_name, user_id)
|
||||
values ($1, $2)
|
||||
returning id
|
||||
`
|
||||
|
||||
type OrderCreateParams struct {
|
||||
StatusName string
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) OrderCreate(ctx context.Context, arg *OrderCreateParams) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, orderCreate, arg.StatusName, arg.UserID)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const orderGetByID = `-- name: OrderGetByID :many
|
||||
select
|
||||
o.id as order_id,
|
||||
o.status_name as status,
|
||||
o.user_id,
|
||||
oi.sku,
|
||||
oi.count
|
||||
from orders o
|
||||
left join order_items oi on oi.order_id = o.id
|
||||
where o.id = $1
|
||||
order by oi.id
|
||||
`
|
||||
|
||||
type OrderGetByIDRow struct {
|
||||
OrderID int64
|
||||
Status string
|
||||
UserID int64
|
||||
Sku *int64
|
||||
Count *int64
|
||||
}
|
||||
|
||||
func (q *Queries) OrderGetByID(ctx context.Context, id int64) ([]*OrderGetByIDRow, error) {
|
||||
rows, err := q.db.Query(ctx, orderGetByID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []*OrderGetByIDRow
|
||||
for rows.Next() {
|
||||
var i OrderGetByIDRow
|
||||
if err := rows.Scan(
|
||||
&i.OrderID,
|
||||
&i.Status,
|
||||
&i.UserID,
|
||||
&i.Sku,
|
||||
&i.Count,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, &i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const orderSetStatus = `-- name: OrderSetStatus :execrows
|
||||
update orders
|
||||
set status_name = $2
|
||||
where id = $1
|
||||
`
|
||||
|
||||
type OrderSetStatusParams struct {
|
||||
ID int64
|
||||
StatusName string
|
||||
}
|
||||
|
||||
func (q *Queries) OrderSetStatus(ctx context.Context, arg *OrderSetStatusParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, orderSetStatus, arg.ID, arg.StatusName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
105
loms/internal/domain/repository/orders/sqlc/repository.go
Normal file
105
loms/internal/domain/repository/orders/sqlc/repository.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"route256/loms/internal/domain/entity"
|
||||
"route256/loms/internal/domain/model"
|
||||
"route256/loms/internal/domain/service"
|
||||
"route256/loms/internal/infra/postgres"
|
||||
)
|
||||
|
||||
type orderRepo struct {
|
||||
pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
func NewOrderRepository(pool *pgxpool.Pool) service.OrderRepository {
|
||||
return &orderRepo{
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *orderRepo) GetQuerier(ctx context.Context) *Queries {
|
||||
tx, ok := postgres.TxFromCtx(ctx)
|
||||
if ok {
|
||||
return New(tx)
|
||||
}
|
||||
|
||||
return New(o.pool)
|
||||
}
|
||||
|
||||
func (o *orderRepo) OrderCreate(ctx context.Context, order *entity.Order) (entity.ID, error) {
|
||||
querier := o.GetQuerier(ctx)
|
||||
|
||||
id, err := querier.OrderCreate(ctx, &OrderCreateParams{
|
||||
StatusName: order.Status,
|
||||
UserID: int64(order.UserID),
|
||||
})
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("querier.OrderCreate: %w", err)
|
||||
}
|
||||
|
||||
for _, item := range order.Items {
|
||||
if err := querier.OrderAddItem(ctx, &OrderAddItemParams{
|
||||
OrderID: id,
|
||||
Sku: int64(item.ID),
|
||||
Count: int64(item.Count),
|
||||
}); err != nil {
|
||||
return 0, fmt.Errorf("querier.OrderAddItem: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return entity.ID(id), nil
|
||||
}
|
||||
|
||||
func (o *orderRepo) OrderGetByID(ctx context.Context, orderID entity.ID) (*entity.Order, error) {
|
||||
querier := o.GetQuerier(ctx)
|
||||
|
||||
rows, err := querier.OrderGetByID(ctx, int64(orderID))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("querier.OrderGetByID: %w", err)
|
||||
}
|
||||
|
||||
if len(rows) == 0 {
|
||||
return nil, model.ErrOrderNotFound
|
||||
}
|
||||
|
||||
items := make([]entity.OrderItem, len(rows))
|
||||
for i, row := range rows {
|
||||
items[i] = entity.OrderItem{
|
||||
ID: entity.Sku(*row.Sku),
|
||||
//nolint:gosec // will not overflow, uint32 is stored as int64
|
||||
Count: uint32(*row.Count),
|
||||
}
|
||||
}
|
||||
|
||||
order := &entity.Order{
|
||||
OrderID: orderID,
|
||||
Status: rows[0].Status,
|
||||
UserID: entity.ID(rows[0].UserID),
|
||||
Items: items,
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (o *orderRepo) OrderSetStatus(ctx context.Context, orderID entity.ID, newStatus string) error {
|
||||
querier := o.GetQuerier(ctx)
|
||||
|
||||
rows, err := querier.OrderSetStatus(ctx, &OrderSetStatusParams{
|
||||
ID: int64(orderID),
|
||||
StatusName: newStatus,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("querier.OrderSetStatus: %w", err)
|
||||
}
|
||||
|
||||
if rows == 0 {
|
||||
return model.ErrOrderNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
32
loms/internal/domain/repository/stocks/sqlc/db.go
Normal file
32
loms/internal/domain/repository/stocks/sqlc/db.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
11
loms/internal/domain/repository/stocks/sqlc/models.go
Normal file
11
loms/internal/domain/repository/stocks/sqlc/models.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
|
||||
type Stock struct {
|
||||
Sku int64
|
||||
TotalCount int64
|
||||
Reserved int64
|
||||
}
|
||||
18
loms/internal/domain/repository/stocks/sqlc/querier.go
Normal file
18
loms/internal/domain/repository/stocks/sqlc/querier.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
StockCancel(ctx context.Context, arg *StockCancelParams) (int64, error)
|
||||
StockGetByID(ctx context.Context, sku int64) (*Stock, error)
|
||||
StockReserve(ctx context.Context, arg *StockReserveParams) (int64, error)
|
||||
StockReserveRemove(ctx context.Context, arg *StockReserveRemoveParams) (int64, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
||||
24
loms/internal/domain/repository/stocks/sqlc/query.sql
Normal file
24
loms/internal/domain/repository/stocks/sqlc/query.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
-- name: StockGetByID :one
|
||||
select sku, total_count, reserved
|
||||
from stocks
|
||||
where sku = $1
|
||||
limit 1;
|
||||
|
||||
-- name: StockReserve :execrows
|
||||
update stocks
|
||||
set reserved = reserved + $2
|
||||
where sku = $1
|
||||
and total_count >= reserved + $2;
|
||||
|
||||
-- name: StockReserveRemove :execrows
|
||||
update stocks
|
||||
set reserved = reserved - $2,
|
||||
total_count = total_count - $2
|
||||
where sku = $1
|
||||
and reserved >= $2 and total_count >= $2;
|
||||
|
||||
-- name: StockCancel :execrows
|
||||
update stocks
|
||||
set reserved = reserved - $2
|
||||
where sku = $1
|
||||
and reserved >= $2;
|
||||
85
loms/internal/domain/repository/stocks/sqlc/query.sql.go
Normal file
85
loms/internal/domain/repository/stocks/sqlc/query.sql.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
// source: query.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const stockCancel = `-- name: StockCancel :execrows
|
||||
update stocks
|
||||
set reserved = reserved - $2
|
||||
where sku = $1
|
||||
and reserved >= $2
|
||||
`
|
||||
|
||||
type StockCancelParams struct {
|
||||
Sku int64
|
||||
Reserved int64
|
||||
}
|
||||
|
||||
func (q *Queries) StockCancel(ctx context.Context, arg *StockCancelParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, stockCancel, arg.Sku, arg.Reserved)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const stockGetByID = `-- name: StockGetByID :one
|
||||
select sku, total_count, reserved
|
||||
from stocks
|
||||
where sku = $1
|
||||
limit 1
|
||||
`
|
||||
|
||||
func (q *Queries) StockGetByID(ctx context.Context, sku int64) (*Stock, error) {
|
||||
row := q.db.QueryRow(ctx, stockGetByID, sku)
|
||||
var i Stock
|
||||
err := row.Scan(&i.Sku, &i.TotalCount, &i.Reserved)
|
||||
return &i, err
|
||||
}
|
||||
|
||||
const stockReserve = `-- name: StockReserve :execrows
|
||||
update stocks
|
||||
set reserved = reserved + $2
|
||||
where sku = $1
|
||||
and total_count >= reserved + $2
|
||||
`
|
||||
|
||||
type StockReserveParams struct {
|
||||
Sku int64
|
||||
Reserved int64
|
||||
}
|
||||
|
||||
func (q *Queries) StockReserve(ctx context.Context, arg *StockReserveParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, stockReserve, arg.Sku, arg.Reserved)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const stockReserveRemove = `-- name: StockReserveRemove :execrows
|
||||
update stocks
|
||||
set reserved = reserved - $2,
|
||||
total_count = total_count - $2
|
||||
where sku = $1
|
||||
and reserved >= $2 and total_count >= $2
|
||||
`
|
||||
|
||||
type StockReserveRemoveParams struct {
|
||||
Sku int64
|
||||
Reserved int64
|
||||
}
|
||||
|
||||
func (q *Queries) StockReserveRemove(ctx context.Context, arg *StockReserveRemoveParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, stockReserveRemove, arg.Sku, arg.Reserved)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
137
loms/internal/domain/repository/stocks/sqlc/repository.go
Normal file
137
loms/internal/domain/repository/stocks/sqlc/repository.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"route256/loms/internal/domain/entity"
|
||||
"route256/loms/internal/domain/model"
|
||||
"route256/loms/internal/domain/service"
|
||||
"route256/loms/internal/infra/postgres"
|
||||
"route256/loms/internal/infra/tools"
|
||||
)
|
||||
|
||||
type stockRepo struct {
|
||||
read *pgxpool.Pool
|
||||
write *pgxpool.Pool
|
||||
}
|
||||
|
||||
func NewStockRepository(write, read *pgxpool.Pool) service.StockRepository {
|
||||
return &stockRepo{
|
||||
read: read,
|
||||
write: write,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stockRepo) GetQuerier(ctx context.Context) *Queries {
|
||||
tx, ok := postgres.TxFromCtx(ctx)
|
||||
if ok {
|
||||
return New(tx)
|
||||
}
|
||||
|
||||
return New(s.write)
|
||||
}
|
||||
|
||||
func (s *stockRepo) StockReserve(ctx context.Context, stock *entity.Stock) error {
|
||||
querier := s.GetQuerier(ctx)
|
||||
|
||||
rows, err := querier.StockReserve(ctx, &StockReserveParams{
|
||||
Sku: int64(stock.Item.ID),
|
||||
Reserved: int64(stock.Reserved),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("querier.StockReserve: %w", err)
|
||||
}
|
||||
|
||||
if rows == 0 {
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stockRepo) StockReserveRemove(ctx context.Context, stock *entity.Stock) error {
|
||||
querier := s.GetQuerier(ctx)
|
||||
|
||||
rows, err := querier.StockReserveRemove(ctx, &StockReserveRemoveParams{
|
||||
Sku: int64(stock.Item.ID),
|
||||
Reserved: int64(stock.Reserved),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("querier.StockReserveRemove: %w", err)
|
||||
}
|
||||
|
||||
if rows > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = querier.StockGetByID(ctx, int64(stock.Item.ID))
|
||||
switch {
|
||||
case errors.Is(err, pgx.ErrNoRows):
|
||||
return model.ErrUnknownStock
|
||||
case err != nil:
|
||||
return fmt.Errorf("querier.StockGetByID: %w", err)
|
||||
default:
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stockRepo) StockCancel(ctx context.Context, stock *entity.Stock) error {
|
||||
querier := s.GetQuerier(ctx)
|
||||
|
||||
rows, err := querier.StockCancel(ctx, &StockCancelParams{
|
||||
Sku: int64(stock.Item.ID),
|
||||
Reserved: int64(stock.Reserved),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("querier.StockCancel: %w", err)
|
||||
}
|
||||
|
||||
if rows > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = querier.StockGetByID(ctx, int64(stock.Item.ID))
|
||||
switch {
|
||||
case errors.Is(err, pgx.ErrNoRows):
|
||||
return model.ErrUnknownStock
|
||||
case err != nil:
|
||||
return fmt.Errorf("querier.StockGetByID: %w", err)
|
||||
default:
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stockRepo) StockGetByID(ctx context.Context, sku entity.Sku) (*entity.Stock, error) {
|
||||
querier := s.GetQuerier(ctx)
|
||||
|
||||
stock, err := querier.StockGetByID(ctx, int64(sku))
|
||||
switch {
|
||||
case errors.Is(err, pgx.ErrNoRows):
|
||||
return nil, model.ErrUnknownStock
|
||||
case err != nil:
|
||||
return nil, fmt.Errorf("querier.StockGetByID: %w", err)
|
||||
default:
|
||||
count, castErr := tools.SafeCastInt64ToUInt32(stock.TotalCount)
|
||||
if castErr != nil {
|
||||
return nil, castErr
|
||||
}
|
||||
|
||||
reserved, castErr := tools.SafeCastInt64ToUInt32(stock.Reserved)
|
||||
if castErr != nil {
|
||||
return nil, castErr
|
||||
}
|
||||
|
||||
return &entity.Stock{
|
||||
Item: entity.OrderItem{
|
||||
ID: entity.Sku(stock.Sku),
|
||||
Count: count,
|
||||
},
|
||||
Reserved: reserved,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user