init
This commit is contained in:
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
Reference in New Issue
Block a user