This commit is contained in:
aditya.siregar
2025-07-18 20:10:29 +07:00
parent 1bceae010b
commit 4f5950543e
511 changed files with 24132 additions and 34137 deletions
+154
View File
@@ -0,0 +1,154 @@
package mappers
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func CategoryEntityToModel(entity *entities.Category) *models.Category {
if entity == nil {
return nil
}
return &models.Category{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
Name: entity.Name,
Description: entity.Description,
ImageURL: nil, // Entity doesn't have ImageURL, model does
SortOrder: 0, // Entity doesn't have SortOrder, model does
IsActive: true, // Entity doesn't have IsActive, default to true
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func CategoryModelToEntity(model *models.Category) *entities.Category {
if model == nil {
return nil
}
metadata := entities.Metadata{}
if model.ImageURL != nil {
metadata["image_url"] = *model.ImageURL
}
metadata["sort_order"] = model.SortOrder
return &entities.Category{
ID: model.ID,
OrganizationID: model.OrganizationID,
Name: model.Name,
Description: model.Description,
BusinessType: "restaurant", // Default business type
Metadata: metadata,
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
func CreateCategoryRequestToEntity(req *models.CreateCategoryRequest) *entities.Category {
if req == nil {
return nil
}
metadata := entities.Metadata{}
if req.ImageURL != nil {
metadata["image_url"] = *req.ImageURL
}
metadata["sort_order"] = req.SortOrder
return &entities.Category{
OrganizationID: req.OrganizationID,
Name: req.Name,
Description: req.Description,
BusinessType: "restaurant", // Default business type
Metadata: metadata,
}
}
func CategoryEntityToResponse(entity *entities.Category) *models.CategoryResponse {
if entity == nil {
return nil
}
// Extract image URL and sort order from metadata
var imageURL *string
var sortOrder int
if entity.Metadata != nil {
if imgURL, exists := entity.Metadata["image_url"]; exists {
if imgURLStr, ok := imgURL.(string); ok {
imageURL = &imgURLStr
}
}
if sort, exists := entity.Metadata["sort_order"]; exists {
if sortInt, ok := sort.(int); ok {
sortOrder = sortInt
} else if sortFloat, ok := sort.(float64); ok {
sortOrder = int(sortFloat)
}
}
}
return &models.CategoryResponse{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
Name: entity.Name,
Description: entity.Description,
ImageURL: imageURL,
SortOrder: sortOrder,
IsActive: true, // Default to true since entity doesn't have this field
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func UpdateCategoryEntityFromRequest(entity *entities.Category, req *models.UpdateCategoryRequest) {
if entity == nil || req == nil {
return
}
if req.Name != nil {
entity.Name = *req.Name
}
if req.Description != nil {
entity.Description = req.Description
}
if entity.Metadata == nil {
entity.Metadata = make(entities.Metadata)
}
if req.ImageURL != nil {
entity.Metadata["image_url"] = *req.ImageURL
}
if req.SortOrder != nil {
entity.Metadata["sort_order"] = *req.SortOrder
}
}
func CategoryEntitiesToModels(entities []*entities.Category) []*models.Category {
if entities == nil {
return nil
}
models := make([]*models.Category, len(entities))
for i, entity := range entities {
models[i] = CategoryEntityToModel(entity)
}
return models
}
func CategoryEntitiesToResponses(entities []*entities.Category) []*models.CategoryResponse {
if entities == nil {
return nil
}
responses := make([]*models.CategoryResponse, len(entities))
for i, entity := range entities {
responses[i] = CategoryEntityToResponse(entity)
}
return responses
}
+71
View File
@@ -0,0 +1,71 @@
package mappers
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
"github.com/google/uuid"
)
// ToCustomerResponse converts a customer entity to a customer response
func ToCustomerResponse(customer *entities.Customer) *models.CustomerResponse {
if customer == nil {
return nil
}
return &models.CustomerResponse{
ID: customer.ID,
OrganizationID: customer.OrganizationID,
Name: customer.Name,
Email: customer.Email,
Phone: customer.Phone,
Address: customer.Address,
IsDefault: customer.IsDefault,
IsActive: customer.IsActive,
Metadata: customer.Metadata,
CreatedAt: customer.CreatedAt,
UpdatedAt: customer.UpdatedAt,
}
}
// ToCustomerResponses converts a slice of customer entities to customer responses
func ToCustomerResponses(customers []entities.Customer) []models.CustomerResponse {
responses := make([]models.CustomerResponse, len(customers))
for i, customer := range customers {
responses[i] = *ToCustomerResponse(&customer)
}
return responses
}
// ToCustomerEntity converts a create customer request to a customer entity
func ToCustomerEntity(req *models.CreateCustomerRequest, organizationID uuid.UUID) *entities.Customer {
return &entities.Customer{
OrganizationID: organizationID,
Name: req.Name,
Email: req.Email,
Phone: req.Phone,
Address: req.Address,
IsDefault: false, // New customers are not default by default
IsActive: true,
Metadata: entities.Metadata{},
}
}
// UpdateCustomerEntity updates a customer entity with update request data
func UpdateCustomerEntity(customer *entities.Customer, req *models.UpdateCustomerRequest) {
if req.Name != nil {
customer.Name = *req.Name
}
if req.Email != nil {
customer.Email = req.Email
}
if req.Phone != nil {
customer.Phone = req.Phone
}
if req.Address != nil {
customer.Address = req.Address
}
if req.IsActive != nil {
customer.IsActive = *req.IsActive
}
}
+98
View File
@@ -0,0 +1,98 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
"strings"
"fmt"
"github.com/google/uuid"
)
func FileEntityToResponse(file *entities.File) *models.FileResponse {
if file == nil {
return nil
}
return &models.FileResponse{
ID: file.ID,
OrganizationID: file.OrganizationID,
UserID: file.UserID,
FileName: file.FileName,
OriginalName: file.OriginalName,
FileURL: file.FileURL,
FileSize: file.FileSize,
MimeType: file.MimeType,
FileType: file.FileType,
UploadPath: file.UploadPath,
IsPublic: file.IsPublic,
Metadata: map[string]interface{}(file.Metadata),
CreatedAt: file.CreatedAt,
UpdatedAt: file.UpdatedAt,
}
}
func UploadFileRequestToEntity(req *models.UploadFileRequest, organizationID, userID uuid.UUID, fileName, originalName, fileURL, mimeType, uploadPath string, fileSize int64) *entities.File {
if req == nil {
return nil
}
isPublic := true
if req.IsPublic != nil {
isPublic = *req.IsPublic
}
return &entities.File{
OrganizationID: organizationID,
UserID: userID,
FileName: fileName,
OriginalName: originalName,
FileURL: fileURL,
FileSize: fileSize,
MimeType: mimeType,
FileType: string(req.FileType),
UploadPath: uploadPath,
IsPublic: isPublic,
Metadata: entities.Metadata(req.Metadata),
}
}
// Update request to entity updates
func UpdateFileRequestToEntityUpdates(req *models.UpdateFileRequest) map[string]interface{} {
updates := make(map[string]interface{})
if req.IsPublic != nil {
updates["is_public"] = *req.IsPublic
}
if req.Metadata != nil {
updates["metadata"] = entities.Metadata(req.Metadata)
}
return updates
}
func FileEntitiesToResponses(files []*entities.File) []*models.FileResponse {
if files == nil {
return nil
}
responses := make([]*models.FileResponse, len(files))
for i, file := range files {
response := FileEntityToResponse(file)
if response != nil {
responses[i] = response
}
}
return responses
}
func GenerateFileName(originalName string, organizationID, userID uuid.UUID) string {
cleanedName := strings.ReplaceAll(originalName, " ", "")
return fmt.Sprintf("/public/%s_%s", organizationID.String(), cleanedName)
}
func GetFileTypeFromMimeType(mimeType string) constants.FileType {
return constants.GetFileTypeFromMimeType(mimeType)
}
+114
View File
@@ -0,0 +1,114 @@
package mappers
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func InventoryEntityToModel(entity *entities.Inventory) *models.Inventory {
if entity == nil {
return nil
}
return &models.Inventory{
ID: entity.ID,
OutletID: entity.OutletID,
ProductID: entity.ProductID,
Quantity: entity.Quantity,
ReorderLevel: entity.ReorderLevel,
UpdatedAt: entity.UpdatedAt,
}
}
func InventoryModelToEntity(model *models.Inventory) *entities.Inventory {
if model == nil {
return nil
}
return &entities.Inventory{
ID: model.ID,
OutletID: model.OutletID,
ProductID: model.ProductID,
Quantity: model.Quantity,
ReorderLevel: model.ReorderLevel,
UpdatedAt: model.UpdatedAt,
}
}
func CreateInventoryRequestToEntity(req *models.CreateInventoryRequest) *entities.Inventory {
if req == nil {
return nil
}
return &entities.Inventory{
OutletID: req.OutletID,
ProductID: req.ProductID,
Quantity: req.Quantity,
ReorderLevel: req.ReorderLevel,
}
}
func InventoryEntityToResponse(entity *entities.Inventory) *models.InventoryResponse {
if entity == nil {
return nil
}
return &models.InventoryResponse{
ID: entity.ID,
OutletID: entity.OutletID,
ProductID: entity.ProductID,
Quantity: entity.Quantity,
ReorderLevel: entity.ReorderLevel,
IsLowStock: entity.IsLowStock(),
UpdatedAt: entity.UpdatedAt,
}
}
func UpdateInventoryEntityFromRequest(entity *entities.Inventory, req *models.UpdateInventoryRequest) {
if entity == nil || req == nil {
return
}
if req.Quantity != nil {
entity.Quantity = *req.Quantity
}
if req.ReorderLevel != nil {
entity.ReorderLevel = *req.ReorderLevel
}
}
func InventoryAdjustmentRequestToModel(req *models.InventoryAdjustmentRequest) *models.InventoryAdjustmentRequest {
if req == nil {
return nil
}
return &models.InventoryAdjustmentRequest{
Delta: req.Delta,
Reason: req.Reason,
}
}
func InventoryEntitiesToModels(entities []*entities.Inventory) []*models.Inventory {
if entities == nil {
return nil
}
models := make([]*models.Inventory, len(entities))
for i, entity := range entities {
models[i] = InventoryEntityToModel(entity)
}
return models
}
func InventoryEntitiesToResponses(entities []*entities.Inventory) []*models.InventoryResponse {
if entities == nil {
return nil
}
responses := make([]*models.InventoryResponse, len(entities))
for i, entity := range entities {
responses[i] = InventoryEntityToResponse(entity)
}
return responses
}
+298
View File
@@ -0,0 +1,298 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
"github.com/google/uuid"
)
// Entity to Response mappers
func OrderEntityToResponse(order *entities.Order) *models.OrderResponse {
if order == nil {
return nil
}
response := &models.OrderResponse{
ID: order.ID,
OrganizationID: order.OrganizationID,
OutletID: order.OutletID,
UserID: order.UserID,
CustomerID: order.CustomerID,
OrderNumber: order.OrderNumber,
TableNumber: order.TableNumber,
OrderType: constants.OrderType(order.OrderType),
Status: constants.OrderStatus(order.Status),
Subtotal: order.Subtotal,
TaxAmount: order.TaxAmount,
DiscountAmount: order.DiscountAmount,
TotalAmount: order.TotalAmount,
TotalCost: order.TotalCost,
PaymentStatus: constants.PaymentStatus(order.PaymentStatus),
RefundAmount: order.RefundAmount,
IsVoid: order.IsVoid,
IsRefund: order.IsRefund,
VoidReason: order.VoidReason,
VoidedAt: order.VoidedAt,
VoidedBy: order.VoidedBy,
RefundReason: order.RefundReason,
RefundedAt: order.RefundedAt,
RefundedBy: order.RefundedBy,
Metadata: map[string]interface{}(order.Metadata),
CreatedAt: order.CreatedAt,
UpdatedAt: order.UpdatedAt,
}
// Map order items
if order.OrderItems != nil {
response.OrderItems = make([]models.OrderItemResponse, len(order.OrderItems))
for i, item := range order.OrderItems {
response.OrderItems[i] = *OrderItemEntityToResponse(&item)
}
}
// Map payments
if order.Payments != nil {
response.Payments = make([]models.PaymentResponse, len(order.Payments))
for i, payment := range order.Payments {
response.Payments[i] = *PaymentEntityToResponse(&payment)
}
}
return response
}
func OrderItemEntityToResponse(item *entities.OrderItem) *models.OrderItemResponse {
if item == nil {
return nil
}
response := &models.OrderItemResponse{
ID: item.ID,
OrderID: item.OrderID,
ProductID: item.ProductID,
ProductVariantID: item.ProductVariantID,
Quantity: item.Quantity,
UnitPrice: item.UnitPrice,
TotalPrice: item.TotalPrice,
UnitCost: item.UnitCost,
TotalCost: item.TotalCost,
RefundAmount: item.RefundAmount,
RefundQuantity: item.RefundQuantity,
IsPartiallyRefunded: item.IsPartiallyRefunded,
IsFullyRefunded: item.IsFullyRefunded,
RefundReason: item.RefundReason,
RefundedAt: item.RefundedAt,
RefundedBy: item.RefundedBy,
Modifiers: []map[string]interface{}(item.Modifiers),
Notes: item.Notes,
Metadata: map[string]interface{}(item.Metadata),
Status: constants.OrderItemStatus(item.Status),
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
// Set product name if product is preloaded
if item.Product.ID != uuid.Nil {
response.ProductName = item.Product.Name
}
// Set product variant name if product variant is preloaded
if item.ProductVariant != nil {
response.ProductVariantName = &item.ProductVariant.Name
}
return response
}
func PaymentEntityToResponse(payment *entities.Payment) *models.PaymentResponse {
if payment == nil {
return nil
}
response := &models.PaymentResponse{
ID: payment.ID,
OrderID: payment.OrderID,
PaymentMethodID: payment.PaymentMethodID,
Amount: payment.Amount,
Status: constants.PaymentTransactionStatus(payment.Status),
TransactionID: payment.TransactionID,
SplitNumber: payment.SplitNumber,
SplitTotal: payment.SplitTotal,
SplitDescription: payment.SplitDescription,
RefundAmount: payment.RefundAmount,
RefundReason: payment.RefundReason,
RefundedAt: payment.RefundedAt,
RefundedBy: payment.RefundedBy,
Metadata: map[string]interface{}(payment.Metadata),
CreatedAt: payment.CreatedAt,
UpdatedAt: payment.UpdatedAt,
}
// Map payment order items
if payment.PaymentOrderItems != nil {
response.PaymentOrderItems = make([]models.PaymentOrderItemResponse, len(payment.PaymentOrderItems))
for i, item := range payment.PaymentOrderItems {
response.PaymentOrderItems[i] = *PaymentOrderItemEntityToResponse(&item)
}
}
return response
}
func PaymentOrderItemEntityToResponse(item *entities.PaymentOrderItem) *models.PaymentOrderItemResponse {
if item == nil {
return nil
}
return &models.PaymentOrderItemResponse{
ID: item.ID,
PaymentID: item.PaymentID,
OrderItemID: item.OrderItemID,
Amount: item.Amount,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
}
// Request to Entity mappers
func CreateOrderRequestToEntity(req *models.CreateOrderRequest, organizationID uuid.UUID) *entities.Order {
if req == nil {
return nil
}
order := &entities.Order{
OrganizationID: organizationID,
OutletID: req.OutletID,
UserID: req.UserID,
CustomerID: req.CustomerID,
TableNumber: req.TableNumber,
OrderType: entities.OrderType(req.OrderType),
Status: entities.OrderStatusPending,
PaymentStatus: entities.PaymentStatusPending,
IsVoid: false,
IsRefund: false,
Metadata: entities.Metadata(req.Metadata),
}
return order
}
func CreateOrderItemRequestToEntity(req *models.CreateOrderItemRequest) *entities.OrderItem {
if req == nil {
return nil
}
// UnitPrice will be set from database product price, not from request
return &entities.OrderItem{
ProductID: req.ProductID,
ProductVariantID: req.ProductVariantID,
Quantity: req.Quantity,
UnitPrice: 0, // Will be set from database product price
Modifiers: entities.Modifiers(req.Modifiers),
Notes: req.Notes,
Metadata: entities.Metadata(req.Metadata),
Status: entities.OrderItemStatusPending,
}
}
func CreatePaymentRequestToEntity(req *models.CreatePaymentRequest) *entities.Payment {
if req == nil {
return nil
}
payment := &entities.Payment{
OrderID: req.OrderID,
PaymentMethodID: req.PaymentMethodID,
Amount: req.Amount,
Status: entities.PaymentTransactionStatusPending,
TransactionID: req.TransactionID,
SplitNumber: req.SplitNumber,
SplitTotal: req.SplitTotal,
SplitDescription: req.SplitDescription,
Metadata: entities.Metadata(req.Metadata),
}
return payment
}
func CreatePaymentOrderItemRequestToEntity(req *models.CreatePaymentOrderItemRequest) *entities.PaymentOrderItem {
if req == nil {
return nil
}
return &entities.PaymentOrderItem{
OrderItemID: req.OrderItemID,
Amount: req.Amount,
}
}
// Update request to entity updates
func UpdateOrderRequestToEntityUpdates(req *models.UpdateOrderRequest) map[string]interface{} {
updates := make(map[string]interface{})
if req.TableNumber != nil {
updates["table_number"] = *req.TableNumber
}
if req.Status != nil {
updates["status"] = entities.OrderStatus(*req.Status)
}
if req.DiscountAmount != nil {
updates["discount_amount"] = *req.DiscountAmount
}
if req.Metadata != nil {
updates["metadata"] = entities.Metadata(req.Metadata)
}
return updates
}
// Helper functions for list responses
func OrderEntitiesToResponses(orders []*entities.Order) []models.OrderResponse {
if orders == nil {
return nil
}
responses := make([]models.OrderResponse, len(orders))
for i, order := range orders {
response := OrderEntityToResponse(order)
if response != nil {
responses[i] = *response
}
}
return responses
}
func OrderItemEntitiesToResponses(items []*entities.OrderItem) []models.OrderItemResponse {
if items == nil {
return nil
}
responses := make([]models.OrderItemResponse, len(items))
for i, item := range items {
response := OrderItemEntityToResponse(item)
if response != nil {
responses[i] = *response
}
}
return responses
}
func PaymentEntitiesToResponses(payments []*entities.Payment) []models.PaymentResponse {
if payments == nil {
return nil
}
responses := make([]models.PaymentResponse, len(payments))
for i, payment := range payments {
response := PaymentEntityToResponse(payment)
if response != nil {
responses[i] = *response
}
}
return responses
}
+142
View File
@@ -0,0 +1,142 @@
package mappers
import (
"testing"
"time"
"apskel-pos-be/internal/entities"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestOrderItemEntityToResponse_WithProductNames(t *testing.T) {
// Arrange
productID := uuid.New()
variantID := uuid.New()
orderID := uuid.New()
itemID := uuid.New()
product := entities.Product{
ID: productID,
Name: "Test Product",
}
productVariant := entities.ProductVariant{
ID: variantID,
Name: "Test Variant",
}
orderItem := &entities.OrderItem{
ID: itemID,
OrderID: orderID,
ProductID: productID,
ProductVariantID: &variantID,
Quantity: 2,
UnitPrice: 10.0,
TotalPrice: 20.0,
UnitCost: 5.0,
TotalCost: 10.0,
Status: entities.OrderItemStatusPending,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Product: product,
ProductVariant: &productVariant,
}
// Act
result := OrderItemEntityToResponse(orderItem)
// Assert
assert.NotNil(t, result)
assert.Equal(t, itemID, result.ID)
assert.Equal(t, orderID, result.OrderID)
assert.Equal(t, productID, result.ProductID)
assert.Equal(t, "Test Product", result.ProductName)
assert.Equal(t, &variantID, result.ProductVariantID)
assert.Equal(t, "Test Variant", *result.ProductVariantName)
assert.Equal(t, 2, result.Quantity)
assert.Equal(t, 10.0, result.UnitPrice)
assert.Equal(t, 20.0, result.TotalPrice)
}
func TestOrderItemEntityToResponse_WithoutProductVariant(t *testing.T) {
// Arrange
productID := uuid.New()
orderID := uuid.New()
itemID := uuid.New()
product := entities.Product{
ID: productID,
Name: "Test Product",
}
orderItem := &entities.OrderItem{
ID: itemID,
OrderID: orderID,
ProductID: productID,
ProductVariantID: nil,
Quantity: 1,
UnitPrice: 15.0,
TotalPrice: 15.0,
UnitCost: 7.0,
TotalCost: 7.0,
Status: entities.OrderItemStatusPending,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Product: product,
ProductVariant: nil,
}
// Act
result := OrderItemEntityToResponse(orderItem)
// Assert
assert.NotNil(t, result)
assert.Equal(t, itemID, result.ID)
assert.Equal(t, orderID, result.OrderID)
assert.Equal(t, productID, result.ProductID)
assert.Equal(t, "Test Product", result.ProductName)
assert.Nil(t, result.ProductVariantID)
assert.Nil(t, result.ProductVariantName)
assert.Equal(t, 1, result.Quantity)
assert.Equal(t, 15.0, result.UnitPrice)
assert.Equal(t, 15.0, result.TotalPrice)
}
func TestOrderItemEntityToResponse_WithoutProductPreload(t *testing.T) {
// Arrange
productID := uuid.New()
orderID := uuid.New()
itemID := uuid.New()
// Create order item without preloaded product (empty product)
orderItem := &entities.OrderItem{
ID: itemID,
OrderID: orderID,
ProductID: productID,
ProductVariantID: nil,
Quantity: 1,
UnitPrice: 10.0,
TotalPrice: 10.0,
UnitCost: 5.0,
TotalCost: 5.0,
Status: entities.OrderItemStatusPending,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Product: entities.Product{}, // Empty product
ProductVariant: nil,
}
// Act
result := OrderItemEntityToResponse(orderItem)
// Assert
assert.NotNil(t, result)
assert.Equal(t, itemID, result.ID)
assert.Equal(t, orderID, result.OrderID)
assert.Equal(t, productID, result.ProductID)
assert.Equal(t, "", result.ProductName) // Should be empty since product is not preloaded
assert.Nil(t, result.ProductVariantID)
assert.Nil(t, result.ProductVariantName)
}
+79
View File
@@ -0,0 +1,79 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func OrganizationEntityToModel(entity *entities.Organization) *models.Organization {
if entity == nil {
return nil
}
return &models.Organization{
ID: entity.ID,
Name: entity.Name,
Email: entity.Email,
PhoneNumber: entity.PhoneNumber,
PlanType: constants.PlanType(entity.PlanType),
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func OrganizationModelToEntity(model *models.Organization) *entities.Organization {
if model == nil {
return nil
}
return &entities.Organization{
ID: model.ID,
Name: model.Name,
Email: model.Email,
PhoneNumber: model.PhoneNumber,
PlanType: string(model.PlanType),
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
func OrganizationEntityToResponse(entity *entities.Organization) *models.OrganizationResponse {
if entity == nil {
return nil
}
return &models.OrganizationResponse{
ID: entity.ID,
Name: entity.Name,
Email: entity.Email,
PhoneNumber: entity.PhoneNumber,
PlanType: constants.PlanType(entity.PlanType),
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func OrganizationEntitiesToModels(entities []*entities.Organization) []*models.Organization {
if entities == nil {
return nil
}
models := make([]*models.Organization, len(entities))
for i, entity := range entities {
models[i] = OrganizationEntityToModel(entity)
}
return models
}
func OrganizationEntitiesToResponses(entities []*entities.Organization) []*models.OrganizationResponse {
if entities == nil {
return nil
}
responses := make([]*models.OrganizationResponse, len(entities))
for i, entity := range entities {
responses[i] = OrganizationEntityToResponse(entity)
}
return responses
}
+37
View File
@@ -0,0 +1,37 @@
package mappers
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func OutletEntityToResponse(entity *entities.Outlet) *models.OutletResponse {
if entity == nil {
return nil
}
return &models.OutletResponse{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
Name: entity.Name,
Address: entity.Address,
Timezone: entity.Timezone,
Currency: entity.Currency,
TaxRate: entity.TaxRate,
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func OutletEntitiesToResponses(entities []*entities.Outlet) []*models.OutletResponse {
if entities == nil {
return nil
}
responses := make([]*models.OutletResponse, len(entities))
for i, entity := range entities {
responses[i] = OutletEntityToResponse(entity)
}
return responses
}
+179
View File
@@ -0,0 +1,179 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func CreatePaymentMethodRequestToEntity(req *models.CreatePaymentMethodRequest) *entities.PaymentMethod {
paymentMethod := &entities.PaymentMethod{
OrganizationID: req.OrganizationID,
Name: req.Name,
Type: entities.PaymentMethodType(req.Type),
Processor: req.Processor,
Configuration: entities.Metadata(req.Configuration),
IsActive: true, // Default to active
}
if req.IsActive != nil {
paymentMethod.IsActive = *req.IsActive
}
return paymentMethod
}
func UpdatePaymentMethodEntityFromRequest(entity *entities.PaymentMethod, req *models.UpdatePaymentMethodRequest) {
if req.Name != nil {
entity.Name = *req.Name
}
if req.Type != nil {
entity.Type = entities.PaymentMethodType(*req.Type)
}
if req.Processor != nil {
entity.Processor = req.Processor
}
if req.Configuration != nil {
entity.Configuration = entities.Metadata(req.Configuration)
}
if req.IsActive != nil {
entity.IsActive = *req.IsActive
}
}
func PaymentMethodEntityToResponse(entity *entities.PaymentMethod) *models.PaymentMethodResponse {
if entity == nil {
return nil
}
return &models.PaymentMethodResponse{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
Name: entity.Name,
Type: constants.PaymentMethodType(entity.Type),
Processor: entity.Processor,
Configuration: map[string]interface{}(entity.Configuration),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func PaymentMethodEntityToModel(entity *entities.PaymentMethod) *models.PaymentMethod {
if entity == nil {
return nil
}
return &models.PaymentMethod{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
Name: entity.Name,
Type: constants.PaymentMethodType(entity.Type),
Processor: entity.Processor,
Configuration: map[string]interface{}(entity.Configuration),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func PaymentMethodModelToEntity(model *models.PaymentMethod) *entities.PaymentMethod {
if model == nil {
return nil
}
return &entities.PaymentMethod{
ID: model.ID,
OrganizationID: model.OrganizationID,
Name: model.Name,
Type: entities.PaymentMethodType(model.Type),
Processor: model.Processor,
Configuration: entities.Metadata(model.Configuration),
IsActive: model.IsActive,
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
// Contract to Model mappers
func CreatePaymentMethodContractToModel(req *contract.CreatePaymentMethodRequest) *models.CreatePaymentMethodRequest {
return &models.CreatePaymentMethodRequest{
OrganizationID: req.OrganizationID,
Name: req.Name,
Type: constants.PaymentMethodType(req.Type),
Processor: req.Processor,
Configuration: req.Configuration,
IsActive: req.IsActive,
}
}
func UpdatePaymentMethodContractToModel(req *contract.UpdatePaymentMethodRequest) *models.UpdatePaymentMethodRequest {
var paymentMethodType *constants.PaymentMethodType
if req.Type != nil {
pmt := constants.PaymentMethodType(*req.Type)
paymentMethodType = &pmt
}
return &models.UpdatePaymentMethodRequest{
Name: req.Name,
Type: paymentMethodType,
Processor: req.Processor,
Configuration: req.Configuration,
IsActive: req.IsActive,
}
}
func ListPaymentMethodsContractToModel(req *contract.ListPaymentMethodsRequest) *models.ListPaymentMethodsRequest {
var paymentMethodType *constants.PaymentMethodType
if req.Type != nil {
pmt := constants.PaymentMethodType(*req.Type)
paymentMethodType = &pmt
}
return &models.ListPaymentMethodsRequest{
OrganizationID: req.OrganizationID,
Type: paymentMethodType,
IsActive: req.IsActive,
Search: req.Search,
Page: req.Page,
Limit: req.Limit,
}
}
// Model to Contract mappers
func PaymentMethodResponseToContract(response *models.PaymentMethodResponse) *contract.PaymentMethodResponse {
if response == nil {
return nil
}
return &contract.PaymentMethodResponse{
ID: response.ID,
OrganizationID: response.OrganizationID,
Name: response.Name,
Type: string(response.Type),
Processor: response.Processor,
Configuration: response.Configuration,
IsActive: response.IsActive,
CreatedAt: response.CreatedAt,
UpdatedAt: response.UpdatedAt,
}
}
func ListPaymentMethodsResponseToContract(response *models.ListPaymentMethodsResponse) *contract.ListPaymentMethodsResponse {
paymentMethods := make([]contract.PaymentMethodResponse, len(response.PaymentMethods))
for i, pm := range response.PaymentMethods {
contractPM := PaymentMethodResponseToContract(&pm)
if contractPM != nil {
paymentMethods[i] = *contractPM
}
}
return &contract.ListPaymentMethodsResponse{
PaymentMethods: paymentMethods,
TotalCount: response.TotalCount,
Page: response.Page,
Limit: response.Limit,
TotalPages: response.TotalPages,
}
}
+315
View File
@@ -0,0 +1,315 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func ProductEntityToModel(entity *entities.Product) *models.Product {
if entity == nil {
return nil
}
return &models.Product{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
CategoryID: entity.CategoryID,
SKU: entity.SKU,
Name: entity.Name,
Description: entity.Description,
Price: entity.Price,
Cost: entity.Cost,
BusinessType: constants.BusinessType(entity.BusinessType),
Metadata: map[string]interface{}(entity.Metadata),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func ProductModelToEntity(model *models.Product) *entities.Product {
if model == nil {
return nil
}
return &entities.Product{
ID: model.ID,
OrganizationID: model.OrganizationID,
CategoryID: model.CategoryID,
SKU: model.SKU,
Name: model.Name,
Description: model.Description,
Price: model.Price,
Cost: model.Cost,
BusinessType: string(model.BusinessType),
Metadata: entities.Metadata(model.Metadata),
IsActive: model.IsActive,
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
func CreateProductRequestToEntity(req *models.CreateProductRequest) *entities.Product {
if req == nil {
return nil
}
cost := float64(0)
if req.Cost > 0 {
cost = req.Cost
}
businessType := "restaurant"
if req.BusinessType != "" {
businessType = string(req.BusinessType)
}
metadata := entities.Metadata{}
if req.Metadata != nil {
metadata = entities.Metadata(req.Metadata)
}
return &entities.Product{
OrganizationID: req.OrganizationID,
CategoryID: req.CategoryID,
SKU: req.SKU,
Name: req.Name,
Description: req.Description,
Price: req.Price,
Cost: cost,
BusinessType: businessType,
Metadata: metadata,
IsActive: true, // Default to active
}
}
func ProductEntityToResponse(entity *entities.Product) *models.ProductResponse {
if entity == nil {
return nil
}
// Convert variants to response models
var variantResponses []models.ProductVariantResponse
if entity.ProductVariants != nil {
variantResponses = make([]models.ProductVariantResponse, len(entity.ProductVariants))
for i, variant := range entity.ProductVariants {
variantResponses[i] = models.ProductVariantResponse{
ID: variant.ID,
ProductID: variant.ProductID,
Name: variant.Name,
PriceModifier: variant.PriceModifier,
Cost: variant.Cost,
Metadata: map[string]interface{}(variant.Metadata),
CreatedAt: variant.CreatedAt,
UpdatedAt: variant.UpdatedAt,
}
}
}
return &models.ProductResponse{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
CategoryID: entity.CategoryID,
SKU: entity.SKU,
Name: entity.Name,
Description: entity.Description,
Price: entity.Price,
Cost: entity.Cost,
BusinessType: constants.BusinessType(entity.BusinessType),
Metadata: map[string]interface{}(entity.Metadata),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
Variants: variantResponses,
}
}
func UpdateProductEntityFromRequest(entity *entities.Product, req *models.UpdateProductRequest) {
if entity == nil || req == nil {
return
}
if req.CategoryID != nil {
entity.CategoryID = *req.CategoryID
}
if req.SKU != nil {
entity.SKU = req.SKU
}
if req.Name != nil {
entity.Name = *req.Name
}
if req.Description != nil {
entity.Description = req.Description
}
if req.Price != nil {
entity.Price = *req.Price
}
if req.Cost != nil {
entity.Cost = *req.Cost
}
if req.Metadata != nil {
if entity.Metadata == nil {
entity.Metadata = make(entities.Metadata)
}
for k, v := range req.Metadata {
entity.Metadata[k] = v
}
}
if req.IsActive != nil {
entity.IsActive = *req.IsActive
}
}
func ProductEntitiesToModels(entities []*entities.Product) []*models.Product {
if entities == nil {
return nil
}
models := make([]*models.Product, len(entities))
for i, entity := range entities {
models[i] = ProductEntityToModel(entity)
}
return models
}
func ProductEntitiesToResponses(entities []*entities.Product) []*models.ProductResponse {
if entities == nil {
return nil
}
responses := make([]*models.ProductResponse, len(entities))
for i, entity := range entities {
responses[i] = ProductEntityToResponse(entity)
}
return responses
}
// Product Variant Mappers
func ProductVariantEntityToModel(entity *entities.ProductVariant) *models.ProductVariant {
if entity == nil {
return nil
}
return &models.ProductVariant{
ID: entity.ID,
ProductID: entity.ProductID,
Name: entity.Name,
PriceModifier: entity.PriceModifier,
Cost: entity.Cost,
Metadata: map[string]interface{}(entity.Metadata),
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func ProductVariantModelToEntity(model *models.ProductVariant) *entities.ProductVariant {
if model == nil {
return nil
}
return &entities.ProductVariant{
ID: model.ID,
ProductID: model.ProductID,
Name: model.Name,
PriceModifier: model.PriceModifier,
Cost: model.Cost,
Metadata: entities.Metadata(model.Metadata),
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
func CreateProductVariantRequestToEntity(req *models.CreateProductVariantRequest) *entities.ProductVariant {
if req == nil {
return nil
}
metadata := entities.Metadata{}
if req.Metadata != nil {
metadata = entities.Metadata(req.Metadata)
}
return &entities.ProductVariant{
ProductID: req.ProductID,
Name: req.Name,
PriceModifier: req.PriceModifier,
Cost: req.Cost,
Metadata: metadata,
}
}
func ProductVariantEntityToResponse(entity *entities.ProductVariant) *models.ProductVariantResponse {
if entity == nil {
return nil
}
return &models.ProductVariantResponse{
ID: entity.ID,
ProductID: entity.ProductID,
Name: entity.Name,
PriceModifier: entity.PriceModifier,
Cost: entity.Cost,
Metadata: map[string]interface{}(entity.Metadata),
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func UpdateProductVariantEntityFromRequest(entity *entities.ProductVariant, req *models.UpdateProductVariantRequest) {
if entity == nil || req == nil {
return
}
if req.Name != nil {
entity.Name = *req.Name
}
if req.PriceModifier != nil {
entity.PriceModifier = *req.PriceModifier
}
if req.Cost != nil {
entity.Cost = *req.Cost
}
if req.Metadata != nil {
if entity.Metadata == nil {
entity.Metadata = make(entities.Metadata)
}
for k, v := range req.Metadata {
entity.Metadata[k] = v
}
}
}
func ProductVariantEntitiesToModels(entities []*entities.ProductVariant) []*models.ProductVariant {
if entities == nil {
return nil
}
models := make([]*models.ProductVariant, len(entities))
for i, entity := range entities {
models[i] = ProductVariantEntityToModel(entity)
}
return models
}
func ProductVariantEntitiesToResponses(entities []*entities.ProductVariant) []*models.ProductVariantResponse {
if entities == nil {
return nil
}
responses := make([]*models.ProductVariantResponse, len(entities))
for i, entity := range entities {
responses[i] = ProductVariantEntityToResponse(entity)
}
return responses
}
+110
View File
@@ -0,0 +1,110 @@
package mappers
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
)
func UserEntityToModel(entity *entities.User) *models.User {
if entity == nil {
return nil
}
return &models.User{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
OutletID: entity.OutletID,
Name: entity.Name,
Email: entity.Email,
Role: constants.UserRole(entity.Role),
Permissions: map[string]interface{}(entity.Permissions),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func UserModelToEntity(model *models.User) *entities.User {
if model == nil {
return nil
}
return &entities.User{
ID: model.ID,
OrganizationID: model.OrganizationID,
OutletID: model.OutletID,
Name: model.Name,
Email: model.Email,
Role: entities.UserRole(model.Role),
Permissions: entities.Permissions(model.Permissions),
IsActive: model.IsActive,
CreatedAt: model.CreatedAt,
UpdatedAt: model.UpdatedAt,
}
}
func UserCreateRequestToEntity(req *models.CreateUserRequest, passwordHash string) *entities.User {
if req == nil {
return nil
}
permissions := entities.Permissions{}
if req.Permissions != nil {
permissions = entities.Permissions(req.Permissions)
}
return &entities.User{
OrganizationID: req.OrganizationID,
OutletID: req.OutletID,
Name: req.Name,
Email: req.Email,
PasswordHash: passwordHash,
Role: entities.UserRole(req.Role),
Permissions: permissions,
IsActive: true,
}
}
func UserEntityToResponse(entity *entities.User) *models.UserResponse {
if entity == nil {
return nil
}
return &models.UserResponse{
ID: entity.ID,
OrganizationID: entity.OrganizationID,
OutletID: entity.OutletID,
Name: entity.Name,
Email: entity.Email,
Role: constants.UserRole(entity.Role),
Permissions: map[string]interface{}(entity.Permissions),
IsActive: entity.IsActive,
CreatedAt: entity.CreatedAt,
UpdatedAt: entity.UpdatedAt,
}
}
func UserEntitiesToModels(entities []*entities.User) []*models.User {
if entities == nil {
return nil
}
models := make([]*models.User, len(entities))
for i, entity := range entities {
models[i] = UserEntityToModel(entity)
}
return models
}
func UserEntitiesToResponses(entities []*entities.User) []*models.UserResponse {
if entities == nil {
return nil
}
responses := make([]*models.UserResponse, len(entities))
for i, entity := range entities {
responses[i] = UserEntityToResponse(entity)
}
return responses
}