diff --git a/internal/http/handler/order_handler.go b/internal/http/handler/order_handler.go index fac3d6e..bc8ed6c 100644 --- a/internal/http/handler/order_handler.go +++ b/internal/http/handler/order_handler.go @@ -5,6 +5,7 @@ import ( "Ticketing/internal/http/validator" "Ticketing/internal/service" "net/http" + "errors" "github.com/labstack/echo/v4" ) @@ -19,25 +20,47 @@ func NewOrderHandler(OrderService service.OrderUsecase) *OrderHandler { // func untuk create order func (h *OrderHandler) CreateOrder(ctx echo.Context) error { - var input struct { - TicketID int64 `json:"ticket_id" validate:"required"` - Quantity int64 `json:"quantity" validate:"required"` - UserID int64 `json:"user_id" validate:"required"` - Status string `json:"status" validate:"required"` - - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - order := entity.NewOrder(input.TicketID, input.Quantity, input.UserID, input.Status) - err := h.OrderService.CreateOrder(ctx.Request().Context(), order) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - return ctx.JSON(http.StatusCreated, "Order created successfully") - + var input struct { + TicketID int64 `json:"ticket_id" validate:"required"` + Quantity int64 `json:"quantity" validate:"required"` + UserID int64 `json:"user_id" validate:"required"` + Status string `json:"status" validate:"required"` + } + + if err := ctx.Bind(&input); err != nil { + return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) + } + + // Mendapatkan informasi saldo pengguna sebelum membuat pesanan + userBalance, err := h.OrderService.GetUserBalance(ctx.Request().Context(), input.UserID) + if err != nil { + return ctx.JSON(http.StatusUnprocessableEntity, err) + } + + // Mengambil informasi tiket dari TicketService untuk mendapatkan harga tiket + ticketPrice, err := h.OrderService.GetTicketPrice(ctx.Request().Context(), input.TicketID) + if err != nil { + return ctx.JSON(http.StatusUnprocessableEntity, err) + } + + // Memeriksa apakah saldo cukup untuk membuat pesanan + if userBalance < (input.Quantity * ticketPrice) { + return ctx.JSON(http.StatusUnprocessableEntity, errors.New("insufficient balance")) + } + + order := entity.NewOrder(input.TicketID, input.Quantity, input.UserID, input.Status) + err = h.OrderService.CreateOrder(ctx.Request().Context(), order) + if err != nil { + return ctx.JSON(http.StatusUnprocessableEntity, err) + } + + // Mengurangkan saldo pengguna setelah membuat pesanan + err = h.OrderService.UpdateUserBalance(ctx.Request().Context(), input.UserID, input.Quantity*ticketPrice) + if err != nil { + return ctx.JSON(http.StatusUnprocessableEntity, err) + } + + return ctx.JSON(http.StatusCreated, "Order created successfully") } // Get All Order diff --git a/internal/repository/order_repository.go b/internal/repository/order_repository.go index e3e804e..0d9c2c6 100644 --- a/internal/repository/order_repository.go +++ b/internal/repository/order_repository.go @@ -4,7 +4,7 @@ import ( "Ticketing/entity" "context" "gorm.io/gorm" - // "errors" + "errors" ) type OrderRepository struct { @@ -74,20 +74,40 @@ func (r *OrderRepository) GetOrderByUserID(ctx context.Context, userID int64) ([ } //UpdateUserBalance -// func (r *OrderRepository) UpdateUserBalance(ctx context.Context, userID int64, total int64) error { -// user := new(entity.User) -// if err := r.db.WithContext(ctx).Where("id = ?", userID).First(user).Error; err != nil { -// return err -// } - -// if user.Saldo < total { -// return errors.New("insufficient balance") -// } - -// user.Saldo -= total -// if err := r.db.WithContext(ctx).Model(&entity.User{}).Where("id = ?", userID).Updates(user).Error; err != nil { -// return err -// } - -// return nil -// } \ No newline at end of file +func (r *OrderRepository) UpdateUserBalance(ctx context.Context, userID int64, total int64) error { + user := new(entity.User) + if err := r.db.WithContext(ctx).Where("id = ?", userID).First(user).Error; err != nil { + return err + } + + if user.Saldo < total { + return errors.New("insufficient balance") + } + + user.Saldo -= total + if err := r.db.WithContext(ctx).Model(&entity.User{}).Where("id = ?", userID).Updates(user).Error; err != nil { + return err + } + + return nil +} + +// get user balance +func (r *OrderRepository) GetUserBalance(ctx context.Context, userID int64) (int64, error) { + user := new(entity.User) + if err := r.db.WithContext(ctx).Where("id = ?", userID).First(user).Error; err != nil { + return 0, err + } + + return user.Saldo, nil +} + +// GetTicketPrice +func (r *OrderRepository) GetTicketPrice(ctx context.Context, ticketID int64) (int64, error) { + ticket := new(entity.Ticket) + if err := r.db.WithContext(ctx).Where("id = ?", ticketID).First(ticket).Error; err != nil { + return 0, err + } + + return int64(ticket.Price), nil +} \ No newline at end of file diff --git a/internal/service/order_service.go b/internal/service/order_service.go index df60b66..1d1af6a 100644 --- a/internal/service/order_service.go +++ b/internal/service/order_service.go @@ -13,7 +13,9 @@ type OrderUsecase interface { GetOrders(ctx context.Context) ([]*entity.Order, error) GetTicketByID(ctx context.Context, id int64) (*entity.Ticket, error) GetOrderByUserID(ctx context.Context, userID int64) ([]*entity.Order, error) - // UpdateUserBalance(ctx context.Context, userID int64, amount int64) error + UpdateUserBalance(ctx context.Context, userID int64, amount int64) error + GetUserBalance(ctx context.Context, userID int64) (int64, error) + GetTicketPrice(ctx context.Context, ticketID int64) (int64, error) } type OrderRepository interface { @@ -23,7 +25,9 @@ type OrderRepository interface { GetOrders(ctx context.Context) ([]*entity.Order, error) GetTicketByID(ctx context.Context, id int64) (*entity.Ticket, error) GetOrderByUserID(ctx context.Context, userID int64) ([]*entity.Order, error) - // UpdateUserBalance(ctx context.Context, userID int64, amount int64) error + UpdateUserBalance(ctx context.Context, userID int64, amount int64) error + GetUserBalance(ctx context.Context, userID int64) (int64, error) + GetTicketPrice(ctx context.Context, ticketID int64) (int64, error) } type OrderService struct { @@ -34,43 +38,42 @@ func NewOrderService(repository OrderRepository) *OrderService { return &OrderService{repository} } +// Updated CreateOrder method in OrderService to receive TicketService func (s *OrderService) CreateOrder(ctx context.Context, order *entity.Order) error { - // Mendapatkan informasi tiket berdasarkan ID tiket dalam pesanan - ticket, err := s.repository.GetTicket(ctx, order.TicketID) - if err != nil { - return err - } - - // Memeriksa ketersediaan tiket - if int64(ticket.Quota) < order.Quantity { - return errors.New("ticket is not available") - } - - // Melakukan perhitungan total harga pesanan - order.Total = ticket.Price * int64(order.Quantity) - - // Membuat pesanan - if err := s.repository.CreateOrder(ctx, order); err != nil { - return err - } - - // Mengurangi ketersediaan tiket - ticket.Quota -= order.Quantity - if err := s.repository.UpdateTicket(ctx, ticket); err != nil { - return err - } - - // Mengurangi saldo pengguna - // if err := s.repository.UpdateUserBalance(ctx, order.UserID, order.Total); err != nil { - // return err - // } - // Contoh: Mengupdate informasi pengguna setelah melakukan pembelian - // Anda dapat menyesuaikan logika ini sesuai dengan kebutuhan - // ... - - return nil + // Mendapatkan informasi tiket berdasarkan ID tiket dalam pesanan + ticket, err := s.repository.GetTicket(ctx, order.TicketID) + if err != nil { + return err + } + + // Memeriksa ketersediaan tiket + if int64(ticket.Quota) < order.Quantity { + return errors.New("ticket is not available") + } + + // Melakukan perhitungan total harga pesanan + order.Total = ticket.Price * int64(order.Quantity) + + // Membuat pesanan + if err := s.repository.CreateOrder(ctx, order); err != nil { + return err + } + + // Mengurangi ketersediaan tiket + ticket.Quota -= order.Quantity + if err := s.repository.UpdateTicket(ctx, ticket); err != nil { + return err + } + + // Mengurangi saldo pengguna + if err := s.repository.UpdateUserBalance(ctx, order.UserID, order.Total); err != nil { + return err + } + + return nil } + // Implementasi fungsi GetTicket func (s *OrderService) GetTicket(ctx context.Context, ticketID int64) (*entity.Ticket, error) { return s.repository.GetTicket(ctx, ticketID) @@ -82,8 +85,9 @@ func (s *OrderService) UpdateTicket(ctx context.Context, ticket *entity.Ticket) } // implementasi fungsi update user balance -// func (s *OrderService) UpdateUserBalance(ctx context.Context, userID int64, amount int64) error { -// return s.repository.UpdateUserBalance(ctx, userID, amount) +func (s *OrderService) UpdateUserBalance(ctx context.Context, userID int64, saldo int64) error { + return s.repository.UpdateUserBalance(ctx, userID, saldo) +} func (s *OrderService) GetOrders(ctx context.Context) ([]*entity.Order, error) { return s.repository.GetOrders(ctx) @@ -97,3 +101,17 @@ func (s *OrderService) GetTicketByID(ctx context.Context, id int64) (*entity.Tic func (s *OrderService) GetOrderByUserID(ctx context.Context, userID int64) ([]*entity.Order, error) { return s.repository.GetOrderByUserID(ctx, userID) } + +// get user balance +func (s *OrderService) GetUserBalance(ctx context.Context, userID int64) (int64, error) { + return s.repository.GetUserBalance(ctx, userID) +} + +// GetTicketPrice +func (s *OrderService) GetTicketPrice(ctx context.Context, ticketID int64) (int64, error) { + ticket, err := s.repository.GetTicket(ctx, ticketID) + if err != nil { + return 0, err + } + return int64(ticket.Price), nil +}