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
+210
View File
@@ -0,0 +1,210 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type PaymentMethodAnalyticsRequest struct {
OrganizationID uuid.UUID `form:"organization_id"`
OutletID *uuid.UUID `form:"outlet_id,omitempty"`
DateFrom string `form:"date_from" validate:"required"`
DateTo string `form:"date_to" validate:"required"`
GroupBy string `form:"group_by,default=day" validate:"omitempty,oneof=day hour week month"`
}
// PaymentMethodAnalyticsResponse represents the response for payment method analytics
type PaymentMethodAnalyticsResponse struct {
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
DateFrom time.Time `json:"date_from"`
DateTo time.Time `json:"date_to"`
GroupBy string `json:"group_by"`
Summary PaymentMethodSummary `json:"summary"`
Data []PaymentMethodAnalyticsData `json:"data"`
}
// PaymentMethodSummary represents the summary of payment method analytics
type PaymentMethodSummary struct {
TotalAmount float64 `json:"total_amount"`
TotalOrders int64 `json:"total_orders"`
TotalPayments int64 `json:"total_payments"`
AverageOrderValue float64 `json:"average_order_value"`
}
type PaymentMethodAnalyticsData struct {
PaymentMethodID uuid.UUID `json:"payment_method_id"`
PaymentMethodName string `json:"payment_method_name"`
PaymentMethodType string `json:"payment_method_type"`
TotalAmount float64 `json:"total_amount"`
OrderCount int64 `json:"order_count"`
PaymentCount int64 `json:"payment_count"`
Percentage float64 `json:"percentage"`
}
type SalesAnalyticsRequest struct {
OrganizationID uuid.UUID
OutletID *uuid.UUID `form:"outlet_id,omitempty"`
DateFrom string `form:"date_from" validate:"required"`
DateTo string `form:"date_to" validate:"required"`
GroupBy string `form:"group_by,default=day" validate:"omitempty,oneof=day hour week month"`
}
type SalesAnalyticsResponse struct {
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
DateFrom time.Time `json:"date_from"`
DateTo time.Time `json:"date_to"`
GroupBy string `json:"group_by"`
Summary SalesSummary `json:"summary"`
Data []SalesAnalyticsData `json:"data"`
}
// SalesSummary represents the summary of sales analytics
type SalesSummary struct {
TotalSales float64 `json:"total_sales"`
TotalOrders int64 `json:"total_orders"`
TotalItems int64 `json:"total_items"`
AverageOrderValue float64 `json:"average_order_value"`
TotalTax float64 `json:"total_tax"`
TotalDiscount float64 `json:"total_discount"`
NetSales float64 `json:"net_sales"`
}
// SalesAnalyticsData represents individual sales analytics data point
type SalesAnalyticsData struct {
Date time.Time `json:"date"`
Sales float64 `json:"sales"`
Orders int64 `json:"orders"`
Items int64 `json:"items"`
Tax float64 `json:"tax"`
Discount float64 `json:"discount"`
NetSales float64 `json:"net_sales"`
}
// ProductAnalyticsRequest represents the request for product analytics
type ProductAnalyticsRequest struct {
OrganizationID uuid.UUID
OutletID *uuid.UUID `form:"outlet_id,omitempty"`
DateFrom string `form:"date_from" validate:"required"`
DateTo string `form:"date_to" validate:"required"`
Limit int `form:"limit,default=10" validate:"min=1,max=100"`
}
// ProductAnalyticsResponse represents the response for product analytics
type ProductAnalyticsResponse struct {
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
DateFrom time.Time `json:"date_from"`
DateTo time.Time `json:"date_to"`
Data []ProductAnalyticsData `json:"data"`
}
// ProductAnalyticsData represents individual product analytics data
type ProductAnalyticsData struct {
ProductID uuid.UUID `json:"product_id"`
ProductName string `json:"product_name"`
CategoryID uuid.UUID `json:"category_id"`
CategoryName string `json:"category_name"`
QuantitySold int64 `json:"quantity_sold"`
Revenue float64 `json:"revenue"`
AveragePrice float64 `json:"average_price"`
OrderCount int64 `json:"order_count"`
}
// DashboardAnalyticsRequest represents the request for dashboard analytics
type DashboardAnalyticsRequest struct {
OrganizationID uuid.UUID
OutletID *uuid.UUID `form:"outlet_id,omitempty"`
DateFrom string `form:"date_from" validate:"required"`
DateTo string `form:"date_to" validate:"required"`
}
// DashboardAnalyticsResponse represents the response for dashboard analytics
type DashboardAnalyticsResponse struct {
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
DateFrom time.Time `json:"date_from"`
DateTo time.Time `json:"date_to"`
Overview DashboardOverview `json:"overview"`
TopProducts []ProductAnalyticsData `json:"top_products"`
PaymentMethods []PaymentMethodAnalyticsData `json:"payment_methods"`
RecentSales []SalesAnalyticsData `json:"recent_sales"`
}
// DashboardOverview represents the overview data for dashboard
type DashboardOverview struct {
TotalSales float64 `json:"total_sales"`
TotalOrders int64 `json:"total_orders"`
AverageOrderValue float64 `json:"average_order_value"`
TotalCustomers int64 `json:"total_customers"`
VoidedOrders int64 `json:"voided_orders"`
RefundedOrders int64 `json:"refunded_orders"`
}
// ProfitLossAnalyticsRequest represents the request for profit and loss analytics
type ProfitLossAnalyticsRequest struct {
OrganizationID uuid.UUID
OutletID *uuid.UUID `form:"outlet_id,omitempty"`
DateFrom string `form:"date_from" validate:"required"`
DateTo string `form:"date_to" validate:"required"`
GroupBy string `form:"group_by,default=day" validate:"omitempty,oneof=day hour week month"`
}
// ProfitLossAnalyticsResponse represents the response for profit and loss analytics
type ProfitLossAnalyticsResponse struct {
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
DateFrom time.Time `json:"date_from"`
DateTo time.Time `json:"date_to"`
GroupBy string `json:"group_by"`
Summary ProfitLossSummary `json:"summary"`
Data []ProfitLossData `json:"data"`
ProductData []ProductProfitData `json:"product_data"`
}
// ProfitLossSummary represents the summary of profit and loss analytics
type ProfitLossSummary struct {
TotalRevenue float64 `json:"total_revenue"`
TotalCost float64 `json:"total_cost"`
GrossProfit float64 `json:"gross_profit"`
GrossProfitMargin float64 `json:"gross_profit_margin"`
TotalTax float64 `json:"total_tax"`
TotalDiscount float64 `json:"total_discount"`
NetProfit float64 `json:"net_profit"`
NetProfitMargin float64 `json:"net_profit_margin"`
TotalOrders int64 `json:"total_orders"`
AverageProfit float64 `json:"average_profit"`
ProfitabilityRatio float64 `json:"profitability_ratio"`
}
// ProfitLossData represents individual profit and loss data point by time period
type ProfitLossData struct {
Date time.Time `json:"date"`
Revenue float64 `json:"revenue"`
Cost float64 `json:"cost"`
GrossProfit float64 `json:"gross_profit"`
GrossProfitMargin float64 `json:"gross_profit_margin"`
Tax float64 `json:"tax"`
Discount float64 `json:"discount"`
NetProfit float64 `json:"net_profit"`
NetProfitMargin float64 `json:"net_profit_margin"`
Orders int64 `json:"orders"`
}
// ProductProfitData represents profit data for individual products
type ProductProfitData struct {
ProductID uuid.UUID `json:"product_id"`
ProductName string `json:"product_name"`
CategoryID uuid.UUID `json:"category_id"`
CategoryName string `json:"category_name"`
QuantitySold int64 `json:"quantity_sold"`
Revenue float64 `json:"revenue"`
Cost float64 `json:"cost"`
GrossProfit float64 `json:"gross_profit"`
GrossProfitMargin float64 `json:"gross_profit_margin"`
AveragePrice float64 `json:"average_price"`
AverageCost float64 `json:"average_cost"`
ProfitPerUnit float64 `json:"profit_per_unit"`
}
+49
View File
@@ -0,0 +1,49 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateCategoryRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Description *string `json:"description,omitempty"`
BusinessType *string `json:"business_type,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type UpdateCategoryRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Description *string `json:"description,omitempty"`
BusinessType *string `json:"business_type,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type ListCategoriesRequest struct {
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
BusinessType string `json:"business_type,omitempty"`
Search string `json:"search,omitempty"`
Page int `json:"page" validate:"required,min=1"`
Limit int `json:"limit" validate:"required,min=1,max=100"`
}
// Category Response DTOs
type CategoryResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
Name string `json:"name"`
Description *string `json:"description"`
BusinessType string `json:"business_type"`
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListCategoriesResponse struct {
Categories []CategoryResponse `json:"categories"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
+49
View File
@@ -0,0 +1,49 @@
package contract
import "time"
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Details map[string]interface{} `json:"details,omitempty"`
Code int `json:"code"`
}
type ValidationErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Details map[string]string `json:"details"`
Code int `json:"code"`
}
type SuccessResponse struct {
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
type PaginationRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
}
type PaginationResponse struct {
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
type SearchRequest struct {
Query string `json:"query,omitempty"`
}
type DateRangeRequest struct {
From *time.Time `json:"from,omitempty"`
To *time.Time `json:"to,omitempty"`
}
type HealthResponse struct {
Status string `json:"status"`
Timestamp time.Time `json:"timestamp"`
Version string `json:"version"`
}
+58
View File
@@ -0,0 +1,58 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateCustomerRequest struct {
Name string `json:"name" validate:"required"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
Phone *string `json:"phone,omitempty"`
Address *string `json:"address,omitempty"`
}
type UpdateCustomerRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,required"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
Phone *string `json:"phone,omitempty"`
Address *string `json:"address,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
type CustomerResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
Name string `json:"name"`
Email *string `json:"email,omitempty"`
Phone *string `json:"phone,omitempty"`
Address *string `json:"address,omitempty"`
IsDefault bool `json:"is_default"`
IsActive bool `json:"is_active"`
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListCustomersRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
Search string `json:"search"`
IsActive *bool `json:"is_active"`
IsDefault *bool `json:"is_default"`
SortBy string `json:"sort_by" validate:"omitempty,oneof=name email created_at updated_at"`
SortOrder string `json:"sort_order" validate:"omitempty,oneof=asc desc"`
}
type SetDefaultCustomerRequest struct {
CustomerID uuid.UUID `json:"customer_id" validate:"required"`
}
type PaginatedCustomerResponse struct {
Data []CustomerResponse `json:"data"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
+73
View File
@@ -0,0 +1,73 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type ListFilesQuery struct {
OrganizationID string `form:"organization_id"`
UserID string `form:"user_id"`
FileType string `form:"file_type"`
IsPublic string `form:"is_public"`
DateFrom string `form:"date_from"`
DateTo string `form:"date_to"`
Search string `form:"search"`
Page int `form:"page,default=1"`
Limit int `form:"limit,default=10"`
}
// Request DTOs
type UploadFileRequest struct {
FileType string `json:"file_type" validate:"required"`
IsPublic *bool `json:"is_public,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type UpdateFileRequest struct {
IsPublic *bool `json:"is_public,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type ListFilesRequest struct {
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
UserID *uuid.UUID `json:"user_id,omitempty"`
FileType *string `json:"file_type,omitempty"`
IsPublic *bool `json:"is_public,omitempty"`
DateFrom *time.Time `json:"date_from,omitempty"`
DateTo *time.Time `json:"date_to,omitempty"`
Search string `json:"search,omitempty"`
Page int `json:"page" validate:"required,min=1"`
Limit int `json:"limit" validate:"required,min=1,max=100"`
}
// Response DTOs
type FileResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
UserID uuid.UUID `json:"user_id"`
FileName string `json:"file_name"`
OriginalName string `json:"original_name"`
FileURL string `json:"file_url"`
FileSize int64 `json:"file_size"`
MimeType string `json:"mime_type"`
FileType string `json:"file_type"`
UploadPath string `json:"upload_path"`
IsPublic bool `json:"is_public"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListFilesResponse struct {
Files []*FileResponse `json:"files"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
type UploadFileResponse struct {
File FileResponse `json:"file"`
}
+72
View File
@@ -0,0 +1,72 @@
package contract
import (
"time"
"github.com/google/uuid"
)
// Inventory Request DTOs
type CreateInventoryRequest struct {
OutletID uuid.UUID `json:"outlet_id" validate:"required"`
ProductID uuid.UUID `json:"product_id" validate:"required"`
Quantity int `json:"quantity" validate:"min=0"`
ReorderLevel int `json:"reorder_level" validate:"min=0"`
}
type UpdateInventoryRequest struct {
Quantity *int `json:"quantity,omitempty" validate:"omitempty,min=0"`
ReorderLevel *int `json:"reorder_level,omitempty" validate:"omitempty,min=0"`
}
type AdjustInventoryRequest struct {
ProductID uuid.UUID `json:"product_id" validate:"required"`
OutletID uuid.UUID `json:"outlet_id" validate:"required"`
Delta int `json:"delta" validate:"required"` // Can be positive or negative
Reason string `json:"reason" validate:"required,min=1,max=255"`
}
type ListInventoryRequest struct {
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
ProductID *uuid.UUID `json:"product_id,omitempty"`
CategoryID *uuid.UUID `json:"category_id,omitempty"`
LowStockOnly *bool `json:"low_stock_only,omitempty"`
ZeroStockOnly *bool `json:"zero_stock_only,omitempty"`
Search string `json:"search,omitempty"`
Page int `json:"page" validate:"required,min=1"`
Limit int `json:"limit" validate:"required,min=1,max=100"`
}
// Inventory Response DTOs
type InventoryResponse struct {
ID uuid.UUID `json:"id"`
OutletID uuid.UUID `json:"outlet_id"`
ProductID uuid.UUID `json:"product_id"`
Quantity int `json:"quantity"`
ReorderLevel int `json:"reorder_level"`
IsLowStock bool `json:"is_low_stock"`
UpdatedAt time.Time `json:"updated_at"`
// Related data (optional)
Product *ProductResponse `json:"product,omitempty"`
Outlet *OutletResponse `json:"outlet,omitempty"`
}
type ListInventoryResponse struct {
Inventory []InventoryResponse `json:"inventory"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
type InventoryAdjustmentResponse struct {
InventoryID uuid.UUID `json:"inventory_id"`
ProductID uuid.UUID `json:"product_id"`
OutletID uuid.UUID `json:"outlet_id"`
PreviousQty int `json:"previous_quantity"`
NewQty int `json:"new_quantity"`
Delta int `json:"delta"`
Reason string `json:"reason"`
AdjustedAt time.Time `json:"adjusted_at"`
}
+215
View File
@@ -0,0 +1,215 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateOrderRequest struct {
OutletID uuid.UUID `json:"outlet_id" validate:"required"`
UserID uuid.UUID `json:"user_id" validate:"required"`
TableNumber *string `json:"table_number,omitempty" validate:"omitempty,max=50"`
OrderType string `json:"order_type" validate:"required,oneof=dine_in takeaway delivery"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000"`
OrderItems []CreateOrderItemRequest `json:"order_items" validate:"required,min=1,dive"`
CustomerName *string `json:"customer_name,omitempty" validate:"omitempty,max=255"`
}
type AddToOrderRequest struct {
OrderItems []CreateOrderItemRequest `json:"order_items" validate:"required,min=1,dive"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type AddToOrderResponse struct {
OrderID uuid.UUID `json:"order_id"`
OrderNumber string `json:"order_number"`
AddedItems []OrderItemResponse `json:"added_items"`
UpdatedOrder OrderResponse `json:"updated_order"`
}
type UpdateOrderRequest struct {
TableNumber *string `json:"table_number,omitempty" validate:"omitempty,max=50"`
Status *string `json:"status,omitempty" validate:"omitempty,oneof=pending preparing ready completed cancelled"`
DiscountAmount *float64 `json:"discount_amount,omitempty" validate:"omitempty,min=0"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type CreateOrderItemRequest struct {
ProductID uuid.UUID `json:"product_id" validate:"required"`
ProductVariantID *uuid.UUID `json:"product_variant_id,omitempty"`
Quantity int `json:"quantity" validate:"required,min=1"`
UnitPrice *float64 `json:"unit_price,omitempty" validate:"omitempty,min=0"` // Optional, will use database price if not provided
Modifiers []map[string]interface{} `json:"modifiers,omitempty"`
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type UpdateOrderItemRequest struct {
Quantity *int `json:"quantity,omitempty" validate:"omitempty,min=1"`
UnitPrice *float64 `json:"unit_price,omitempty" validate:"omitempty,min=0"`
Modifiers []map[string]interface{} `json:"modifiers,omitempty"`
Status *string `json:"status,omitempty" validate:"omitempty,oneof=pending preparing completed cancelled"`
}
type OrderResponse struct {
ID uuid.UUID `json:"id"`
OrderNumber string `json:"order_number"`
OutletID uuid.UUID `json:"outlet_id"`
UserID uuid.UUID `json:"user_id"`
TableNumber *string `json:"table_number"`
OrderType string `json:"order_type"`
Status string `json:"status"`
Subtotal float64 `json:"subtotal"`
TaxAmount float64 `json:"tax_amount"`
DiscountAmount float64 `json:"discount_amount"`
TotalAmount float64 `json:"total_amount"`
Notes *string `json:"notes"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrderItems []OrderItemResponse `json:"order_items,omitempty"`
}
type OrderItemResponse struct {
ID uuid.UUID `json:"id"`
OrderID uuid.UUID `json:"order_id"`
ProductID uuid.UUID `json:"product_id"`
ProductName string `json:"product_name"`
ProductVariantID *uuid.UUID `json:"product_variant_id"`
ProductVariantName *string `json:"product_variant_name,omitempty"`
Quantity int `json:"quantity"`
UnitPrice float64 `json:"unit_price"`
TotalPrice float64 `json:"total_price"`
Modifiers []map[string]interface{} `json:"modifiers"`
Notes *string `json:"notes,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListOrdersQuery struct {
OrganizationID string `form:"organization_id"`
OutletID string `form:"outlet_id"`
UserID string `form:"user_id"`
CustomerID string `form:"customer_id"`
OrderType string `form:"order_type"`
Status string `form:"status"`
PaymentStatus string `form:"payment_status"`
IsVoid string `form:"is_void"`
IsRefund string `form:"is_refund"`
DateFrom string `form:"date_from"`
DateTo string `form:"date_to"`
Search string `form:"search"`
Page int `form:"page,default=1"`
Limit int `form:"limit,default=10"`
}
type ListOrdersRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
UserID *uuid.UUID `json:"user_id,omitempty"`
Status *string `json:"status,omitempty" validate:"omitempty,oneof=pending preparing ready completed cancelled"`
OrderType *string `json:"order_type,omitempty" validate:"omitempty,oneof=dine_in takeaway delivery"`
DateFrom *time.Time `json:"date_from,omitempty"`
DateTo *time.Time `json:"date_to,omitempty"`
}
type ListOrdersResponse struct {
Orders []OrderResponse `json:"orders"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
type VoidOrderRequest struct {
OrderID uuid.UUID `json:"order_id" validate:"required"`
Reason string `json:"reason" validate:"required"`
Type string `json:"type" validate:"required,oneof=ALL ITEM"`
Items []VoidItemRequest `json:"items,omitempty" validate:"required_if=Type ITEM,dive"`
}
type VoidItemRequest struct {
OrderItemID uuid.UUID `json:"order_item_id" validate:"required"`
Quantity int `json:"quantity" validate:"required,min=1"`
}
type SetOrderCustomerRequest struct {
CustomerID uuid.UUID `json:"customer_id" validate:"required"`
}
type SetOrderCustomerResponse struct {
OrderID uuid.UUID `json:"order_id"`
CustomerID uuid.UUID `json:"customer_id"`
Message string `json:"message"`
}
// Payment-related contracts
type CreatePaymentRequest struct {
OrderID uuid.UUID `json:"order_id" validate:"required"`
PaymentMethodID uuid.UUID `json:"payment_method_id" validate:"required"`
Amount float64 `json:"amount" validate:"required,min=0"`
TransactionID *string `json:"transaction_id,omitempty" validate:"omitempty"`
SplitNumber int `json:"split_number,omitempty" validate:"omitempty,min=1"`
SplitTotal int `json:"split_total,omitempty" validate:"omitempty,min=1"`
SplitDescription *string `json:"split_description,omitempty" validate:"omitempty,max=255"`
PaymentOrderItems []CreatePaymentOrderItemRequest `json:"payment_order_items,omitempty" validate:"omitempty,dive"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type CreatePaymentOrderItemRequest struct {
OrderItemID uuid.UUID `json:"order_item_id" validate:"required"`
Amount float64 `json:"amount" validate:"required,min=0"`
}
type PaymentResponse struct {
ID uuid.UUID `json:"id"`
OrderID uuid.UUID `json:"order_id"`
PaymentMethodID uuid.UUID `json:"payment_method_id"`
Amount float64 `json:"amount"`
Status string `json:"status"`
TransactionID *string `json:"transaction_id,omitempty"`
SplitNumber int `json:"split_number"`
SplitTotal int `json:"split_total"`
SplitDescription *string `json:"split_description,omitempty"`
RefundAmount float64 `json:"refund_amount"`
RefundReason *string `json:"refund_reason,omitempty"`
RefundedAt *time.Time `json:"refunded_at,omitempty"`
RefundedBy *uuid.UUID `json:"refunded_by,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
PaymentOrderItems []PaymentOrderItemResponse `json:"payment_order_items,omitempty"`
}
type PaymentOrderItemResponse struct {
ID uuid.UUID `json:"id"`
PaymentID uuid.UUID `json:"payment_id"`
OrderItemID uuid.UUID `json:"order_item_id"`
Amount float64 `json:"amount"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type RefundOrderRequest struct {
Reason *string `json:"reason,omitempty" validate:"omitempty,max=255"`
RefundAmount *float64 `json:"refund_amount,omitempty" validate:"omitempty,min=0"`
OrderItems []RefundOrderItemRequest `json:"order_items,omitempty" validate:"omitempty,dive"`
}
type RefundOrderItemRequest struct {
OrderItemID uuid.UUID `json:"order_item_id" validate:"required"`
RefundQuantity int `json:"refund_quantity,omitempty" validate:"omitempty,min=1"`
RefundAmount *float64 `json:"refund_amount,omitempty" validate:"omitempty,min=0"`
Reason *string `json:"reason,omitempty" validate:"omitempty,max=255"`
}
type RefundPaymentRequest struct {
RefundAmount float64 `json:"refund_amount" validate:"required,min=0"`
Reason string `json:"reason" validate:"omitempty,max=255"`
}
@@ -0,0 +1,61 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateOrganizationRequest struct {
OrganizationName string `json:"organization_name" validate:"required,min=1,max=255"`
OrganizationEmail *string `json:"organization_email,omitempty" validate:"omitempty,email"`
OrganizationPhoneNumber *string `json:"organization_phone_number,omitempty"`
PlanType string `json:"plan_type" validate:"required,oneof=basic premium enterprise"`
AdminName string `json:"admin_name" validate:"required,min=1,max=255"`
AdminEmail string `json:"admin_email" validate:"required,email"`
AdminPassword string `json:"admin_password" validate:"required,min=6"`
OutletName string `json:"outlet_name" validate:"required,min=1,max=255"`
OutletAddress *string `json:"outlet_address,omitempty"`
OutletTimezone *string `json:"outlet_timezone,omitempty"`
OutletCurrency string `json:"outlet_currency" validate:"required,len=3"`
}
type UpdateOrganizationRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
PhoneNumber *string `json:"phone_number,omitempty"`
PlanType *string `json:"plan_type,omitempty" validate:"omitempty,oneof=basic premium enterprise"`
}
type OrganizationResponse struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Email *string `json:"email"`
PhoneNumber *string `json:"phone_number"`
PlanType string `json:"plan_type"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateOrganizationResponse struct {
Organization OrganizationResponse `json:"organization"`
AdminUser UserResponse `json:"admin_user"`
DefaultOutlet OutletResponse `json:"default_outlet"`
}
type ListOrganizationsRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
Search string `json:"search,omitempty"`
PlanType string `json:"plan_type,omitempty" validate:"omitempty,oneof=basic premium enterprise"`
}
type ListOrganizationsResponse struct {
Organizations []OrganizationResponse `json:"organizations"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
+57
View File
@@ -0,0 +1,57 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateOutletRequest struct {
OrganizationID uuid.UUID `json:"organization_id" validate:"required"`
Name string `json:"name" validate:"required,min=1,max=255"`
Address string `json:"address" validate:"required,min=1,max=500"`
PhoneNumber *string `json:"phone_number,omitempty" validate:"omitempty,e164"`
BusinessType string `json:"business_type" validate:"required,oneof=restaurant cafe bar fastfood retail"`
Currency string `json:"currency" validate:"required,len=3"`
TaxRate float64 `json:"tax_rate" validate:"min=0,max=1"`
}
type UpdateOutletRequest struct {
OrganizationID uuid.UUID
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Address *string `json:"address,omitempty" validate:"omitempty,min=1,max=500"`
PhoneNumber *string `json:"phone_number,omitempty" validate:"omitempty,e164"`
TaxRate *float64 `json:"tax_rate,omitempty" validate:"omitempty,min=0,max=1"`
IsActive *bool `json:"is_active,omitempty"`
}
type OutletResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
Name string `json:"name"`
Address string `json:"address"`
PhoneNumber *string `json:"phone_number"`
BusinessType string `json:"business_type"`
Currency string `json:"currency"`
TaxRate float64 `json:"tax_rate"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListOutletsRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
Search string `json:"search,omitempty"`
OrganizationID uuid.UUID `json:"organization_id,omitempty"`
BusinessType *string `json:"business_type,omitempty" validate:"omitempty,oneof=restaurant cafe bar fastfood retail"`
IsActive *bool `json:"is_active,omitempty"`
}
type ListOutletsResponse struct {
Outlets []OutletResponse `json:"outlets"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
@@ -0,0 +1,53 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreatePaymentMethodRequest struct {
OrganizationID uuid.UUID `json:"organization_id" validate:"required"`
Name string `json:"name" validate:"required,min=1,max=100"`
Type string `json:"type" validate:"required,oneof=cash card digital_wallet qr edc"`
Processor *string `json:"processor,omitempty" validate:"omitempty,max=100"`
Configuration map[string]interface{} `json:"configuration,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
type UpdatePaymentMethodRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
Type *string `json:"type,omitempty" validate:"omitempty,oneof=cash card digital_wallet qr edc"`
Processor *string `json:"processor,omitempty" validate:"omitempty,max=100"`
Configuration map[string]interface{} `json:"configuration,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
}
type PaymentMethodResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
Name string `json:"name"`
Type string `json:"type"`
Processor *string `json:"processor,omitempty"`
Configuration map[string]interface{} `json:"configuration,omitempty"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListPaymentMethodsRequest struct {
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
Type *string `json:"type,omitempty" validate:"omitempty,oneof=cash card digital_wallet qr edc"`
IsActive *bool `json:"is_active,omitempty"`
Search string `json:"search,omitempty"`
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
}
type ListPaymentMethodsResponse struct {
PaymentMethods []PaymentMethodResponse `json:"payment_methods"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
+103
View File
@@ -0,0 +1,103 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateProductRequest struct {
CategoryID uuid.UUID `json:"category_id" validate:"required"`
SKU *string `json:"sku,omitempty"`
Name string `json:"name" validate:"required,min=1,max=255"`
Description *string `json:"description,omitempty"`
Price float64 `json:"price" validate:"required,min=0"`
Cost *float64 `json:"cost,omitempty" validate:"omitempty,min=0"`
BusinessType *string `json:"business_type,omitempty"`
Image *string `json:"image,omitempty"` // Will be stored in metadata["image"]
Metadata map[string]interface{} `json:"metadata,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Variants []CreateProductVariantRequest `json:"variants,omitempty"`
InitialStock *int `json:"initial_stock,omitempty" validate:"omitempty,min=0"` // Initial stock quantity for all outlets
ReorderLevel *int `json:"reorder_level,omitempty" validate:"omitempty,min=0"` // Reorder level for all outlets
CreateInventory bool `json:"create_inventory,omitempty"` // Whether to create inventory records for all outlets
}
type UpdateProductRequest struct {
CategoryID *uuid.UUID `json:"category_id,omitempty"`
SKU *string `json:"sku,omitempty"`
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Description *string `json:"description,omitempty"`
Price *float64 `json:"price,omitempty" validate:"omitempty,min=0"`
Cost *float64 `json:"cost,omitempty" validate:"omitempty,min=0"`
BusinessType *string `json:"business_type,omitempty"`
Image *string `json:"image,omitempty"` // Will be stored in metadata["image"]
Metadata map[string]interface{} `json:"metadata,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
// Stock management fields
ReorderLevel *int `json:"reorder_level,omitempty" validate:"omitempty,min=0"` // Update reorder level for all existing inventory records
}
type CreateProductVariantRequest struct {
ProductID uuid.UUID `json:"product_id" validate:"required"`
Name string `json:"name" validate:"required,min=1,max=255"`
PriceModifier float64 `json:"price_modifier" validate:"required"`
Cost float64 `json:"cost" validate:"min=0"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type UpdateProductVariantRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
PriceModifier *float64 `json:"price_modifier,omitempty"`
Cost *float64 `json:"cost,omitempty" validate:"omitempty,min=0"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
type ProductResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
CategoryID uuid.UUID `json:"category_id"`
SKU *string `json:"sku"`
Name string `json:"name"`
Description *string `json:"description"`
Price float64 `json:"price"`
Cost float64 `json:"cost"`
BusinessType string `json:"business_type"`
Metadata map[string]interface{} `json:"metadata"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Category *CategoryResponse `json:"category,omitempty"`
Variants []ProductVariantResponse `json:"variants,omitempty"`
}
type ProductVariantResponse struct {
ID uuid.UUID `json:"id"`
ProductID uuid.UUID `json:"product_id"`
Name string `json:"name"`
PriceModifier float64 `json:"price_modifier"`
Cost float64 `json:"cost"`
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListProductsRequest struct {
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
CategoryID *uuid.UUID `json:"category_id,omitempty"`
BusinessType string `json:"business_type,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Search string `json:"search,omitempty"`
MinPrice *float64 `json:"min_price,omitempty" validate:"omitempty,min=0"`
MaxPrice *float64 `json:"max_price,omitempty" validate:"omitempty,min=0"`
Page int `json:"page" validate:"required,min=1"`
Limit int `json:"limit" validate:"required,min=1,max=100"`
}
type ListProductsResponse struct {
Products []ProductResponse `json:"products"`
TotalCount int `json:"total_count"`
Page int `json:"page"`
Limit int `json:"limit"`
TotalPages int `json:"total_pages"`
}
+39
View File
@@ -0,0 +1,39 @@
package contract
type Response struct {
Success bool `json:"success"`
Data interface{} `json:"data"`
Errors []*ResponseError `json:"errors"`
}
func (r *Response) GetSuccess() bool {
return r.Success
}
func (r *Response) GetData() interface{} {
return r.Data
}
func (r *Response) GetErrors() []*ResponseError {
return r.Errors
}
func BuildSuccessResponse(data interface{}) *Response {
return &Response{
Success: true,
Data: data,
Errors: []*ResponseError(nil),
}
}
func BuildErrorResponse(errorList []*ResponseError) *Response {
return &Response{
Success: false,
Data: nil,
Errors: errorList,
}
}
func (r *Response) HasErrors() bool {
return r.GetErrors() != nil && len(r.GetErrors()) > 0
}
+33
View File
@@ -0,0 +1,33 @@
package contract
import "fmt"
type ResponseError struct {
Code string `json:"code"`
Entity string `json:"entity"`
Cause string `json:"cause"`
}
func NewResponseError(code, entity, cause string) *ResponseError {
return &ResponseError{
Code: code,
Cause: cause,
Entity: entity,
}
}
func (e *ResponseError) GetCode() string {
return e.Code
}
func (e *ResponseError) GetEntity() string {
return e.Entity
}
func (e *ResponseError) GetCause() string {
return e.Cause
}
func (e *ResponseError) Error() string {
return fmt.Sprintf("%s: %s: %s", e.GetCode(), e.GetEntity(), e.GetCause())
}
+69
View File
@@ -0,0 +1,69 @@
package contract
import (
"time"
"github.com/google/uuid"
)
type CreateUserRequest struct {
OrganizationID uuid.UUID `json:"organization_id" validate:"required"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
Name string `json:"name" validate:"required,min=1,max=255"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=6"`
Role string `json:"role" validate:"required,oneof=admin manager cashier waiter"`
Permissions map[string]interface{} `json:"permissions,omitempty"`
}
type UpdateUserRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
Role *string `json:"role,omitempty" validate:"omitempty,oneof=admin manager cashier waiter"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
Permissions *map[string]interface{} `json:"permissions,omitempty"`
}
type ChangePasswordRequest struct {
CurrentPassword string `json:"current_password" validate:"required"`
NewPassword string `json:"new_password" validate:"required,min=6"`
}
type LoginRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}
type LoginResponse struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
User UserResponse `json:"user"`
}
type UserResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
OutletID *uuid.UUID `json:"outlet_id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
Permissions map[string]interface{} `json:"permissions"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListUsersRequest struct {
Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"`
Role *string `json:"role,omitempty"`
OutletID *uuid.UUID `json:"outlet_id,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
OrganizationID *uuid.UUID `json:"organization_id,omitempty"`
}
type ListUsersResponse struct {
Users []UserResponse `json:"users"`
Pagination PaginationResponse `json:"pagination"`
}