package domain import ( "strings" "time" "github.com/gofrs/uuid/v5" ) // CompanyID and UserID are UUIDv7 identifiers for performance-friendly indexing. type CompanyID = uuid.UUID type UserID = uuid.UUID // Tenant represents a B2B actor (pharmacy/distributor) in the marketplace. type Tenant struct { ID CompanyID `db:"id" json:"id"` CNPJ string `db:"cnpj" json:"cnpj"` CorporateName string `db:"corporate_name" json:"corporate_name"` Category string `db:"category" json:"category"` // farmacia, distribuidora LicenseNumber string `db:"license_number" json:"license_number"` IsVerified bool `db:"is_verified" json:"is_verified"` // Location Latitude float64 `db:"latitude" json:"latitude"` Longitude float64 `db:"longitude" json:"longitude"` City string `db:"city" json:"city"` State string `db:"state" json:"state"` // Contact & Hours Phone string `db:"phone" json:"phone"` OperatingHours string `db:"operating_hours" json:"operating_hours"` // e.g. "Seg-Sex: 08:00-18:00, Sab: 08:00-12:00" Is24Hours bool `db:"is_24_hours" json:"is_24_hours"` // Credit Lines (Boleto a Prazo) CreditLimitCents int64 `db:"credit_limit_cents" json:"credit_limit_cents"` // max credit allowed CreditUsedCents int64 `db:"credit_used_cents" json:"credit_used_cents"` // currently in use // Timestamps CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } // Company is an alias for Tenant for backward compatibility. type Company = Tenant // Role constants const ( RoleAdmin = "admin" RoleOwner = "owner" RoleEmployee = "employee" RoleDelivery = "delivery" ) func NormalizeRole(role string) string { switch strings.ToLower(strings.TrimSpace(role)) { case "admin", "superadmin", "super_admin", "admin_master": return RoleAdmin case "owner", "dono", "seller", "vendedor", "comprador", "gerente", "manager": return RoleOwner case "employee", "colaborador": return RoleEmployee case "delivery", "entregador": return RoleDelivery default: return RoleOwner } } func IsAdminRole(role string) bool { return NormalizeRole(role) == RoleAdmin } // User represents an authenticated actor inside a company. type User struct { ID UserID `db:"id" json:"id"` CompanyID CompanyID `db:"company_id" json:"company_id"` Role string `db:"role" json:"role"` Name string `db:"name" json:"name"` Username string `db:"username" json:"username"` Email string `db:"email" json:"email"` EmailVerified bool `db:"email_verified" json:"email_verified"` PasswordHash string `db:"password_hash" json:"-"` Superadmin bool `db:"superadmin" json:"superadmin"` NomeSocial string `db:"nome_social" json:"nome_social"` CPF string `db:"cpf" json:"cpf"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` // Rich Data (Populated manually) Enderecos []Address `db:"-" json:"enderecos"` EmpresasDados []Company `db:"-" json:"empresas_dados"` } // UserFilter captures listing constraints. type UserFilter struct { CompanyID *CompanyID 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"` // Who created this catalog entry (usually Admin/Master) EANCode string `db:"ean_code" json:"ean_code"` Name string `db:"name" json:"name"` Description string `db:"description" json:"description"` Manufacturer string `db:"manufacturer" json:"manufacturer"` Category string `db:"category" json:"category"` Subcategory string `db:"subcategory" json:"subcategory"` PriceCents int64 `db:"price_cents" json:"price_cents"` // Base/List Price // Compatibility for frontend SalePriceCents int64 `db:"price_cents" json:"sale_price_cents,omitempty"` // New Fields (Reference Data) InternalCode string `db:"internal_code" json:"internal_code"` FactoryPriceCents int64 `db:"factory_price_cents" json:"factory_price_cents"` PMCCents int64 `db:"pmc_cents" json:"pmc_cents"` CommercialDiscountCents int64 `db:"commercial_discount_cents" json:"commercial_discount_cents"` TaxSubstitutionCents int64 `db:"tax_substitution_cents" json:"tax_substitution_cents"` InvoicePriceCents int64 `db:"invoice_price_cents" json:"invoice_price_cents"` Observations string `db:"observations" json:"observations"` // Inventory/Batch Fields Batch string `db:"batch" json:"batch"` Stock int64 `db:"stock" json:"stock"` 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"` } // InventoryItem represents a product in a specific seller's stock. type InventoryItem struct { ID uuid.UUID `db:"id" json:"id"` ProductID uuid.UUID `db:"product_id" json:"product_id"` // catalogo_id SellerID uuid.UUID `db:"seller_id" json:"seller_id"` // empresa_id SalePriceCents int64 `db:"sale_price_cents" json:"sale_price_cents"` // preco_venda StockQuantity int64 `db:"stock_quantity" json:"stock_quantity"` // qtdade_estoque Batch string `db:"batch" json:"batch"` ExpiresAt time.Time `db:"expires_at" json:"expires_at"` // data_validade Observations string `db:"observations" json:"observations"` ProductName string `db:"product_name" json:"nome"` // Added for frontend display CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` // Compatibility fields for frontend Name string `db:"product_name" json:"name,omitempty"` Quantity int64 `db:"stock_quantity" json:"quantity,omitempty"` PriceCents int64 `db:"sale_price_cents" json:"price_cents,omitempty"` EANCode string `db:"ean_code" json:"ean_code,omitempty"` } // InventoryFilter allows filtering by expiration window with pagination. type InventoryFilter struct { ExpiringBefore *time.Time SellerID *uuid.UUID Limit int Offset int } // InventoryPage wraps paginated inventory results. type InventoryPage struct { Items []InventoryItem `json:"items"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // ProductFilter captures product listing constraints. type ProductFilter struct { SellerID *uuid.UUID Category string Search string Limit int Offset int } // ProductPage wraps paginated product results. type ProductPage struct { Products []Product `json:"products"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // CompanyFilter captures company/tenant listing constraints. type CompanyFilter struct { Category string Search string City string State string IsVerified *bool Limit int Offset int } // TenantFilter is an alias for CompanyFilter. type TenantFilter = CompanyFilter // CompanyPage wraps paginated company/tenant results. type CompanyPage struct { Companies []Company `json:"tenants"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // TenantPage is an alias for CompanyPage. type TenantPage = CompanyPage // OrderFilter captures order listing constraints. type OrderFilter struct { BuyerID *uuid.UUID SellerID *uuid.UUID Status OrderStatus Limit int Offset int } // OrderPage wraps paginated order results. type OrderPage struct { Orders []Order `json:"orders"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // 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"` PaymentMethod PaymentMethod `db:"payment_method" json:"payment_method"` ShippingFeeCents int64 `db:"shipping_fee_cents" json:"shipping_fee_cents"` // Adicionado DistanceKm float64 `db:"distance_km" json:"distance_km"` // Adicionado 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"` PaymentID string `json:"payment_id"` 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"` } // PaymentResult represents the result of a payment confirmation. type PaymentResult struct { PaymentID string `json:"payment_id"` Status string `json:"status"` Gateway string `json:"gateway"` Message string `json:"message,omitempty"` ConfirmedAt time.Time `json:"confirmed_at"` } // RefundResult represents the result of a refund operation. type RefundResult struct { RefundID string `json:"refund_id"` PaymentID string `json:"payment_id"` AmountCents int64 `json:"amount_cents"` Status string `json:"status"` RefundedAt time.Time `json:"refunded_at"` } // PixPaymentResult represents a Pix payment with QR code. type PixPaymentResult struct { PaymentID string `json:"payment_id"` OrderID uuid.UUID `json:"order_id"` Gateway string `json:"gateway"` PixKey string `json:"pix_key"` QRCode string `json:"qr_code"` QRCodeBase64 string `json:"qr_code_base64"` CopyPasta string `json:"copy_pasta"` AmountCents int64 `json:"amount_cents"` MarketplaceFee int64 `json:"marketplace_fee"` SellerReceivable int64 `json:"seller_receivable"` ExpiresAt time.Time `json:"expires_at"` Status string `json:"status"` } // BoletoPaymentResult represents a Boleto payment. type BoletoPaymentResult struct { PaymentID string `json:"payment_id"` OrderID uuid.UUID `json:"order_id"` Gateway string `json:"gateway"` BoletoURL string `json:"boleto_url"` BarCode string `json:"bar_code"` DigitableLine string `json:"digitable_line"` AmountCents int64 `json:"amount_cents"` MarketplaceFee int64 `json:"marketplace_fee"` SellerReceivable int64 `json:"seller_receivable"` DueDate time.Time `json:"due_date"` Status string `json:"status"` } // SellerPaymentAccount represents a seller's payment gateway account. type SellerPaymentAccount struct { SellerID uuid.UUID `json:"seller_id" db:"seller_id"` Gateway string `json:"gateway" db:"gateway"` AccountID string `json:"account_id" db:"account_id"` AccountType string `json:"account_type" db:"account_type"` // "connect", "subaccount" Status string `json:"status" db:"status"` // "pending", "active", "suspended" CreatedAt time.Time `json:"created_at" db:"created_at"` } // Customer represents a buyer for payment gateway purposes. type Customer struct { ID uuid.UUID `json:"id" db:"id"` Name string `json:"name" db:"name"` Email string `json:"email" db:"email"` CPF string `json:"cpf,omitempty" db:"cpf"` Phone string `json:"phone,omitempty" db:"phone"` CreatedAt time.Time `json:"created_at" db:"created_at"` } // PaymentGatewayConfig stores encrypted gateway credentials. type PaymentGatewayConfig struct { Provider string `json:"provider" db:"provider"` // mercadopago, stripe, asaas Active bool `json:"active" db:"active"` Credentials string `json:"-" db:"credentials"` // Encrypted JSON Environment string `json:"environment" db:"environment"` // sandbox, production Commission float64 `json:"commission" db:"commission"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } // Address represents a physical location for users or companies. type Address struct { ID uuid.UUID `db:"id" json:"id"` EntityID uuid.UUID `db:"entity_id" json:"entity_id"` Title string `db:"title" json:"titulo"` ZipCode string `db:"zip_code" json:"cep"` Street string `db:"street" json:"logradouro"` Number string `db:"number" json:"numero"` Complement string `db:"complement" json:"complemento"` District string `db:"district" json:"bairro"` City string `db:"city" json:"cidade"` State string `db:"state" json:"uf"` Latitude float64 `db:"latitude" json:"latitude"` Longitude float64 `db:"longitude" json:"longitude"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } // 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"` Latitude float64 `json:"latitude" db:"shipping_latitude"` Longitude float64 `json:"longitude" db:"shipping_longitude"` } // ShippingSettings stores configuration for calculating delivery fees. type ShippingSettings struct { VendorID uuid.UUID `db:"vendor_id" json:"vendor_id"` Active bool `db:"active" json:"active"` MaxRadiusKm float64 `db:"max_radius_km" json:"max_radius_km"` PricePerKmCents int64 `db:"price_per_km_cents" json:"price_per_km_cents"` MinFeeCents int64 `db:"min_fee_cents" json:"min_fee_cents"` FreeShippingThresholdCents *int64 `db:"free_shipping_threshold_cents" json:"free_shipping_threshold_cents"` PickupActive bool `db:"pickup_active" json:"pickup_active"` PickupAddress string `db:"pickup_address" json:"pickup_address"` PickupHours string `db:"pickup_hours" json:"pickup_hours"` Latitude float64 `db:"latitude" json:"latitude"` Longitude float64 `db:"longitude" json:"longitude"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } // 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"` } // ReviewFilter captures review listing constraints. type ReviewFilter struct { SellerID *uuid.UUID Limit int Offset int } // ReviewPage wraps paginated review results. type ReviewPage struct { Reviews []Review `json:"reviews"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // ShipmentFilter captures shipment listing constraints. type ShipmentFilter struct { SellerID *uuid.UUID Limit int Offset int } // ShipmentPage wraps paginated shipment results. type ShipmentPage struct { Shipments []Shipment `json:"shipments"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` } // OrderStatus enumerates supported transitions. type OrderStatus string const ( OrderStatusPending OrderStatus = "Pendente" OrderStatusPaid OrderStatus = "Pago" OrderStatusInvoiced OrderStatus = "Faturado" OrderStatusShipped OrderStatus = "Enviado" OrderStatusDelivered OrderStatus = "Entregue" OrderStatusCompleted OrderStatus = "ConcluĂ­do" OrderStatusCancelled OrderStatus = "Cancelado" ) // PaymentMethod enumerates supported payment types. type PaymentMethod string const ( PaymentMethodPix PaymentMethod = "pix" PaymentMethodCredit PaymentMethod = "credit_card" PaymentMethodDebit PaymentMethod = "debit_card" ) // 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 { ID uuid.UUID `json:"id"` // Virtual Cart ID (equals BuyerID) 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 CompanyID `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 `db:"product_id" json:"product_id"` Name string `db:"name" json:"name"` TotalQuantity int64 `db:"total_quantity" json:"total_quantity"` RevenueCents int64 `db:"revenue_cents" 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"` } // CompanyDocument represents a KYC/KYB document (CNPJ card, Permit). type CompanyDocument struct { ID uuid.UUID `db:"id" json:"id"` CompanyID CompanyID `db:"company_id" json:"company_id"` Type string `db:"type" json:"type"` // CNPJ, PERMIT, IDENTITY URL string `db:"url" json:"url"` Status string `db:"status" json:"status"` // PENDING, APPROVED, REJECTED RejectionReason string `db:"rejection_reason" json:"rejection_reason,omitempty"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } // LedgerEntry represents an immutable financial record. type LedgerEntry struct { ID uuid.UUID `db:"id" json:"id"` CompanyID CompanyID `db:"company_id" json:"company_id"` AmountCents int64 `db:"amount_cents" json:"amount_cents"` Type string `db:"type" json:"type"` // SALE, FEE, WITHDRAWAL, REFUND Description string `db:"description" json:"description"` ReferenceID *uuid.UUID `db:"reference_id" json:"reference_id,omitempty"` CreatedAt time.Time `db:"created_at" json:"created_at"` } // Withdrawal represents a payout request. type Withdrawal struct { ID uuid.UUID `db:"id" json:"id"` CompanyID CompanyID `db:"company_id" json:"company_id"` AmountCents int64 `db:"amount_cents" json:"amount_cents"` Status string `db:"status" json:"status"` // PENDING, APPROVED, PAID, REJECTED BankAccountInfo string `db:"bank_account_info" json:"bank_account_info"` TransactionID string `db:"transaction_id" json:"transaction_id,omitempty"` RejectionReason string `db:"rejection_reason" json:"rejection_reason,omitempty"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } // StockReservation holds a temporary lock on inventory during checkout. type StockReservation struct { ID uuid.UUID `db:"id" json:"id"` ProductID uuid.UUID `db:"product_id" json:"product_id"` InventoryItemID uuid.UUID `db:"inventory_item_id" json:"inventory_item_id"` BuyerID uuid.UUID `db:"buyer_id" json:"buyer_id"` Quantity int64 `db:"quantity" json:"quantity"` Status string `db:"status" json:"status"` // active, completed, expired ExpiresAt time.Time `db:"expires_at" json:"expires_at"` CreatedAt time.Time `db:"created_at" json:"created_at"` }