168 lines
5.2 KiB
Go
168 lines
5.2 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"apskel-pos-be/internal/entities"
|
|
"apskel-pos-be/internal/mappers"
|
|
"apskel-pos-be/internal/models"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type ExpenseProcessor interface {
|
|
CreateExpense(ctx context.Context, organizationID uuid.UUID, req *models.CreateExpenseRequest) (*models.ExpenseResponse, error)
|
|
UpdateExpense(ctx context.Context, id, organizationID uuid.UUID, req *models.UpdateExpenseRequest) (*models.ExpenseResponse, error)
|
|
DeleteExpense(ctx context.Context, id, organizationID uuid.UUID) error
|
|
GetExpenseByID(ctx context.Context, id, organizationID uuid.UUID) (*models.ExpenseResponse, error)
|
|
ListExpenses(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, page, limit int) ([]*models.ExpenseResponse, int, error)
|
|
}
|
|
|
|
type ExpenseProcessorImpl struct {
|
|
expenseRepo ExpenseRepository
|
|
}
|
|
|
|
func NewExpenseProcessorImpl(expenseRepo ExpenseRepository) *ExpenseProcessorImpl {
|
|
return &ExpenseProcessorImpl{
|
|
expenseRepo: expenseRepo,
|
|
}
|
|
}
|
|
|
|
func (p *ExpenseProcessorImpl) CreateExpense(ctx context.Context, organizationID uuid.UUID, req *models.CreateExpenseRequest) (*models.ExpenseResponse, error) {
|
|
chartOfAccountID, err := uuid.Parse(req.ChartOfAccountID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid chart_of_account_id: %w", err)
|
|
}
|
|
|
|
outletID, err := uuid.Parse(req.OutletID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid outlet_id: %w", err)
|
|
}
|
|
|
|
transactionDate, err := time.Parse("2006-01-02", req.TransactionDate)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid transaction_date format, expected YYYY-MM-DD: %w", err)
|
|
}
|
|
|
|
expenseEntity := &entities.Expense{
|
|
OrganizationID: organizationID,
|
|
OutletID: outletID,
|
|
Receiver: req.Receiver,
|
|
TransactionDate: transactionDate,
|
|
CodeNumber: req.CodeNumber,
|
|
ChartOfAccountID: chartOfAccountID,
|
|
Description: req.Description,
|
|
Tax: req.Tax,
|
|
Total: req.Total,
|
|
}
|
|
|
|
err = p.expenseRepo.Create(ctx, expenseEntity)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create expense: %w", err)
|
|
}
|
|
|
|
created, err := p.expenseRepo.GetByID(ctx, expenseEntity.ID)
|
|
if err != nil {
|
|
return mappers.ExpenseEntityToResponse(expenseEntity), nil
|
|
}
|
|
|
|
return mappers.ExpenseEntityToResponse(created), nil
|
|
}
|
|
|
|
func (p *ExpenseProcessorImpl) UpdateExpense(ctx context.Context, id, organizationID uuid.UUID, req *models.UpdateExpenseRequest) (*models.ExpenseResponse, error) {
|
|
expenseEntity, err := p.expenseRepo.GetByIDAndOrganizationID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("expense not found: %w", err)
|
|
}
|
|
|
|
if req.Receiver != nil {
|
|
expenseEntity.Receiver = *req.Receiver
|
|
}
|
|
if req.TransactionDate != nil {
|
|
parsedDate, err := time.Parse("2006-01-02", *req.TransactionDate)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid transaction_date format, expected YYYY-MM-DD: %w", err)
|
|
}
|
|
expenseEntity.TransactionDate = parsedDate
|
|
}
|
|
if req.CodeNumber != nil {
|
|
expenseEntity.CodeNumber = *req.CodeNumber
|
|
}
|
|
if req.ChartOfAccountID != nil {
|
|
chartOfAccountID, err := uuid.Parse(*req.ChartOfAccountID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid chart_of_account_id: %w", err)
|
|
}
|
|
expenseEntity.ChartOfAccountID = chartOfAccountID
|
|
}
|
|
if req.OutletID != nil {
|
|
outletID, err := uuid.Parse(*req.OutletID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid outlet_id: %w", err)
|
|
}
|
|
expenseEntity.OutletID = outletID
|
|
}
|
|
if req.Description != nil {
|
|
expenseEntity.Description = req.Description
|
|
}
|
|
if req.Tax != nil {
|
|
expenseEntity.Tax = *req.Tax
|
|
}
|
|
if req.Total != nil {
|
|
expenseEntity.Total = *req.Total
|
|
}
|
|
if req.Reserved1 != nil {
|
|
expenseEntity.Reserved1 = req.Reserved1
|
|
}
|
|
|
|
err = p.expenseRepo.Update(ctx, expenseEntity)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to update expense: %w", err)
|
|
}
|
|
|
|
updated, err := p.expenseRepo.GetByID(ctx, id)
|
|
if err != nil {
|
|
return mappers.ExpenseEntityToResponse(expenseEntity), nil
|
|
}
|
|
|
|
return mappers.ExpenseEntityToResponse(updated), nil
|
|
}
|
|
|
|
func (p *ExpenseProcessorImpl) DeleteExpense(ctx context.Context, id, organizationID uuid.UUID) error {
|
|
_, err := p.expenseRepo.GetByIDAndOrganizationID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return fmt.Errorf("expense not found: %w", err)
|
|
}
|
|
|
|
err = p.expenseRepo.Delete(ctx, id)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete expense: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *ExpenseProcessorImpl) GetExpenseByID(ctx context.Context, id, organizationID uuid.UUID) (*models.ExpenseResponse, error) {
|
|
expenseEntity, err := p.expenseRepo.GetByIDAndOrganizationID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("expense not found: %w", err)
|
|
}
|
|
|
|
return mappers.ExpenseEntityToResponse(expenseEntity), nil
|
|
}
|
|
|
|
func (p *ExpenseProcessorImpl) ListExpenses(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, page, limit int) ([]*models.ExpenseResponse, int, error) {
|
|
offset := (page - 1) * limit
|
|
expenseEntities, total, err := p.expenseRepo.List(ctx, organizationID, filters, limit, offset)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("failed to list expenses: %w", err)
|
|
}
|
|
|
|
expenseResponses := mappers.ExpenseEntitiesToResponses(expenseEntities)
|
|
totalPages := int((total + int64(limit) - 1) / int64(limit))
|
|
|
|
return expenseResponses, totalPages, nil
|
|
}
|