Initialize base
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Customer represents a mobile app user (customer)
|
||||
type Customer struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
Email string `json:"email" bson:"email"`
|
||||
Password string `json:"-" bson:"password"` // Never serialize password
|
||||
FirstName string `json:"first_name" bson:"first_name"`
|
||||
LastName string `json:"last_name" bson:"last_name"`
|
||||
Phone string `json:"phone" bson:"phone"`
|
||||
Role CustomerRole `json:"role" bson:"role"`
|
||||
CompanyID uuid.UUID `json:"company_id" bson:"company_id"`
|
||||
IsActive bool `json:"is_active" bson:"is_active"`
|
||||
IsVerified bool `json:"is_verified" bson:"is_verified"`
|
||||
DeviceTokens []string `json:"device_tokens" bson:"device_tokens"` // For push notifications
|
||||
Preferences CustomerPreferences `json:"preferences" bson:"preferences"`
|
||||
LastLoginAt *time.Time `json:"last_login_at,omitempty" bson:"last_login_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// CustomerPreferences represents customer-specific preferences
|
||||
type CustomerPreferences struct {
|
||||
Language string `json:"language" bson:"language"`
|
||||
NotificationSettings NotificationSettings `json:"notification_settings" bson:"notification_settings"`
|
||||
TenderAlerts bool `json:"tender_alerts" bson:"tender_alerts"`
|
||||
EmailNotifications bool `json:"email_notifications" bson:"email_notifications"`
|
||||
PushNotifications bool `json:"push_notifications" bson:"push_notifications"`
|
||||
PreferredCategories []string `json:"preferred_categories" bson:"preferred_categories"`
|
||||
}
|
||||
|
||||
// NotificationSettings represents notification preferences
|
||||
type NotificationSettings struct {
|
||||
NewTenders bool `json:"new_tenders" bson:"new_tenders"`
|
||||
DeadlineReminder bool `json:"deadline_reminder" bson:"deadline_reminder"`
|
||||
StatusUpdates bool `json:"status_updates" bson:"status_updates"`
|
||||
SystemAlerts bool `json:"system_alerts" bson:"system_alerts"`
|
||||
}
|
||||
|
||||
// CustomerRole defines roles for mobile app users
|
||||
type CustomerRole string
|
||||
|
||||
const (
|
||||
CustomerRoleUser CustomerRole = "customer_user" // Regular customer
|
||||
CustomerRoleManager CustomerRole = "customer_manager" // Company manager
|
||||
)
|
||||
|
||||
// User represents a panel user (admin/staff)
|
||||
type User struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
Email string `json:"email" bson:"email"`
|
||||
Password string `json:"-" bson:"password"` // Never serialize password
|
||||
FirstName string `json:"first_name" bson:"first_name"`
|
||||
LastName string `json:"last_name" bson:"last_name"`
|
||||
Role UserRole `json:"role" bson:"role"`
|
||||
Department string `json:"department" bson:"department"`
|
||||
IsActive bool `json:"is_active" bson:"is_active"`
|
||||
Permissions []string `json:"permissions" bson:"permissions"`
|
||||
LastLoginAt *time.Time `json:"last_login_at,omitempty" bson:"last_login_at,omitempty"`
|
||||
CreatedBy *uuid.UUID `json:"created_by,omitempty" bson:"created_by,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// UserRole defines roles for panel users
|
||||
type UserRole string
|
||||
|
||||
const (
|
||||
UserRoleAdmin UserRole = "admin" // Full system administrator
|
||||
UserRoleModerator UserRole = "moderator" // Moderator with limited admin access
|
||||
UserRoleSupport UserRole = "support" // Support user with read-only access
|
||||
UserRoleAnalyst UserRole = "analyst" // Data analyst with reporting access
|
||||
)
|
||||
|
||||
// Customer methods
|
||||
func (c *Customer) HasRole(role CustomerRole) bool {
|
||||
return c.Role == role
|
||||
}
|
||||
|
||||
func (c *Customer) IsManager() bool {
|
||||
return c.Role == CustomerRoleManager
|
||||
}
|
||||
|
||||
func (c *Customer) CanAccessCompanySettings() bool {
|
||||
return c.IsActive && c.IsVerified && c.IsManager()
|
||||
}
|
||||
|
||||
func (c *Customer) FullName() string {
|
||||
return c.FirstName + " " + c.LastName
|
||||
}
|
||||
|
||||
// User methods
|
||||
func (u *User) HasRole(role UserRole) bool {
|
||||
return u.Role == role
|
||||
}
|
||||
|
||||
func (u *User) HasAnyRole(roles ...UserRole) bool {
|
||||
for _, role := range roles {
|
||||
if u.Role == role {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *User) HasPermission(permission string) bool {
|
||||
for _, perm := range u.Permissions {
|
||||
if perm == permission {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *User) IsAdmin() bool {
|
||||
return u.Role == UserRoleAdmin
|
||||
}
|
||||
|
||||
func (u *User) CanManageUsers() bool {
|
||||
return u.IsActive && (u.Role == UserRoleAdmin || u.HasPermission("manage_users"))
|
||||
}
|
||||
|
||||
func (u *User) CanManageTenders() bool {
|
||||
return u.IsActive && (u.Role == UserRoleAdmin || u.Role == UserRoleModerator || u.HasPermission("manage_tenders"))
|
||||
}
|
||||
|
||||
func (u *User) CanViewReports() bool {
|
||||
return u.IsActive && (u.Role == UserRoleAdmin || u.Role == UserRoleAnalyst || u.HasPermission("view_reports"))
|
||||
}
|
||||
|
||||
func (u *User) FullName() string {
|
||||
return u.FirstName + " " + u.LastName
|
||||
}
|
||||
|
||||
// Company represents a company profile
|
||||
type Company struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Industry string `json:"industry" bson:"industry"`
|
||||
Country string `json:"country" bson:"country"`
|
||||
Website string `json:"website" bson:"website"`
|
||||
Keywords []string `json:"keywords" bson:"keywords"`
|
||||
Products []string `json:"products" bson:"products"`
|
||||
Services []string `json:"services" bson:"services"`
|
||||
Capabilities []string `json:"capabilities" bson:"capabilities"`
|
||||
Documents []Document `json:"documents" bson:"documents"`
|
||||
Interests InterestProfile `json:"interests" bson:"interests"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// InterestProfile represents company's tender interests
|
||||
type InterestProfile struct {
|
||||
Keywords []string `json:"keywords" bson:"keywords"`
|
||||
Industries []string `json:"industries" bson:"industries"`
|
||||
CPVCodes []string `json:"cpv_codes" bson:"cpv_codes"`
|
||||
MinBudget *float64 `json:"min_budget,omitempty" bson:"min_budget,omitempty"`
|
||||
MaxBudget *float64 `json:"max_budget,omitempty" bson:"max_budget,omitempty"`
|
||||
Regions []string `json:"regions" bson:"regions"`
|
||||
Embeddings []float32 `json:"-" bson:"embeddings"` // AI embeddings for matching
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// Tender represents a tender opportunity
|
||||
type Tender struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
Title string `json:"title" bson:"title"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Summary string `json:"summary" bson:"summary"`
|
||||
Type TenderType `json:"type" bson:"type"`
|
||||
Status TenderStatus `json:"status" bson:"status"`
|
||||
PublicationDate time.Time `json:"publication_date" bson:"publication_date"`
|
||||
Deadline time.Time `json:"deadline" bson:"deadline"`
|
||||
Budget *float64 `json:"budget,omitempty" bson:"budget,omitempty"`
|
||||
Currency string `json:"currency" bson:"currency"`
|
||||
Region string `json:"region" bson:"region"`
|
||||
Country string `json:"country" bson:"country"`
|
||||
CPVCodes []string `json:"cpv_codes" bson:"cpv_codes"`
|
||||
Categories []string `json:"categories" bson:"categories"`
|
||||
Keywords []string `json:"keywords" bson:"keywords"`
|
||||
Tags []string `json:"tags" bson:"tags"`
|
||||
Language string `json:"language" bson:"language"`
|
||||
SourceURL string `json:"source_url" bson:"source_url"`
|
||||
SourceName string `json:"source_name" bson:"source_name"`
|
||||
Documents []TenderDocument `json:"documents" bson:"documents"`
|
||||
Requirements []Requirement `json:"requirements" bson:"requirements"`
|
||||
Embeddings []float32 `json:"-" bson:"embeddings"` // AI embeddings for matching
|
||||
ProcessedAt *time.Time `json:"processed_at,omitempty" bson:"processed_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// TenderType defines types of tenders
|
||||
type TenderType string
|
||||
|
||||
const (
|
||||
TenderTypeRFI TenderType = "RFI" // Request for Information
|
||||
TenderTypeRFP TenderType = "RFP" // Request for Proposal
|
||||
TenderTypeRFQ TenderType = "RFQ" // Request for Quote
|
||||
TenderTypeTender TenderType = "TENDER" // Public Tender
|
||||
)
|
||||
|
||||
// TenderStatus defines tender statuses
|
||||
type TenderStatus string
|
||||
|
||||
const (
|
||||
TenderStatusActive TenderStatus = "active"
|
||||
TenderStatusExpired TenderStatus = "expired"
|
||||
TenderStatusCancelled TenderStatus = "cancelled"
|
||||
TenderStatusAwarded TenderStatus = "awarded"
|
||||
)
|
||||
|
||||
// TenderDocument represents documents associated with a tender
|
||||
type TenderDocument struct {
|
||||
ID uuid.UUID `json:"id" bson:"id"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Type DocumentType `json:"type" bson:"type"`
|
||||
URL string `json:"url" bson:"url"`
|
||||
LocalPath string `json:"local_path" bson:"local_path"`
|
||||
Size int64 `json:"size" bson:"size"`
|
||||
ContentType string `json:"content_type" bson:"content_type"`
|
||||
Checksum string `json:"checksum" bson:"checksum"`
|
||||
Downloaded bool `json:"downloaded" bson:"downloaded"`
|
||||
DownloadedAt *time.Time `json:"downloaded_at,omitempty" bson:"downloaded_at,omitempty"`
|
||||
}
|
||||
|
||||
// Requirement represents tender requirements
|
||||
type Requirement struct {
|
||||
ID uuid.UUID `json:"id" bson:"id"`
|
||||
Type RequirementType `json:"type" bson:"type"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
Mandatory bool `json:"mandatory" bson:"mandatory"`
|
||||
Category string `json:"category" bson:"category"`
|
||||
}
|
||||
|
||||
// RequirementType defines types of requirements
|
||||
type RequirementType string
|
||||
|
||||
const (
|
||||
RequirementTypeLegal RequirementType = "legal"
|
||||
RequirementTypeTechnical RequirementType = "technical"
|
||||
RequirementTypeFinancial RequirementType = "financial"
|
||||
RequirementTypeExperience RequirementType = "experience"
|
||||
)
|
||||
|
||||
// Document represents uploaded company documents
|
||||
type Document struct {
|
||||
ID uuid.UUID `json:"id" bson:"id"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Type DocumentType `json:"type" bson:"type"`
|
||||
Category string `json:"category" bson:"category"`
|
||||
Description string `json:"description" bson:"description"`
|
||||
FilePath string `json:"file_path" bson:"file_path"`
|
||||
Size int64 `json:"size" bson:"size"`
|
||||
ContentType string `json:"content_type" bson:"content_type"`
|
||||
Checksum string `json:"checksum" bson:"checksum"`
|
||||
ExpiryDate *time.Time `json:"expiry_date,omitempty" bson:"expiry_date,omitempty"`
|
||||
Keywords []string `json:"keywords" bson:"keywords"`
|
||||
UploadedBy uuid.UUID `json:"uploaded_by" bson:"uploaded_by"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// DocumentType defines types of documents
|
||||
type DocumentType string
|
||||
|
||||
const (
|
||||
DocumentTypePDF DocumentType = "pdf"
|
||||
DocumentTypeWord DocumentType = "word"
|
||||
DocumentTypeExcel DocumentType = "excel"
|
||||
DocumentTypeImage DocumentType = "image"
|
||||
DocumentTypeCertificate DocumentType = "certificate"
|
||||
DocumentTypeLicense DocumentType = "license"
|
||||
DocumentTypeContract DocumentType = "contract"
|
||||
DocumentTypeCatalog DocumentType = "catalog"
|
||||
)
|
||||
|
||||
// TenderSource represents tender source configuration
|
||||
type TenderSource struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
BaseURL string `json:"base_url" bson:"base_url"`
|
||||
Type SourceType `json:"type" bson:"type"`
|
||||
AuthRequired bool `json:"auth_required" bson:"auth_required"`
|
||||
CredentialsID *uuid.UUID `json:"credentials_id,omitempty" bson:"credentials_id,omitempty"`
|
||||
CheckInterval time.Duration `json:"check_interval" bson:"check_interval"`
|
||||
CategoryTags []string `json:"category_tags" bson:"category_tags"`
|
||||
Region string `json:"region" bson:"region"`
|
||||
Language string `json:"language" bson:"language"`
|
||||
Status SourceStatus `json:"status" bson:"status"`
|
||||
LastCheckedAt *time.Time `json:"last_checked_at,omitempty" bson:"last_checked_at,omitempty"`
|
||||
Configuration SourceConfiguration `json:"configuration" bson:"configuration"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// SourceType defines types of tender sources
|
||||
type SourceType string
|
||||
|
||||
const (
|
||||
SourceTypeAPI SourceType = "api"
|
||||
SourceTypeHTML SourceType = "html"
|
||||
SourceTypeJS SourceType = "js"
|
||||
SourceTypePDF SourceType = "pdf"
|
||||
SourceTypeRSS SourceType = "rss"
|
||||
)
|
||||
|
||||
// SourceStatus defines tender source statuses
|
||||
type SourceStatus string
|
||||
|
||||
const (
|
||||
SourceStatusActive SourceStatus = "active"
|
||||
SourceStatusInactive SourceStatus = "inactive"
|
||||
SourceStatusError SourceStatus = "error"
|
||||
)
|
||||
|
||||
// SourceConfiguration holds source-specific configuration
|
||||
type SourceConfiguration struct {
|
||||
Headers map[string]string `json:"headers,omitempty" bson:"headers,omitempty"`
|
||||
QueryParams map[string]string `json:"query_params,omitempty" bson:"query_params,omitempty"`
|
||||
Selectors map[string]string `json:"selectors,omitempty" bson:"selectors,omitempty"`
|
||||
PaginationKey string `json:"pagination_key,omitempty" bson:"pagination_key,omitempty"`
|
||||
MaxPages int `json:"max_pages,omitempty" bson:"max_pages,omitempty"`
|
||||
RateLimitDelay time.Duration `json:"rate_limit_delay,omitempty" bson:"rate_limit_delay,omitempty"`
|
||||
}
|
||||
|
||||
// TenderMatch represents AI-powered tender recommendations
|
||||
type TenderMatch struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
CompanyID uuid.UUID `json:"company_id" bson:"company_id"`
|
||||
TenderID uuid.UUID `json:"tender_id" bson:"tender_id"`
|
||||
Score float64 `json:"score" bson:"score"`
|
||||
Explanation string `json:"explanation" bson:"explanation"`
|
||||
Tags []string `json:"tags" bson:"tags"`
|
||||
Status MatchStatus `json:"status" bson:"status"`
|
||||
UserAction *UserAction `json:"user_action,omitempty" bson:"user_action,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||
}
|
||||
|
||||
// MatchStatus defines tender match statuses
|
||||
type MatchStatus string
|
||||
|
||||
const (
|
||||
MatchStatusPending MatchStatus = "pending"
|
||||
MatchStatusViewed MatchStatus = "viewed"
|
||||
MatchStatusLiked MatchStatus = "liked"
|
||||
MatchStatusDisliked MatchStatus = "disliked"
|
||||
MatchStatusApplied MatchStatus = "applied"
|
||||
)
|
||||
|
||||
// UserAction represents user interaction with tender matches
|
||||
type UserAction struct {
|
||||
Action MatchStatus `json:"action" bson:"action"`
|
||||
Timestamp time.Time `json:"timestamp" bson:"timestamp"`
|
||||
UserID uuid.UUID `json:"user_id" bson:"user_id"`
|
||||
}
|
||||
|
||||
// Notification represents system notifications
|
||||
type Notification struct {
|
||||
ID uuid.UUID `json:"id" bson:"_id"`
|
||||
UserID uuid.UUID `json:"user_id" bson:"user_id"`
|
||||
CompanyID uuid.UUID `json:"company_id" bson:"company_id"`
|
||||
Type NotificationType `json:"type" bson:"type"`
|
||||
Title string `json:"title" bson:"title"`
|
||||
Message string `json:"message" bson:"message"`
|
||||
Data map[string]any `json:"data,omitempty" bson:"data,omitempty"`
|
||||
Read bool `json:"read" bson:"read"`
|
||||
Sent bool `json:"sent" bson:"sent"`
|
||||
SentAt *time.Time `json:"sent_at,omitempty" bson:"sent_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
||||
}
|
||||
|
||||
// NotificationType defines types of notifications
|
||||
type NotificationType string
|
||||
|
||||
const (
|
||||
NotificationTypeNewTender NotificationType = "new_tender"
|
||||
NotificationTypeDeadline NotificationType = "deadline_reminder"
|
||||
NotificationTypeStatusUpdate NotificationType = "status_update"
|
||||
NotificationTypeSystemAlert NotificationType = "system_alert"
|
||||
)
|
||||
@@ -0,0 +1,321 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Repository interfaces define data access contracts
|
||||
|
||||
// CustomerRepository defines methods for customer (mobile user) data access
|
||||
type CustomerRepository interface {
|
||||
Create(ctx context.Context, customer *Customer) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*Customer, error)
|
||||
GetByEmail(ctx context.Context, email string) (*Customer, error)
|
||||
Update(ctx context.Context, customer *Customer) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*Customer, error)
|
||||
GetByCompanyID(ctx context.Context, companyID uuid.UUID, limit, offset int) ([]*Customer, error)
|
||||
UpdatePreferences(ctx context.Context, id uuid.UUID, preferences *CustomerPreferences) error
|
||||
AddDeviceToken(ctx context.Context, id uuid.UUID, token string) error
|
||||
RemoveDeviceToken(ctx context.Context, id uuid.UUID, token string) error
|
||||
}
|
||||
|
||||
// UserRepository defines methods for panel user data access
|
||||
type UserRepository interface {
|
||||
Create(ctx context.Context, user *User) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*User, error)
|
||||
GetByEmail(ctx context.Context, email string) (*User, error)
|
||||
Update(ctx context.Context, user *User) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*User, error)
|
||||
GetByRole(ctx context.Context, role UserRole, limit, offset int) ([]*User, error)
|
||||
UpdatePermissions(ctx context.Context, id uuid.UUID, permissions []string) error
|
||||
}
|
||||
|
||||
// CompanyRepository defines methods for company data access
|
||||
type CompanyRepository interface {
|
||||
Create(ctx context.Context, company *Company) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*Company, error)
|
||||
Update(ctx context.Context, company *Company) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*Company, error)
|
||||
UpdateInterests(ctx context.Context, id uuid.UUID, interests *InterestProfile) error
|
||||
}
|
||||
|
||||
// TenderRepository defines methods for tender data access
|
||||
type TenderRepository interface {
|
||||
Create(ctx context.Context, tender *Tender) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*Tender, error)
|
||||
Update(ctx context.Context, tender *Tender) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, filters TenderFilters, limit, offset int) ([]*Tender, error)
|
||||
ListByStatus(ctx context.Context, status TenderStatus, limit, offset int) ([]*Tender, error)
|
||||
Search(ctx context.Context, query string, filters TenderFilters, limit, offset int) ([]*Tender, error)
|
||||
GetExpiringTenders(ctx context.Context, days int) ([]*Tender, error)
|
||||
BulkCreate(ctx context.Context, tenders []*Tender) error
|
||||
}
|
||||
|
||||
// TenderSourceRepository defines methods for tender source data access
|
||||
type TenderSourceRepository interface {
|
||||
Create(ctx context.Context, source *TenderSource) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*TenderSource, error)
|
||||
Update(ctx context.Context, source *TenderSource) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*TenderSource, error)
|
||||
GetActiveources(ctx context.Context) ([]*TenderSource, error)
|
||||
UpdateLastChecked(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// TenderMatchRepository defines methods for tender match data access
|
||||
type TenderMatchRepository interface {
|
||||
Create(ctx context.Context, match *TenderMatch) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*TenderMatch, error)
|
||||
Update(ctx context.Context, match *TenderMatch) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
GetByCompany(ctx context.Context, companyID uuid.UUID, limit, offset int) ([]*TenderMatch, error)
|
||||
GetByTender(ctx context.Context, tenderID uuid.UUID, limit, offset int) ([]*TenderMatch, error)
|
||||
UpdateUserAction(ctx context.Context, id uuid.UUID, action *UserAction) error
|
||||
BulkCreate(ctx context.Context, matches []*TenderMatch) error
|
||||
}
|
||||
|
||||
// DocumentRepository defines methods for document data access
|
||||
type DocumentRepository interface {
|
||||
Create(ctx context.Context, document *Document) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*Document, error)
|
||||
Update(ctx context.Context, document *Document) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
GetByCompany(ctx context.Context, companyID uuid.UUID) ([]*Document, error)
|
||||
GetByCategory(ctx context.Context, companyID uuid.UUID, category string) ([]*Document, error)
|
||||
}
|
||||
|
||||
// NotificationRepository defines methods for notification data access
|
||||
type NotificationRepository interface {
|
||||
Create(ctx context.Context, notification *Notification) error
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*Notification, error)
|
||||
Update(ctx context.Context, notification *Notification) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
GetByUser(ctx context.Context, userID uuid.UUID, limit, offset int) ([]*Notification, error)
|
||||
GetUnreadByUser(ctx context.Context, userID uuid.UUID) ([]*Notification, error)
|
||||
MarkAsRead(ctx context.Context, id uuid.UUID) error
|
||||
MarkAsSent(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// Service interfaces define business logic contracts
|
||||
|
||||
// CustomerAuthService defines authentication methods for mobile customers
|
||||
type CustomerAuthService interface {
|
||||
Register(ctx context.Context, req CustomerRegisterRequest) (*CustomerAuthResponse, error)
|
||||
Login(ctx context.Context, req LoginRequest) (*CustomerAuthResponse, error)
|
||||
RefreshToken(ctx context.Context, refreshToken string) (*CustomerAuthResponse, error)
|
||||
ValidateToken(ctx context.Context, token string) (*Customer, error)
|
||||
ChangePassword(ctx context.Context, customerID uuid.UUID, oldPassword, newPassword string) error
|
||||
ResetPassword(ctx context.Context, email string) error
|
||||
VerifyEmail(ctx context.Context, customerID uuid.UUID, token string) error
|
||||
ResendVerification(ctx context.Context, email string) error
|
||||
}
|
||||
|
||||
// UserAuthService defines authentication methods for panel users
|
||||
type UserAuthService interface {
|
||||
Login(ctx context.Context, req LoginRequest) (*UserAuthResponse, error)
|
||||
RefreshToken(ctx context.Context, refreshToken string) (*UserAuthResponse, error)
|
||||
ValidateToken(ctx context.Context, token string) (*User, error)
|
||||
ChangePassword(ctx context.Context, userID uuid.UUID, oldPassword, newPassword string) error
|
||||
CreatePanelUser(ctx context.Context, req CreateUserRequest, createdBy uuid.UUID) (*User, error)
|
||||
UpdateUserPermissions(ctx context.Context, userID uuid.UUID, permissions []string, updatedBy uuid.UUID) error
|
||||
}
|
||||
|
||||
// TenderService defines tender management methods
|
||||
type TenderService interface {
|
||||
GetTenders(ctx context.Context, filters TenderFilters, limit, offset int) ([]*Tender, error)
|
||||
GetTenderByID(ctx context.Context, id uuid.UUID) (*Tender, error)
|
||||
SearchTenders(ctx context.Context, query string, filters TenderFilters, limit, offset int) ([]*Tender, error)
|
||||
GetTenderMatches(ctx context.Context, companyID uuid.UUID, limit, offset int) ([]*TenderMatch, error)
|
||||
ProcessTenderAction(ctx context.Context, matchID uuid.UUID, action MatchStatus, customerID uuid.UUID) error
|
||||
}
|
||||
|
||||
// CompanyService defines company management methods
|
||||
type CompanyService interface {
|
||||
CreateCompany(ctx context.Context, req CreateCompanyRequest) (*Company, error)
|
||||
GetCompany(ctx context.Context, id uuid.UUID) (*Company, error)
|
||||
UpdateCompany(ctx context.Context, id uuid.UUID, req UpdateCompanyRequest, updatedBy uuid.UUID) (*Company, error)
|
||||
UpdateInterests(ctx context.Context, companyID uuid.UUID, interests *InterestProfile) error
|
||||
UploadDocument(ctx context.Context, companyID uuid.UUID, req UploadDocumentRequest) (*Document, error)
|
||||
GetDocuments(ctx context.Context, companyID uuid.UUID) ([]*Document, error)
|
||||
}
|
||||
|
||||
// CustomerService defines customer management methods (for panel users)
|
||||
type CustomerService interface {
|
||||
GetCustomers(ctx context.Context, limit, offset int) ([]*Customer, error)
|
||||
GetCustomerByID(ctx context.Context, id uuid.UUID) (*Customer, error)
|
||||
GetCustomersByCompany(ctx context.Context, companyID uuid.UUID, limit, offset int) ([]*Customer, error)
|
||||
UpdateCustomerStatus(ctx context.Context, customerID uuid.UUID, isActive bool, updatedBy uuid.UUID) error
|
||||
UpdateCustomerPreferences(ctx context.Context, customerID uuid.UUID, preferences *CustomerPreferences) error
|
||||
}
|
||||
|
||||
// ScrapingService defines tender scraping methods
|
||||
type ScrapingService interface {
|
||||
ScrapeTenderSource(ctx context.Context, sourceID uuid.UUID) error
|
||||
ProcessTenderData(ctx context.Context, rawData []byte, sourceID uuid.UUID) ([]*Tender, error)
|
||||
DownloadTenderDocuments(ctx context.Context, tenderID uuid.UUID) error
|
||||
ScheduleScrapingJobs(ctx context.Context) error
|
||||
}
|
||||
|
||||
// AIService defines AI and machine learning methods
|
||||
type AIService interface {
|
||||
GenerateEmbeddings(ctx context.Context, text string) ([]float32, error)
|
||||
MatchTenders(ctx context.Context, companyID uuid.UUID) ([]*TenderMatch, error)
|
||||
ExtractTenderRequirements(ctx context.Context, tenderID uuid.UUID) ([]*Requirement, error)
|
||||
TranslateDocument(ctx context.Context, text, sourceLanguage, targetLanguage string) (string, error)
|
||||
ClassifyTender(ctx context.Context, tender *Tender) ([]string, error)
|
||||
ExtractKeywords(ctx context.Context, text string) ([]string, error)
|
||||
}
|
||||
|
||||
// NotificationService defines notification methods
|
||||
type NotificationService interface {
|
||||
SendNotification(ctx context.Context, notification *Notification) error
|
||||
SendBulkNotifications(ctx context.Context, notifications []*Notification) error
|
||||
GetUserNotifications(ctx context.Context, userID uuid.UUID, limit, offset int) ([]*Notification, error)
|
||||
MarkNotificationAsRead(ctx context.Context, id uuid.UUID) error
|
||||
CreateTenderNotification(ctx context.Context, tender *Tender, companyIDs []uuid.UUID) error
|
||||
}
|
||||
|
||||
// Cache interface defines caching methods
|
||||
type CacheService interface {
|
||||
Set(ctx context.Context, key string, value interface{}, ttl int) error
|
||||
Get(ctx context.Context, key string, dest interface{}) error
|
||||
Delete(ctx context.Context, key string) error
|
||||
Exists(ctx context.Context, key string) (bool, error)
|
||||
SetHash(ctx context.Context, key, field string, value interface{}) error
|
||||
GetHash(ctx context.Context, key, field string, dest interface{}) error
|
||||
}
|
||||
|
||||
// Queue interface defines message queue methods
|
||||
type QueueService interface {
|
||||
Publish(ctx context.Context, queue string, message interface{}) error
|
||||
Subscribe(ctx context.Context, queue string, handler func([]byte) error) error
|
||||
PublishDelayed(ctx context.Context, queue string, message interface{}, delay int) error
|
||||
}
|
||||
|
||||
// Search interface defines search engine methods
|
||||
type SearchService interface {
|
||||
IndexTender(ctx context.Context, tender *Tender) error
|
||||
SearchTenders(ctx context.Context, query string, filters map[string]interface{}, limit, offset int) ([]*Tender, error)
|
||||
DeleteTender(ctx context.Context, tenderID uuid.UUID) error
|
||||
BulkIndexTenders(ctx context.Context, tenders []*Tender) error
|
||||
}
|
||||
|
||||
// DTOs and Request/Response types
|
||||
|
||||
// TenderFilters defines filters for tender queries
|
||||
type TenderFilters struct {
|
||||
Type *TenderType `json:"type,omitempty"`
|
||||
Status *TenderStatus `json:"status,omitempty"`
|
||||
CPVCodes []string `json:"cpv_codes,omitempty"`
|
||||
Categories []string `json:"categories,omitempty"`
|
||||
Region *string `json:"region,omitempty"`
|
||||
Country *string `json:"country,omitempty"`
|
||||
MinBudget *float64 `json:"min_budget,omitempty"`
|
||||
MaxBudget *float64 `json:"max_budget,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
DateFrom *string `json:"date_from,omitempty"`
|
||||
DateTo *string `json:"date_to,omitempty"`
|
||||
}
|
||||
|
||||
// Customer Authentication DTOs
|
||||
type CustomerRegisterRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required,min=8"`
|
||||
FirstName string `json:"first_name" validate:"required"`
|
||||
LastName string `json:"last_name" validate:"required"`
|
||||
Phone string `json:"phone"`
|
||||
CompanyID string `json:"company_id,omitempty"` // Optional, will create new company if not provided
|
||||
}
|
||||
|
||||
type CustomerAuthResponse struct {
|
||||
Customer *Customer `json:"customer"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
}
|
||||
|
||||
// Panel User Authentication DTOs
|
||||
type CreateUserRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required,min=8"`
|
||||
FirstName string `json:"first_name" validate:"required"`
|
||||
LastName string `json:"last_name" validate:"required"`
|
||||
Role UserRole `json:"role" validate:"required"`
|
||||
Department string `json:"department"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
type UserAuthResponse struct {
|
||||
User *User `json:"user"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
}
|
||||
|
||||
// Shared Authentication DTOs
|
||||
type LoginRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
|
||||
// RegisterRequest defines user registration request (kept for backward compatibility)
|
||||
type RegisterRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Password string `json:"password" validate:"required,min=8"`
|
||||
FirstName string `json:"first_name" validate:"required"`
|
||||
LastName string `json:"last_name" validate:"required"`
|
||||
CompanyID string `json:"company_id,omitempty"`
|
||||
}
|
||||
|
||||
// AuthResponse defines authentication response (kept for backward compatibility)
|
||||
type AuthResponse struct {
|
||||
User *User `json:"user,omitempty"`
|
||||
Customer *Customer `json:"customer,omitempty"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
}
|
||||
|
||||
// CreateCompanyRequest defines company creation request
|
||||
type CreateCompanyRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Industry string `json:"industry" validate:"required"`
|
||||
Country string `json:"country" validate:"required"`
|
||||
Website string `json:"website"`
|
||||
Keywords []string `json:"keywords"`
|
||||
Products []string `json:"products"`
|
||||
Services []string `json:"services"`
|
||||
}
|
||||
|
||||
// UpdateCompanyRequest defines company update request
|
||||
type UpdateCompanyRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Industry *string `json:"industry,omitempty"`
|
||||
Country *string `json:"country,omitempty"`
|
||||
Website *string `json:"website,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Products []string `json:"products,omitempty"`
|
||||
Services []string `json:"services,omitempty"`
|
||||
Capabilities []string `json:"capabilities,omitempty"`
|
||||
}
|
||||
|
||||
// UploadDocumentRequest defines document upload request
|
||||
type UploadDocumentRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Type DocumentType `json:"type" validate:"required"`
|
||||
Category string `json:"category" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
FilePath string `json:"file_path" validate:"required"`
|
||||
Size int64 `json:"size"`
|
||||
ContentType string `json:"content_type"`
|
||||
ExpiryDate *string `json:"expiry_date,omitempty"`
|
||||
Keywords []string `json:"keywords"`
|
||||
}
|
||||
Reference in New Issue
Block a user