257 lines
11 KiB
Java
257 lines
11 KiB
Java
package dev.lions.roi;
|
|
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import java.util.Map;
|
|
import java.util.HashMap;
|
|
|
|
/**
|
|
* Calculateur de ROI pour démontrer la valeur de la digitalisation
|
|
*/
|
|
@ApplicationScoped
|
|
public class ROICalculator {
|
|
|
|
/**
|
|
* Calcule le ROI basé sur les gains de productivité
|
|
*/
|
|
public ROIResult calculateROI(ROIInput input) {
|
|
ROIResult result = new ROIResult();
|
|
|
|
// Calculs des gains annuels
|
|
double productivityGains = calculateProductivityGains(input);
|
|
double errorReduction = calculateErrorReduction(input);
|
|
double timesSavings = calculateTimeSavings(input);
|
|
double complianceGains = calculateComplianceGains(input);
|
|
|
|
double totalAnnualGains = productivityGains + errorReduction + timesSavings + complianceGains;
|
|
|
|
// Coûts
|
|
double implementationCost = input.getInvestmentAmount();
|
|
double annualMaintenanceCost = implementationCost * 0.15; // 15% par an
|
|
|
|
// ROI sur 3 ans
|
|
double totalGains3Years = totalAnnualGains * 3;
|
|
double totalCosts3Years = implementationCost + (annualMaintenanceCost * 3);
|
|
|
|
double roi3Years = ((totalGains3Years - totalCosts3Years) / totalCosts3Years) * 100;
|
|
|
|
// Période de retour sur investissement
|
|
double paybackPeriod = implementationCost / totalAnnualGains;
|
|
|
|
// Remplissage du résultat
|
|
result.setAnnualProductivityGains(productivityGains);
|
|
result.setAnnualErrorReduction(errorReduction);
|
|
result.setAnnualTimeSavings(timesSavings);
|
|
result.setAnnualComplianceGains(complianceGains);
|
|
result.setTotalAnnualGains(totalAnnualGains);
|
|
result.setImplementationCost(implementationCost);
|
|
result.setAnnualMaintenanceCost(annualMaintenanceCost);
|
|
result.setRoi3Years(roi3Years);
|
|
result.setPaybackPeriodMonths(paybackPeriod * 12);
|
|
result.setNetPresentValue3Years(totalGains3Years - totalCosts3Years);
|
|
|
|
// Détails par catégorie
|
|
result.setGainsByCategory(Map.of(
|
|
"Productivité", productivityGains,
|
|
"Réduction erreurs", errorReduction,
|
|
"Gain de temps", timesSavings,
|
|
"Conformité", complianceGains
|
|
));
|
|
|
|
return result;
|
|
}
|
|
|
|
private double calculateProductivityGains(ROIInput input) {
|
|
// Gain de productivité basé sur l'automatisation
|
|
double baseProductivity = input.getEmployeeCount() * input.getAverageSalary() * 0.12; // 12% de gain
|
|
|
|
// Ajustement selon les modules
|
|
double multiplier = 1.0;
|
|
if (input.getSelectedModules().contains("CRM")) multiplier += 0.15;
|
|
if (input.getSelectedModules().contains("STOCK")) multiplier += 0.10;
|
|
if (input.getSelectedModules().contains("COMPTA")) multiplier += 0.08;
|
|
if (input.getSelectedModules().contains("RH")) multiplier += 0.05;
|
|
|
|
return baseProductivity * multiplier;
|
|
}
|
|
|
|
private double calculateErrorReduction(ROIInput input) {
|
|
// Réduction des erreurs et reprises
|
|
double currentErrorCost = input.getTurnover() * 0.02; // 2% du CA en erreurs
|
|
double reductionRate = 0.70; // 70% de réduction des erreurs
|
|
|
|
return currentErrorCost * reductionRate;
|
|
}
|
|
|
|
private double calculateTimeSavings(ROIInput input) {
|
|
// Gain de temps sur les tâches administratives
|
|
double adminTimeHours = input.getEmployeeCount() * 2 * 250; // 2h/jour/employé, 250 jours/an
|
|
double hourlyRate = input.getAverageSalary() / (8 * 250); // Taux horaire
|
|
double timeSavingRate = 0.40; // 40% de gain de temps
|
|
|
|
return adminTimeHours * hourlyRate * timeSavingRate;
|
|
}
|
|
|
|
private double calculateComplianceGains(ROIInput input) {
|
|
// Évitement des pénalités et amendes
|
|
double potentialFines = 500000; // 500K FCFA de pénalités potentielles par an
|
|
double complianceImprovement = 0.80; // 80% d'amélioration de la conformité
|
|
|
|
return potentialFines * complianceImprovement;
|
|
}
|
|
|
|
/**
|
|
* Génère des recommandations basées sur le ROI
|
|
*/
|
|
public String generateRecommendations(ROIResult result) {
|
|
StringBuilder recommendations = new StringBuilder();
|
|
|
|
if (result.getRoi3Years() > 200) {
|
|
recommendations.append("🚀 ROI EXCELLENT (>200%) : Investissement hautement recommandé !\n\n");
|
|
} else if (result.getRoi3Years() > 100) {
|
|
recommendations.append("✅ ROI TRÈS BON (>100%) : Investissement très rentable.\n\n");
|
|
} else if (result.getRoi3Years() > 50) {
|
|
recommendations.append("👍 ROI CORRECT (>50%) : Investissement rentable à moyen terme.\n\n");
|
|
} else {
|
|
recommendations.append("⚠️ ROI FAIBLE (<50%) : Revoir la configuration ou étaler l'investissement.\n\n");
|
|
}
|
|
|
|
recommendations.append("POINTS CLÉS :\n");
|
|
recommendations.append(String.format("• Retour sur investissement en %.1f mois\n", result.getPaybackPeriodMonths()));
|
|
recommendations.append(String.format("• Gains annuels : %,.0f FCFA\n", result.getTotalAnnualGains()));
|
|
recommendations.append(String.format("• Bénéfice net sur 3 ans : %,.0f FCFA\n", result.getNetPresentValue3Years()));
|
|
|
|
recommendations.append("\nPRIORITÉS D'IMPLÉMENTATION :\n");
|
|
|
|
// Recommandations par gain le plus élevé
|
|
result.getGainsByCategory().entrySet().stream()
|
|
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
|
|
.forEach(entry -> {
|
|
recommendations.append(String.format("• %s : %,.0f FCFA/an\n",
|
|
entry.getKey(), entry.getValue()));
|
|
});
|
|
|
|
return recommendations.toString();
|
|
}
|
|
|
|
/**
|
|
* Calcule le ROI pour différents scénarios
|
|
*/
|
|
public Map<String, ROIResult> calculateScenarios(ROIInput baseInput) {
|
|
Map<String, ROIResult> scenarios = new HashMap<>();
|
|
|
|
// Scénario conservateur (gains -30%)
|
|
ROIInput conservative = baseInput.copy();
|
|
conservative.setAverageSalary(baseInput.getAverageSalary() * 0.7);
|
|
scenarios.put("Conservateur", calculateROI(conservative));
|
|
|
|
// Scénario réaliste (base)
|
|
scenarios.put("Réaliste", calculateROI(baseInput));
|
|
|
|
// Scénario optimiste (gains +50%)
|
|
ROIInput optimistic = baseInput.copy();
|
|
optimistic.setAverageSalary(baseInput.getAverageSalary() * 1.5);
|
|
scenarios.put("Optimiste", calculateROI(optimistic));
|
|
|
|
return scenarios;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Données d'entrée pour le calcul ROI
|
|
*/
|
|
class ROIInput {
|
|
private int employeeCount;
|
|
private double averageSalary; // Salaire moyen annuel
|
|
private double turnover; // CA annuel
|
|
private double investmentAmount; // Montant investissement
|
|
private java.util.List<String> selectedModules;
|
|
private String sector;
|
|
|
|
// Constructeurs
|
|
public ROIInput() {}
|
|
|
|
public ROIInput copy() {
|
|
ROIInput copy = new ROIInput();
|
|
copy.employeeCount = this.employeeCount;
|
|
copy.averageSalary = this.averageSalary;
|
|
copy.turnover = this.turnover;
|
|
copy.investmentAmount = this.investmentAmount;
|
|
copy.selectedModules = new java.util.ArrayList<>(this.selectedModules);
|
|
copy.sector = this.sector;
|
|
return copy;
|
|
}
|
|
|
|
// Getters et Setters
|
|
public int getEmployeeCount() { return employeeCount; }
|
|
public void setEmployeeCount(int employeeCount) { this.employeeCount = employeeCount; }
|
|
|
|
public double getAverageSalary() { return averageSalary; }
|
|
public void setAverageSalary(double averageSalary) { this.averageSalary = averageSalary; }
|
|
|
|
public double getTurnover() { return turnover; }
|
|
public void setTurnover(double turnover) { this.turnover = turnover; }
|
|
|
|
public double getInvestmentAmount() { return investmentAmount; }
|
|
public void setInvestmentAmount(double investmentAmount) { this.investmentAmount = investmentAmount; }
|
|
|
|
public java.util.List<String> getSelectedModules() { return selectedModules; }
|
|
public void setSelectedModules(java.util.List<String> selectedModules) { this.selectedModules = selectedModules; }
|
|
|
|
public String getSector() { return sector; }
|
|
public void setSector(String sector) { this.sector = sector; }
|
|
}
|
|
|
|
/**
|
|
* Résultat du calcul ROI
|
|
*/
|
|
class ROIResult {
|
|
private double annualProductivityGains;
|
|
private double annualErrorReduction;
|
|
private double annualTimeSavings;
|
|
private double annualComplianceGains;
|
|
private double totalAnnualGains;
|
|
private double implementationCost;
|
|
private double annualMaintenanceCost;
|
|
private double roi3Years;
|
|
private double paybackPeriodMonths;
|
|
private double netPresentValue3Years;
|
|
private Map<String, Double> gainsByCategory;
|
|
|
|
// Constructeurs
|
|
public ROIResult() {}
|
|
|
|
// Getters et Setters
|
|
public double getAnnualProductivityGains() { return annualProductivityGains; }
|
|
public void setAnnualProductivityGains(double annualProductivityGains) { this.annualProductivityGains = annualProductivityGains; }
|
|
|
|
public double getAnnualErrorReduction() { return annualErrorReduction; }
|
|
public void setAnnualErrorReduction(double annualErrorReduction) { this.annualErrorReduction = annualErrorReduction; }
|
|
|
|
public double getAnnualTimeSavings() { return annualTimeSavings; }
|
|
public void setAnnualTimeSavings(double annualTimeSavings) { this.annualTimeSavings = annualTimeSavings; }
|
|
|
|
public double getAnnualComplianceGains() { return annualComplianceGains; }
|
|
public void setAnnualComplianceGains(double annualComplianceGains) { this.annualComplianceGains = annualComplianceGains; }
|
|
|
|
public double getTotalAnnualGains() { return totalAnnualGains; }
|
|
public void setTotalAnnualGains(double totalAnnualGains) { this.totalAnnualGains = totalAnnualGains; }
|
|
|
|
public double getImplementationCost() { return implementationCost; }
|
|
public void setImplementationCost(double implementationCost) { this.implementationCost = implementationCost; }
|
|
|
|
public double getAnnualMaintenanceCost() { return annualMaintenanceCost; }
|
|
public void setAnnualMaintenanceCost(double annualMaintenanceCost) { this.annualMaintenanceCost = annualMaintenanceCost; }
|
|
|
|
public double getRoi3Years() { return roi3Years; }
|
|
public void setRoi3Years(double roi3Years) { this.roi3Years = roi3Years; }
|
|
|
|
public double getPaybackPeriodMonths() { return paybackPeriodMonths; }
|
|
public void setPaybackPeriodMonths(double paybackPeriodMonths) { this.paybackPeriodMonths = paybackPeriodMonths; }
|
|
|
|
public double getNetPresentValue3Years() { return netPresentValue3Years; }
|
|
public void setNetPresentValue3Years(double netPresentValue3Years) { this.netPresentValue3Years = netPresentValue3Years; }
|
|
|
|
public Map<String, Double> getGainsByCategory() { return gainsByCategory; }
|
|
public void setGainsByCategory(Map<String, Double> gainsByCategory) { this.gainsByCategory = gainsByCategory; }
|
|
}
|