Add refund order

This commit is contained in:
aditya.siregar 2025-06-14 21:17:13 +07:00
parent 58d3b32c40
commit ebb33186b8
42 changed files with 1152 additions and 2094 deletions

View 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
}

View File

@ -0,0 +1,9 @@
package entity
type Category struct {
ID int64
PartnerID int64
Name string
CreatedAt int64
UpdatedAt int64
}

View File

@ -26,6 +26,7 @@ type Order struct {
User User `gorm:"foreignKey:CreatedBy;constraint:OnDelete:CASCADE;"` User User `gorm:"foreignKey:CreatedBy;constraint:OnDelete:CASCADE;"`
Source string `gorm:"type:varchar;column:source"` Source string `gorm:"type:varchar;column:source"`
OrderType string `gorm:"type:varchar;column:order_type"` OrderType string `gorm:"type:varchar;column:order_type"`
CashierSessionID int64 `gorm:"type:varchar;column:cashier_session_id"`
TableNumber string TableNumber string
InProgressOrderID int64 InProgressOrderID int64
} }
@ -113,6 +114,7 @@ type OrderRequest struct {
PaymentProvider string PaymentProvider string
OrderType string OrderType string
ID int64 ID int64
CashierSessionID int64
} }
type OrderItemRequest struct { type OrderItemRequest struct {

View File

@ -26,6 +26,7 @@ type OrderInquiry struct {
PaymentProvider string `json:"payment_provider"` PaymentProvider string `json:"payment_provider"`
TableNumber string `json:"table_number"` TableNumber string `json:"table_number"`
OrderType string `json:"order_type"` OrderType string `json:"order_type"`
CashierSessionID int64 `json:"cashier_session_id"`
} }
type OrderCalculation struct { type OrderCalculation struct {
@ -54,6 +55,7 @@ func NewOrderInquiry(
paymentProvider string, paymentProvider string,
tableNumber string, tableNumber string,
orderType string, orderType string,
cashierSessionID int64,
) *OrderInquiry { ) *OrderInquiry {
return &OrderInquiry{ return &OrderInquiry{
ID: constants.GenerateUUID(), ID: constants.GenerateUUID(),
@ -75,6 +77,7 @@ func NewOrderInquiry(
PaymentProvider: paymentProvider, PaymentProvider: paymentProvider,
TableNumber: tableNumber, TableNumber: tableNumber,
OrderType: orderType, OrderType: orderType,
CashierSessionID: cashierSessionID,
} }
} }
@ -111,6 +114,7 @@ func (i *OrderInquiry) ToOrder(paymentMethod, paymentProvider string) *Order {
OrderType: i.OrderType, OrderType: i.OrderType,
CustomerName: i.CustomerName, CustomerName: i.CustomerName,
TableNumber: i.TableNumber, TableNumber: i.TableNumber,
CashierSessionID: i.CashierSessionID,
} }
for idx, item := range i.OrderItems { for idx, item := range i.OrderItems {

View File

@ -2,6 +2,7 @@ package entity
import ( import (
"enaklo-pos-be/internal/constants/product" "enaklo-pos-be/internal/constants/product"
"enaklo-pos-be/internal/repository/models"
"time" "time"
) )
@ -19,6 +20,8 @@ type Product struct {
CreatedBy int64 `gorm:"type:int;column:created_by"` CreatedBy int64 `gorm:"type:int;column:created_by"`
UpdatedBy int64 `gorm:"type:int;column:updated_by"` UpdatedBy int64 `gorm:"type:int;column:updated_by"`
Image string `gorm:"type:varchar;column:image"` 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 { func (Product) TableName() string {
@ -34,6 +37,7 @@ type ProductSearch struct {
Available product.ProductStock Available product.ProductStock
Limit int Limit int
Offset int Offset int
CategoryID int64
} }
type ProductPOS struct { type ProductPOS struct {
@ -72,6 +76,8 @@ func (e *ProductDB) ToProduct() *Product {
CreatedBy: e.CreatedBy, CreatedBy: e.CreatedBy,
UpdatedBy: e.UpdatedBy, UpdatedBy: e.UpdatedBy,
Image: e.Image, Image: e.Image,
Category: e.Category,
CategoryID: e.CategoryID,
} }
} }

View 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),
})
}

View 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,
})
}

