package order import ( "context" "fmt" "furtuna-be/internal/common/logger" "furtuna-be/internal/common/mycontext" "furtuna-be/internal/constants/order" "furtuna-be/internal/constants/transaction" "furtuna-be/internal/entity" "furtuna-be/internal/repository" "go.uber.org/zap" ) type OrderService struct { repo repository.Order prodRepo repository.Product studioRepo repository.Studio } func NewOrderService(repo repository.Order, prodRepo repository.Product, studioRepo repository.Studio) *OrderService { return &OrderService{ repo: repo, prodRepo: prodRepo, studioRepo: studioRepo, } } func (o *OrderService) Create(ctx mycontext.Context, req *entity.Order) error { for i, oi := range req.OrderItem { if oi.ItemType.IsProduct() { item, err := o.prodRepo.GetProductByID(ctx, oi.ItemID) if err != nil { logger.ContextLogger(ctx).Error("error when get product item", zap.Error(err)) return err } req.OrderItem[i].Price = item.Price req.OrderItem[i].CreatedBy = ctx.RequestedBy() } else if oi.ItemType.IsStudio() { //get data studio item, err := o.studioRepo.GetStudioByID(ctx, oi.ItemID) if err != nil { logger.ContextLogger(ctx).Error("error when get studio item", zap.Error(err)) return err } req.OrderItem[i].Price = item.Price req.OrderItem[i].CreatedBy = ctx.RequestedBy() } } orderDB := req.ToOrderDB() orderDB.CreatedBy = ctx.RequestedBy() orderDB.Transaction.CreatedBy = ctx.RequestedBy() //set status orderDB.Status = order.Paid orderDB.Transaction.Status = transaction.Paid orderDB, err := o.repo.CreateOrder(ctx, orderDB) if err != nil { logger.ContextLogger(ctx).Error("error when create order", zap.Error(err)) return err } return nil } func (s *OrderService) GetByID(ctx context.Context, id int64) (*entity.Order, error) { orderDB, err := s.repo.GetOrderByID(ctx, id) if err != nil { logger.ContextLogger(ctx).Error("error when get order by id", zap.Error(err)) return nil, err } return orderDB.ToOrder(), nil } func (s *OrderService) GetAll(ctx context.Context, search entity.OrderSearch) ([]*entity.Order, int, error) { orders, total, err := s.repo.GetAllOrders(ctx, search) if err != nil { logger.ContextLogger(ctx).Error("error when get all orders", zap.Error(err)) return nil, 0, err } return orders.ToOrderList(), total, nil } func (s *OrderService) GetTotalRevenue(ctx context.Context, search entity.OrderTotalRevenueSearch) (float64, int64, error) { rev, trans, err := s.repo.GetTotalRevenue(ctx, search) if err != nil { logger.ContextLogger(ctx).Error("error when get total revenue orders", zap.Error(err)) return 0, 0, err } return rev, trans, nil } func (s *OrderService) GetYearlyRevenue(ctx context.Context, year int) (entity.OrderYearlyRevenueList, error) { result, err := s.repo.GetYearlyRevenue(ctx, year) if err != nil { logger.ContextLogger(ctx).Error("error when get yearly revenue orders", zap.Error(err)) return nil, err } return result, nil } func (s *OrderService) GetBranchRevenue(ctx context.Context, req entity.OrderBranchRevenueSearch) (entity.OrderBranchRevenueList, error) { result, err := s.repo.GetBranchRevenue(ctx, req) if err != nil { logger.ContextLogger(ctx).Error("error when get branch revenue orders", zap.Error(err)) return nil, err } return result, nil } func (s *OrderService) UpdateStatus(ctx mycontext.Context, id int64, orderReq *entity.Order) (*entity.Order, error) { existingOrder, err := s.repo.GetOrderByID(ctx, id) if err != nil { return nil, err } //validate state if !existingOrder.Status.IsNew() { return nil, fmt.Errorf("Invalid order status") } if existingOrder.Status == orderReq.Status { return nil, fmt.Errorf("Order status already %s", existingOrder.Status) } existingOrder.ToUpdatedOrder(ctx.RequestedBy(), *orderReq) _, err = s.repo.UpdateOrder(ctx, existingOrder) if err != nil { logger.ContextLogger(ctx).Error("error when update user", zap.Error(err)) return nil, err } return existingOrder.ToOrder(), nil }