mirror of
https://github.com/3ybactuk/marketplace-go-service-project.git
synced 2025-10-30 14:03:45 +03:00
[hw-3] loms service
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"route256/loms/internal/domain/entity"
|
||||
"route256/loms/internal/domain/model"
|
||||
)
|
||||
|
||||
type storage = map[entity.ID]*entity.Order
|
||||
|
||||
type InMemoryRepository struct {
|
||||
storage storage
|
||||
mx sync.RWMutex
|
||||
idCounter entity.ID
|
||||
}
|
||||
|
||||
func NewInMemoryRepository(cap int) *InMemoryRepository {
|
||||
return &InMemoryRepository{
|
||||
storage: make(storage, cap),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) OrderCreate(_ context.Context, order *entity.Order) (entity.ID, error) {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
r.idCounter++
|
||||
|
||||
orderCopy := &entity.Order{
|
||||
OrderID: r.idCounter,
|
||||
Status: order.Status,
|
||||
UserID: order.UserID,
|
||||
Items: make([]entity.OrderItem, len(order.Items)),
|
||||
}
|
||||
|
||||
copy(orderCopy.Items, order.Items)
|
||||
|
||||
r.storage[orderCopy.OrderID] = orderCopy
|
||||
|
||||
return r.idCounter, nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) OrderSetStatus(_ context.Context, orderID entity.ID, newStatus string) error {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
if _, ok := r.storage[orderID]; !ok {
|
||||
return model.ErrOrderNotFound
|
||||
}
|
||||
|
||||
r.storage[orderID].Status = newStatus
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) OrderGetByID(_ context.Context, orderID entity.ID) (*entity.Order, error) {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
order, ok := r.storage[orderID]
|
||||
if !ok {
|
||||
return nil, model.ErrOrderNotFound
|
||||
}
|
||||
|
||||
orderCopy := &entity.Order{
|
||||
OrderID: order.OrderID,
|
||||
Status: order.Status,
|
||||
UserID: order.UserID,
|
||||
Items: make([]entity.OrderItem, len(order.Items)),
|
||||
}
|
||||
|
||||
copy(orderCopy.Items, order.Items)
|
||||
|
||||
return orderCopy, nil
|
||||
}
|
||||
114
loms/internal/domain/repository/stocks/in_memory_repository.go
Normal file
114
loms/internal/domain/repository/stocks/in_memory_repository.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
|
||||
"route256/loms/internal/domain/entity"
|
||||
"route256/loms/internal/domain/model"
|
||||
)
|
||||
|
||||
//go:embed stock-data.json
|
||||
var stockData []byte
|
||||
|
||||
type storage = map[entity.Sku]*entity.Stock
|
||||
|
||||
type InMemoryRepository struct {
|
||||
storage storage
|
||||
mx sync.RWMutex
|
||||
}
|
||||
|
||||
func NewInMemoryRepository(cap int) (*InMemoryRepository, error) {
|
||||
var rows []struct {
|
||||
Sku entity.Sku `json:"sku"`
|
||||
TotalCount uint32 `json:"total_count"`
|
||||
Reserved uint32 `json:"reserved"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(stockData, &rows); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo := &InMemoryRepository{
|
||||
storage: make(storage, cap),
|
||||
}
|
||||
|
||||
for _, r := range rows {
|
||||
repo.storage[r.Sku] = &entity.Stock{
|
||||
Item: entity.OrderItem{
|
||||
ID: r.Sku,
|
||||
Count: r.TotalCount,
|
||||
},
|
||||
Reserved: r.Reserved,
|
||||
}
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) StockReserve(_ context.Context, stock *entity.Stock) error {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
if _, ok := r.storage[stock.Item.ID]; !ok {
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
|
||||
if r.storage[stock.Item.ID].Item.Count < stock.Reserved {
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
|
||||
r.storage[stock.Item.ID].Item.Count -= stock.Reserved
|
||||
r.storage[stock.Item.ID].Reserved += stock.Reserved
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) StockReserveRemove(_ context.Context, stock *entity.Stock) error {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
if _, ok := r.storage[stock.Item.ID]; !ok {
|
||||
return model.ErrUnknownStock
|
||||
}
|
||||
|
||||
if r.storage[stock.Item.ID].Reserved < stock.Reserved {
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
|
||||
r.storage[stock.Item.ID].Reserved -= stock.Reserved
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) StockCancel(_ context.Context, stock *entity.Stock) error {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
if _, ok := r.storage[stock.Item.ID]; !ok {
|
||||
return model.ErrUnknownStock
|
||||
}
|
||||
|
||||
if r.storage[stock.Item.ID].Reserved < stock.Reserved {
|
||||
return model.ErrNotEnoughStocks
|
||||
}
|
||||
|
||||
r.storage[stock.Item.ID].Reserved -= stock.Reserved
|
||||
r.storage[stock.Item.ID].Item.Count += stock.Reserved
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *InMemoryRepository) StockGetByID(_ context.Context, sku entity.Sku) (*entity.Stock, error) {
|
||||
r.mx.Lock()
|
||||
defer r.mx.Unlock()
|
||||
|
||||
stock, ok := r.storage[sku]
|
||||
if !ok {
|
||||
return nil, model.ErrUnknownStock
|
||||
}
|
||||
|
||||
return stock, nil
|
||||
}
|
||||
37
loms/internal/domain/repository/stocks/stock-data.json
Normal file
37
loms/internal/domain/repository/stocks/stock-data.json
Normal file
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"sku": 139275865,
|
||||
"total_count": 65534,
|
||||
"reserved": 0
|
||||
},
|
||||
{
|
||||
"sku": 2956315,
|
||||
"total_count": 100,
|
||||
"reserved": 30
|
||||
},
|
||||
{
|
||||
"sku": 1076963,
|
||||
"total_count": 100,
|
||||
"reserved": 35
|
||||
},
|
||||
{
|
||||
"sku": 135717466,
|
||||
"total_count": 100,
|
||||
"reserved": 20
|
||||
},
|
||||
{
|
||||
"sku": 135937324,
|
||||
"total_count": 100,
|
||||
"reserved": 30
|
||||
},
|
||||
{
|
||||
"sku": 1625903,
|
||||
"total_count": 10000,
|
||||
"reserved": 0
|
||||
},
|
||||
{
|
||||
"sku": 1148162,
|
||||
"total_count": 100,
|
||||
"reserved": 0
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user