View File

@ -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
}

View File

@ -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,
}
}

View File

@ -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,
}
}

View File

@ -56,7 +56,7 @@ func (h *MenuHandler) GetProducts(c *gin.Context) {
return return
} }
searchParam := req.ToEntity() searchParam := req.ToEntity(partnerID)
searchParam.PartnerID = partnerID searchParam.PartnerID = partnerID
products, total, err := h.service.GetProductsByPartnerID(ctx, searchParam) products, total, err := h.service.GetProductsByPartnerID(ctx, searchParam)

View File

@ -29,6 +29,7 @@ func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
route.POST("/inquiry", jwt, h.Inquiry) route.POST("/inquiry", jwt, h.Inquiry)
route.POST("/execute", jwt, h.Execute) route.POST("/execute", jwt, h.Execute)
route.POST("/refund", jwt, h.Refund)
route.GET("/history", jwt, h.GetOrderHistory) route.GET("/history", jwt, h.GetOrderHistory)
route.GET("/payment-analysis", jwt, h.GetPaymentMethodAnalysis) route.GET("/payment-analysis", jwt, h.GetPaymentMethodAnalysis)
route.GET("/revenue-overview", jwt, h.GetRevenueOverview) route.GET("/revenue-overview", jwt, h.GetRevenueOverview)
@ -47,6 +48,7 @@ type InquiryRequest struct {
OrderType string `json:"order_type"` OrderType string `json:"order_type"`
PaymentProvider string `json:"payment_provider"` PaymentProvider string `json:"payment_provider"`
TableNumber string `json:"table_number"` TableNumber string `json:"table_number"`
CashierSessionID int64 `json:"cashier_session_id"`
} }
func (o *InquiryRequest) GetPaymentProvider() string { func (o *InquiryRequest) GetPaymentProvider() string {
@ -70,6 +72,11 @@ type ExecuteRequest struct {
Token string `json:"token"` 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) { func (h *Handler) Inquiry(c *gin.Context) {
ctx := request.GetMyContext(c) ctx := request.GetMyContext(c)
userID := ctx.RequestedBy() userID := ctx.RequestedBy()
@ -109,6 +116,7 @@ func (h *Handler) Inquiry(c *gin.Context) {
OrderType: req.OrderType, OrderType: req.OrderType,
PaymentProvider: req.GetPaymentProvider(), PaymentProvider: req.GetPaymentProvider(),
TableNumber: req.TableNumber, TableNumber: req.TableNumber,
CashierSessionID: req.CashierSessionID,
} }
result, err := h.service.CreateOrderInquiry(ctx, orderReq) 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) { func (h *Handler) GetOrderHistory(c *gin.Context) {
ctx := request.GetMyContext(c) ctx := request.GetMyContext(c)
partnerID := ctx.GetPartnerID() partnerID := ctx.GetPartnerID()

View File

@ -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,
}
}

View File

@ -55,7 +55,6 @@ func (h *Handler) Create(c *gin.Context) {
} }
req.PartnerID = *ctx.GetPartnerID() req.PartnerID = *ctx.GetPartnerID()
req.SiteID = *ctx.GetSiteID()
res, err := h.service.Create(ctx, req.ToEntity()) res, err := h.service.Create(ctx, req.ToEntity())
@ -140,7 +139,9 @@ func (h *Handler) GetAll(c *gin.Context) {
return 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 { if err != nil {
response.ErrorWrapper(c, err) response.ErrorWrapper(c, err)
return return
@ -266,6 +267,13 @@ func (h *Handler) GetByID(c *gin.Context) {
} }
func (h *Handler) toProductResponse(resp *entity.Product) response.Product { 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{ return response.Product{
ID: resp.ID, ID: resp.ID,
Name: resp.Name, Name: resp.Name,
@ -274,6 +282,7 @@ func (h *Handler) toProductResponse(resp *entity.Product) response.Product {
Status: resp.Status, Status: resp.Status,
Description: resp.Description, Description: resp.Description,
Image: resp.Image, Image: resp.Image,
Category: category,
} }
} }

View File

@ -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,
}
}

View 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,
}
}

View 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,
}
}

View File

