Add refund order
This commit is contained in:
parent
58d3b32c40
commit
ebb33186b8
27
internal/entity/casheer_session.go
Normal file
27
internal/entity/casheer_session.go
Normal file
@ -0,0 +1,27 @@
|
||||
package entity
|
||||
|
||||
import "time"
|
||||
|
||||
type CashierSession struct {
|
||||
ID int64
|
||||
CashierID int64
|
||||
OpenedAt time.Time
|
||||
ClosedAt *time.Time
|
||||
OpeningAmount float64
|
||||
ClosingAmount *float64
|
||||
ExpectedAmount *float64
|
||||
Status string
|
||||
}
|
||||
|
||||
type PaymentSummary struct {
|
||||
PaymentType string
|
||||
PaymentProvider string
|
||||
TotalAmount float64
|
||||
}
|
||||
|
||||
type CashierSessionReport struct {
|
||||
SessionID int64
|
||||
ExpectedAmount float64
|
||||
ClosingAmount float64
|
||||
Payments []PaymentSummary
|
||||
}
|
||||
9
internal/entity/category.go
Normal file
9
internal/entity/category.go
Normal file
@ -0,0 +1,9 @@
|
||||
package entity
|
||||
|
||||
type Category struct {
|
||||
ID int64
|
||||
PartnerID int64
|
||||
Name string
|
||||
CreatedAt int64
|
||||
UpdatedAt int64
|
||||
}
|
||||
@ -26,6 +26,7 @@ type Order struct {
|
||||
User User `gorm:"foreignKey:CreatedBy;constraint:OnDelete:CASCADE;"`
|
||||
Source string `gorm:"type:varchar;column:source"`
|
||||
OrderType string `gorm:"type:varchar;column:order_type"`
|
||||
CashierSessionID int64 `gorm:"type:varchar;column:cashier_session_id"`
|
||||
TableNumber string
|
||||
InProgressOrderID int64
|
||||
}
|
||||
@ -113,6 +114,7 @@ type OrderRequest struct {
|
||||
PaymentProvider string
|
||||
OrderType string
|
||||
ID int64
|
||||
CashierSessionID int64
|
||||
}
|
||||
|
||||
type OrderItemRequest struct {
|
||||
|
||||
@ -26,6 +26,7 @@ type OrderInquiry struct {
|
||||
PaymentProvider string `json:"payment_provider"`
|
||||
TableNumber string `json:"table_number"`
|
||||
OrderType string `json:"order_type"`
|
||||
CashierSessionID int64 `json:"cashier_session_id"`
|
||||
}
|
||||
|
||||
type OrderCalculation struct {
|
||||
@ -54,6 +55,7 @@ func NewOrderInquiry(
|
||||
paymentProvider string,
|
||||
tableNumber string,
|
||||
orderType string,
|
||||
cashierSessionID int64,
|
||||
) *OrderInquiry {
|
||||
return &OrderInquiry{
|
||||
ID: constants.GenerateUUID(),
|
||||
@ -75,6 +77,7 @@ func NewOrderInquiry(
|
||||
PaymentProvider: paymentProvider,
|
||||
TableNumber: tableNumber,
|
||||
OrderType: orderType,
|
||||
CashierSessionID: cashierSessionID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,22 +98,23 @@ func (i *OrderInquiry) ToOrder(paymentMethod, paymentProvider string) *Order {
|
||||
now := time.Now()
|
||||
|
||||
order := &Order{
|
||||
PartnerID: i.PartnerID,
|
||||
CustomerID: &i.CustomerID,
|
||||
InquiryID: &i.ID,
|
||||
Status: constants.StatusPaid,
|
||||
Amount: i.Amount,
|
||||
Tax: i.Tax,
|
||||
Total: i.Total,
|
||||
PaymentType: paymentMethod,
|
||||
PaymentProvider: paymentProvider,
|
||||
Source: i.Source,
|
||||
CreatedBy: i.CreatedBy,
|
||||
CreatedAt: now,
|
||||
OrderItems: make([]OrderItem, len(i.OrderItems)),
|
||||
OrderType: i.OrderType,
|
||||
CustomerName: i.CustomerName,
|
||||
TableNumber: i.TableNumber,
|
||||
PartnerID: i.PartnerID,
|
||||
CustomerID: &i.CustomerID,
|
||||
InquiryID: &i.ID,
|
||||
Status: constants.StatusPaid,
|
||||
Amount: i.Amount,
|
||||
Tax: i.Tax,
|
||||
Total: i.Total,
|
||||
PaymentType: paymentMethod,
|
||||
PaymentProvider: paymentProvider,
|
||||
Source: i.Source,
|
||||
CreatedBy: i.CreatedBy,
|
||||
CreatedAt: now,
|
||||
OrderItems: make([]OrderItem, len(i.OrderItems)),
|
||||
OrderType: i.OrderType,
|
||||
CustomerName: i.CustomerName,
|
||||
TableNumber: i.TableNumber,
|
||||
CashierSessionID: i.CashierSessionID,
|
||||
}
|
||||
|
||||
for idx, item := range i.OrderItems {
|
||||
|
||||
@ -2,23 +2,26 @@ package entity
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/constants/product"
|
||||
"enaklo-pos-be/internal/repository/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Product struct {
|
||||
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||
PartnerID int64 `gorm:"type:int;column:partner_id"`
|
||||
Name string `gorm:"type:varchar(255);not null;column:name"`
|
||||
Type string `gorm:"type:varchar;column:type"`
|
||||
Price float64 `gorm:"type:decimal;column:price"`
|
||||
Status string `gorm:"type:varchar;column:status"`
|
||||
Description string `gorm:"type:varchar(255);not null;column:description"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||
DeletedAt *time.Time `gorm:"column:deleted_at"`
|
||||
CreatedBy int64 `gorm:"type:int;column:created_by"`
|
||||
UpdatedBy int64 `gorm:"type:int;column:updated_by"`
|
||||
Image string `gorm:"type:varchar;column:image"`
|
||||
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||
PartnerID int64 `gorm:"type:int;column:partner_id"`
|
||||
Name string `gorm:"type:varchar(255);not null;column:name"`
|
||||
Type string `gorm:"type:varchar;column:type"`
|
||||
Price float64 `gorm:"type:decimal;column:price"`
|
||||
Status string `gorm:"type:varchar;column:status"`
|
||||
Description string `gorm:"type:varchar(255);not null;column:description"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||
DeletedAt *time.Time `gorm:"column:deleted_at"`
|
||||
CreatedBy int64 `gorm:"type:int;column:created_by"`
|
||||
UpdatedBy int64 `gorm:"type:int;column:updated_by"`
|
||||
Image string `gorm:"type:varchar;column:image"`
|
||||
CategoryID *int64 `gorm:"column:category_id"`
|
||||
Category *models.CategoryDB `gorm:"foreignKey:CategoryID;references:ID"`
|
||||
}
|
||||
|
||||
func (Product) TableName() string {
|
||||
@ -26,14 +29,15 @@ func (Product) TableName() string {
|
||||
}
|
||||
|
||||
type ProductSearch struct {
|
||||
Search string
|
||||
Name string
|
||||
Type product.ProductType
|
||||
BranchID int64
|
||||
PartnerID int64
|
||||
Available product.ProductStock
|
||||
Limit int
|
||||
Offset int
|
||||
Search string
|
||||
Name string
|
||||
Type product.ProductType
|
||||
BranchID int64
|
||||
PartnerID int64
|
||||
Available product.ProductStock
|
||||
Limit int
|
||||
Offset int
|
||||
CategoryID int64
|
||||
}
|
||||
|
||||
type ProductPOS struct {
|
||||
@ -72,6 +76,8 @@ func (e *ProductDB) ToProduct() *Product {
|
||||
CreatedBy: e.CreatedBy,
|
||||
UpdatedBy: e.UpdatedBy,
|
||||
Image: e.Image,
|
||||
Category: e.Category,
|
||||
CategoryID: e.CategoryID,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
123
internal/handlers/http/cashier.go
Normal file
123
internal/handlers/http/cashier.go
Normal file
@ -0,0 +1,123 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services/v2/cashier_session"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type CashierSessionHandler struct {
|
||||
service cashier_session.Service
|
||||
}
|
||||
|
||||
func NewCashierSession(service cashier_session.Service) *CashierSessionHandler {
|
||||
return &CashierSessionHandler{service: service}
|
||||
}
|
||||
|
||||
func (h *CashierSessionHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/cashier-sessions")
|
||||
route.Use(jwt)
|
||||
|
||||
route.POST("/open", h.OpenSession)
|
||||
route.POST("/close/:id", h.CloseSession)
|
||||
route.GET("/open", h.GetOpenSession)
|
||||
route.GET("/report/:id", h.GetSessionReport)
|
||||
}
|
||||
|
||||
func (h *CashierSessionHandler) OpenSession(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.OpenCashierSessionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
session, err := h.service.OpenSession(ctx, req.ToEntity(ctx.RequestedBy()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCashierSessionResponse(session),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CashierSessionHandler) CloseSession(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
idStr := c.Param("id")
|
||||
sessionID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var body struct {
|
||||
ClosingAmount float64 `json:"closing_amount"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
report, err := h.service.CloseSession(ctx, sessionID, body.ClosingAmount)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCashierSessionReport(report),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CashierSessionHandler) GetOpenSession(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
cashierID := ctx.RequestedBy()
|
||||
|
||||
session, err := h.service.GetOpenSession(ctx, cashierID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCashierSessionResponse(session),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CashierSessionHandler) GetSessionReport(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
idStr := c.Param("id")
|
||||
|
||||
sessionID, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
report, err := h.service.GetSessionReport(ctx, sessionID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCashierSessionReport(report),
|
||||
})
|
||||
}
|
||||
139
internal/handlers/http/categories.go
Normal file
139
internal/handlers/http/categories.go
Normal file
@ -0,0 +1,139 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
category "enaklo-pos-be/internal/services/v2/categories"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type CategoryHandler struct {
|
||||
service category.Service
|
||||
}
|
||||
|
||||
func NewCategoryHandler(service category.Service) *CategoryHandler {
|
||||
return &CategoryHandler{service: service}
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/categories")
|
||||
route.Use(jwt)
|
||||
|
||||
route.POST("/create", h.Create)
|
||||
route.GET("/list", h.GetByPartner)
|
||||
route.GET("/:id", h.GetByID)
|
||||
route.PUT("/:id", h.Update)
|
||||
route.DELETE("/:id", h.Delete)
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) Create(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.CategoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
category, err := h.service.Create(ctx, req.ToEntity(ctx.RequestedBy()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCategoryResponse(category),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) GetByPartner(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
categories, err := h.service.GetByPartnerID(ctx, ctx.RequestedBy())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCategoryListResponse(categories),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) GetByID(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
category, err := h.service.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.MapToCategoryResponse(category),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) Update(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req request.CategoryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
category := req.ToEntity(ctx.RequestedBy())
|
||||
category.ID = id
|
||||
|
||||
if err := h.service.Update(ctx, category); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *CategoryHandler) Delete(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(ctx, id); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
@ -1,268 +0,0 @@
|
||||
package customerorder
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service services.Order
|
||||
}
|
||||
|
||||
func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/order")
|
||||
|
||||
route.POST("/inquiry", h.Inquiry)
|
||||
route.POST("/execute", jwt, h.Execute)
|
||||
route.GET("/history", jwt, h.History)
|
||||
route.GET("/detail", jwt, h.Detail)
|
||||
}
|
||||
|
||||
func NewHandler(service services.Order) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) Inquiry(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.CustomerOrder
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := request.ValidateAndHandleError(req); err != nil {
|
||||
response.ErrorWrapper(c, errors.NewErrorMessage(errors.ErrorBadRequest, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
order, err := h.service.CreateOrder(ctx, req.ToEntity(ctx.RequestedBy()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToCreateOrderResponse(order, req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Execute(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.Execute
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
order, err := h.service.Execute(ctx, req.ToOrderExecuteRequest(ctx.RequestedBy()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToExecuteOrderResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
func MapOrderToCreateOrderResponse(orderResponse *entity.OrderResponse, req request.CustomerOrder) response.CreateOrderResponse {
|
||||
order := orderResponse.Order
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.CreateOrderResponse{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
PaymentType: order.PaymentType,
|
||||
CreatedAt: order.CreatedAt,
|
||||
OrderItems: orderItems,
|
||||
Tax: order.Tax,
|
||||
Total: order.Total,
|
||||
}
|
||||
}
|
||||
|
||||
func MapOrderToExecuteOrderResponse(orderResponse *entity.ExecuteOrderResponse) response.ExecuteOrderResponse {
|
||||
order := orderResponse.Order
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.ExecuteOrderResponse{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
PaymentType: order.PaymentType,
|
||||
CreatedAt: order.CreatedAt,
|
||||
OrderItems: orderItems,
|
||||
PaymentToken: orderResponse.PaymentToken,
|
||||
RedirectURL: orderResponse.RedirectURL,
|
||||
QRcode: orderResponse.QRCode,
|
||||
VirtualAccount: orderResponse.VirtualAccount,
|
||||
BankName: orderResponse.BankName,
|
||||
BankCode: orderResponse.BankCode,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) toHistoryOrderResponse(resp *entity.HistoryOrder) response.HistoryOrder {
|
||||
return response.HistoryOrder{
|
||||
ID: resp.ID,
|
||||
Employee: resp.Employee,
|
||||
Site: resp.Site,
|
||||
Timestamp: resp.Timestamp.Format(time.RFC3339),
|
||||
BookingTime: resp.BookingTime.Format(time.RFC3339),
|
||||
Tickets: resp.Tickets,
|
||||
PaymentType: resp.PaymentType,
|
||||
Status: resp.GetPaymentStatus(),
|
||||
Amount: resp.Amount,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) toHistoryOrderList(resp []*entity.HistoryOrder, total int64, req request.OrderParamCustomer) response.HistoryOrderList {
|
||||
var orders []response.HistoryOrder
|
||||
for _, b := range resp {
|
||||
orders = append(orders, h.toHistoryOrderResponse(b))
|
||||
}
|
||||
|
||||
return response.HistoryOrderList{
|
||||
Orders: orders,
|
||||
Total: total,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) History(c *gin.Context) {
|
||||
var req request.OrderParamCustomer
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
orders, total, err := h.service.GetAllHistoryOrders(ctx, req.ToOrderEntity(ctx))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toHistoryOrderList(orders, int64(total), req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Detail(c *gin.Context) {
|
||||
var req request.OrderParamCustomer
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
order, err := h.service.GetByID(ctx, req.ID, req.ReferenceID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toOrderDetail(order),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) toOrderDetail(order *entity.Order) *response.OrderDetail {
|
||||
if order == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
payment := map[string]string{}
|
||||
paymentLink := ""
|
||||
paymentToken := ""
|
||||
|
||||
if order.Payment.RequestMetadata != nil && order.Status != "EXPIRED" {
|
||||
json.Unmarshal(order.Payment.RequestMetadata, &payment)
|
||||
paymentLink = payment["payment_redirect_url"]
|
||||
paymentToken = payment["payment_token"]
|
||||
}
|
||||
|
||||
qrCode := ""
|
||||
|
||||
var siteName string
|
||||
|
||||
if order.Site != nil {
|
||||
siteName = order.Site.Name
|
||||
}
|
||||
|
||||
orderDetail := &response.OrderDetail{
|
||||
ID: order.ID,
|
||||
QRCode: qrCode,
|
||||
FullName: order.User.Name,
|
||||
Email: order.User.Email,
|
||||
PhoneNumber: order.User.PhoneNumber,
|
||||
TotalAmount: order.Total,
|
||||
CreatedAt: order.CreatedAt,
|
||||
Status: order.Status,
|
||||
PaymentLink: paymentLink,
|
||||
PaymentToken: paymentToken,
|
||||
SiteName: siteName,
|
||||
Fee: order.Tax,
|
||||
}
|
||||
|
||||
orderDetail.OrderItems = make([]response.OrderDetailItem, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderDetail.OrderItems[i] = response.OrderDetailItem{
|
||||
Name: item.Product.Name,
|
||||
ItemType: item.ItemType,
|
||||
Description: "",
|
||||
Quantity: int(item.Quantity),
|
||||
UnitPrice: item.Price,
|
||||
TotalPrice: float64(item.Quantity) * item.Price,
|
||||
}
|
||||
}
|
||||
|
||||
return orderDetail
|
||||
}
|
||||
@ -1,229 +0,0 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service services.DiscoverService
|
||||
}
|
||||
|
||||
func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/discovery")
|
||||
|
||||
route.GET("/home", h.DisoveryHome)
|
||||
route.GET("/search", h.DisoverySearch)
|
||||
route.GET("/site/detail", h.DiscoveryGetByID)
|
||||
route.GET("/site/products", h.DiscoveryProducts)
|
||||
|
||||
}
|
||||
|
||||
func NewHandler(service services.DiscoverService) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) DisoveryHome(c *gin.Context) {
|
||||
var req request.DiscoveryHomeParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.Home(c.Request.Context(), req.ToEntity())
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: ConvertEntityToResponse(res),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) DisoverySearch(c *gin.Context) {
|
||||
var req request.DiscoveryHomeParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, total, err := h.service.Search(c.Request.Context(), req.ToEntity())
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: ConvertEntityToSearchResponse(res, total, req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) DiscoveryGetByID(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.DiscoverySearchByID
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.GetByID(ctx, req.ID)
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: ConvertEntityToGetByIDResp(res),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) DiscoveryProducts(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.DiscoverySearchByID
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.GetProductsByID(ctx, req.ID)
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: ConvertToProductResp(res),
|
||||
})
|
||||
}
|
||||
|
||||
func ConvertEntityToResponse(entityResp *entity.DiscoverySearchResp) *response.ExploreResponse {
|
||||
// Convert ExploreRegions
|
||||
exploreRegions := make([]response.Region, len(entityResp.ExploreRegions))
|
||||
for i, region := range entityResp.ExploreRegions {
|
||||
exploreRegions[i] = response.Region{
|
||||
Name: region.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert ExploreDestinations
|
||||
exploreDestinations := make([]response.Destination, len(entityResp.ExploreDestinations))
|
||||
for i, destination := range entityResp.ExploreDestinations {
|
||||
exploreDestinations[i] = response.Destination{
|
||||
Name: destination.Name,
|
||||
ImageURL: destination.ImageURL,
|
||||
}
|
||||
}
|
||||
|
||||
mustVisit := make([]response.MustVisit, len(entityResp.MustVisit))
|
||||
for i, mv := range entityResp.MustVisit {
|
||||
mustVisit[i] = response.MustVisit{
|
||||
Name: mv.Name,
|
||||
Region: mv.Region,
|
||||
Rating: mv.Rating,
|
||||
ReviewCount: mv.ReviewCount,
|
||||
Price: mv.Price,
|
||||
ImageURL: mv.ImageURL,
|
||||
SiteID: mv.SiteID,
|
||||
Regency: mv.Regency,
|
||||
}
|
||||
}
|
||||
|
||||
return &response.ExploreResponse{
|
||||
ExploreRegions: exploreRegions,
|
||||
ExploreDestinations: exploreDestinations,
|
||||
MustVisit: mustVisit,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertEntityToSearchResponse(entityResp *entity.DiscoverySearchResp, total int64, req request.DiscoveryHomeParam) *response.SearchResponse {
|
||||
data := make([]response.SiteSeach, len(entityResp.MustVisit))
|
||||
for i, mv := range entityResp.MustVisit {
|
||||
data[i] = response.SiteSeach{
|
||||
Name: mv.Name,
|
||||
Region: mv.Region,
|
||||
Rating: mv.Rating,
|
||||
ReviewCount: mv.ReviewCount,
|
||||
Price: mv.Price,
|
||||
ImageURL: mv.ImageURL,
|
||||
SiteID: mv.SiteID,
|
||||
Regency: mv.Regency,
|
||||
}
|
||||
}
|
||||
|
||||
return &response.SearchResponse{
|
||||
Data: data,
|
||||
Total: int(total),
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertEntityToGetByIDResp(resp *entity.Site) *response.SearchSiteByIDResponse {
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &response.SearchSiteByIDResponse{
|
||||
ID: resp.ID,
|
||||
Name: resp.Name,
|
||||
Image: resp.Image,
|
||||
Address: resp.Address,
|
||||
LocationLink: resp.LocationLink,
|
||||
Description: resp.Description,
|
||||
Highlight: resp.Highlight,
|
||||
ContactPerson: resp.ContactPerson,
|
||||
TnC: resp.TnC,
|
||||
AdditionalInfo: resp.AdditionalInfo,
|
||||
PartnerID: resp.PartnerID,
|
||||
Regency: resp.Regency,
|
||||
Region: resp.Region,
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertToProductResp(resp []*entity.Product) *response.SearchProductSiteResponse {
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var productResp []response.SearchProductSiteByIDResponse
|
||||
|
||||
partnerID := int64(0)
|
||||
for _, res := range resp {
|
||||
productResp = append(productResp, response.SearchProductSiteByIDResponse{
|
||||
ID: res.ID,
|
||||
Name: res.Name,
|
||||
Price: res.Price,
|
||||
Description: res.Description,
|
||||
Type: res.Type,
|
||||
})
|
||||
|
||||
partnerID = res.PartnerID
|
||||
}
|
||||
|
||||
return &response.SearchProductSiteResponse{
|
||||
Product: productResp,
|
||||
PartnerID: partnerID,
|
||||
}
|
||||
}
|
||||
@ -1,205 +0,0 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service services.Event
|
||||
}
|
||||
|
||||
func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/event")
|
||||
|
||||
route.POST("/", jwt, h.Create)
|
||||
route.GET("/list", jwt, h.GetAll)
|
||||
route.PUT("/:id", jwt, h.Update)
|
||||
route.GET("/:id", jwt, h.GetByID)
|
||||
route.DELETE("/:id", jwt, h.Delete)
|
||||
}
|
||||
|
||||
func NewHandler(service services.Event) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req request.Event
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := req.Validate(); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorInvalidRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.Create(c.Request.Context(), req.ToEntity())
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toEventResponse(res),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
eventID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req request.Event
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := req.Validate(); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
updatedEvent, err := h.service.Update(c.Request.Context(), eventID, req.ToEntity())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toEventResponse(updatedEvent),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetAll(c *gin.Context) {
|
||||
var req request.EventParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
events, total, err := h.service.GetAll(c.Request.Context(), req.ToEntity())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toEventResponseList(events, int64(total), req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// Parse the ID into a uint
|
||||
eventID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.service.Delete(c.Request.Context(), eventID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.BaseResponse{
|
||||
Success: false,
|
||||
Status: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
Data: nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: nil,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetByID(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// Parse the ID into a uint
|
||||
eventID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.GetByID(c.Request.Context(), eventID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.BaseResponse{
|
||||
Success: false,
|
||||
Status: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
Data: nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toEventResponse(res),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) toEventResponse(resp *entity.Event) response.Event {
|
||||
return response.Event{
|
||||
ID: resp.ID,
|
||||
Name: resp.Name,
|
||||
Description: resp.Description,
|
||||
StartDate: resp.StartDate.Format("2006-01-02"),
|
||||
EndDate: resp.EndDate.Format("2006-01-02"),
|
||||
StartTime: resp.StartDate.Format("15:04:05"),
|
||||
EndTime: resp.EndDate.Format("15:04:05"),
|
||||
Location: resp.Location,
|
||||
Level: resp.Level,
|
||||
Included: resp.Included,
|
||||
Price: resp.Price,
|
||||
Paid: resp.Paid,
|
||||
LocationID: resp.LocationID,
|
||||
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
Status: string(resp.Status),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) toEventResponseList(resp []*entity.Event, total int64, req request.EventParam) response.EventList {
|
||||
var events []response.Event
|
||||
for _, evt := range resp {
|
||||
events = append(events, h.toEventResponse(evt))
|
||||
}
|
||||
|
||||
return response.EventList{
|
||||
Events: events,
|
||||
Total: total,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ func (h *MenuHandler) GetProducts(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
searchParam := req.ToEntity()
|
||||
searchParam := req.ToEntity(partnerID)
|
||||
searchParam.PartnerID = partnerID
|
||||
|
||||
products, total, err := h.service.GetProductsByPartnerID(ctx, searchParam)
|
||||
|
||||
@ -29,6 +29,7 @@ func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
|
||||
route.POST("/inquiry", jwt, h.Inquiry)
|
||||
route.POST("/execute", jwt, h.Execute)
|
||||
route.POST("/refund", jwt, h.Refund)
|
||||
route.GET("/history", jwt, h.GetOrderHistory)
|
||||
route.GET("/payment-analysis", jwt, h.GetPaymentMethodAnalysis)
|
||||
route.GET("/revenue-overview", jwt, h.GetRevenueOverview)
|
||||
@ -47,6 +48,7 @@ type InquiryRequest struct {
|
||||
OrderType string `json:"order_type"`
|
||||
PaymentProvider string `json:"payment_provider"`
|
||||
TableNumber string `json:"table_number"`
|
||||
CashierSessionID int64 `json:"cashier_session_id"`
|
||||
}
|
||||
|
||||
func (o *InquiryRequest) GetPaymentProvider() string {
|
||||
@ -70,6 +72,11 @@ type ExecuteRequest struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type RefundRequest struct {
|
||||
OrderID int64 `json:"order_id" validate:"required"`
|
||||
Reason string `json:"reason" validate:"required"`
|
||||
}
|
||||
|
||||
func (h *Handler) Inquiry(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
userID := ctx.RequestedBy()
|
||||
@ -109,6 +116,7 @@ func (h *Handler) Inquiry(c *gin.Context) {
|
||||
OrderType: req.OrderType,
|
||||
PaymentProvider: req.GetPaymentProvider(),
|
||||
TableNumber: req.TableNumber,
|
||||
CashierSessionID: req.CashierSessionID,
|
||||
}
|
||||
|
||||
result, err := h.service.CreateOrderInquiry(ctx, orderReq)
|
||||
@ -152,6 +160,33 @@ func (h *Handler) Execute(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Refund(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req RefundRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.RefundRequest(ctx, *ctx.GetPartnerID(), req.OrderID, req.Reason)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetOrderHistory(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
partnerID := ctx.GetPartnerID()
|
||||
|
||||
@ -1,461 +0,0 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service services.Order
|
||||
}
|
||||
|
||||
func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/order")
|
||||
|
||||
route.POST("/inquiry", jwt, h.Inquiry)
|
||||
route.GET("/print-detail", jwt, h.PrintDetail)
|
||||
route.POST("/execute", jwt, h.Execute)
|
||||
route.GET("/history", jwt, h.GetAllHistoryOrders)
|
||||
route.GET("/ticket-sold", jwt, h.CountSoldOfTicket)
|
||||
route.POST("/checkin/inquiry", jwt, h.CheckInInquiry)
|
||||
route.POST("/checkin/execute", jwt, h.CheckInExecute)
|
||||
route.GET("/sum-amount", jwt, h.SumAmount)
|
||||
route.GET("/daily-sales", jwt, h.GetDailySalesTicket)
|
||||
route.GET("/payment-distribution", jwt, h.GetPaymentDistributionChart)
|
||||
}
|
||||
|
||||
func NewHandler(service services.Order) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) Inquiry(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.Order
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
orderRequest := req.ToEntity(*ctx.GetPartnerID(), ctx.RequestedBy())
|
||||
|
||||
order, err := h.service.CreateOrder(ctx, orderRequest)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToCreateOrderResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) PrintDetail(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.OrderPrintDetail
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
order, err := h.service.GetPrintDetail(ctx, req.ID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToPrintDetailResponse(order, ctx.GetName()),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) Execute(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.Execute
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.IsCasheer() {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
req.PartnerID = *ctx.GetPartnerID()
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
order, err := h.service.Execute(ctx, req.ToOrderExecuteRequest(ctx.RequestedBy()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToExecuteOrderResponse(order),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) CheckInInquiry(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.Checkin
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.IsCasheer() || req.QRCode == "" {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
partnerID := ctx.GetPartnerID()
|
||||
|
||||
resp, err := h.service.CheckInInquiry(ctx, req.QRCode, partnerID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.CheckingInquiryResponse{
|
||||
Token: resp.Token,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) CheckInExecute(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.CheckinExecute
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.IsCasheer() || req.Token == "" {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
partnerID := ctx.GetPartnerID()
|
||||
|
||||
resp, err := h.service.CheckInExecute(ctx, req.Token, partnerID)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: MapOrderToExecuteCheckinResponse(resp.Order),
|
||||
})
|
||||
}
|
||||
|
||||
func MapOrderToCreateOrderResponse(orderResponse *entity.OrderResponse) response.CreateOrderResponse {
|
||||
order := orderResponse.Order
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.CreateOrderResponse{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
Total: order.Total,
|
||||
Tax: order.Tax,
|
||||
PaymentType: order.PaymentType,
|
||||
CreatedAt: order.CreatedAt,
|
||||
OrderItems: orderItems,
|
||||
}
|
||||
}
|
||||
|
||||
func MapOrderToExecuteOrderResponse(orderResponse *entity.ExecuteOrderResponse) response.ExecuteOrderResponse {
|
||||
order := orderResponse.Order
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.ExecuteOrderResponse{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
PaymentType: order.PaymentType,
|
||||
CreatedAt: order.CreatedAt,
|
||||
OrderItems: orderItems,
|
||||
PaymentToken: orderResponse.PaymentToken,
|
||||
RedirectURL: orderResponse.RedirectURL,
|
||||
QRcode: orderResponse.QRCode,
|
||||
}
|
||||
}
|
||||
|
||||
func MapOrderToExecuteCheckinResponse(order *entity.Order) response.ExecuteCheckinResponse {
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.ExecuteCheckinResponse{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
PaymentType: order.PaymentType,
|
||||
CreatedAt: order.CreatedAt,
|
||||
OrderItems: orderItems,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) toHistoryOrderResponse(resp *entity.HistoryOrder) response.HistoryOrder {
|
||||
return response.HistoryOrder{
|
||||
ID: resp.ID,
|
||||
Employee: resp.Employee,
|
||||
Site: resp.Site,
|
||||
Timestamp: resp.Timestamp.Format("2006-01-02 15:04:05"),
|
||||
BookingTime: resp.BookingTime.Format("2006-01-02 15:04:05"),
|
||||
Tickets: resp.Tickets,
|
||||
PaymentType: resp.PaymentType,
|
||||
Status: resp.Status,
|
||||
Amount: resp.Amount,
|
||||
VisitDate: resp.VisitDate.Format("2006-01-02"),
|
||||
TicketStatus: resp.TicketStatus,
|
||||
Source: resp.Source,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) SumAmount(c *gin.Context) {
|
||||
var req request.OrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
order, err := h.service.SumAmount(ctx, req.ToOrderEntity(ctx))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.OrderAmount{
|
||||
Amount: order.Amount,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetAllHistoryOrders(c *gin.Context) {
|
||||
var req request.OrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
orders, total, err := h.service.GetAllHistoryOrders(ctx, req.ToOrderEntity(ctx))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toHistoryOrderList(orders, int64(total), req),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) CountSoldOfTicket(c *gin.Context) {
|
||||
var req request.OrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
res, err := h.service.CountSoldOfTicket(ctx, req.ToOrderEntity(ctx))
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: response.TicketSold{
|
||||
Count: res.Count,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetDailySalesTicket(c *gin.Context) {
|
||||
var req request.OrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
resp, err := h.service.GetDailySales(ctx, req.ToOrderEntity(ctx))
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toDailySales(resp),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) GetPaymentDistributionChart(c *gin.Context) {
|
||||
var req request.OrderParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
resp, err := h.service.GetPaymentDistribution(ctx, req.ToOrderEntity(ctx))
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toPaymentDistributionChart(resp),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) toHistoryOrderList(resp []*entity.HistoryOrder, total int64, req request.OrderParam) response.HistoryOrderList {
|
||||
var orders []response.HistoryOrder
|
||||
for _, b := range resp {
|
||||
orders = append(orders, h.toHistoryOrderResponse(b))
|
||||
}
|
||||
|
||||
return response.HistoryOrderList{
|
||||
Orders: orders,
|
||||
Total: total,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) toDailySales(resp []entity.ProductDailySales) []response.ProductDailySales {
|
||||
var dailySales []response.ProductDailySales
|
||||
for _, b := range resp {
|
||||
dailySales = append(dailySales, response.ProductDailySales{
|
||||
Day: b.Day,
|
||||
SiteID: b.SiteID,
|
||||
Total: b.Total,
|
||||
SiteName: b.SiteName,
|
||||
PaymentType: b.PaymentType,
|
||||
})
|
||||
}
|
||||
return dailySales
|
||||
}
|
||||
|
||||
func (h *Handler) toPaymentDistributionChart(resp []entity.PaymentTypeDistribution) []response.PaymentDistribution {
|
||||
var dailySales []response.PaymentDistribution
|
||||
for _, b := range resp {
|
||||
dailySales = append(dailySales, response.PaymentDistribution{
|
||||
PaymentType: b.PaymentType,
|
||||
Count: b.Count,
|
||||
})
|
||||
}
|
||||
return dailySales
|
||||
}
|
||||
|
||||
func MapOrderToPrintDetailResponse(order *entity.OrderPrintDetail, casherName string) response.PrintDetailResponse {
|
||||
orderItems := make([]response.CreateOrderItemResponse, len(order.OrderItems))
|
||||
for i, item := range order.OrderItems {
|
||||
orderItems[i] = response.CreateOrderItemResponse{
|
||||
ID: item.ID,
|
||||
ItemID: item.ItemID,
|
||||
Quantity: item.Quantity,
|
||||
Price: item.Price,
|
||||
Name: item.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return response.PrintDetailResponse{
|
||||
ID: order.ID,
|
||||
OrderID: order.OrderID,
|
||||
Total: order.Total,
|
||||
Fee: order.Fee,
|
||||
PaymentType: order.GetPaymanetType(),
|
||||
Source: order.Source,
|
||||
VisitDateAt: order.VisitDate.Format("2006-01-02"),
|
||||
VisitTime: time.Now().Format("15:04:05"),
|
||||
OrderItems: orderItems,
|
||||
CasheerName: casherName,
|
||||
PartnerName: order.SiteName,
|
||||
Logo: order.Logo,
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,6 @@ func (h *Handler) Create(c *gin.Context) {
|
||||
}
|
||||
|
||||
req.PartnerID = *ctx.GetPartnerID()
|
||||
req.SiteID = *ctx.GetSiteID()
|
||||
|
||||
res, err := h.service.Create(ctx, req.ToEntity())
|
||||
|
||||
@ -140,7 +139,9 @@ func (h *Handler) GetAll(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
products, total, err := h.service.GetAll(c.Request.Context(), req.ToEntity())
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
products, total, err := h.service.GetAll(ctx, req.ToEntity(*ctx.GetPartnerID()))
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
@ -266,6 +267,13 @@ func (h *Handler) GetByID(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *Handler) toProductResponse(resp *entity.Product) response.Product {
|
||||
category := response.Category{}
|
||||
|
||||
if resp.Category != nil {
|
||||
category.ID = resp.Category.ID
|
||||
category.Name = resp.Category.Name
|
||||
}
|
||||
|
||||
return response.Product{
|
||||
ID: resp.ID,
|
||||
Name: resp.Name,
|
||||
@ -274,6 +282,7 @@ func (h *Handler) toProductResponse(resp *entity.Product) response.Product {
|
||||
Status: resp.Status,
|
||||
Description: resp.Description,
|
||||
Image: resp.Image,
|
||||
Category: category,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
package studio
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/errors"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/handlers/request"
|
||||
"enaklo-pos-be/internal/handlers/response"
|
||||
"enaklo-pos-be/internal/services"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type StudioHandler struct {
|
||||
service services.Studio
|
||||
}
|
||||
|
||||
func (h *StudioHandler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||
route := group.Group("/studio")
|
||||
|
||||
route.POST("/", jwt, h.Create)
|
||||
route.PUT("/:id", jwt, h.Update)
|
||||
route.GET("/:id", jwt, h.GetByID)
|
||||
route.GET("/search", jwt, h.Search)
|
||||
}
|
||||
|
||||
func NewStudioHandler(service services.Studio) *StudioHandler {
|
||||
return &StudioHandler{
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// Create handles the creation of a new studio.
|
||||
// @Summary Create a new studio
|
||||
// @Description Create a new studio based on the provided details.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "JWT token"
|
||||
// @Param req body request.Studio true "New studio details"
|
||||
// @Success 200 {object} response.BaseResponse{data=response.Studio} "Studio created successfully"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||
// @Router /api/v1/studio [post]
|
||||
// @Tags Studio APIs
|
||||
func (h *StudioHandler) Create(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
var req request.Studio
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.Create(ctx, req.ToEntity())
|
||||
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toStudioResponse(res),
|
||||
})
|
||||
}
|
||||
|
||||
// Update handles the update of an existing studio.
|
||||
// @Summary Update an existing studio
|
||||
// @Description Update the details of an existing studio based on the provided ID.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "JWT token"
|
||||
// @Param id path int64 true "Studio ID to update"
|
||||
// @Param req body request.Studio true "Updated studio details"
|
||||
// @Success 200 {object} response.BaseResponse{data=response.Studio} "Studio updated successfully"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||
// @Router /api/v1/studio/{id} [put]
|
||||
// @Tags Studio APIs
|
||||
func (h *StudioHandler) Update(c *gin.Context) {
|
||||
ctx := request.GetMyContext(c)
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
studioID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req request.Studio
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(req); err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
updatedStudio, err := h.service.Update(ctx, studioID, req.ToEntity())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toStudioResponse(updatedStudio),
|
||||
})
|
||||
}
|
||||
|
||||
// Search retrieves a list of studios based on search criteria.
|
||||
// @Summary Search for studios
|
||||
// @Description Search for studios based on query parameters.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "JWT token"
|
||||
// @Param Name query string false "Studio name for search"
|
||||
// @Param Status query string false "Studio status for search"
|
||||
// @Param Limit query int false "Number of items to retrieve (default 10)"
|
||||
// @Param Offset query int false "Offset for pagination (default 0)"
|
||||
// @Success 200 {object} response.BaseResponse{data=response.StudioList} "List of studios"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||
// @Router /api/v1/studio/search [get]
|
||||
// @Tags Studio APIs
|
||||
func (h *StudioHandler) Search(c *gin.Context) {
|
||||
var req request.StudioParam
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
studios, total, err := h.service.Search(c.Request.Context(), req.ToEntity())
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toStudioResponseList(studios, int64(total), req),
|
||||
})
|
||||
}
|
||||
|
||||
// GetByID retrieves details of a specific studio by ID.
|
||||
// @Summary Get details of a studio by ID
|
||||
// @Description Get details of a studio based on the provided ID.
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "JWT token"
|
||||
// @Param id path int64 true "Studio ID to retrieve"
|
||||
// @Success 200 {object} response.BaseResponse{data=response.Studio} "Studio details"
|
||||
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||
// @Router /api/v1/studio/{id} [get]
|
||||
// @Tags Studio APIs
|
||||
func (h *StudioHandler) GetByID(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
studioID, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := h.service.GetByID(c.Request.Context(), studioID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.BaseResponse{
|
||||
Success: false,
|
||||
Status: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
Data: nil,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response.BaseResponse{
|
||||
Success: true,
|
||||
Status: http.StatusOK,
|
||||
Data: h.toStudioResponse(res),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *StudioHandler) toStudioResponse(resp *entity.Studio) response.Studio {
|
||||
metadata := make(map[string]interface{})
|
||||
if err := json.Unmarshal(resp.Metadata, &metadata); err != nil {
|
||||
//TODO taufanvps
|
||||
// Handle the error if the metadata cannot be unmarshaled.
|
||||
}
|
||||
|
||||
return response.Studio{
|
||||
ID: &resp.ID,
|
||||
BranchId: &resp.BranchId,
|
||||
Name: resp.Name,
|
||||
Status: string(resp.Status),
|
||||
Price: resp.Price,
|
||||
Metadata: metadata,
|
||||
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *StudioHandler) toStudioResponseList(resp []*entity.Studio, total int64, req request.StudioParam) response.StudioList {
|
||||
var studios []response.Studio
|
||||
for _, b := range resp {
|
||||
studios = append(studios, h.toStudioResponse(b))
|
||||
}
|
||||
|
||||
return response.StudioList{
|
||||
Studios: studios,
|
||||
Total: total,
|
||||
Limit: req.Limit,
|
||||
Offset: req.Offset,
|
||||
}
|
||||
}
|
||||
18
internal/handlers/request/cashier.go
Normal file
18
internal/handlers/request/cashier.go
Normal file
@ -0,0 +1,18 @@
|
||||
package request
|
||||
|
||||
import "enaklo-pos-be/internal/entity"
|
||||
|
||||
type OpenCashierSessionRequest struct {
|
||||
OpeningAmount float64 `json:"opening_amount" validate:"required,gt=0"`
|
||||
}
|
||||
|
||||
type CloseCashierSessionRequest struct {
|
||||
ClosingAmount float64 `json:"closing_amount" validate:"required"`
|
||||
}
|
||||
|
||||
func (o *OpenCashierSessionRequest) ToEntity(cashierID int64) *entity.CashierSession {
|
||||
return &entity.CashierSession{
|
||||
CashierID: cashierID,
|
||||
OpeningAmount: o.OpeningAmount,
|
||||
}
|
||||
}
|
||||
14
internal/handlers/request/category.go
Normal file
14
internal/handlers/request/category.go
Normal file
@ -0,0 +1,14 @@
|
||||
package request
|
||||
|
||||
import "enaklo-pos-be/internal/entity"
|
||||
|
||||
type CategoryRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
}
|
||||
|
||||
func (r *CategoryRequest) ToEntity(partnerID int64) *entity.Category {
|
||||
return &entity.Category{
|
||||
PartnerID: partnerID,
|
||||
Name: r.Name,
|
||||
}
|
||||
}
|
||||
@ -6,24 +6,26 @@ import (
|
||||
)
|
||||
|
||||
type ProductParam struct {
|
||||
Search string `form:"search" json:"search" example:"Nasi Goreng"`
|
||||
Name string `form:"name" json:"name" example:"Nasi Goreng"`
|
||||
Type product.ProductType `form:"type" json:"type" example:"FOOD/BEVERAGE"`
|
||||
BranchID int64 `form:"branch_id" json:"branch_id" example:"1"`
|
||||
Available product.ProductStock `form:"available" json:"available" example:"1" example:"AVAILABLE/UNAVAILABLE"`
|
||||
Limit int `form:"limit" json:"limit" example:"10"`
|
||||
Offset int `form:"offset" json:"offset" example:"0"`
|
||||
Search string `form:"search" json:"search" example:"Nasi Goreng"`
|
||||
Name string `form:"name" json:"name" example:"Nasi Goreng"`
|
||||
Type product.ProductType `form:"type" json:"type" example:"FOOD/BEVERAGE"`
|
||||
BranchID int64 `form:"branch_id" json:"branch_id" example:"1"`
|
||||
Available product.ProductStock `form:"available" json:"available" example:"1" example:"AVAILABLE/UNAVAILABLE"`
|
||||
Limit int `form:"limit" json:"limit" example:"10"`
|
||||
Offset int `form:"offset" json:"offset" example:"0"`
|
||||
CategoryID int64 `form:"category_id" json:"category_id" example:"1"`
|
||||
}
|
||||
|
||||
func (p *ProductParam) ToEntity() entity.ProductSearch {
|
||||
func (p *ProductParam) ToEntity(partnerID int64) entity.ProductSearch {
|
||||
return entity.ProductSearch{
|
||||
Search: p.Search,
|
||||
Name: p.Name,
|
||||
Type: p.Type,
|
||||
BranchID: p.BranchID,
|
||||
Available: p.Available,
|
||||
Limit: p.Limit,
|
||||
Offset: p.Offset,
|
||||
Search: p.Search,
|
||||
Name: p.Name,
|
||||
Type: p.Type,
|
||||
PartnerID: partnerID,
|
||||
Available: p.Available,
|
||||
Limit: p.Limit,
|
||||
Offset: p.Offset,
|
||||
CategoryID: p.CategoryID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +42,7 @@ type Product struct {
|
||||
Description string `json:"description"`
|
||||
Stock int64 `json:"stock"`
|
||||
Image string `json:"image"`
|
||||
CategoryID int64 `json:"category_id"`
|
||||
}
|
||||
|
||||
func (e *Product) ToEntity() *entity.Product {
|
||||
@ -51,5 +54,6 @@ func (e *Product) ToEntity() *entity.Product {
|
||||
Description: e.Description,
|
||||
PartnerID: e.PartnerID,
|
||||
Image: e.Image,
|
||||
CategoryID: &e.CategoryID,
|
||||
}
|
||||
}
|
||||
|
||||
62
internal/handlers/response/cashier.go
Normal file
62
internal/handlers/response/cashier.go
Normal file
@ -0,0 +1,62 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CashierSessionResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
CashierID int64 `json:"cashier_id"`
|
||||
OpenedAt time.Time `json:"opened_at"`
|
||||
ClosedAt *time.Time `json:"closed_at,omitempty"`
|
||||
OpeningAmount float64 `json:"opening_amount"`
|
||||
ClosingAmount *float64 `json:"closing_amount,omitempty"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type PaymentSummaryResponse struct {
|
||||
PaymentType string `json:"payment_type"`
|
||||
PaymentProvider string `json:"payment_provider"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
}
|
||||
|
||||
type CashierSessionReportResponse struct {
|
||||
SessionID int64 `json:"session_id"`
|
||||
ExpectedAmount float64 `json:"expected_amount"`
|
||||
ClosingAmount float64 `json:"closing_amount"`
|
||||
Payments []PaymentSummaryResponse `json:"payments"`
|
||||
}
|
||||
|
||||
func MapToCashierSessionResponse(e *entity.CashierSession) *CashierSessionResponse {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &CashierSessionResponse{
|
||||
ID: e.ID,
|
||||
CashierID: e.CashierID,
|
||||
OpenedAt: e.OpenedAt,
|
||||
ClosedAt: e.ClosedAt,
|
||||
OpeningAmount: e.OpeningAmount,
|
||||
ClosingAmount: e.ClosingAmount,
|
||||
Status: e.Status,
|
||||
}
|
||||
}
|
||||
|
||||
func MapToCashierSessionReport(e *entity.CashierSessionReport) *CashierSessionReportResponse {
|
||||
payments := make([]PaymentSummaryResponse, len(e.Payments))
|
||||
for i, p := range e.Payments {
|
||||
payments[i] = PaymentSummaryResponse{
|
||||
PaymentType: p.PaymentType,
|
||||
PaymentProvider: p.PaymentProvider,
|
||||
TotalAmount: p.TotalAmount,
|
||||
}
|
||||
}
|
||||
return &CashierSessionReportResponse{
|
||||
SessionID: e.SessionID,
|
||||
ExpectedAmount: e.ExpectedAmount,
|
||||
ClosingAmount: e.ClosingAmount,
|
||||
Payments: payments,
|
||||
}
|
||||
}
|
||||
29
internal/handlers/response/category.go
Normal file
29
internal/handlers/response/category.go
Normal file
@ -0,0 +1,29 @@
|
||||
package response
|
||||
|
||||
import "enaklo-pos-be/internal/entity"
|
||||
|
||||
type CategoryResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PartnerID int64 `json:"partner_id"`
|
||||
}
|
||||
|
||||
func MapToCategoryResponse(cat *entity.Category) *CategoryResponse {
|
||||
if cat == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &CategoryResponse{
|
||||
ID: cat.ID,
|
||||
Name: cat.Name,
|
||||
PartnerID: cat.PartnerID,
|
||||
}
|
||||
}
|
||||
|
||||
func MapToCategoryListResponse(cats []*entity.Category) []*CategoryResponse {
|
||||
result := make([]*CategoryResponse, len(cats))
|
||||
for i, c := range cats {
|
||||
result[i] = MapToCategoryResponse(c)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -1,13 +1,19 @@
|
||||
package response
|
||||
|
||||
type Product struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Price float64 `json:"price"`
|
||||
Status string `json:"status"`
|
||||
Description string `json:"description"`
|
||||
Image string `json:"image"`
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Price float64 `json:"price"`
|
||||
Status string `json:"status"`
|
||||
Description string `json:"description"`
|
||||
Image string `json:"image"`
|
||||
Category Category `json:"category"`
|
||||
}
|
||||
|
||||
type Category struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ProductList struct {
|
||||
|
||||
137
internal/repository/casheer_seasion.go
Normal file
137
internal/repository/casheer_seasion.go
Normal file
@ -0,0 +1,137 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository/models"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CashierSessionRepository interface {
|
||||
CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error)
|
||||
CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error
|
||||
GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
|
||||
GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error)
|
||||
GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error)
|
||||
}
|
||||
|
||||
type cashierSessionRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewCashierSessionRepository(db *gorm.DB) CashierSessionRepository {
|
||||
return &cashierSessionRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) {
|
||||
dbModel := models.CashierSessionDB{
|
||||
CashierID: session.CashierID,
|
||||
OpenedAt: time.Now(),
|
||||
OpeningAmount: session.OpeningAmount,
|
||||
Status: "open",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := r.db.Create(&dbModel).Error; err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create cashier session")
|
||||
}
|
||||
|
||||
session.ID = dbModel.ID
|
||||
session.Status = dbModel.Status
|
||||
session.OpenedAt = dbModel.OpenedAt
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error {
|
||||
result := r.db.Model(&models.CashierSessionDB{}).
|
||||
Where("id = ?", sessionID).
|
||||
Updates(map[string]interface{}{
|
||||
"closed_at": time.Now(),
|
||||
"closing_amount": closingAmount,
|
||||
"expected_amount": expectedAmount,
|
||||
"status": "closed",
|
||||
})
|
||||
|
||||
if result.Error != nil {
|
||||
return errors.Wrap(result.Error, "failed to close session")
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return errors.New("no session updated")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) {
|
||||
var dbModel models.CashierSessionDB
|
||||
if err := r.db.Where("cashier_id = ? AND status = 'open'", cashierID).
|
||||
Order("opened_at DESC").First(&dbModel).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed to get open session")
|
||||
}
|
||||
|
||||
return r.toEntity(&dbModel), nil
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error) {
|
||||
var dbModel models.CashierSessionDB
|
||||
if err := r.db.First(&dbModel, sessionID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed to get session by ID")
|
||||
}
|
||||
|
||||
return r.toEntity(&dbModel), nil
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) toEntity(db *models.CashierSessionDB) *entity.CashierSession {
|
||||
return &entity.CashierSession{
|
||||
ID: db.ID,
|
||||
CashierID: db.CashierID,
|
||||
OpenedAt: db.OpenedAt,
|
||||
ClosedAt: db.ClosedAt,
|
||||
OpeningAmount: db.OpeningAmount,
|
||||
ClosingAmount: db.ClosingAmount,
|
||||
ExpectedAmount: db.ExpectedAmount,
|
||||
Status: db.Status,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *cashierSessionRepository) GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error) {
|
||||
type result struct {
|
||||
PaymentType string
|
||||
PaymentProvider string
|
||||
TotalAmount float64
|
||||
}
|
||||
|
||||
var rows []result
|
||||
|
||||
err := r.db.WithContext(ctx).
|
||||
Table("orders").
|
||||
Select("payment_type, payment_provider, SUM(total) AS total_amount").
|
||||
Where("cashier_session_id = ?", sessionID).
|
||||
Group("payment_type, payment_provider").
|
||||
Scan(&rows).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to summarize payments from orders")
|
||||
}
|
||||
|
||||
summary := make([]entity.PaymentSummary, len(rows))
|
||||
for i, row := range rows {
|
||||
summary[i] = entity.PaymentSummary{
|
||||
PaymentType: row.PaymentType,
|
||||
PaymentProvider: row.PaymentProvider,
|
||||
TotalAmount: row.TotalAmount,
|
||||
}
|
||||
}
|
||||
|
||||
return summary, nil
|
||||
}
|
||||
94
internal/repository/categories_repo.go
Normal file
94
internal/repository/categories_repo.go
Normal file
@ -0,0 +1,94 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository/models"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CategoryRepository interface {
|
||||
Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error)
|
||||
GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error)
|
||||
GetByID(ctx mycontext.Context, id int64) (*entity.Category, error)
|
||||
Update(ctx mycontext.Context, category *entity.Category) error
|
||||
Delete(ctx mycontext.Context, id int64) error
|
||||
}
|
||||
|
||||
type categoryRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewCategoryRepository(db *gorm.DB) CategoryRepository {
|
||||
return &categoryRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *categoryRepository) Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error) {
|
||||
dbModel := &models.CategoryDB{
|
||||
PartnerID: category.PartnerID,
|
||||
Name: category.Name,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
if err := r.db.WithContext(ctx).Create(dbModel).Error; err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create category")
|
||||
}
|
||||
category.ID = dbModel.ID
|
||||
return category, nil
|
||||
}
|
||||
|
||||
func (r *categoryRepository) GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error) {
|
||||
var dbModels []models.CategoryDB
|
||||
if err := r.db.WithContext(ctx).
|
||||
Where("partner_id = ? AND deleted_at IS NULL", partnerID).
|
||||
Find(&dbModels).Error; err != nil {
|
||||
return nil, errors.Wrap(err, "failed to fetch categories by partner ID")
|
||||
}
|
||||
|
||||
var result []*entity.Category
|
||||
for _, db := range dbModels {
|
||||
result = append(result, r.toEntity(&db))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *categoryRepository) GetByID(ctx mycontext.Context, id int64) (*entity.Category, error) {
|
||||
var db models.CategoryDB
|
||||
if err := r.db.WithContext(ctx).
|
||||
Where("id = ? AND deleted_at IS NULL", id).
|
||||
First(&db).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed to get category by ID")
|
||||
}
|
||||
return r.toEntity(&db), nil
|
||||
}
|
||||
|
||||
func (r *categoryRepository) Update(ctx mycontext.Context, category *entity.Category) error {
|
||||
return r.db.WithContext(ctx).Model(&models.CategoryDB{}).
|
||||
Where("id = ?", category.ID).
|
||||
Updates(map[string]interface{}{
|
||||
"name": category.Name,
|
||||
"updated_at": time.Now(),
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (r *categoryRepository) Delete(ctx mycontext.Context, id int64) error {
|
||||
return r.db.WithContext(ctx).
|
||||
Model(&models.CategoryDB{}).
|
||||
Where("id = ?", id).
|
||||
Update("deleted_at", time.Now()).Error
|
||||
}
|
||||
|
||||
func (r *categoryRepository) toEntity(db *models.CategoryDB) *entity.Category {
|
||||
return &entity.Category{
|
||||
ID: db.ID,
|
||||
PartnerID: db.PartnerID,
|
||||
Name: db.Name,
|
||||
CreatedAt: db.CreatedAt.Unix(),
|
||||
UpdatedAt: db.UpdatedAt.Unix(),
|
||||
}
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
)
|
||||
|
||||
type EventRepoImpl struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewEventRepo(db *gorm.DB) *EventRepoImpl {
|
||||
return &EventRepoImpl{DB: db}
|
||||
}
|
||||
|
||||
func (e *EventRepoImpl) CreateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error) {
|
||||
err := e.DB.Create(event).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create event", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *EventRepoImpl) UpdateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error) {
|
||||
if err := e.DB.Save(event).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update event", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *EventRepoImpl) GetEventByID(ctx context.Context, id int64) (*entity.EventDB, error) {
|
||||
event := new(entity.EventDB)
|
||||
if err := e.DB.First(event, id).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get event by id", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *EventRepoImpl) GetAllEvents(ctx context.Context, nameFilter string, limit, offset int) (entity.EventList, int, error) {
|
||||
var events []*entity.EventDB
|
||||
var total int64
|
||||
|
||||
query := e.DB
|
||||
query = query.Where("deleted_at is null")
|
||||
|
||||
if nameFilter != "" {
|
||||
query = query.Where("name LIKE ?", "%"+nameFilter+"%")
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
query = query.Limit(limit)
|
||||
}
|
||||
if offset > 0 {
|
||||
query = query.Offset(offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&events).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all events", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := e.DB.Model(&entity.EventDB{}).Where(query).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when count event", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return events, int(total), nil
|
||||
}
|
||||
|
||||
func (e *EventRepoImpl) DeleteEvent(ctx context.Context, id int64) error {
|
||||
event := new(entity.EventDB)
|
||||
event.ID = id
|
||||
if err := e.DB.Delete(event).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all events", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
20
internal/repository/models/casheer_seasion.go
Normal file
20
internal/repository/models/casheer_seasion.go
Normal file
@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type CashierSessionDB struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
CashierID int64 `gorm:"not null"`
|
||||
OpenedAt time.Time `gorm:"not null"`
|
||||
ClosedAt *time.Time
|
||||
OpeningAmount float64 `gorm:"not null"`
|
||||
ClosingAmount *float64
|
||||
ExpectedAmount *float64
|
||||
Notes *string
|
||||
Status string `gorm:"not null"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (CashierSessionDB) TableName() string {
|
||||
return "cashier_sessions"
|
||||
}
|
||||
16
internal/repository/models/categories.go
Normal file
16
internal/repository/models/categories.go
Normal file
@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type CategoryDB struct {
|
||||
ID int64 `gorm:"primaryKey;autoIncrement"`
|
||||
PartnerID int64 `gorm:"not null"`
|
||||
Name string `gorm:"type:varchar(255);not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||
DeletedAt *time.Time
|
||||
}
|
||||
|
||||
func (CategoryDB) TableName() string {
|
||||
return "categories"
|
||||
}
|
||||
@ -5,24 +5,26 @@ import (
|
||||
)
|
||||
|
||||
type OrderDB struct {
|
||||
ID int64 `gorm:"primaryKey;column:id"`
|
||||
PartnerID int64 `gorm:"column:partner_id"`
|
||||
CustomerID *int64 `gorm:"column:customer_id"`
|
||||
InquiryID *string `gorm:"column:inquiry_id"`
|
||||
Status string `gorm:"column:status"`
|
||||
Amount float64 `gorm:"column:amount"`
|
||||
Tax float64 `gorm:"column:tax"`
|
||||
Total float64 `gorm:"column:total"`
|
||||
PaymentType string `gorm:"column:payment_type"`
|
||||
Source string `gorm:"column:source"`
|
||||
CreatedBy int64 `gorm:"column:created_by"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
OrderItems []OrderItemDB `gorm:"foreignKey:OrderID"`
|
||||
OrderType string `gorm:"column:order_type"`
|
||||
TableNumber string `gorm:"column:table_number"`
|
||||
PaymentProvider string `gorm:"column:payment_provider"`
|
||||
CustomerName string `gorm:"column:customer_name"`
|
||||
ID int64 `gorm:"primaryKey;column:id"`
|
||||
PartnerID int64 `gorm:"column:partner_id"`
|
||||
CustomerID *int64 `gorm:"column:customer_id"`
|
||||
InquiryID *string `gorm:"column:inquiry_id"`
|
||||
Status string `gorm:"column:status"`
|
||||
Amount float64 `gorm:"column:amount"`
|
||||
Tax float64 `gorm:"column:tax"`
|
||||
Total float64 `gorm:"column:total"`
|
||||
PaymentType string `gorm:"column:payment_type"`
|
||||
Source string `gorm:"column:source"`
|
||||
CreatedBy int64 `gorm:"column:created_by"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
OrderItems []OrderItemDB `gorm:"foreignKey:OrderID"`
|
||||
OrderType string `gorm:"column:order_type"`
|
||||
TableNumber string `gorm:"column:table_number"`
|
||||
PaymentProvider string `gorm:"column:payment_provider"`
|
||||
CustomerName string `gorm:"column:customer_name"`
|
||||
CashierSessionID int64 `gorm:"column:cashier_session_id"`
|
||||
Description string `gorm:"column:description"`
|
||||
}
|
||||
|
||||
func (OrderDB) TableName() string {
|
||||
@ -68,6 +70,7 @@ type OrderInquiryDB struct {
|
||||
PaymentProvider string `gorm:"column:payment_provider"`
|
||||
TableNumber string `gorm:"column:table_number"`
|
||||
OrderType string `gorm:"column:order_type"`
|
||||
CashierSessionID int64 `gorm:"column:cashier_session_id"`
|
||||
}
|
||||
|
||||
func (OrderInquiryDB) TableName() string {
|
||||
|
||||
@ -40,6 +40,7 @@ type OrderRepository interface {
|
||||
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error)
|
||||
GetOrderHistoryByUserID(ctx mycontext.Context, userID int64, req entity.SearchRequest) ([]*entity.Order, int64, error)
|
||||
FindByIDAndCustomerID(ctx mycontext.Context, id int64, customerID int64) (*entity.Order, error)
|
||||
UpdateOrder(ctx mycontext.Context, id int64, status string, description string) error
|
||||
}
|
||||
|
||||
type orderRepository struct {
|
||||
@ -232,25 +233,48 @@ func (r *orderRepository) UpdateInquiryStatus(ctx mycontext.Context, id string,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *orderRepository) UpdateOrder(ctx mycontext.Context, id int64, status string, description string) error {
|
||||
now := time.Now()
|
||||
|
||||
result := r.db.Model(&models.OrderDB{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"updated_at": now,
|
||||
"description": description,
|
||||
})
|
||||
|
||||
if result.Error != nil {
|
||||
return errors.Wrap(result.Error, "failed to update order status")
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
logger.ContextLogger(ctx).Warn("no order updated")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *orderRepository) toOrderDBModel(order *entity.Order) models.OrderDB {
|
||||
return models.OrderDB{
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
CustomerID: order.CustomerID,
|
||||
InquiryID: order.InquiryID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
Tax: order.Tax,
|
||||
Total: order.Total,
|
||||
PaymentType: order.PaymentType,
|
||||
Source: order.Source,
|
||||
CreatedBy: order.CreatedBy,
|
||||
CreatedAt: order.CreatedAt,
|
||||
UpdatedAt: order.UpdatedAt,
|
||||
OrderType: order.OrderType,
|
||||
TableNumber: order.TableNumber,
|
||||
PaymentProvider: order.PaymentProvider,
|
||||
CustomerName: order.CustomerName,
|
||||
ID: order.ID,
|
||||
PartnerID: order.PartnerID,
|
||||
CustomerID: order.CustomerID,
|
||||
InquiryID: order.InquiryID,
|
||||
Status: order.Status,
|
||||
Amount: order.Amount,
|
||||
Tax: order.Tax,
|
||||
Total: order.Total,
|
||||
PaymentType: order.PaymentType,
|
||||
Source: order.Source,
|
||||
CreatedBy: order.CreatedBy,
|
||||
CreatedAt: order.CreatedAt,
|
||||
UpdatedAt: order.UpdatedAt,
|
||||
OrderType: order.OrderType,
|
||||
TableNumber: order.TableNumber,
|
||||
PaymentProvider: order.PaymentProvider,
|
||||
CustomerName: order.CustomerName,
|
||||
CashierSessionID: order.CashierSessionID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,27 +370,29 @@ func (r *orderRepository) toOrderInquiryDBModel(inquiry *entity.OrderInquiry) mo
|
||||
PaymentProvider: inquiry.PaymentProvider,
|
||||
OrderType: inquiry.OrderType,
|
||||
TableNumber: inquiry.TableNumber,
|
||||
CashierSessionID: inquiry.CashierSessionID,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *orderRepository) toDomainOrderInquiryModel(dbModel *models.OrderInquiryDB) *entity.OrderInquiry {
|
||||
inquiry := &entity.OrderInquiry{
|
||||
ID: dbModel.ID,
|
||||
PartnerID: dbModel.PartnerID,
|
||||
Status: dbModel.Status,
|
||||
Amount: dbModel.Amount,
|
||||
Tax: dbModel.Tax,
|
||||
Total: dbModel.Total,
|
||||
PaymentType: dbModel.PaymentType,
|
||||
Source: dbModel.Source,
|
||||
CreatedBy: dbModel.CreatedBy,
|
||||
CreatedAt: dbModel.CreatedAt,
|
||||
ExpiresAt: dbModel.ExpiresAt,
|
||||
OrderItems: []entity.OrderItem{},
|
||||
OrderType: dbModel.OrderType,
|
||||
CustomerName: dbModel.CustomerName,
|
||||
PaymentProvider: dbModel.PaymentProvider,
|
||||
TableNumber: dbModel.TableNumber,
|
||||
ID: dbModel.ID,
|
||||
PartnerID: dbModel.PartnerID,
|
||||
Status: dbModel.Status,
|
||||
Amount: dbModel.Amount,
|
||||
Tax: dbModel.Tax,
|
||||
Total: dbModel.Total,
|
||||
PaymentType: dbModel.PaymentType,
|
||||
Source: dbModel.Source,
|
||||
CreatedBy: dbModel.CreatedBy,
|
||||
CreatedAt: dbModel.CreatedAt,
|
||||
ExpiresAt: dbModel.ExpiresAt,
|
||||
OrderItems: []entity.OrderItem{},
|
||||
OrderType: dbModel.OrderType,
|
||||
CustomerName: dbModel.CustomerName,
|
||||
PaymentProvider: dbModel.PaymentProvider,
|
||||
TableNumber: dbModel.TableNumber,
|
||||
CashierSessionID: dbModel.CashierSessionID,
|
||||
}
|
||||
|
||||
if dbModel.CustomerID != nil {
|
||||
@ -718,7 +744,7 @@ func (r *orderRepository) GetRevenueOverview(
|
||||
ctx mycontext.Context,
|
||||
req entity.RevenueOverviewRequest,
|
||||
) ([]entity.RevenueOverviewItem, error) {
|
||||
var overview []entity.RevenueOverviewItem
|
||||
overview := []entity.RevenueOverviewItem{}
|
||||
|
||||
baseQuery := r.db.Model(&models.OrderDB{}).
|
||||
Where("partner_id = ?", req.PartnerID).
|
||||
|
||||
@ -38,7 +38,7 @@ func (b *ProductRepository) UpdateProduct(ctx context.Context, product *entity.P
|
||||
|
||||
func (b *ProductRepository) GetProductByID(ctx context.Context, id int64) (*entity.ProductDB, error) {
|
||||
product := new(entity.ProductDB)
|
||||
if err := b.db.First(product, id).Error; err != nil {
|
||||
if err := b.db.Preload("Category").First(product, id).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get by id product", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
@ -84,8 +84,12 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
|
||||
query = query.Where("type = ? ", req.Type)
|
||||
}
|
||||
|
||||
if req.BranchID > 0 {
|
||||
query = query.Where("branch_id = ? ", req.BranchID)
|
||||
if req.CategoryID > 0 {
|
||||
query = query.Where("category_id = ? ", req.CategoryID)
|
||||
}
|
||||
|
||||
if req.PartnerID > 0 {
|
||||
query = query.Where("partner_id = ? ", req.PartnerID)
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
@ -96,7 +100,7 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&products).Error; err != nil {
|
||||
if err := query.Preload("Category").Find(&products).Order("id ASC").Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all products", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@ import (
|
||||
pg "enaklo-pos-be/internal/repository/payment_gateway"
|
||||
"enaklo-pos-be/internal/repository/products"
|
||||
"enaklo-pos-be/internal/repository/sites"
|
||||
"enaklo-pos-be/internal/repository/studios"
|
||||
transactions "enaklo-pos-be/internal/repository/transaction"
|
||||
"enaklo-pos-be/internal/repository/trx"
|
||||
"enaklo-pos-be/internal/repository/users"
|
||||
@ -28,15 +27,12 @@ import (
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository/auth"
|
||||
"enaklo-pos-be/internal/repository/crypto"
|
||||
event "enaklo-pos-be/internal/repository/events"
|
||||
)
|
||||
|
||||
type RepoManagerImpl struct {
|
||||
Crypto Crypto
|
||||
Auth Auth
|
||||
Event Event
|
||||
User User
|
||||
Studio Studio
|
||||
Product Product
|
||||
Order Order
|
||||
OSS OSSRepository
|
||||
@ -60,15 +56,15 @@ type RepoManagerImpl struct {
|
||||
MemberRepository MemberRepository
|
||||
PartnerSetting PartnerSettingsRepository
|
||||
UndianRepository UndianRepo
|
||||
CashierSeasionRepo CashierSessionRepository
|
||||
CategoryRepository CategoryRepository
|
||||
}
|
||||
|
||||
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
|
||||
return &RepoManagerImpl{
|
||||
Crypto: crypto.NewCrypto(cfg.Auth()),
|
||||
Auth: auth.NewAuthRepository(db),
|
||||
Event: event.NewEventRepo(db),
|
||||
User: users.NewUserRepository(db),
|
||||
Studio: studios.NewStudioRepository(db),
|
||||
Product: products.NewProductRepository(db),
|
||||
Order: orders.NewOrderRepository(db),
|
||||
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
|
||||
@ -92,6 +88,8 @@ func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
|
||||
InProgressOrderRepo: NewInProgressOrderRepository(db),
|
||||
PartnerSetting: NewPartnerSettingsRepository(db),
|
||||
UndianRepository: NewUndianRepository(db),
|
||||
CashierSeasionRepo: NewCashierSessionRepository(db),
|
||||
CategoryRepository: NewCategoryRepository(db),
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,14 +99,6 @@ type Auth interface {
|
||||
UpdatePassword(ctx context.Context, trx *gorm.DB, newHashedPassword string, userID int64, resetPassword bool) error
|
||||
}
|
||||
|
||||
type Event interface {
|
||||
CreateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error)
|
||||
UpdateEvent(ctx context.Context, event *entity.EventDB) (*entity.EventDB, error)
|
||||
GetEventByID(ctx context.Context, id int64) (*entity.EventDB, error)
|
||||
GetAllEvents(ctx context.Context, nameFilter string, limit, offset int) (entity.EventList, int, error)
|
||||
DeleteEvent(ctx context.Context, id int64) error
|
||||
}
|
||||
|
||||
type Crypto interface {
|
||||
CompareHashAndPassword(hash string, password string) bool
|
||||
ValidateWT(tokenString string) (*jwt.Token, error)
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
package studios
|
||||
|
||||
import (
|
||||
"context"
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type StudioRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewStudioRepository(db *gorm.DB) *StudioRepository {
|
||||
return &StudioRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StudioRepository) CreateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error) {
|
||||
err := s.db.Omit("ID").Create(studio).Error
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when creating studio", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return studio, nil
|
||||
}
|
||||
|
||||
func (s *StudioRepository) UpdateStudio(ctx context.Context, studio *entity.StudioDB) (*entity.StudioDB, error) {
|
||||
if err := s.db.Save(studio).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when updating studio", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return studio, nil
|
||||
}
|
||||
|
||||
func (s *StudioRepository) GetStudioByID(ctx context.Context, id int64) (*entity.StudioDB, error) {
|
||||
studio := new(entity.StudioDB)
|
||||
if err := s.db.First(studio, id).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when getting studio by ID", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return studio, nil
|
||||
}
|
||||
|
||||
func (s *StudioRepository) SearchStudios(ctx context.Context, req entity.StudioSearch) (entity.StudioList, int, error) {
|
||||
var studios []*entity.StudioDB
|
||||
var total int64
|
||||
|
||||
query := s.db
|
||||
|
||||
if req.Id > 0 {
|
||||
query = query.Where("id = ?", req.Id)
|
||||
}
|
||||
|
||||
if req.Name != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
|
||||
if req.Status != "" {
|
||||
query = query.Where("status = ?", req.Status)
|
||||
}
|
||||
|
||||
if req.BranchId > 0 {
|
||||
query = query.Where("branch_id = ?", req.BranchId)
|
||||
}
|
||||
|
||||
if req.Limit > 0 {
|
||||
query = query.Limit(req.Limit)
|
||||
}
|
||||
|
||||
if req.Offset > 0 {
|
||||
query = query.Offset(req.Offset)
|
||||
}
|
||||
|
||||
if err := query.Find(&studios).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when getting all studios", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := s.db.Model(&entity.StudioDB{}).Where(query).Count(&total).Error; err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when counting studios", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return studios, int(total), nil
|
||||
}
|
||||
@ -3,7 +3,6 @@ package routes
|
||||
import (
|
||||
"enaklo-pos-be/internal/handlers/http"
|
||||
"enaklo-pos-be/internal/handlers/http/customerauth"
|
||||
"enaklo-pos-be/internal/handlers/http/discovery"
|
||||
"enaklo-pos-be/internal/middlewares"
|
||||
|
||||
"enaklo-pos-be/internal/app"
|
||||
@ -19,7 +18,6 @@ func RegisterCustomerRoutes(app *app.Server, serviceManager *services.ServiceMan
|
||||
optionlMiddleWare := middlewares.OptionalCustomerAuthorizationMiddleware(repoManager.Crypto)
|
||||
|
||||
serverRoutes := []HTTPHandlerRoutes{
|
||||
discovery.NewHandler(serviceManager.DiscoverService),
|
||||
customerauth.NewAuthHandler(serviceManager.AuthV2Svc, serviceManager.MemberRegistrationSvc),
|
||||
http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc),
|
||||
http.NewCustomerOrderHandler(serviceManager.OrderV2Svc),
|
||||
|
||||
@ -8,14 +8,12 @@ import (
|
||||
"enaklo-pos-be/internal/handlers/http/partner"
|
||||
"enaklo-pos-be/internal/handlers/http/product"
|
||||
site "enaklo-pos-be/internal/handlers/http/sites"
|
||||
"enaklo-pos-be/internal/handlers/http/studio"
|
||||
"enaklo-pos-be/internal/handlers/http/transaction"
|
||||
"enaklo-pos-be/internal/handlers/http/user"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"net/http"
|
||||
|
||||
"enaklo-pos-be/internal/handlers/http/event"
|
||||
"enaklo-pos-be/internal/middlewares"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -46,9 +44,7 @@ func RegisterPrivateRoutes(app *app.Server, serviceManager *services.ServiceMana
|
||||
authMiddleware := middlewares.AuthorizationMiddleware(repoManager.Crypto)
|
||||
serverRoutes := []HTTPHandlerRoutes{
|
||||
auth.NewAuthHandler(serviceManager.AuthSvc),
|
||||
event.NewHandler(serviceManager.EventSvc),
|
||||
user.NewHandler(serviceManager.UserSvc),
|
||||
studio.NewStudioHandler(serviceManager.StudioSvc),
|
||||
product.NewHandler(serviceManager.ProductSvc),
|
||||
oss.NewOssHandler(serviceManager.OSSSvc),
|
||||
partner.NewHandler(serviceManager.PartnerSvc),
|
||||
@ -74,6 +70,8 @@ func RegisterPrivateRoutesV2(app *app.Server, serviceManager *services.ServiceMa
|
||||
http2.NewMemberRegistrationHandler(serviceManager.MemberRegistrationSvc),
|
||||
http2.NewCustomerHandler(serviceManager.CustomerV2Svc),
|
||||
http2.NewInProgressOrderHandler(serviceManager.InProgressSvc),
|
||||
http2.NewCashierSession(serviceManager.CashierSvc),
|
||||
http2.NewCategoryHandler(serviceManager.CategorySvc),
|
||||
}
|
||||
|
||||
for _, handler := range serverRoutes {
|
||||
|
||||
@ -1,168 +0,0 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"context"
|
||||
"enaklo-pos-be/config"
|
||||
"errors"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLatitude = -6.2088
|
||||
defaultLongitude = 106.8456
|
||||
radius = 10000
|
||||
)
|
||||
|
||||
type DiscoveryService struct {
|
||||
repo repository.SiteRepository
|
||||
cfg config.Discovery
|
||||
product repository.Product
|
||||
}
|
||||
|
||||
func NewDiscoveryService(repo repository.SiteRepository, cfg config.Discovery, product repository.Product) *DiscoveryService {
|
||||
return &DiscoveryService{
|
||||
repo: repo,
|
||||
cfg: cfg,
|
||||
product: product,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DiscoveryService) Home(ctx context.Context, search *entity.DiscoverySearch) (*entity.DiscoverySearchResp, error) {
|
||||
if search.Lat == 0 || search.Long == 0 {
|
||||
search.Lat = defaultLatitude
|
||||
search.Long = defaultLongitude
|
||||
}
|
||||
|
||||
siteProducts, err := s.repo.GetNearestSites(ctx, search.Lat, search.Long, radius)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exploreDestinations := []entity.ExploreDestination{}
|
||||
for _, exploreDestination := range s.cfg.ExploreDestinations {
|
||||
exploreDestinations = append(exploreDestinations, entity.ExploreDestination{
|
||||
Name: exploreDestination.Name,
|
||||
ImageURL: exploreDestination.ImageURL,
|
||||
})
|
||||
}
|
||||
|
||||
exploreRegions := []entity.ExploreRegion{}
|
||||
for _, exploreRegion := range s.cfg.ExploreRegions {
|
||||
exploreRegions = append(exploreRegions, entity.ExploreRegion{
|
||||
Name: exploreRegion.Name,
|
||||
})
|
||||
}
|
||||
|
||||
mustVisits := []entity.MustVisit{}
|
||||
|
||||
for _, siteProduct := range siteProducts {
|
||||
if siteProduct.Status == "Active" {
|
||||
mustVisits = append(mustVisits, entity.MustVisit{
|
||||
Name: siteProduct.SiteName,
|
||||
Price: siteProduct.ProductPrice,
|
||||
Region: siteProduct.Region,
|
||||
SiteID: siteProduct.SiteID,
|
||||
ImageURL: siteProduct.Image,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
response := &entity.DiscoverySearchResp{
|
||||
ExploreRegions: exploreRegions,
|
||||
ExploreDestinations: exploreDestinations,
|
||||
MustVisit: mustVisits,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *DiscoveryService) Search(ctx context.Context, search *entity.DiscoverySearch) (*entity.DiscoverySearchResp, int64, error) {
|
||||
if search.Lat == 0 || search.Long == 0 {
|
||||
search.Lat = defaultLatitude
|
||||
search.Long = defaultLongitude
|
||||
search.Radius = radius
|
||||
}
|
||||
|
||||
search.Status = "Active"
|
||||
siteProducts, total, err := s.repo.SearchSites(ctx, search)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
exploreDestinations := []entity.ExploreDestination{}
|
||||
for _, exploreDestination := range s.cfg.ExploreDestinations {
|
||||
exploreDestinations = append(exploreDestinations, entity.ExploreDestination{
|
||||
Name: exploreDestination.Name,
|
||||
ImageURL: exploreDestination.ImageURL,
|
||||
})
|
||||
}
|
||||
|
||||
exploreRegions := []entity.ExploreRegion{}
|
||||
for _, exploreRegion := range s.cfg.ExploreRegions {
|
||||
exploreRegions = append(exploreRegions, entity.ExploreRegion{
|
||||
Name: exploreRegion.Name,
|
||||
})
|
||||
}
|
||||
|
||||
mustVisits := []entity.MustVisit{}
|
||||
|
||||
for _, siteProduct := range siteProducts {
|
||||
mustVisits = append(mustVisits, entity.MustVisit{
|
||||
Name: siteProduct.SiteName,
|
||||
Price: siteProduct.ProductPrice,
|
||||
Region: siteProduct.Region,
|
||||
SiteID: siteProduct.SiteID,
|
||||
ImageURL: siteProduct.Image,
|
||||
Regency: siteProduct.Regency,
|
||||
})
|
||||
}
|
||||
|
||||
response := &entity.DiscoverySearchResp{
|
||||
ExploreRegions: exploreRegions,
|
||||
ExploreDestinations: exploreDestinations,
|
||||
MustVisit: mustVisits,
|
||||
}
|
||||
|
||||
return response, total, nil
|
||||
}
|
||||
|
||||
func (s *DiscoveryService) GetByID(ctx context.Context, id int64) (*entity.Site, error) {
|
||||
site, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if site.Status != "Active" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return site.ToSite(), nil
|
||||
}
|
||||
|
||||
func (s *DiscoveryService) GetProductsByID(ctx context.Context, id int64) ([]*entity.Product, error) {
|
||||
site, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if site.Status == "Inactive" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
product, err := s.product.GetProductsBySiteID(ctx, site.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return product.ToProductList(), nil
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository"
|
||||
)
|
||||
|
||||
type EventService struct {
|
||||
repo repository.Event
|
||||
}
|
||||
|
||||
func NewEventService(repo repository.Event) *EventService {
|
||||
return &EventService{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EventService) Create(ctx context.Context, eventReq *entity.Event) (*entity.Event, error) {
|
||||
eventDB := eventReq.ToEventDB()
|
||||
|
||||
eventDB, err := s.repo.CreateEvent(ctx, eventDB)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when create event", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return eventDB.ToEvent(), nil
|
||||
}
|
||||
|
||||
func (s *EventService) Update(ctx context.Context, id int64, eventReq *entity.Event) (*entity.Event, error) {
|
||||
existingEvent, err := s.repo.GetEventByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingEvent.ToUpdatedEvent(*eventReq)
|
||||
|
||||
updatedEventDB, err := s.repo.UpdateEvent(ctx, existingEvent.ToEventDB())
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update event", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return updatedEventDB.ToEvent(), nil
|
||||
}
|
||||
|
||||
func (s *EventService) GetByID(ctx context.Context, id int64) (*entity.Event, error) {
|
||||
eventDB, err := s.repo.GetEventByID(ctx, id)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get event by id", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return eventDB.ToEvent(), nil
|
||||
}
|
||||
|
||||
func (s *EventService) GetAll(ctx context.Context, search entity.EventSearch) ([]*entity.Event, int, error) {
|
||||
events, total, err := s.repo.GetAllEvents(ctx, search.Name, search.Limit, search.Offset)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get all events", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return events.ToEventList(), total, nil
|
||||
}
|
||||
|
||||
func (s *EventService) Delete(ctx context.Context, id int64) error {
|
||||
eventDB, err := s.repo.GetEventByID(ctx, id)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when get event by id", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
eventDB.SetDeleted()
|
||||
|
||||
_, err = s.repo.UpdateEvent(ctx, eventDB)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when update event", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -4,17 +4,17 @@ import (
|
||||
"context"
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/services/balance"
|
||||
"enaklo-pos-be/internal/services/discovery"
|
||||
service "enaklo-pos-be/internal/services/license"
|
||||
"enaklo-pos-be/internal/services/member"
|
||||
"enaklo-pos-be/internal/services/oss"
|
||||
"enaklo-pos-be/internal/services/partner"
|
||||
"enaklo-pos-be/internal/services/product"
|
||||
site "enaklo-pos-be/internal/services/sites"
|
||||
"enaklo-pos-be/internal/services/studio"
|
||||
"enaklo-pos-be/internal/services/transaction"
|
||||
"enaklo-pos-be/internal/services/users"
|
||||
authSvc "enaklo-pos-be/internal/services/v2/auth"
|
||||
"enaklo-pos-be/internal/services/v2/cashier_session"
|
||||
category "enaklo-pos-be/internal/services/v2/categories"
|
||||
customerSvc "enaklo-pos-be/internal/services/v2/customer"
|
||||
"enaklo-pos-be/internal/services/v2/inprogress_order"
|
||||
orderSvc "enaklo-pos-be/internal/services/v2/order"
|
||||
@ -29,22 +29,18 @@ import (
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository"
|
||||
"enaklo-pos-be/internal/services/auth"
|
||||
"enaklo-pos-be/internal/services/event"
|
||||
)
|
||||
|
||||
type ServiceManagerImpl struct {
|
||||
AuthSvc Auth
|
||||
EventSvc Event
|
||||
UserSvc User
|
||||
StudioSvc Studio
|
||||
ProductSvc Product
|
||||
OSSSvc OSSService
|
||||
PartnerSvc Partner
|
||||
SiteSvc Site
|
||||
LicenseSvc License
|
||||
Transaction Transaction
|
||||
Balance Balance
|
||||
DiscoverService DiscoverService
|
||||
AuthSvc Auth
|
||||
UserSvc User
|
||||
ProductSvc Product
|
||||
OSSSvc OSSService
|
||||
PartnerSvc Partner
|
||||
SiteSvc Site
|
||||
LicenseSvc License
|
||||
Transaction Transaction
|
||||
Balance Balance
|
||||
|
||||
OrderV2Svc orderSvc.Service
|
||||
CustomerV2Svc customerSvc.Service
|
||||
@ -53,6 +49,8 @@ type ServiceManagerImpl struct {
|
||||
InProgressSvc inprogress_order.InProgressOrderService
|
||||
AuthV2Svc authSvc.Service
|
||||
UndianSvc undian.Service
|
||||
CashierSvc cashier_session.Service
|
||||
CategorySvc category.Service
|
||||
}
|
||||
|
||||
func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl) *ServiceManagerImpl {
|
||||
@ -60,14 +58,16 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
|
||||
custSvcV2 := customerSvc.New(repo.CustomerRepo, repo.EmailService)
|
||||
productSvcV2 := productSvc.New(repo.ProductRepo)
|
||||
partnerSettings := partner_settings.NewPartnerSettingsService(repo.PartnerSetting)
|
||||
|
||||
orderService := orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings, repo.UndianRepository)
|
||||
cashierSvc := cashier_session.New(repo.CashierSeasionRepo)
|
||||
orderService := orderSvc.New(repo.OrderRepo,
|
||||
productSvcV2, custSvcV2, repo.TransactionRepo,
|
||||
repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings,
|
||||
repo.UndianRepository, cashierSvc)
|
||||
inprogressOrder := inprogress_order.NewInProgressOrderService(repo.OrderRepo, orderService, productSvcV2)
|
||||
categorySvc := category.New(repo.CategoryRepository)
|
||||
return &ServiceManagerImpl{
|
||||
AuthSvc: auth.New(repo.Auth, repo.Crypto, repo.User, repo.EmailService, cfg.Email, repo.Trx, repo.License),
|
||||
EventSvc: event.NewEventService(repo.Event),
|
||||
UserSvc: users.NewUserService(repo.User),
|
||||
StudioSvc: studio.NewStudioService(repo.Studio),
|
||||
ProductSvc: product.NewProductService(repo.Product),
|
||||
OSSSvc: oss.NewOSSService(repo.OSS),
|
||||
PartnerSvc: partner.NewPartnerService(
|
||||
@ -76,14 +76,15 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
|
||||
LicenseSvc: service.NewLicenseService(repo.License),
|
||||
Transaction: transaction.New(repo.Transaction, repo.Wallet, repo.Trx),
|
||||
Balance: balance.NewBalanceService(repo.Wallet, repo.Trx, repo.Crypto, &cfg.Withdraw, repo.Transaction),
|
||||
DiscoverService: discovery.NewDiscoveryService(repo.Site, cfg.Discovery, repo.Product),
|
||||
OrderV2Svc: orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings, repo.UndianRepository),
|
||||
OrderV2Svc: orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings, repo.UndianRepository, cashierSvc),
|
||||
MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2, repo.Crypto),
|
||||
CustomerV2Svc: custSvcV2,
|
||||
InProgressSvc: inprogressOrder,
|
||||
ProductV2Svc: productSvcV2,
|
||||
AuthV2Svc: authSvc.New(repo.CustomerRepo, repo.Crypto),
|
||||
UndianSvc: undian.New(repo.UndianRepository),
|
||||
CashierSvc: cashierSvc,
|
||||
CategorySvc: categorySvc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,14 +94,6 @@ type Auth interface {
|
||||
ResetPassword(ctx mycontext.Context, oldPassword, newPassword string) error
|
||||
}
|
||||
|
||||
type Event interface {
|
||||
Create(ctx context.Context, eventReq *entity.Event) (*entity.Event, error)
|
||||
Update(ctx context.Context, id int64, eventReq *entity.Event) (*entity.Event, error)
|
||||
GetByID(ctx context.Context, id int64) (*entity.Event, error)
|
||||
GetAll(ctx context.Context, search entity.EventSearch) ([]*entity.Event, int, error)
|
||||
Delete(ctx context.Context, id int64) error
|
||||
}
|
||||
|
||||
type User interface {
|
||||
Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error)
|
||||
CreateWithTx(ctx mycontext.Context, tx *gorm.DB, userReq *entity.User) (*entity.User, error)
|
||||
@ -112,13 +105,6 @@ type User interface {
|
||||
Delete(ctx mycontext.Context, id int64) error
|
||||
}
|
||||
|
||||
type Studio interface {
|
||||
Create(ctx mycontext.Context, studioReq *entity.Studio) (*entity.Studio, error)
|
||||
Update(ctx mycontext.Context, id int64, studioReq *entity.Studio) (*entity.Studio, error)
|
||||
GetByID(ctx context.Context, id int64) (*entity.Studio, error)
|
||||
Search(ctx context.Context, search entity.StudioSearch) ([]*entity.Studio, int, error)
|
||||
}
|
||||
|
||||
type Product interface {
|
||||
Create(ctx mycontext.Context, productReq *entity.Product) (*entity.Product, error)
|
||||
Update(ctx mycontext.Context, id int64, productReq *entity.Product) (*entity.Product, error)
|
||||
@ -128,23 +114,6 @@ type Product interface {
|
||||
Delete(ctx mycontext.Context, id int64) error
|
||||
}
|
||||
|
||||
type Order interface {
|
||||
CreateOrder(ctx mycontext.Context, req *entity.OrderRequest) (*entity.OrderResponse, error)
|
||||
CheckInInquiry(ctx mycontext.Context, qrCode string, partnerID *int64) (*entity.CheckinResponse, error)
|
||||
CheckInExecute(ctx mycontext.Context,
|
||||
token string, partnerID *int64) (*entity.CheckinExecute, error)
|
||||
Execute(ctx mycontext.Context, req *entity.OrderExecuteRequest) (*entity.ExecuteOrderResponse, error)
|
||||
ProcessCallback(ctx context.Context, req *entity.CallbackRequest) error
|
||||
GetAllHistoryOrders(ctx mycontext.Context, req entity.OrderSearch) ([]*entity.HistoryOrder, int, error)
|
||||
CountSoldOfTicket(ctx mycontext.Context, req entity.OrderSearch) (*entity.TicketSold, error)
|
||||
SumAmount(ctx mycontext.Context, req entity.OrderSearch) (*entity.Order, error)
|
||||
GetDailySales(ctx mycontext.Context, req entity.OrderSearch) ([]entity.ProductDailySales, error)
|
||||
GetPaymentDistribution(ctx mycontext.Context, req entity.OrderSearch) ([]entity.PaymentTypeDistribution, error)
|
||||
GetByID(ctx mycontext.Context, id int64, referenceID string) (*entity.Order, error)
|
||||
GetPrintDetail(ctx mycontext.Context, id int64) (*entity.OrderPrintDetail, error)
|
||||
ProcessLinkQuCallback(ctx context.Context, req *entity.LinkQuCallback) error
|
||||
}
|
||||
|
||||
type OSSService interface {
|
||||
UploadFile(ctx context.Context, req *entity.UploadFileRequest) (*entity.UploadFileResponse, error)
|
||||
}
|
||||
@ -183,10 +152,3 @@ type Balance interface {
|
||||
WithdrawInquiry(ctx context.Context, req *entity.BalanceWithdrawInquiry) (*entity.BalanceWithdrawInquiryResponse, error)
|
||||
WithdrawExecute(ctx mycontext.Context, req *entity.WalletWithdrawRequest) (*entity.WalletWithdrawResponse, error)
|
||||
}
|
||||
|
||||
type DiscoverService interface {
|
||||
Home(ctx context.Context, search *entity.DiscoverySearch) (*entity.DiscoverySearchResp, error)
|
||||
Search(ctx context.Context, search *entity.DiscoverySearch) (*entity.DiscoverySearchResp, int64, error)
|
||||
GetByID(ctx context.Context, id int64) (*entity.Site, error)
|
||||
GetProductsByID(ctx context.Context, id int64) ([]*entity.Product, error)
|
||||
}
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
package studio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"enaklo-pos-be/internal/repository"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type StudioService struct {
|
||||
repo repository.Studio
|
||||
}
|
||||
|
||||
func NewStudioService(repo repository.Studio) *StudioService {
|
||||
return &StudioService{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StudioService) Create(ctx mycontext.Context, studioReq *entity.Studio) (*entity.Studio, error) {
|
||||
newStudioDB := studioReq.NewStudiosDB()
|
||||
newStudioDB.CreatedBy = ctx.RequestedBy()
|
||||
|
||||
newStudioDB, err := s.repo.CreateStudio(ctx, newStudioDB)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when creating studio", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newStudioDB.ToStudio(), nil
|
||||
}
|
||||
|
||||
func (s *StudioService) Update(ctx mycontext.Context, id int64, studioReq *entity.Studio) (*entity.Studio, error) {
|
||||
existingStudio, err := s.repo.GetStudioByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingStudio.ToUpdatedStudio(ctx.RequestedBy(), *studioReq)
|
||||
|
||||
updatedStudioDB, err := s.repo.UpdateStudio(ctx, existingStudio.ToStudioDB())
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when updating studio", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return updatedStudioDB.ToStudio(), nil
|
||||
}
|
||||
|
||||
func (s *StudioService) GetByID(ctx context.Context, id int64) (*entity.Studio, error) {
|
||||
studioDB, err := s.repo.GetStudioByID(ctx, id)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when getting studio by id", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return studioDB.ToStudio(), nil
|
||||
}
|
||||
|
||||
func (s *StudioService) Search(ctx context.Context, search entity.StudioSearch) ([]*entity.Studio, int, error) {
|
||||
studios, total, err := s.repo.SearchStudios(ctx, search)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("error when getting all studios", zap.Error(err))
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return studios.ToStudioList(), total, nil
|
||||
}
|
||||
99
internal/services/v2/cashier_session/casheer_session.go
Normal file
99
internal/services/v2/cashier_session/casheer_session.go
Normal file
@ -0,0 +1,99 @@
|
||||
package cashier_session
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
OpenSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error)
|
||||
CloseSession(ctx mycontext.Context, sessionID int64, closingAmount float64) (*entity.CashierSessionReport, error)
|
||||
GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
|
||||
GetSessionReport(ctx mycontext.Context, sessionID int64) (*entity.CashierSessionReport, error)
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error)
|
||||
CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error
|
||||
GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
|
||||
GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error)
|
||||
GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error)
|
||||
}
|
||||
|
||||
type cashierSessionSvc struct {
|
||||
repo Repository
|
||||
}
|
||||
|
||||
func New(repo Repository) Service {
|
||||
return &cashierSessionSvc{repo: repo}
|
||||
}
|
||||
|
||||
func (s *cashierSessionSvc) OpenSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) {
|
||||
openSession, err := s.repo.GetOpenSessionByCashierID(ctx, session.CashierID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to check existing open session")
|
||||
}
|
||||
if openSession != nil {
|
||||
return nil, errors.New("cashier already has an open session")
|
||||
}
|
||||
|
||||
newSession, err := s.repo.CreateSession(ctx, session)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("failed to create cashier session", zap.Error(err))
|
||||
return nil, errors.Wrap(err, "failed to create cashier session")
|
||||
}
|
||||
|
||||
return newSession, nil
|
||||
}
|
||||
|
||||
func (s *cashierSessionSvc) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount float64) (*entity.CashierSessionReport, error) {
|
||||
report, err := s.repo.GetPaymentSummaryBySessionID(ctx, sessionID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get payment summary")
|
||||
}
|
||||
|
||||
var expectedAmount float64
|
||||
for _, r := range report {
|
||||
expectedAmount += r.TotalAmount
|
||||
}
|
||||
|
||||
if err := s.repo.CloseSession(ctx, sessionID, closingAmount, expectedAmount); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to close session")
|
||||
}
|
||||
|
||||
return &entity.CashierSessionReport{
|
||||
SessionID: sessionID,
|
||||
ClosingAmount: closingAmount,
|
||||
ExpectedAmount: expectedAmount,
|
||||
Payments: report,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *cashierSessionSvc) GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) {
|
||||
session, err := s.repo.GetOpenSessionByCashierID(ctx, cashierID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get open session")
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (s *cashierSessionSvc) GetSessionReport(ctx mycontext.Context, sessionID int64) (*entity.CashierSessionReport, error) {
|
||||
report, err := s.repo.GetPaymentSummaryBySessionID(ctx, sessionID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get payment summary")
|
||||
}
|
||||
|
||||
var expectedAmount float64
|
||||
for _, r := range report {
|
||||
expectedAmount += r.TotalAmount
|
||||
}
|
||||
|
||||
return &entity.CashierSessionReport{
|
||||
SessionID: sessionID,
|
||||
ExpectedAmount: expectedAmount,
|
||||
Payments: report,
|
||||
}, nil
|
||||
}
|
||||
88
internal/services/v2/categories/categories.go
Normal file
88
internal/services/v2/categories/categories.go
Normal file
@ -0,0 +1,88 @@
|
||||
package category
|
||||
|
||||
import (
|
||||
"enaklo-pos-be/internal/common/logger"
|
||||
"enaklo-pos-be/internal/common/mycontext"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error)
|
||||
GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error)
|
||||
Update(ctx mycontext.Context, category *entity.Category) error
|
||||
Delete(ctx mycontext.Context, id int64) error
|
||||
GetByID(ctx mycontext.Context, id int64) (*entity.Category, error)
|
||||
}
|
||||
|
||||
type Repository interface {
|
||||
Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error)
|
||||
GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error)
|
||||
Update(ctx mycontext.Context, category *entity.Category) error
|
||||
Delete(ctx mycontext.Context, id int64) error
|
||||
GetByID(ctx mycontext.Context, id int64) (*entity.Category, error)
|
||||
}
|
||||
|
||||
type categorySvc struct {
|
||||
repo Repository
|
||||
}
|
||||
|
||||
func New(repo Repository) Service {
|
||||
return &categorySvc{repo: repo}
|
||||
}
|
||||
|
||||
func (s *categorySvc) Create(ctx mycontext.Context, category *entity.Category) (*entity.Category, error) {
|
||||
existing, err := s.repo.GetByPartnerID(ctx, category.PartnerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to fetch categories")
|
||||
}
|
||||
|
||||
for _, cat := range existing {
|
||||
if cat.Name == category.Name {
|
||||
return nil, errors.New("category name already exists for this partner")
|
||||
}
|
||||
}
|
||||
|
||||
newCategory, err := s.repo.Create(ctx, category)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("failed to create category", zap.Error(err))
|
||||
return nil, errors.Wrap(err, "failed to create category")
|
||||
}
|
||||
|
||||
return newCategory, nil
|
||||
}
|
||||
|
||||
func (s *categorySvc) GetByPartnerID(ctx mycontext.Context, partnerID int64) ([]*entity.Category, error) {
|
||||
categories, err := s.repo.GetByPartnerID(ctx, partnerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get categories by partner")
|
||||
}
|
||||
return categories, nil
|
||||
}
|
||||
|
||||
func (s *categorySvc) Update(ctx mycontext.Context, category *entity.Category) error {
|
||||
err := s.repo.Update(ctx, category)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("failed to update category", zap.Error(err))
|
||||
return errors.Wrap(err, "failed to update category")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *categorySvc) Delete(ctx mycontext.Context, id int64) error {
|
||||
err := s.repo.Delete(ctx, id)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("failed to delete category", zap.Error(err))
|
||||
return errors.Wrap(err, "failed to delete category")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *categorySvc) GetByID(ctx mycontext.Context, id int64) (*entity.Category, error) {
|
||||
category, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get category by ID")
|
||||
}
|
||||
return category, nil
|
||||
}
|
||||
@ -12,6 +12,13 @@ import (
|
||||
|
||||
func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context,
|
||||
req *entity.OrderRequest) (*entity.OrderInquiryResponse, error) {
|
||||
|
||||
cashierSession, err := s.cashierSvc.GetOpenSession(ctx, ctx.RequestedBy())
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("no open session found for cashier", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
productIDs, filteredItems, err := s.ValidateOrderItems(ctx, req.OrderItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -60,6 +67,7 @@ func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context,
|
||||
req.PaymentProvider,
|
||||
req.TableNumber,
|
||||
req.OrderType,
|
||||
cashierSession.ID,
|
||||
)
|
||||
|
||||
for _, item := range req.OrderItems {
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"enaklo-pos-be/internal/constants"
|
||||
"enaklo-pos-be/internal/entity"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
)
|
||||
@ -36,6 +37,20 @@ func (s *orderSvc) ExecuteOrderInquiry(ctx mycontext.Context,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *orderSvc) RefundRequest(ctx mycontext.Context, partnerID, orderID int64, reason string) error {
|
||||
order, err := s.repo.FindByIDAndPartnerID(ctx, partnerID, orderID)
|
||||
if err != nil {
|
||||
logger.ContextLogger(ctx).Error("failed to create order", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
if order.Status != "PAID" {
|
||||
return errors.New("only paid order can be refund")
|
||||
}
|
||||
|
||||
return s.repo.UpdateOrder(ctx, order.ID, "REFUNDED", reason)
|
||||
}
|
||||
|
||||
func (s *orderSvc) processPostOrderActions(
|
||||
ctx mycontext.Context,
|
||||
order *entity.Order,
|
||||
|
||||
@ -12,6 +12,7 @@ type Repository interface {
|
||||
CreateInquiry(ctx mycontext.Context, inquiry *entity.OrderInquiry) (*entity.OrderInquiry, error)
|
||||
FindInquiryByID(ctx mycontext.Context, id string) (*entity.OrderInquiry, error)
|
||||
UpdateInquiryStatus(ctx mycontext.Context, id string, status string) error
|
||||
UpdateOrder(ctx mycontext.Context, id int64, status string, description string) error
|
||||
GetOrderHistoryByPartnerID(ctx mycontext.Context, partnerID int64, req entity.SearchRequest) ([]*entity.Order, int64, error)
|
||||
GetOrderPaymentMethodBreakdown(
|
||||
ctx mycontext.Context,
|
||||
@ -65,6 +66,7 @@ type Service interface {
|
||||
req *entity.OrderRequest) (*entity.OrderInquiryResponse, error)
|
||||
ExecuteOrderInquiry(ctx mycontext.Context,
|
||||
token string, paymentMethod, paymentProvider string, inProgressOrderID int64) (*entity.OrderResponse, error)
|
||||
RefundRequest(ctx mycontext.Context, partnerID, orderID int64, reason string) error
|
||||
GetOrderHistory(ctx mycontext.Context, partnerID int64, request entity.SearchRequest) ([]*entity.Order, int64, error)
|
||||
CalculateOrderTotals(
|
||||
ctx mycontext.Context,
|
||||
@ -122,6 +124,10 @@ type VoucherUndianRepo interface {
|
||||
CreateUndianVouchers(ctx mycontext.Context, vouchers []*entity.UndianVoucherDB) error
|
||||
}
|
||||
|
||||
type CashierSvc interface {
|
||||
GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
|
||||
}
|
||||
|
||||
type orderSvc struct {
|
||||
repo Repository
|
||||
product ProductService
|
||||
@ -133,6 +139,7 @@ type orderSvc struct {
|
||||
partnerSetting PartnerSettings
|
||||
inprogressOrder InProgressOrderRepository
|
||||
voucherUndianRepo VoucherUndianRepo
|
||||
cashierSvc CashierSvc
|
||||
}
|
||||
|
||||
func New(
|
||||
@ -145,6 +152,7 @@ func New(
|
||||
notification NotificationService,
|
||||
partnerSetting PartnerSettings,
|
||||
voucherUndianRepo VoucherUndianRepo,
|
||||
cashierSvc CashierSvc,
|
||||
) Service {
|
||||
return &orderSvc{
|
||||
repo: repo,
|
||||
@ -156,5 +164,6 @@ func New(
|
||||
notification: notification,
|
||||
partnerSetting: partnerSetting,
|
||||
voucherUndianRepo: voucherUndianRepo,
|
||||
cashierSvc: cashierSvc,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user