mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
149 lines
6.2 KiB
Go
149 lines
6.2 KiB
Go
package domain
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/lib/pq"
|
|
"gorm.io/datatypes"
|
|
)
|
|
|
|
// CommunityListingType defines the type of community listing
|
|
type CommunityListingType string
|
|
|
|
const (
|
|
CommunityListingTypeProduct CommunityListingType = "product"
|
|
CommunityListingTypeService CommunityListingType = "service"
|
|
CommunityListingTypeTool CommunityListingType = "tool"
|
|
CommunityListingTypeSkill CommunityListingType = "skill"
|
|
CommunityListingTypeNeed CommunityListingType = "need"
|
|
)
|
|
|
|
// CommunityListingPriceType defines how the listing is priced
|
|
type CommunityListingPriceType string
|
|
|
|
const (
|
|
CommunityListingPriceTypeFree CommunityListingPriceType = "free"
|
|
CommunityListingPriceTypeSale CommunityListingPriceType = "sale"
|
|
CommunityListingPriceTypeRent CommunityListingPriceType = "rent"
|
|
CommunityListingPriceTypeTrade CommunityListingPriceType = "trade"
|
|
CommunityListingPriceTypeBorrow CommunityListingPriceType = "borrow"
|
|
)
|
|
|
|
// CommunityListingStatus defines the status of a listing
|
|
type CommunityListingStatus string
|
|
|
|
const (
|
|
CommunityListingStatusActive CommunityListingStatus = "active"
|
|
CommunityListingStatusReserved CommunityListingStatus = "reserved"
|
|
CommunityListingStatusCompleted CommunityListingStatus = "completed"
|
|
CommunityListingStatusArchived CommunityListingStatus = "archived"
|
|
)
|
|
|
|
// CommunityListingCondition defines the condition of a product/tool
|
|
type CommunityListingCondition string
|
|
|
|
const (
|
|
CommunityListingConditionNew CommunityListingCondition = "new"
|
|
CommunityListingConditionLikeNew CommunityListingCondition = "like_new"
|
|
CommunityListingConditionGood CommunityListingCondition = "good"
|
|
CommunityListingConditionFair CommunityListingCondition = "fair"
|
|
CommunityListingConditionNeedsRepair CommunityListingCondition = "needs_repair"
|
|
)
|
|
|
|
// CommunityListing represents a listing created by a community member (user)
|
|
// This extends the platform beyond business-only listings to enable "I Don't Know Who Has What" for citizens
|
|
type CommunityListing struct {
|
|
ID string `gorm:"primaryKey;type:text"`
|
|
UserID string `gorm:"not null;type:text;index"` // References users table
|
|
User *User `gorm:"foreignKey:UserID"` // User who created the listing
|
|
|
|
// Listing Information
|
|
Title string `gorm:"not null;type:varchar(255);index"`
|
|
Description string `gorm:"type:text"`
|
|
ListingType CommunityListingType `gorm:"not null;type:varchar(50);index"`
|
|
Category string `gorm:"not null;type:varchar(100);index"`
|
|
Subcategory string `gorm:"type:varchar(100)"`
|
|
|
|
// For Products/Tools
|
|
Condition *CommunityListingCondition `gorm:"type:varchar(50)"` // Condition of item (new, like_new, good, etc.)
|
|
Price *float64 `gorm:"type:decimal(10,2)"` // NULL = free
|
|
PriceType *CommunityListingPriceType `gorm:"type:varchar(50)"` // free, sale, rent, trade, borrow
|
|
|
|
// For Services/Skills
|
|
ServiceType *string `gorm:"type:varchar(50)"` // 'offering' or 'seeking'
|
|
Rate *float64 `gorm:"type:decimal(10,2)"` // Rate for service/skill
|
|
RateType *string `gorm:"type:varchar(50)"` // 'hourly', 'fixed', 'negotiable', 'free', 'trade'
|
|
|
|
// Availability
|
|
AvailabilityStatus string `gorm:"type:varchar(20);default:'available';index"` // available, limited, reserved, unavailable
|
|
AvailabilitySchedule datatypes.JSON `gorm:"type:jsonb"` // Time-based availability schedule
|
|
QuantityAvailable *int `gorm:"type:integer"` // For products (NULL = unlimited)
|
|
|
|
// Location
|
|
Location Point `gorm:"type:geometry(Point,4326)"` // PostGIS geometry point
|
|
PickupAvailable bool `gorm:"default:true"` // Can be picked up
|
|
DeliveryAvailable bool `gorm:"default:false"` // Can be delivered
|
|
DeliveryRadiusKm *float64 `gorm:"type:decimal(5,2)"` // Delivery radius in km
|
|
|
|
// Media
|
|
Images pq.StringArray `gorm:"type:text[]"` // Array of image URLs
|
|
|
|
// Metadata
|
|
Tags pq.StringArray `gorm:"type:text[]"` // Searchable tags array
|
|
SearchKeywords string `gorm:"type:text"` // Full-text search keywords
|
|
|
|
// Trust & Verification
|
|
UserRating *float64 `gorm:"type:decimal(3,2)"` // Average rating from reviews (0-5)
|
|
ReviewCount int `gorm:"default:0"` // Number of reviews
|
|
Verified bool `gorm:"default:false"` // Platform verification
|
|
|
|
// Status
|
|
Status CommunityListingStatus `gorm:"type:varchar(20);default:'active';index"` // active, reserved, completed, archived
|
|
|
|
// Timestamps
|
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
|
ExpiresAt *time.Time `gorm:"type:timestamp with time zone"` // Auto-archive after expiration
|
|
}
|
|
|
|
// TableName specifies the table name for GORM
|
|
func (CommunityListing) TableName() string {
|
|
return "community_listings"
|
|
}
|
|
|
|
// Validate performs business rule validation
|
|
func (cl *CommunityListing) Validate() error {
|
|
if cl.Title == "" {
|
|
return fmt.Errorf("listing title cannot be empty")
|
|
}
|
|
if cl.Category == "" {
|
|
return fmt.Errorf("listing category cannot be empty")
|
|
}
|
|
if cl.UserID == "" {
|
|
return fmt.Errorf("user ID cannot be empty")
|
|
}
|
|
if cl.Price != nil && *cl.Price < 0 {
|
|
return fmt.Errorf("price cannot be negative")
|
|
}
|
|
if cl.Rate != nil && *cl.Rate < 0 {
|
|
return fmt.Errorf("rate cannot be negative")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CommunityListingRepository defines operations for community listing management
|
|
type CommunityListingRepository interface {
|
|
Create(ctx context.Context, listing *CommunityListing) error
|
|
GetByID(ctx context.Context, id string) (*CommunityListing, error)
|
|
GetByUser(ctx context.Context, userID string) ([]*CommunityListing, error)
|
|
GetByType(ctx context.Context, listingType CommunityListingType) ([]*CommunityListing, error)
|
|
GetByCategory(ctx context.Context, category string) ([]*CommunityListing, error)
|
|
SearchWithLocation(ctx context.Context, query string, location *Point, radiusKm float64) ([]*CommunityListing, error)
|
|
GetNearby(ctx context.Context, lat, lng, radiusKm float64) ([]*CommunityListing, error)
|
|
Update(ctx context.Context, listing *CommunityListing) error
|
|
Delete(ctx context.Context, id string) error
|
|
GetAll(ctx context.Context) ([]*CommunityListing, error)
|
|
}
|