@ -13,17 +13,19 @@ type ProductParam struct {
Available product.ProductStock `form:"available" json:"available" example:"1" example:"AVAILABLE/UNAVAILABLE"` Available product.ProductStock `form:"available" json:"available" example:"1" example:"AVAILABLE/UNAVAILABLE"`
Limit int `form:"limit" json:"limit" example:"10"` Limit int `form:"limit" json:"limit" example:"10"`
Offset int `form:"offset" json:"offset" example:"0"` 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{ return entity.ProductSearch{
Search: p.Search, Search: p.Search,
Name: p.Name, Name: p.Name,
Type: p.Type, Type: p.Type,
BranchID: p.BranchID, PartnerID: partnerID,
Available: p.Available, Available: p.Available,
Limit: p.Limit, Limit: p.Limit,
Offset: p.Offset, Offset: p.Offset,
CategoryID: p.CategoryID,
} }
} }
@ -40,6 +42,7 @@ type Product struct {
Description string `json:"description"` Description string `json:"description"`
Stock int64 `json:"stock"` Stock int64 `json:"stock"`
Image string `json:"image"` Image string `json:"image"`
CategoryID int64 `json:"category_id"`
} }
func (e *Product) ToEntity() *entity.Product { func (e *Product) ToEntity() *entity.Product {
@ -51,5 +54,6 @@ func (e *Product) ToEntity() *entity.Product {
Description: e.Description, Description: e.Description,
PartnerID: e.PartnerID, PartnerID: e.PartnerID,
Image: e.Image, Image: e.Image,
CategoryID: &e.CategoryID,
} }
} }

View 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,
}
}

View 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
}

View File

@ -8,6 +8,12 @@ type Product struct {
Status string `json:"status"` Status string `json:"status"`
Description string `json:"description"` Description string `json:"description"`
Image string `json:"image"` Image string `json:"image"`
Category Category `json:"category"`
}
type Category struct {
ID int64 `json:"id"`
Name string `json:"name"`
} }
type ProductList struct { type ProductList struct {

View 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
}

View 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(),
}
}

View File

@ -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
}

View 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"
}

View 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"
}

View File

