saveinmed/backend/internal/domain/models.go
2025-12-18 13:19:21 -03:00

240 lines
9.1 KiB
Go

package domain
import (
"time"
"github.com/gofrs/uuid/v5"
)
// Company represents a B2B actor in the marketplace.
type Company struct {
ID uuid.UUID `db:"id" json:"id"`
Role string `db:"role" json:"role"` // pharmacy, distributor, admin
CNPJ string `db:"cnpj" json:"cnpj"`
CorporateName string `db:"corporate_name" json:"corporate_name"`
LicenseNumber string `db:"license_number" json:"license_number"`
IsVerified bool `db:"is_verified" json:"is_verified"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// User represents an authenticated actor inside a company.
type User struct {
ID uuid.UUID `db:"id" json:"id"`
CompanyID uuid.UUID `db:"company_id" json:"company_id"`
Role string `db:"role" json:"role"`
Name string `db:"name" json:"name"`
Email string `db:"email" json:"email"`
PasswordHash string `db:"password_hash" json:"-"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// UserFilter captures listing constraints.
type UserFilter struct {
CompanyID *uuid.UUID
Limit int
Offset int
}
// UserPage wraps paginated results.
type UserPage struct {
Users []User `json:"users"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
// Product represents a medicine SKU with batch tracking.
type Product struct {
ID uuid.UUID `db:"id" json:"id"`
SellerID uuid.UUID `db:"seller_id" json:"seller_id"`
Name string `db:"name" json:"name"`
Description string `db:"description" json:"description"`
Batch string `db:"batch" json:"batch"`
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
PriceCents int64 `db:"price_cents" json:"price_cents"`
Stock int64 `db:"stock" json:"stock"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// InventoryItem exposes stock tracking tied to product batches.
type InventoryItem struct {
ProductID uuid.UUID `db:"product_id" json:"product_id"`
SellerID uuid.UUID `db:"seller_id" json:"seller_id"`
Name string `db:"name" json:"name"`
Batch string `db:"batch" json:"batch"`
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
Quantity int64 `db:"quantity" json:"quantity"`
PriceCents int64 `db:"price_cents" json:"price_cents"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// InventoryFilter allows filtering by expiration window.
type InventoryFilter struct {
ExpiringBefore *time.Time
}
// InventoryAdjustment records manual stock corrections.
type InventoryAdjustment struct {
ID uuid.UUID `db:"id" json:"id"`
ProductID uuid.UUID `db:"product_id" json:"product_id"`
Delta int64 `db:"delta" json:"delta"`
Reason string `db:"reason" json:"reason"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
// Order captures the status lifecycle and payment intent.
type Order struct {
ID uuid.UUID `db:"id" json:"id"`
BuyerID uuid.UUID `db:"buyer_id" json:"buyer_id"`
SellerID uuid.UUID `db:"seller_id" json:"seller_id"`
Status OrderStatus `db:"status" json:"status"`
TotalCents int64 `db:"total_cents" json:"total_cents"`
Items []OrderItem `json:"items"`
Shipping ShippingAddress `json:"shipping"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// OrderItem stores SKU-level batch tracking.
type OrderItem struct {
ID uuid.UUID `db:"id" json:"id"`
OrderID uuid.UUID `db:"order_id" json:"order_id"`
ProductID uuid.UUID `db:"product_id" json:"product_id"`
Quantity int64 `db:"quantity" json:"quantity"`
UnitCents int64 `db:"unit_cents" json:"unit_cents"`
Batch string `db:"batch" json:"batch"`
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
}
// PaymentPreference wraps the data needed for Mercado Pago split payments.
type PaymentPreference struct {
OrderID uuid.UUID `json:"order_id"`
Gateway string `json:"gateway"`
CommissionPct float64 `json:"commission_pct"`
MarketplaceFee int64 `json:"marketplace_fee"`
SellerReceivable int64 `json:"seller_receivable"`
PaymentURL string `json:"payment_url"`
}
// PaymentWebhookEvent represents Mercado Pago notifications with split amounts.
type PaymentWebhookEvent struct {
PaymentID string `json:"payment_id"`
OrderID uuid.UUID `json:"order_id"`
Status string `json:"status"`
MarketplaceFee int64 `json:"marketplace_fee"`
SellerAmount int64 `json:"seller_amount"`
TotalPaidAmount int64 `json:"total_paid_amount"`
}
// PaymentSplitResult echoes the amounts distributed between actors.
type PaymentSplitResult struct {
OrderID uuid.UUID `json:"order_id"`
PaymentID string `json:"payment_id"`
Status string `json:"status"`
MarketplaceFee int64 `json:"marketplace_fee"`
SellerReceivable int64 `json:"seller_receivable"`
TotalPaidAmount int64 `json:"total_paid_amount"`
}
// ShippingAddress captures delivery details at order time.
type ShippingAddress struct {
RecipientName string `json:"recipient_name" db:"shipping_recipient_name"`
Street string `json:"street" db:"shipping_street"`
Number string `json:"number" db:"shipping_number"`
Complement string `json:"complement,omitempty" db:"shipping_complement"`
District string `json:"district" db:"shipping_district"`
City string `json:"city" db:"shipping_city"`
State string `json:"state" db:"shipping_state"`
ZipCode string `json:"zip_code" db:"shipping_zip_code"`
Country string `json:"country" db:"shipping_country"`
}
// Shipment stores freight label data and tracking linkage.
type Shipment struct {
ID uuid.UUID `db:"id" json:"id"`
OrderID uuid.UUID `db:"order_id" json:"order_id"`
Carrier string `db:"carrier" json:"carrier"`
TrackingCode string `db:"tracking_code" json:"tracking_code"`
ExternalTracking string `db:"external_tracking" json:"external_tracking"`
Status string `db:"status" json:"status"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// OrderStatus enumerates supported transitions.
type OrderStatus string
const (
OrderStatusPending OrderStatus = "Pendente"
OrderStatusPaid OrderStatus = "Pago"
OrderStatusInvoiced OrderStatus = "Faturado"
OrderStatusDelivered OrderStatus = "Entregue"
)
// CartItem stores buyer selections with unit pricing.
type CartItem struct {
ID uuid.UUID `db:"id" json:"id"`
BuyerID uuid.UUID `db:"buyer_id" json:"buyer_id"`
ProductID uuid.UUID `db:"product_id" json:"product_id"`
Quantity int64 `db:"quantity" json:"quantity"`
UnitCents int64 `db:"unit_cents" json:"unit_cents"`
ProductName string `db:"product_name" json:"product_name"`
Batch string `db:"batch" json:"batch"`
ExpiresAt time.Time `db:"expires_at" json:"expires_at"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
// CartSummary aggregates cart totals and discounts.
type CartSummary struct {
Items []CartItem `json:"items"`
SubtotalCents int64 `json:"subtotal_cents"`
DiscountCents int64 `json:"discount_cents"`
TotalCents int64 `json:"total_cents"`
DiscountReason string `json:"discount_reason,omitempty"`
}
// Review captures the buyer feedback for a completed order.
type Review struct {
ID uuid.UUID `db:"id" json:"id"`
OrderID uuid.UUID `db:"order_id" json:"order_id"`
BuyerID uuid.UUID `db:"buyer_id" json:"buyer_id"`
SellerID uuid.UUID `db:"seller_id" json:"seller_id"`
Rating int `db:"rating" json:"rating"`
Comment string `db:"comment" json:"comment"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
// CompanyRating exposes the aggregate score for a seller or pharmacy.
type CompanyRating struct {
CompanyID uuid.UUID `json:"company_id"`
AverageScore float64 `json:"average_score"`
TotalReviews int64 `json:"total_reviews"`
}
// TopProduct aggregates seller performance per SKU.
type TopProduct struct {
ProductID uuid.UUID `json:"product_id"`
Name string `json:"name"`
TotalQuantity int64 `json:"total_quantity"`
RevenueCents int64 `json:"revenue_cents"`
}
// SellerDashboard summarizes commercial metrics for sellers.
type SellerDashboard struct {
SellerID uuid.UUID `json:"seller_id"`
TotalSalesCents int64 `json:"total_sales_cents"`
OrdersCount int64 `json:"orders_count"`
TopProducts []TopProduct `json:"top_products"`
LowStockAlerts []Product `json:"low_stock_alerts"`
}
// AdminDashboard surfaces platform-wide KPIs.
type AdminDashboard struct {
GMVCents int64 `json:"gmv_cents"`
NewCompanies int64 `json:"new_companies"`
WindowStartAt time.Time `json:"window_start_at"`
}