turash/bugulma/backend/internal/domain/organization.go

668 lines
27 KiB
Go

package domain
import (
"context"
"encoding/json"
"time"
"gorm.io/datatypes"
)
// unmarshalStringSlice safely unmarshals datatypes.JSON to []string
func unmarshalStringSlice(data datatypes.JSON) []string {
if len(data) == 0 {
return []string{}
}
var result []string
if err := json.Unmarshal(data, &result); err != nil {
// If it's not an array, return empty slice
return []string{}
}
return result
}
// MarshalJSON custom marshaling to ensure arrays are always arrays
func (o Organization) MarshalJSON() ([]byte, error) {
type Alias Organization
return json.Marshal(&struct {
GalleryImages []string `json:"GalleryImages"`
Certifications []string `json:"Certifications"`
BusinessFocus []string `json:"BusinessFocus"`
TechnicalExpertise []string `json:"TechnicalExpertise"`
AvailableTechnology []string `json:"AvailableTechnology"`
ManagementSystems []string `json:"ManagementSystems"`
TrustNetwork []string `json:"TrustNetwork"`
ExistingSymbioticRelationships []string `json:"ExistingSymbioticRelationships"`
*Alias
}{
GalleryImages: unmarshalStringSlice(o.GalleryImages),
Certifications: unmarshalStringSlice(o.Certifications),
BusinessFocus: unmarshalStringSlice(o.BusinessFocus),
TechnicalExpertise: unmarshalStringSlice(o.TechnicalExpertise),
AvailableTechnology: unmarshalStringSlice(o.AvailableTechnology),
ManagementSystems: unmarshalStringSlice(o.ManagementSystems),
TrustNetwork: unmarshalStringSlice(o.TrustNetwork),
ExistingSymbioticRelationships: unmarshalStringSlice(o.ExistingSymbioticRelationships),
Alias: (*Alias)(&o),
})
}
// OrganizationSubtype defines the specific business type of organization
type OrganizationSubtype string
// OrganizationSector defines the broader economic sector of organization
type OrganizationSector string
// Sector constants
const (
SectorHealthcare OrganizationSector = "healthcare"
SectorReligious OrganizationSector = "religious"
SectorFoodBeverage OrganizationSector = "food_beverage"
SectorRetail OrganizationSector = "retail"
SectorServices OrganizationSector = "services"
SectorEducation OrganizationSector = "education"
SectorBeautyWellness OrganizationSector = "beauty_wellness"
SectorAutomotive OrganizationSector = "automotive"
SectorHospitality OrganizationSector = "hospitality"
SectorManufacturing OrganizationSector = "manufacturing"
SectorEnergy OrganizationSector = "energy"
SectorConstruction OrganizationSector = "construction"
SectorFinancial OrganizationSector = "financial"
SectorEntertainment OrganizationSector = "entertainment"
SectorFurniture OrganizationSector = "furniture"
SectorSports OrganizationSector = "sports"
SectorAgriculture OrganizationSector = "agriculture"
SectorTechnology OrganizationSector = "technology"
SectorInfrastructure OrganizationSector = "infrastructure"
SectorGovernment OrganizationSector = "government"
SectorOther OrganizationSector = "other"
)
// Healthcare subtypes
const (
SubtypePharmacy OrganizationSubtype = "pharmacy"
SubtypeClinic OrganizationSubtype = "clinic"
SubtypeDentist OrganizationSubtype = "dentist"
SubtypeHospital OrganizationSubtype = "hospital"
SubtypeLaboratory OrganizationSubtype = "laboratory"
SubtypeTherapy OrganizationSubtype = "therapy"
SubtypeOptician OrganizationSubtype = "optician"
SubtypeVeterinary OrganizationSubtype = "veterinary"
)
// Religious subtypes
const (
SubtypeMosque OrganizationSubtype = "mosque"
SubtypeTemple OrganizationSubtype = "temple"
SubtypeChurch OrganizationSubtype = "church"
SubtypeSynagogue OrganizationSubtype = "synagogue"
SubtypeGurudwara OrganizationSubtype = "gurudwara"
SubtypeBuddhistCenter OrganizationSubtype = "buddhist_center"
SubtypeReligiousSchool OrganizationSubtype = "religious_school"
)
// Food & Beverage subtypes
const (
SubtypeRestaurant OrganizationSubtype = "restaurant"
SubtypeCafe OrganizationSubtype = "cafe"
SubtypeFastFood OrganizationSubtype = "fast_food"
SubtypeBakery OrganizationSubtype = "bakery"
SubtypeBar OrganizationSubtype = "bar"
SubtypeCatering OrganizationSubtype = "catering"
SubtypeFoodTruck OrganizationSubtype = "food_truck"
)
// Retail subtypes
const (
SubtypeGroceryStore OrganizationSubtype = "grocery_store"
SubtypeDepartmentStore OrganizationSubtype = "department_store"
SubtypeBoutique OrganizationSubtype = "boutique"
SubtypeElectronicsStore OrganizationSubtype = "electronics_store"
SubtypeBookstore OrganizationSubtype = "bookstore"
SubtypeConvenienceStore OrganizationSubtype = "convenience_store"
SubtypeMarket OrganizationSubtype = "market"
)
// Services subtypes
const (
SubtypeLawyer OrganizationSubtype = "lawyer"
SubtypeAccountant OrganizationSubtype = "accountant"
SubtypeConsultant OrganizationSubtype = "consultant"
SubtypeITServices OrganizationSubtype = "it_services"
SubtypeCleaning OrganizationSubtype = "cleaning"
SubtypeRepairService OrganizationSubtype = "repair_service"
SubtypeTutoring OrganizationSubtype = "tutoring"
)
// Education subtypes
const (
SubtypeSchool OrganizationSubtype = "school"
SubtypeCollege OrganizationSubtype = "college"
SubtypeUniversity OrganizationSubtype = "university"
SubtypeKindergarten OrganizationSubtype = "kindergarten"
SubtypeTrainingCenter OrganizationSubtype = "training_center"
)
// Personal services subtypes
const (
SubtypeSalon OrganizationSubtype = "salon"
SubtypeSpa OrganizationSubtype = "spa"
SubtypeBarber OrganizationSubtype = "barber"
SubtypeGym OrganizationSubtype = "gym"
SubtypeNailSalon OrganizationSubtype = "nail_salon"
SubtypeMassageTherapy OrganizationSubtype = "massage_therapy"
SubtypeBeautySupply OrganizationSubtype = "beauty_supply"
SubtypePersonalServices OrganizationSubtype = "personal_services"
)
// Automotive & Transportation subtypes
const (
SubtypeCarDealership OrganizationSubtype = "car_dealership"
SubtypeAutoRepair OrganizationSubtype = "auto_repair"
SubtypeCarWash OrganizationSubtype = "car_wash"
SubtypeAutoParts OrganizationSubtype = "auto_parts"
SubtypeTireShop OrganizationSubtype = "tire_shop"
SubtypeMotorcycleShop OrganizationSubtype = "motorcycle_shop"
SubtypeTaxi OrganizationSubtype = "taxi"
SubtypeBusStation OrganizationSubtype = "bus_station"
SubtypeDelivery OrganizationSubtype = "delivery"
SubtypeTransportation OrganizationSubtype = "transportation"
)
// Hospitality subtypes
const (
SubtypeHotel OrganizationSubtype = "hotel"
SubtypeHostel OrganizationSubtype = "hostel"
)
// Manufacturing & Industrial subtypes
const (
SubtypeFactory OrganizationSubtype = "factory"
SubtypeWorkshop OrganizationSubtype = "workshop"
SubtypeManufacturing OrganizationSubtype = "manufacturing"
)
// Energy subtypes
const (
SubtypePowerPlant OrganizationSubtype = "power_plant"
SubtypeFuelStation OrganizationSubtype = "fuel_station"
SubtypeEnergy OrganizationSubtype = "energy"
)
// Construction subtypes
const (
SubtypeConstructionContractor OrganizationSubtype = "construction_contractor"
SubtypeConstruction OrganizationSubtype = "construction"
)
// Financial subtypes
const (
SubtypeBank OrganizationSubtype = "bank"
SubtypeInsurance OrganizationSubtype = "insurance"
SubtypeFinancial OrganizationSubtype = "financial"
)
// Entertainment & Cultural subtypes
const (
SubtypeTheater OrganizationSubtype = "theater"
SubtypeCinema OrganizationSubtype = "cinema"
SubtypeMuseum OrganizationSubtype = "museum"
SubtypeConcertHall OrganizationSubtype = "concert_hall"
SubtypeGamingCenter OrganizationSubtype = "gaming_center"
SubtypeNightclub OrganizationSubtype = "nightclub"
SubtypeCultural OrganizationSubtype = "cultural"
)
// Furniture subtypes
const (
SubtypeFurnitureStore OrganizationSubtype = "furniture_store"
SubtypeFurnitureManufacturer OrganizationSubtype = "furniture_manufacturer"
SubtypeInteriorDesign OrganizationSubtype = "interior_design"
SubtypeFurnitureRepair OrganizationSubtype = "furniture_repair"
)
// Sports subtypes
const (
SubtypeSportsClub OrganizationSubtype = "sports_club"
SubtypeStadium OrganizationSubtype = "stadium"
SubtypeSportsEquipment OrganizationSubtype = "sports_equipment"
)
// Agriculture subtypes
const (
SubtypeFarm OrganizationSubtype = "farm"
SubtypeAgriculturalSupplier OrganizationSubtype = "agricultural_supplier"
SubtypeGreenhouse OrganizationSubtype = "greenhouse"
SubtypeLivestock OrganizationSubtype = "livestock"
)
// Technology subtypes
const (
SubtypeSoftwareCompany OrganizationSubtype = "software_company"
SubtypeHardwareCompany OrganizationSubtype = "hardware_company"
SubtypeTechSupport OrganizationSubtype = "tech_support"
SubtypeWebDevelopment OrganizationSubtype = "web_development"
SubtypeTelecommunications OrganizationSubtype = "telecommunications"
)
// Infrastructure subtypes
const (
SubtypePowerStation OrganizationSubtype = "power_station"
SubtypeWaterTreatment OrganizationSubtype = "water_treatment"
SubtypeWasteManagement OrganizationSubtype = "waste_management"
)
// Legacy/Generic subtypes (kept for backward compatibility and migration)
const (
SubtypeCommercial OrganizationSubtype = "commercial"
SubtypeGovernment OrganizationSubtype = "government"
SubtypeReligious OrganizationSubtype = "religious"
SubtypeEducational OrganizationSubtype = "educational"
SubtypeInfrastructure OrganizationSubtype = "infrastructure"
SubtypeHealthcare OrganizationSubtype = "healthcare"
SubtypeOther OrganizationSubtype = "other"
SubtypeNeedsReview OrganizationSubtype = "needs_review" // Temporary for migration
)
// IsValidSubtype checks if a subtype value is valid
func IsValidSubtype(subtype OrganizationSubtype) bool {
validSubtypes := map[OrganizationSubtype]bool{
// Healthcare
SubtypePharmacy: true, SubtypeClinic: true, SubtypeDentist: true, SubtypeHospital: true,
SubtypeLaboratory: true, SubtypeTherapy: true, SubtypeOptician: true, SubtypeVeterinary: true,
// Religious
SubtypeMosque: true, SubtypeTemple: true, SubtypeChurch: true, SubtypeSynagogue: true,
SubtypeGurudwara: true, SubtypeBuddhistCenter: true, SubtypeReligiousSchool: true,
// Food & Beverage
SubtypeRestaurant: true, SubtypeCafe: true, SubtypeFastFood: true, SubtypeBakery: true,
SubtypeBar: true, SubtypeCatering: true, SubtypeFoodTruck: true,
// Retail
SubtypeGroceryStore: true, SubtypeDepartmentStore: true, SubtypeBoutique: true,
SubtypeElectronicsStore: true, SubtypeBookstore: true, SubtypeConvenienceStore: true, SubtypeMarket: true,
// Services
SubtypeLawyer: true, SubtypeAccountant: true, SubtypeConsultant: true, SubtypeITServices: true,
SubtypeCleaning: true, SubtypeRepairService: true, SubtypeTutoring: true,
// Education
SubtypeSchool: true, SubtypeCollege: true, SubtypeUniversity: true,
SubtypeKindergarten: true, SubtypeTrainingCenter: true,
// Personal services
SubtypeSalon: true, SubtypeSpa: true, SubtypeBarber: true, SubtypeGym: true,
SubtypeNailSalon: true, SubtypeMassageTherapy: true, SubtypeBeautySupply: true, SubtypePersonalServices: true,
// Automotive & Transportation
SubtypeCarDealership: true, SubtypeAutoRepair: true, SubtypeCarWash: true,
SubtypeAutoParts: true, SubtypeTireShop: true, SubtypeMotorcycleShop: true,
SubtypeTaxi: true, SubtypeBusStation: true, SubtypeDelivery: true, SubtypeTransportation: true,
// Hospitality
SubtypeHotel: true, SubtypeHostel: true,
// Manufacturing & Industrial
SubtypeFactory: true, SubtypeWorkshop: true, SubtypeManufacturing: true,
// Energy
SubtypePowerPlant: true, SubtypeFuelStation: true, SubtypeEnergy: true,
// Construction
SubtypeConstructionContractor: true, SubtypeConstruction: true,
// Financial
SubtypeBank: true, SubtypeInsurance: true, SubtypeFinancial: true,
// Entertainment & Cultural
SubtypeTheater: true, SubtypeCinema: true, SubtypeMuseum: true,
SubtypeConcertHall: true, SubtypeGamingCenter: true, SubtypeNightclub: true, SubtypeCultural: true,
// Furniture
SubtypeFurnitureStore: true, SubtypeFurnitureManufacturer: true,
SubtypeInteriorDesign: true, SubtypeFurnitureRepair: true,
// Sports
SubtypeSportsClub: true, SubtypeStadium: true, SubtypeSportsEquipment: true,
// Agriculture
SubtypeFarm: true, SubtypeAgriculturalSupplier: true, SubtypeGreenhouse: true, SubtypeLivestock: true,
// Technology
SubtypeSoftwareCompany: true, SubtypeHardwareCompany: true, SubtypeTechSupport: true,
SubtypeWebDevelopment: true, SubtypeTelecommunications: true,
// Infrastructure
SubtypePowerStation: true, SubtypeWaterTreatment: true, SubtypeWasteManagement: true,
// Legacy/Generic
SubtypeCommercial: true, SubtypeGovernment: true, SubtypeReligious: true,
SubtypeEducational: true, SubtypeInfrastructure: true, SubtypeHealthcare: true, SubtypeOther: true,
// Temporary
SubtypeNeedsReview: true,
}
return validSubtypes[subtype]
}
// GetAllSubtypes returns all valid organization subtypes dynamically
func GetAllSubtypes() []OrganizationSubtype {
return []OrganizationSubtype{
// Healthcare
SubtypePharmacy, SubtypeClinic, SubtypeDentist, SubtypeHospital,
SubtypeLaboratory, SubtypeTherapy, SubtypeOptician, SubtypeVeterinary,
// Religious
SubtypeMosque, SubtypeTemple, SubtypeChurch, SubtypeSynagogue,
SubtypeGurudwara, SubtypeBuddhistCenter, SubtypeReligiousSchool,
// Food & Beverage
SubtypeRestaurant, SubtypeCafe, SubtypeFastFood, SubtypeBakery,
SubtypeBar, SubtypeCatering, SubtypeFoodTruck,
// Retail
SubtypeGroceryStore, SubtypeDepartmentStore, SubtypeBoutique,
SubtypeElectronicsStore, SubtypeBookstore, SubtypeConvenienceStore, SubtypeMarket,
// Services
SubtypeLawyer, SubtypeAccountant, SubtypeConsultant, SubtypeITServices,
SubtypeCleaning, SubtypeRepairService, SubtypeTutoring,
// Education
SubtypeSchool, SubtypeCollege, SubtypeUniversity,
SubtypeKindergarten, SubtypeTrainingCenter,
// Personal services
SubtypeSalon, SubtypeSpa, SubtypeBarber, SubtypeGym,
SubtypeNailSalon, SubtypeMassageTherapy, SubtypeBeautySupply, SubtypePersonalServices,
// Automotive & Transportation
SubtypeCarDealership, SubtypeAutoRepair, SubtypeCarWash,
SubtypeAutoParts, SubtypeTireShop, SubtypeMotorcycleShop,
SubtypeTaxi, SubtypeBusStation, SubtypeDelivery, SubtypeTransportation,
// Hospitality
SubtypeHotel, SubtypeHostel,
// Manufacturing & Industrial
SubtypeFactory, SubtypeWorkshop, SubtypeManufacturing,
// Energy
SubtypePowerPlant, SubtypeFuelStation, SubtypeEnergy,
// Construction
SubtypeConstructionContractor, SubtypeConstruction,
// Financial
SubtypeBank, SubtypeInsurance, SubtypeFinancial,
// Entertainment & Cultural
SubtypeTheater, SubtypeCinema, SubtypeMuseum,
SubtypeConcertHall, SubtypeGamingCenter, SubtypeNightclub, SubtypeCultural,
// Furniture
SubtypeFurnitureStore, SubtypeFurnitureManufacturer,
SubtypeInteriorDesign, SubtypeFurnitureRepair,
// Sports
SubtypeSportsClub, SubtypeStadium, SubtypeSportsEquipment,
// Agriculture
SubtypeFarm, SubtypeAgriculturalSupplier, SubtypeGreenhouse, SubtypeLivestock,
// Technology
SubtypeSoftwareCompany, SubtypeHardwareCompany, SubtypeTechSupport,
SubtypeWebDevelopment, SubtypeTelecommunications,
// Infrastructure
SubtypePowerStation, SubtypeWaterTreatment, SubtypeWasteManagement,
// Legacy/Generic
SubtypeCommercial, SubtypeGovernment, SubtypeReligious,
SubtypeEducational, SubtypeInfrastructure, SubtypeHealthcare, SubtypeOther,
}
}
// GetSubtypesBySector returns subtypes that are commonly associated with a given sector
// This is a helper function for filtering/validation, not a strict requirement
func GetSubtypesBySector(sector OrganizationSector) []OrganizationSubtype {
switch sector {
case SectorHealthcare:
return []OrganizationSubtype{
SubtypePharmacy, SubtypeClinic, SubtypeDentist, SubtypeHospital,
SubtypeLaboratory, SubtypeTherapy, SubtypeOptician, SubtypeVeterinary,
}
case SectorReligious:
return []OrganizationSubtype{
SubtypeMosque, SubtypeTemple, SubtypeChurch, SubtypeSynagogue,
SubtypeGurudwara, SubtypeBuddhistCenter, SubtypeReligiousSchool,
}
case SectorFoodBeverage:
return []OrganizationSubtype{
SubtypeRestaurant, SubtypeCafe, SubtypeFastFood, SubtypeBakery,
SubtypeBar, SubtypeCatering, SubtypeFoodTruck,
}
case SectorRetail:
return []OrganizationSubtype{
SubtypeGroceryStore, SubtypeDepartmentStore, SubtypeBoutique,
SubtypeElectronicsStore, SubtypeBookstore, SubtypeConvenienceStore, SubtypeMarket,
}
case SectorServices:
return []OrganizationSubtype{
SubtypeLawyer, SubtypeAccountant, SubtypeConsultant, SubtypeITServices,
SubtypeCleaning, SubtypeRepairService, SubtypeTutoring,
}
case SectorEducation:
return []OrganizationSubtype{
SubtypeSchool, SubtypeCollege, SubtypeUniversity,
SubtypeKindergarten, SubtypeTrainingCenter,
}
case SectorBeautyWellness:
return []OrganizationSubtype{
SubtypeSalon, SubtypeSpa, SubtypeBarber, SubtypeGym,
SubtypeNailSalon, SubtypeMassageTherapy, SubtypeBeautySupply, SubtypePersonalServices,
}
case SectorAutomotive:
return []OrganizationSubtype{
SubtypeCarDealership, SubtypeAutoRepair, SubtypeCarWash,
SubtypeAutoParts, SubtypeTireShop, SubtypeMotorcycleShop,
SubtypeTaxi, SubtypeBusStation, SubtypeDelivery, SubtypeTransportation,
}
case SectorHospitality:
return []OrganizationSubtype{
SubtypeHotel, SubtypeHostel,
}
case SectorManufacturing:
return []OrganizationSubtype{
SubtypeFactory, SubtypeWorkshop, SubtypeManufacturing,
}
case SectorEnergy:
return []OrganizationSubtype{
SubtypePowerPlant, SubtypeFuelStation, SubtypeEnergy,
}
case SectorConstruction:
return []OrganizationSubtype{
SubtypeConstructionContractor, SubtypeConstruction,
}
case SectorFinancial:
return []OrganizationSubtype{
SubtypeBank, SubtypeInsurance, SubtypeFinancial,
}
case SectorEntertainment:
return []OrganizationSubtype{
SubtypeTheater, SubtypeCinema, SubtypeMuseum,
SubtypeConcertHall, SubtypeGamingCenter, SubtypeNightclub, SubtypeCultural,
}
case SectorFurniture:
return []OrganizationSubtype{
SubtypeFurnitureStore, SubtypeFurnitureManufacturer,
SubtypeInteriorDesign, SubtypeFurnitureRepair,
}
case SectorSports:
return []OrganizationSubtype{
SubtypeSportsClub, SubtypeStadium, SubtypeSportsEquipment,
}
case SectorAgriculture:
return []OrganizationSubtype{
SubtypeFarm, SubtypeAgriculturalSupplier, SubtypeGreenhouse, SubtypeLivestock,
}
case SectorTechnology:
return []OrganizationSubtype{
SubtypeSoftwareCompany, SubtypeHardwareCompany, SubtypeTechSupport,
SubtypeWebDevelopment, SubtypeTelecommunications,
}
default:
// Return all subtypes for unknown sectors or generic sectors
return GetAllSubtypes()
}
}
// SectorStat represents sector statistics
type SectorStat struct {
Sector string `json:"sector"`
Count int `json:"count"`
}
// Image represents an uploaded image
type Image struct {
URL string `json:"url"`
Path string `json:"path"`
}
// LegalForm represents the legal structure of a business organization
type LegalForm string
const (
LegalFormLLC LegalForm = "LLC"
LegalFormCorporation LegalForm = "corporation"
LegalFormPartnership LegalForm = "partnership"
LegalFormSoleProprietorship LegalForm = "sole_proprietorship"
LegalFormGmbH LegalForm = "GmbH"
LegalFormUG LegalForm = "UG"
LegalFormAG LegalForm = "AG"
)
// SupplyChainRole represents the organization's role in the supply chain
type SupplyChainRole string
const (
RoleManufacturer SupplyChainRole = "manufacturer"
RoleSupplier SupplyChainRole = "supplier"
RoleDistributor SupplyChainRole = "distributor"
RoleConsumer SupplyChainRole = "consumer"
)
// PrimaryContact stores contact information
type PrimaryContact struct {
Email string `json:"email"`
Phone string `json:"phone"`
}
// ProductJSON represents a product offered by an organization (for API/JSON serialization)
type ProductJSON struct {
Name string `json:"name"`
Category string `json:"category"`
UnitPrice float64 `json:"unit_price"`
MOQ int `json:"moq,omitempty"`
Certifications []string `json:"certifications,omitempty"`
}
// ServiceJSON represents a service offered by an organization (for API/JSON serialization)
type ServiceJSON struct {
Type string `json:"type"` // maintenance, consulting, transport, inspection
Domain string `json:"domain"` // compressors, HVAC, waste_management, etc.
OnSite bool `json:"on_site"` // on-site or remote
HourlyRate float64 `json:"hourly_rate"` // €/hour
ServiceAreaKm float64 `json:"service_area_km"` // service radius
Certifications []string `json:"certifications,omitempty"`
}
// ServiceNeedJSON represents a service needed by an organization (for API/JSON serialization)
type ServiceNeedJSON struct {
Type string `json:"type"`
Urgency string `json:"urgency,omitempty"` // low, medium, high
Budget float64 `json:"budget,omitempty"`
PreferredProviders []string `json:"preferred_providers,omitempty"` // Organization IDs
}
type Organization struct {
ID string `gorm:"primaryKey;type:text" json:"ID"`
Name string `gorm:"not null;type:text;index" json:"Name"` // Primary name (Russian)
// Subtype categorization (commercial, healthcare, educational, etc.)
Subtype OrganizationSubtype `gorm:"not null;type:varchar(50);index" json:"Subtype"`
Sector OrganizationSector `gorm:"type:varchar(50);index" json:"Sector"` // NACE code or category
// Basic information
Description string `gorm:"type:text" json:"Description"`
LogoURL string `gorm:"column:logo_url;type:text" json:"LogoURL"`
GalleryImages datatypes.JSON `gorm:"column:gallery_images;type:jsonb;default:'[]'" json:"-"` // []string - URLs of gallery images
Website string `gorm:"type:text" json:"Website"`
// Geolocation (from primary address)
Latitude float64 `gorm:"type:double precision;index:idx_org_location" json:"Latitude"`
Longitude float64 `gorm:"type:double precision;index:idx_org_location" json:"Longitude"`
// Business-specific fields (for commercial subtype)
LegalForm string `gorm:"type:varchar(50)" json:"LegalForm"`
PrimaryContact datatypes.JSON `gorm:"type:jsonb" json:"PrimaryContact"` // PrimaryContact
IndustrialSector string `gorm:"type:varchar(10)" json:"IndustrialSector"`
CompanySize int `gorm:"type:integer" json:"CompanySize"`
YearsOperation int `gorm:"type:integer" json:"YearsOperation"`
SupplyChainRole SupplyChainRole `gorm:"type:varchar(50)" json:"SupplyChainRole"`
Certifications datatypes.JSON `gorm:"default:'[]'" json:"-"` // []string
BusinessFocus datatypes.JSON `gorm:"default:'[]'" json:"-"` // []string
StrategicVision string `gorm:"type:text" json:"StrategicVision"`
DriversBarriers string `gorm:"type:text" json:"DriversBarriers"`
ReadinessMaturity int `gorm:"type:integer;default:3" json:"ReadinessMaturity"`
TrustScore float64 `gorm:"type:double precision;default:0.7" json:"TrustScore"`
TechnicalExpertise datatypes.JSON `gorm:"default:'[]'" json:"-"` // []string
AvailableTechnology datatypes.JSON `gorm:"default:'[]'" json:"-"` // []string
ManagementSystems datatypes.JSON `gorm:"default:'[]'" json:"-"` // []string
// Products and Services
SellsProducts datatypes.JSON `gorm:"default:'[]'" json:"SellsProducts"` // []Product
OffersServices datatypes.JSON `gorm:"default:'[]'" json:"OffersServices"` // []Service
NeedsServices datatypes.JSON `gorm:"default:'[]'" json:"NeedsServices"` // []ServiceNeed
// Historical/cultural building fields (for non-commercial subtypes)
YearBuilt string `gorm:"type:text" json:"YearBuilt"`
BuilderOwner string `gorm:"type:text" json:"BuilderOwner"`
Architect string `gorm:"type:text" json:"Architect"`
OriginalPurpose string `gorm:"type:text" json:"OriginalPurpose"`
CurrentUse string `gorm:"type:text" json:"CurrentUse"`
Style string `gorm:"type:text" json:"Style"`
Materials string `gorm:"type:text" json:"Materials"`
Storeys int `gorm:"type:integer" json:"Storeys"`
HeritageStatus string `gorm:"type:text" json:"HeritageStatus"`
// Metadata
Verified bool `gorm:"default:false;index" json:"Verified"`
Notes string `gorm:"type:text" json:"Notes"`
Sources datatypes.JSON `gorm:"type:jsonb" json:"Sources"`
// Relationships (will be populated via associations)
TrustNetwork datatypes.JSON `gorm:"type:jsonb;default:'[]'" json:"-"` // []string - Organization IDs
ExistingSymbioticRelationships datatypes.JSON `gorm:"type:jsonb;default:'[]'" json:"-"` // []string - Organization IDs
// Products/materials for legacy compatibility
Products datatypes.JSON `gorm:"type:jsonb" json:"Products"`
// Timestamps
CreatedAt time.Time `gorm:"autoCreateTime;index" json:"CreatedAt"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"UpdatedAt"`
// Associations
Addresses []Address `gorm:"many2many:organization_addresses;" json:"Addresses,omitempty"`
OwnedSites []Site `gorm:"foreignKey:OwnerOrganizationID" json:"OwnedSites,omitempty"`
OperatingSites []Site `gorm:"many2many:site_operating_organizations;" json:"OperatingSites,omitempty"`
ResourceFlows []ResourceFlow `gorm:"foreignKey:OrganizationID" json:"ResourceFlows,omitempty"`
}
// TableName specifies the table name for GORM
func (Organization) TableName() string {
return "organizations"
}
// PrimaryAddress returns the primary (headquarters) address formatted string
func (o *Organization) PrimaryAddress() string {
for _, addr := range o.Addresses {
if addr.AddressType == AddressTypeHeadquarters {
if addr.FormattedRu != "" {
return addr.FormattedRu
}
if addr.FormattedEn != "" {
return addr.FormattedEn
}
}
}
// Fallback to any address if no headquarters found
if len(o.Addresses) > 0 {
if o.Addresses[0].FormattedRu != "" {
return o.Addresses[0].FormattedRu
}
if o.Addresses[0].FormattedEn != "" {
return o.Addresses[0].FormattedEn
}
}
return ""
}
type OrganizationRepository interface {
Create(ctx context.Context, org *Organization) error
GetByID(ctx context.Context, id string) (*Organization, error)
GetAll(ctx context.Context) ([]*Organization, error)
Update(ctx context.Context, org *Organization) error
Delete(ctx context.Context, id string) error
GetBySector(ctx context.Context, sector OrganizationSector) ([]*Organization, error)
GetBySubtype(ctx context.Context, subtype OrganizationSubtype) ([]*Organization, error)
GetWithinRadius(ctx context.Context, lat, lng, radiusKm float64) ([]*Organization, error)
GetByCertification(ctx context.Context, cert string) ([]*Organization, error)
Search(ctx context.Context, query string, limit int) ([]*Organization, error)
SearchSuggestions(ctx context.Context, query string, limit int) ([]string, error)
GetSectorStats(ctx context.Context, limit int) ([]SectorStat, error)
GetResourceFlowsByTypeAndDirection(ctx context.Context, resourceType string, direction string) ([]*ResourceFlow, error)
}