@ -23,6 +23,8 @@ type OrderDB struct {
TableNumber string `gorm:"column:table_number"` TableNumber string `gorm:"column:table_number"`
PaymentProvider string `gorm:"column:payment_provider"` PaymentProvider string `gorm:"column:payment_provider"`
CustomerName string `gorm:"column:customer_name"` CustomerName string `gorm:"column:customer_name"`
CashierSessionID int64 `gorm:"column:cashier_session_id"`
Description string `gorm:"column:description"`
} }
func (OrderDB) TableName() string { func (OrderDB) TableName() string {
@ -68,6 +70,7 @@ type OrderInquiryDB struct {
PaymentProvider string `gorm:"column:payment_provider"` PaymentProvider string `gorm:"column:payment_provider"`
TableNumber string `gorm:"column:table_number"` TableNumber string `gorm:"column:table_number"`
OrderType string `gorm:"column:order_type"` OrderType string `gorm:"column:order_type"`
CashierSessionID int64 `gorm:"column:cashier_session_id"`
} }
func (OrderInquiryDB) TableName() string { func (OrderInquiryDB) TableName() string {

View File

@ -40,6 +40,7 @@ type OrderRepository interface {
FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error) FindByIDAndPartnerID(ctx mycontext.Context, id int64, partnerID int64) (*entity.Order, error)
GetOrderHistoryByUserID(ctx mycontext.Context, userID int64, req entity.SearchRequest) ([]*entity.Order, int64, 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) 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 { type orderRepository struct {
@ -232,6 +233,28 @@ func (r *orderRepository) UpdateInquiryStatus(ctx mycontext.Context, id string,
return nil 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 { func (r *orderRepository) toOrderDBModel(order *entity.Order) models.OrderDB {
return models.OrderDB{ return models.OrderDB{
ID: order.ID, ID: order.ID,
@ -251,6 +274,7 @@ func (r *orderRepository) toOrderDBModel(order *entity.Order) models.OrderDB {
TableNumber: order.TableNumber, TableNumber: order.TableNumber,
PaymentProvider: order.PaymentProvider, PaymentProvider: order.PaymentProvider,
CustomerName: order.CustomerName, CustomerName: order.CustomerName,
CashierSessionID: order.CashierSessionID,
} }
} }
@ -346,6 +370,7 @@ func (r *orderRepository) toOrderInquiryDBModel(inquiry *entity.OrderInquiry) mo
PaymentProvider: inquiry.PaymentProvider, PaymentProvider: inquiry.PaymentProvider,
OrderType: inquiry.OrderType, OrderType: inquiry.OrderType,
TableNumber: inquiry.TableNumber, TableNumber: inquiry.TableNumber,
CashierSessionID: inquiry.CashierSessionID,
} }
} }
@ -367,6 +392,7 @@ func (r *orderRepository) toDomainOrderInquiryModel(dbModel *models.OrderInquiry
CustomerName: dbModel.CustomerName, CustomerName: dbModel.CustomerName,
PaymentProvider: dbModel.PaymentProvider, PaymentProvider: dbModel.PaymentProvider,
TableNumber: dbModel.TableNumber, TableNumber: dbModel.TableNumber,
CashierSessionID: dbModel.CashierSessionID,
} }
if dbModel.CustomerID != nil { if dbModel.CustomerID != nil {
@ -718,7 +744,7 @@ func (r *orderRepository) GetRevenueOverview(
ctx mycontext.Context, ctx mycontext.Context,
req entity.RevenueOverviewRequest, req entity.RevenueOverviewRequest,
) ([]entity.RevenueOverviewItem, error) { ) ([]entity.RevenueOverviewItem, error) {
var overview []entity.RevenueOverviewItem overview := []entity.RevenueOverviewItem{}
baseQuery := r.db.Model(&models.OrderDB{}). baseQuery := r.db.Model(&models.OrderDB{}).
Where("partner_id = ?", req.PartnerID). Where("partner_id = ?", req.PartnerID).

View File

@ -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) { func (b *ProductRepository) GetProductByID(ctx context.Context, id int64) (*entity.ProductDB, error) {
product := new(entity.ProductDB) 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)) logger.ContextLogger(ctx).Error("error when get by id product", zap.Error(err))
return nil, err return nil, err
} }
@ -84,8 +84,12 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
query = query.Where("type = ? ", req.Type) query = query.Where("type = ? ", req.Type)
} }
if req.BranchID > 0 { if req.CategoryID > 0 {
query = query.Where("branch_id = ? ", req.BranchID) query = query.Where("category_id = ? ", req.CategoryID)
}
if req.PartnerID > 0 {
query = query.Where("partner_id = ? ", req.PartnerID)
} }
if req.Limit > 0 { if req.Limit > 0 {
@ -96,7 +100,7 @@ func (b *ProductRepository) GetAllProducts(ctx context.Context, req entity.Produ
query = query.Offset(req.Offset) 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)) logger.ContextLogger(ctx).Error("error when get all products", zap.Error(err))
return nil, 0, err return nil, 0, err
} }

View File

