turash/bugulma/backend/internal/financial/risk_assessor.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

132 lines
3.8 KiB
Go

package financial
// RiskAssessorImpl implements RiskAssessor interface
type RiskAssessorImpl struct {
config *Config
}
// NewRiskAssessor creates a new risk assessor
func NewRiskAssessor(config *Config) RiskAssessor {
return &RiskAssessorImpl{config: config}
}
// AssessRisk performs comprehensive risk assessment based on resource flow data
func (ra *RiskAssessorImpl) AssessRisk(data *ResourceFlowData) *RiskAssessment {
risk := &RiskAssessment{}
// Technical risk based on distance and resource type
risk.TechnicalRisk = ra.calculateTechnicalRisk(data.DistanceKm, data.ResourceType)
// Regulatory risk based on resource type
risk.RegulatoryRisk = ra.calculateRegulatoryRisk(data.ResourceType)
// Market risk based on volume stability
risk.MarketRisk = ra.calculateMarketRisk(data.AnnualVolume)
// Counterparty risk (simplified - would need more business logic)
risk.CounterpartyRisk = 0.3 // Default medium risk
// Calculate overall risk as weighted average
risk.OverallRisk = (risk.TechnicalRisk*0.4 + risk.RegulatoryRisk*0.3 + risk.MarketRisk*0.2 + risk.CounterpartyRisk*0.1)
// Determine risk level
risk.RiskLevel = ra.calculateRiskLevel(risk.OverallRisk)
// Identify primary risk factors
risk.PrimaryRisks = ra.identifyPrimaryRiskFactors(data, risk)
return risk
}
// calculateTechnicalRisk assesses technical implementation risk
func (ra *RiskAssessorImpl) calculateTechnicalRisk(distanceKm float64, resourceType string) float64 {
risk := 0.0
// Distance risk
if distanceKm > 50 {
risk += 0.3
} else if distanceKm > 20 {
risk += 0.1
}
// Resource type risk
switch resourceType {
case "heat", "steam", "cooling":
risk += 0.2 // Infrastructure complexity
case "biowaste", "CO2":
risk += 0.4 // Handling and safety requirements
case "materials":
risk += 0.1 // Relatively straightforward
}
return risk
}
// calculateRegulatoryRisk assesses regulatory compliance risk
func (ra *RiskAssessorImpl) calculateRegulatoryRisk(resourceType string) float64 {
switch resourceType {
case "biowaste":
return 0.6 // High regulatory requirements
case "CO2", "water":
return 0.4 // Medium regulatory requirements
case "heat", "steam":
return 0.2 // Lower regulatory requirements
default:
return 0.3
}
}
// calculateMarketRisk assesses market and volume stability risk
func (ra *RiskAssessorImpl) calculateMarketRisk(annualVolume float64) float64 {
if annualVolume < 100 {
return 0.7 // High risk for low volume
} else if annualVolume < 1000 {
return 0.4 // Medium risk
}
return 0.1 // Low risk for high volume
}
// calculateRiskLevel determines risk level from overall risk score
func (ra *RiskAssessorImpl) calculateRiskLevel(overallRisk float64) string {
switch {
case overallRisk < ra.config.RiskThresholds.Low:
return "low"
case overallRisk < ra.config.RiskThresholds.Medium:
return "medium"
case overallRisk < ra.config.RiskThresholds.High:
return "high"
default:
return "critical"
}
}
// identifyPrimaryRiskFactors identifies the main risk factors contributing to overall risk
func (ra *RiskAssessorImpl) identifyPrimaryRiskFactors(data *ResourceFlowData, risk *RiskAssessment) []string {
var primaryRisks []string
// Technical risk factors
if data.DistanceKm > 100 {
primaryRisks = append(primaryRisks, "technical_failure")
}
if data.ResourceType == "biowaste" || data.ResourceType == "CO2" {
primaryRisks = append(primaryRisks, "technical_failure")
}
// Regulatory risk factors
if data.ResourceType == "biowaste" {
primaryRisks = append(primaryRisks, "regulatory_changes")
}
// Market risk factors
if data.AnnualVolume < 500 {
primaryRisks = append(primaryRisks, "market_volatility")
}
// Distance-related market risk
if data.DistanceKm > 200 {
primaryRisks = append(primaryRisks, "market_volatility")
}
return primaryRisks
}