263 lines
7.0 KiB
Go
263 lines
7.0 KiB
Go
package processor
|
|
|
|
import (
|
|
"apskel-pos-be/internal/constants"
|
|
"apskel-pos-be/internal/entities"
|
|
"apskel-pos-be/internal/models"
|
|
"apskel-pos-be/internal/repository"
|
|
"context"
|
|
"errors"
|
|
"math"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type TableProcessor struct {
|
|
tableRepo *repository.TableRepository
|
|
orderRepo repository.OrderRepository
|
|
}
|
|
|
|
func NewTableProcessor(tableRepo *repository.TableRepository, orderRepo repository.OrderRepository) *TableProcessor {
|
|
return &TableProcessor{
|
|
tableRepo: tableRepo,
|
|
orderRepo: orderRepo,
|
|
}
|
|
}
|
|
|
|
func (p *TableProcessor) Create(ctx context.Context, req models.CreateTableRequest, organizationID uuid.UUID) (*models.TableResponse, error) {
|
|
table := &entities.Table{
|
|
OrganizationID: organizationID,
|
|
OutletID: req.OutletID,
|
|
TableName: req.TableName,
|
|
PositionX: req.PositionX,
|
|
PositionY: req.PositionY,
|
|
Capacity: req.Capacity,
|
|
Status: string(constants.TableStatusAvailable),
|
|
IsActive: true,
|
|
Metadata: req.Metadata,
|
|
}
|
|
|
|
err := p.tableRepo.Create(ctx, table)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.mapTableToResponse(table), nil
|
|
}
|
|
|
|
func (p *TableProcessor) GetByID(ctx context.Context, id uuid.UUID) (*models.TableResponse, error) {
|
|
table, err := p.tableRepo.GetByID(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.mapTableToResponse(table), nil
|
|
}
|
|
|
|
func (p *TableProcessor) Update(ctx context.Context, id uuid.UUID, req models.UpdateTableRequest) (*models.TableResponse, error) {
|
|
table, err := p.tableRepo.GetByID(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if req.TableName != nil {
|
|
table.TableName = *req.TableName
|
|
}
|
|
if req.Status != nil {
|
|
table.Status = string(*req.Status)
|
|
}
|
|
if req.PositionX != nil {
|
|
table.PositionX = *req.PositionX
|
|
}
|
|
if req.PositionY != nil {
|
|
table.PositionY = *req.PositionY
|
|
}
|
|
if req.Capacity != nil {
|
|
table.Capacity = *req.Capacity
|
|
}
|
|
if req.IsActive != nil {
|
|
table.IsActive = *req.IsActive
|
|
}
|
|
if req.Metadata != nil {
|
|
table.Metadata = req.Metadata
|
|
}
|
|
|
|
err = p.tableRepo.Update(ctx, table)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.mapTableToResponse(table), nil
|
|
}
|
|
|
|
func (p *TableProcessor) Delete(ctx context.Context, id uuid.UUID) error {
|
|
table, err := p.tableRepo.GetByID(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if table.IsOccupied() {
|
|
return errors.New("cannot delete occupied table")
|
|
}
|
|
|
|
return p.tableRepo.Delete(ctx, id)
|
|
}
|
|
|
|
func (p *TableProcessor) List(ctx context.Context, req models.ListTablesRequest) (*models.ListTablesResponse, error) {
|
|
tables, total, err := p.tableRepo.List(ctx, req.OrganizationID, req.OutletID, (*string)(req.Status), req.IsActive, req.Search, req.Page, req.Limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := make([]models.TableResponse, len(tables))
|
|
for i, table := range tables {
|
|
responses[i] = *p.mapTableToResponse(&table)
|
|
}
|
|
|
|
totalPages := int(math.Ceil(float64(total) / float64(req.Limit)))
|
|
|
|
return &models.ListTablesResponse{
|
|
Tables: responses,
|
|
TotalCount: int(total),
|
|
Page: req.Page,
|
|
Limit: req.Limit,
|
|
TotalPages: totalPages,
|
|
}, nil
|
|
}
|
|
|
|
func (p *TableProcessor) OccupyTable(ctx context.Context, tableID uuid.UUID, req models.OccupyTableRequest) (*models.TableResponse, error) {
|
|
table, err := p.tableRepo.GetByID(ctx, tableID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !table.CanBeOccupied() {
|
|
return nil, errors.New("table is not available for occupation")
|
|
}
|
|
|
|
// Verify order exists
|
|
_, err = p.orderRepo.GetByID(ctx, req.OrderID)
|
|
if err != nil {
|
|
return nil, errors.New("order not found")
|
|
}
|
|
|
|
err = p.tableRepo.OccupyTable(ctx, tableID, req.OrderID, &req.StartTime)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get updated table
|
|
updatedTable, err := p.tableRepo.GetByID(ctx, tableID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.mapTableToResponse(updatedTable), nil
|
|
}
|
|
|
|
func (p *TableProcessor) ReleaseTable(ctx context.Context, tableID uuid.UUID, req models.ReleaseTableRequest) (*models.TableResponse, error) {
|
|
table, err := p.tableRepo.GetByID(ctx, tableID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !table.IsOccupied() {
|
|
return nil, errors.New("table is not occupied")
|
|
}
|
|
|
|
err = p.tableRepo.ReleaseTable(ctx, tableID, req.PaymentAmount)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get updated table
|
|
updatedTable, err := p.tableRepo.GetByID(ctx, tableID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.mapTableToResponse(updatedTable), nil
|
|
}
|
|
|
|
func (p *TableProcessor) GetAvailableTables(ctx context.Context, outletID uuid.UUID) ([]models.TableResponse, error) {
|
|
tables, err := p.tableRepo.GetAvailableTables(ctx, outletID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := make([]models.TableResponse, len(tables))
|
|
for i, table := range tables {
|
|
responses[i] = *p.mapTableToResponse(&table)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func (p *TableProcessor) GetOccupiedTables(ctx context.Context, outletID uuid.UUID) ([]models.TableResponse, error) {
|
|
tables, err := p.tableRepo.GetOccupiedTables(ctx, outletID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := make([]models.TableResponse, len(tables))
|
|
for i, table := range tables {
|
|
responses[i] = *p.mapTableToResponse(&table)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func (p *TableProcessor) mapTableToResponse(table *entities.Table) *models.TableResponse {
|
|
response := &models.TableResponse{
|
|
ID: table.ID,
|
|
OrganizationID: table.OrganizationID,
|
|
OutletID: table.OutletID,
|
|
TableName: table.TableName,
|
|
StartTime: table.StartTime,
|
|
Status: constants.TableStatus(table.Status),
|
|
OrderID: table.OrderID,
|
|
PaymentAmount: table.PaymentAmount,
|
|
PositionX: table.PositionX,
|
|
PositionY: table.PositionY,
|
|
Capacity: table.Capacity,
|
|
IsActive: table.IsActive,
|
|
Metadata: table.Metadata,
|
|
CreatedAt: table.CreatedAt,
|
|
UpdatedAt: table.UpdatedAt,
|
|
}
|
|
|
|
if table.Order != nil {
|
|
response.Order = &models.OrderResponse{
|
|
ID: table.Order.ID,
|
|
OrganizationID: table.Order.OrganizationID,
|
|
OutletID: table.Order.OutletID,
|
|
UserID: table.Order.UserID,
|
|
CustomerID: table.Order.CustomerID,
|
|
OrderNumber: table.Order.OrderNumber,
|
|
TableNumber: table.Order.TableNumber,
|
|
OrderType: constants.OrderType(table.Order.OrderType),
|
|
Status: constants.OrderStatus(table.Order.Status),
|
|
Subtotal: table.Order.Subtotal,
|
|
TaxAmount: table.Order.TaxAmount,
|
|
DiscountAmount: table.Order.DiscountAmount,
|
|
TotalAmount: table.Order.TotalAmount,
|
|
TotalCost: table.Order.TotalCost,
|
|
PaymentStatus: constants.PaymentStatus(table.Order.PaymentStatus),
|
|
RefundAmount: table.Order.RefundAmount,
|
|
IsVoid: table.Order.IsVoid,
|
|
IsRefund: table.Order.IsRefund,
|
|
VoidReason: table.Order.VoidReason,
|
|
VoidedAt: table.Order.VoidedAt,
|
|
VoidedBy: table.Order.VoidedBy,
|
|
RefundReason: table.Order.RefundReason,
|
|
RefundedAt: table.Order.RefundedAt,
|
|
RefundedBy: table.Order.RefundedBy,
|
|
Metadata: table.Order.Metadata,
|
|
CreatedAt: table.Order.CreatedAt,
|
|
UpdatedAt: table.Order.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
return response
|
|
}
|