@ -15,7 +15,6 @@ import (
pg "enaklo-pos-be/internal/repository/payment_gateway" pg "enaklo-pos-be/internal/repository/payment_gateway"
"enaklo-pos-be/internal/repository/products" "enaklo-pos-be/internal/repository/products"
"enaklo-pos-be/internal/repository/sites" "enaklo-pos-be/internal/repository/sites"
"enaklo-pos-be/internal/repository/studios"
transactions "enaklo-pos-be/internal/repository/transaction" transactions "enaklo-pos-be/internal/repository/transaction"
"enaklo-pos-be/internal/repository/trx" "enaklo-pos-be/internal/repository/trx"
"enaklo-pos-be/internal/repository/users" "enaklo-pos-be/internal/repository/users"
@ -28,15 +27,12 @@ import (
"enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/repository/auth" "enaklo-pos-be/internal/repository/auth"
"enaklo-pos-be/internal/repository/crypto" "enaklo-pos-be/internal/repository/crypto"
event "enaklo-pos-be/internal/repository/events"
) )
type RepoManagerImpl struct { type RepoManagerImpl struct {
Crypto Crypto Crypto Crypto
Auth Auth Auth Auth
Event Event
User User User User
Studio Studio
Product Product Product Product
Order Order Order Order
OSS OSSRepository OSS OSSRepository
@ -60,15 +56,15 @@ type RepoManagerImpl struct {
MemberRepository MemberRepository MemberRepository MemberRepository
PartnerSetting PartnerSettingsRepository PartnerSetting PartnerSettingsRepository
UndianRepository UndianRepo UndianRepository UndianRepo
CashierSeasionRepo CashierSessionRepository
CategoryRepository CategoryRepository
} }
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl { func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
return &RepoManagerImpl{ return &RepoManagerImpl{
Crypto: crypto.NewCrypto(cfg.Auth()), Crypto: crypto.NewCrypto(cfg.Auth()),
Auth: auth.NewAuthRepository(db), Auth: auth.NewAuthRepository(db),
Event: event.NewEventRepo(db),
User: users.NewUserRepository(db), User: users.NewUserRepository(db),
Studio: studios.NewStudioRepository(db),
Product: products.NewProductRepository(db), Product: products.NewProductRepository(db),
Order: orders.NewOrderRepository(db), Order: orders.NewOrderRepository(db),
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig), OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
@ -92,6 +88,8 @@ func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
InProgressOrderRepo: NewInProgressOrderRepository(db), InProgressOrderRepo: NewInProgressOrderRepository(db),
PartnerSetting: NewPartnerSettingsRepository(db), PartnerSetting: NewPartnerSettingsRepository(db),
UndianRepository: NewUndianRepository(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 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 { type Crypto interface {
CompareHashAndPassword(hash string, password string) bool CompareHashAndPassword(hash string, password string) bool
ValidateWT(tokenString string) (*jwt.Token, error) ValidateWT(tokenString string) (*jwt.Token, error)

View File

@ -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
}

View File

@ -3,7 +3,6 @@ package routes
import ( import (
"enaklo-pos-be/internal/handlers/http" "enaklo-pos-be/internal/handlers/http"
"enaklo-pos-be/internal/handlers/http/customerauth" "enaklo-pos-be/internal/handlers/http/customerauth"
"enaklo-pos-be/internal/handlers/http/discovery"
"enaklo-pos-be/internal/middlewares" "enaklo-pos-be/internal/middlewares"
"enaklo-pos-be/internal/app" "enaklo-pos-be/internal/app"
@ -19,7 +18,6 @@ func RegisterCustomerRoutes(app *app.Server, serviceManager *services.ServiceMan
optionlMiddleWare := middlewares.OptionalCustomerAuthorizationMiddleware(repoManager.Crypto) optionlMiddleWare := middlewares.OptionalCustomerAuthorizationMiddleware(repoManager.Crypto)
serverRoutes := []HTTPHandlerRoutes{ serverRoutes := []HTTPHandlerRoutes{
discovery.NewHandler(serviceManager.DiscoverService),
customerauth.NewAuthHandler(serviceManager.AuthV2Svc, serviceManager.MemberRegistrationSvc), customerauth.NewAuthHandler(serviceManager.AuthV2Svc, serviceManager.MemberRegistrationSvc),
http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc), http.NewMenuHandler(serviceManager.ProductV2Svc, serviceManager.InProgressSvc),
http.NewCustomerOrderHandler(serviceManager.OrderV2Svc), http.NewCustomerOrderHandler(serviceManager.OrderV2Svc),

View File

@ -8,14 +8,12 @@ import (
"enaklo-pos-be/internal/handlers/http/partner" "enaklo-pos-be/internal/handlers/http/partner"
"enaklo-pos-be/internal/handlers/http/product" "enaklo-pos-be/internal/handlers/http/product"
site "enaklo-pos-be/internal/handlers/http/sites" 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/transaction"
"enaklo-pos-be/internal/handlers/http/user" "enaklo-pos-be/internal/handlers/http/user"
swaggerFiles "github.com/swaggo/files" swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
"net/http" "net/http"
"enaklo-pos-be/internal/handlers/http/event"
"enaklo-pos-be/internal/middlewares" "enaklo-pos-be/internal/middlewares"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -46,9 +44,7 @@ func RegisterPrivateRoutes(app *app.Server, serviceManager *services.ServiceMana
authMiddleware := middlewares.AuthorizationMiddleware(repoManager.Crypto) authMiddleware := middlewares.AuthorizationMiddleware(repoManager.Crypto)
serverRoutes := []HTTPHandlerRoutes{ serverRoutes := []HTTPHandlerRoutes{
auth.NewAuthHandler(serviceManager.AuthSvc), auth.NewAuthHandler(serviceManager.AuthSvc),
event.NewHandler(serviceManager.EventSvc),
user.NewHandler(serviceManager.UserSvc), user.NewHandler(serviceManager.UserSvc),
studio.NewStudioHandler(serviceManager.StudioSvc),
product.NewHandler(serviceManager.ProductSvc), product.NewHandler(serviceManager.ProductSvc),
oss.NewOssHandler(serviceManager.OSSSvc), oss.NewOssHandler(serviceManager.OSSSvc),
partner.NewHandler(serviceManager.PartnerSvc), partner.NewHandler(serviceManager.PartnerSvc),
@ -74,6 +70,8 @@ func RegisterPrivateRoutesV2(app *app.Server, serviceManager *services.ServiceMa
http2.NewMemberRegistrationHandler(serviceManager.MemberRegistrationSvc), http2.NewMemberRegistrationHandler(serviceManager.MemberRegistrationSvc),
http2.NewCustomerHandler(serviceManager.CustomerV2Svc), http2.NewCustomerHandler(serviceManager.CustomerV2Svc),
http2.NewInProgressOrderHandler(serviceManager.InProgressSvc), http2.NewInProgressOrderHandler(serviceManager.InProgressSvc),
http2.NewCashierSession(serviceManager.CashierSvc),
http2.NewCategoryHandler(serviceManager.CategorySvc),
} }
for _, handler := range serverRoutes { for _, handler := range serverRoutes {

View File

@ -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
}

View File

@ -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
}

View File

@ -4,17 +4,17 @@ import (
"context" "context"
"enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/common/mycontext"
"enaklo-pos-be/internal/services/balance" "enaklo-pos-be/internal/services/balance"
"enaklo-pos-be/internal/services/discovery"
service "enaklo-pos-be/internal/services/license" service "enaklo-pos-be/internal/services/license"
"enaklo-pos-be/internal/services/member" "enaklo-pos-be/internal/services/member"
"enaklo-pos-be/internal/services/oss" "enaklo-pos-be/internal/services/oss"
"enaklo-pos-be/internal/services/partner" "enaklo-pos-be/internal/services/partner"
"enaklo-pos-be/internal/services/product" "enaklo-pos-be/internal/services/product"
site "enaklo-pos-be/internal/services/sites" site "enaklo-pos-be/internal/services/sites"
"enaklo-pos-be/internal/services/studio"
"enaklo-pos-be/internal/services/transaction" "enaklo-pos-be/internal/services/transaction"
"enaklo-pos-be/internal/services/users" "enaklo-pos-be/internal/services/users"
authSvc "enaklo-pos-be/internal/services/v2/auth" 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" customerSvc "enaklo-pos-be/internal/services/v2/customer"
"enaklo-pos-be/internal/services/v2/inprogress_order" "enaklo-pos-be/internal/services/v2/inprogress_order"
orderSvc "enaklo-pos-be/internal/services/v2/order" orderSvc "enaklo-pos-be/internal/services/v2/order"
@ -29,14 +29,11 @@ import (
"enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/entity"
"enaklo-pos-be/internal/repository" "enaklo-pos-be/internal/repository"
"enaklo-pos-be/internal/services/auth" "enaklo-pos-be/internal/services/auth"
"enaklo-pos-be/internal/services/event"
) )
type ServiceManagerImpl struct { type ServiceManagerImpl struct {
AuthSvc Auth AuthSvc Auth
EventSvc Event
UserSvc User UserSvc User
StudioSvc Studio
ProductSvc Product ProductSvc Product
OSSSvc OSSService OSSSvc OSSService
PartnerSvc Partner PartnerSvc Partner
@ -44,7 +41,6 @@ type ServiceManagerImpl struct {
LicenseSvc License LicenseSvc License
Transaction Transaction Transaction Transaction
Balance Balance Balance Balance
DiscoverService DiscoverService
OrderV2Svc orderSvc.Service OrderV2Svc orderSvc.Service
CustomerV2Svc customerSvc.Service CustomerV2Svc customerSvc.Service
@ -53,6 +49,8 @@ type ServiceManagerImpl struct {
InProgressSvc inprogress_order.InProgressOrderService InProgressSvc inprogress_order.InProgressOrderService
AuthV2Svc authSvc.Service AuthV2Svc authSvc.Service
UndianSvc undian.Service UndianSvc undian.Service
CashierSvc cashier_session.Service
CategorySvc category.Service
} }
func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl) *ServiceManagerImpl { 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) custSvcV2 := customerSvc.New(repo.CustomerRepo, repo.EmailService)
productSvcV2 := productSvc.New(repo.ProductRepo) productSvcV2 := productSvc.New(repo.ProductRepo)
partnerSettings := partner_settings.NewPartnerSettingsService(repo.PartnerSetting) partnerSettings := partner_settings.NewPartnerSettingsService(repo.PartnerSetting)
cashierSvc := cashier_session.New(repo.CashierSeasionRepo)
orderService := orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings, repo.UndianRepository) 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) inprogressOrder := inprogress_order.NewInProgressOrderService(repo.OrderRepo, orderService, productSvcV2)
categorySvc := category.New(repo.CategoryRepository)
return &ServiceManagerImpl{ return &ServiceManagerImpl{
AuthSvc: auth.New(repo.Auth, repo.Crypto, repo.User, repo.EmailService, cfg.Email, repo.Trx, repo.License), 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), UserSvc: users.NewUserService(repo.User),
StudioSvc: studio.NewStudioService(repo.Studio),
ProductSvc: product.NewProductService(repo.Product), ProductSvc: product.NewProductService(repo.Product),
OSSSvc: oss.NewOSSService(repo.OSS), OSSSvc: oss.NewOSSService(repo.OSS),
PartnerSvc: partner.NewPartnerService( PartnerSvc: partner.NewPartnerService(
@ -76,14 +76,15 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
LicenseSvc: service.NewLicenseService(repo.License), LicenseSvc: service.NewLicenseService(repo.License),
Transaction: transaction.New(repo.Transaction, repo.Wallet, repo.Trx), Transaction: transaction.New(repo.Transaction, repo.Wallet, repo.Trx),
Balance: balance.NewBalanceService(repo.Wallet, repo.Trx, repo.Crypto, &cfg.Withdraw, repo.Transaction), 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, cashierSvc),
OrderV2Svc: orderSvc.New(repo.OrderRepo, productSvcV2, custSvcV2, repo.TransactionRepo, repo.Crypto, &cfg.Order, repo.EmailService, partnerSettings, repo.UndianRepository),
MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2, repo.Crypto), MemberRegistrationSvc: member.NewMemberRegistrationService(repo.MemberRepository, repo.EmailService, custSvcV2, repo.Crypto),
CustomerV2Svc: custSvcV2, CustomerV2Svc: custSvcV2,
InProgressSvc: inprogressOrder, InProgressSvc: inprogressOrder,
ProductV2Svc: productSvcV2, ProductV2Svc: productSvcV2,
AuthV2Svc: authSvc.New(repo.CustomerRepo, repo.Crypto), AuthV2Svc: authSvc.New(repo.CustomerRepo, repo.Crypto),
UndianSvc: undian.New(repo.UndianRepository), UndianSvc: undian.New(repo.UndianRepository),
CashierSvc: cashierSvc,
CategorySvc: categorySvc,
} }
} }
@ -93,14 +94,6 @@ type Auth interface {
ResetPassword(ctx mycontext.Context, oldPassword, newPassword string) error 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 { type User interface {
Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error) Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error)
CreateWithTx(ctx mycontext.Context, tx *gorm.DB, 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 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 { type Product interface {
Create(ctx mycontext.Context, productReq *entity.Product) (*entity.Product, error) Create(ctx mycontext.Context, productReq *entity.Product) (*entity.Product, error)
Update(ctx mycontext.Context, id int64, 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 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 { type OSSService interface {
UploadFile(ctx context.Context, req *entity.UploadFileRequest) (*entity.UploadFileResponse, error) 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) WithdrawInquiry(ctx context.Context, req *entity.BalanceWithdrawInquiry) (*entity.BalanceWithdrawInquiryResponse, error)
WithdrawExecute(ctx mycontext.Context, req *entity.WalletWithdrawRequest) (*entity.WalletWithdrawResponse, 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)
}

View File

@ -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
}

View 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
}

View 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
}

View File

@ -12,6 +12,13 @@ import (
func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context, func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context,
req *entity.OrderRequest) (*entity.OrderInquiryResponse, error) { 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) productIDs, filteredItems, err := s.ValidateOrderItems(ctx, req.OrderItems)
if err != nil { if err != nil {
return nil, err return nil, err
@ -60,6 +67,7 @@ func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context,
req.PaymentProvider, req.PaymentProvider,
req.TableNumber, req.TableNumber,
req.OrderType, req.OrderType,
cashierSession.ID,
) )
for _, item := range req.OrderItems { for _, item := range req.OrderItems {

View File

@ -6,6 +6,7 @@ import (
"enaklo-pos-be/internal/constants" "enaklo-pos-be/internal/constants"
"enaklo-pos-be/internal/entity" "enaklo-pos-be/internal/entity"
"fmt" "fmt"
"github.com/pkg/errors"
"go.uber.org/zap" "go.uber.org/zap"
"time" "time"
) )
@ -36,6 +37,20 @@ func (s *orderSvc) ExecuteOrderInquiry(ctx mycontext.Context,
}, nil }, 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( func (s *orderSvc) processPostOrderActions(
ctx mycontext.Context, ctx mycontext.Context,
order *entity.Order, order *entity.Order,

View File

@ -12,6 +12,7 @@ type Repository interface {
CreateInquiry(ctx mycontext.Context, inquiry *entity.OrderInquiry) (*entity.OrderInquiry, error) CreateInquiry(ctx mycontext.Context, inquiry *entity.OrderInquiry) (*entity.OrderInquiry, error)
FindInquiryByID(ctx mycontext.Context, id string) (*entity.OrderInquiry, error) FindInquiryByID(ctx mycontext.Context, id string) (*entity.OrderInquiry, error)
UpdateInquiryStatus(ctx mycontext.Context, id string, status string) 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) GetOrderHistoryByPartnerID(ctx mycontext.Context, partnerID int64, req entity.SearchRequest) ([]*entity.Order, int64, error)
GetOrderPaymentMethodBreakdown( GetOrderPaymentMethodBreakdown(
ctx mycontext.Context, ctx mycontext.Context,
@ -65,6 +66,7 @@ type Service interface {
req *entity.OrderRequest) (*entity.OrderInquiryResponse, error) req *entity.OrderRequest) (*entity.OrderInquiryResponse, error)
ExecuteOrderInquiry(ctx mycontext.Context, ExecuteOrderInquiry(ctx mycontext.Context,
token string, paymentMethod, paymentProvider string, inProgressOrderID int64) (*entity.OrderResponse, error) 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) GetOrderHistory(ctx mycontext.Context, partnerID int64, request entity.SearchRequest) ([]*entity.Order, int64, error)
CalculateOrderTotals( CalculateOrderTotals(
ctx mycontext.Context, ctx mycontext.Context,
@ -122,6 +124,10 @@ type VoucherUndianRepo interface {
CreateUndianVouchers(ctx mycontext.Context, vouchers []*entity.UndianVoucherDB) error CreateUndianVouchers(ctx mycontext.Context, vouchers []*entity.UndianVoucherDB) error
} }
type CashierSvc interface {
GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error)
}
type orderSvc struct { type orderSvc struct {
repo Repository repo Repository
product ProductService product ProductService
@ -133,6 +139,7 @@ type orderSvc struct {
partnerSetting PartnerSettings partnerSetting PartnerSettings
inprogressOrder InProgressOrderRepository inprogressOrder InProgressOrderRepository
voucherUndianRepo VoucherUndianRepo voucherUndianRepo VoucherUndianRepo
cashierSvc CashierSvc
} }
func New( func New(
@ -145,6 +152,7 @@ func New(
notification NotificationService, notification NotificationService,
partnerSetting PartnerSettings, partnerSetting PartnerSettings,
voucherUndianRepo VoucherUndianRepo, voucherUndianRepo VoucherUndianRepo,
cashierSvc CashierSvc,
) Service { ) Service {
return &orderSvc{ return &orderSvc{
repo: repo, repo: repo,
@ -156,5 +164,6 @@ func New(
notification: notification, notification: notification,
partnerSetting: partnerSetting, partnerSetting: partnerSetting,
voucherUndianRepo: voucherUndianRepo, voucherUndianRepo: voucherUndianRepo,
cashierSvc: cashierSvc,
} }
} }