it help me solving the problem.
// SPDX-License-Identifier: UNLICENSED
//pragma solidity >=0.8.17;
pragma solidity >=0.4.22 <0.9.0;
//pragma experimental ABIEncoderV2;
contract Funding {
//============= ENUMERATIONS =====================
enum TransactionStatus {
INIT,
IN_PROGRESS,
PENDING,
CANCELLED,
COMPLETED
}
enum DocumentStatus {
PENDING,
VALIDATED,
REJECTED
}
enum DocumentType {
CARD_ID,
CIP,
PASSPORT,
PERMIS
}
enum SubscriptionType {
UTILISATEUR,
ENTREPRENEUR,
ASSOCIE,
INVESTISSEUR,
EMPLOYE
}
enum CagnotteStatus {
IN_PROGRESS,
PENDING,
CANCELLED,
COMPLETED
}
enum ProjectStep {
IDEE,
PROTOTYPE,
ENTREPRISE,
ACTION
}
enum ServiceType {
RETRAIT,
RECHARDE,
TRANSFERT,
DEPOT
}
enum EntrepreneurType {
SIMPLE,
ASSOCIE
}
enum EntrepreneurNiveau {
DEBUTANT,
INTERMEDIAIRE,
EXPERIMENTE
}
enum RecetteType {
DEPENSE,
REVENU
}
enum RecetteCategory {
PRODUIT,
SERVICE,
ABONNEMENT
}
enum TypeAdresse {
RESIDENCE,
ORIGINE
}
// =========== Structs ================
struct Transaction {
uint32 sent_amount;
uint32 sent_amount_ussd;
uint32 deducted_amount;
uint32 deducted_amount_ussd;
string slug;
string motif;
string gateway;
uint32 amount_with_fees;
uint32 network_fees_ussd;
uint32 transactions_fees_ussd;
string tx_identifier;
string project_identifier;
address sender;
address receiver;
}
struct Document {
bytes32 unique_hash;
DocumentType doc_type;
string recto_url;
string verso_url;
DocumentStatus status;
uint32 created_timestamp;
}
struct Adress {
string country;
string departement ;
string township ;
string dictrict ;
}
enum AbonnementType { Entrepreneur, Investisseur, Employe, Juriste, Utilisateur }
// event DocumentAdded(bytes32,DocumentType , string);
//event FinancialModalAdded(bytes32,string, string,string,string);
enum ProjectEvolutionStatus {
PENDING,
STARTING,
COMPLETED,
CANCELLED,
FALLEN
}
/* Repetition start*/
struct FinancialModal{
bytes32 unique_hash;
string description;
string[] income_sources;
string rentability_analysis;
string evolutivity_strategy;
string durability_strategy;
string[] partenership ;
string modal_file_url;
uint32 objective_amount;
}
// event ProjectCreated(bytes32,string, string);
struct BusinessPlan{
bytes32 unique_hash;
string[] commercial_objectives;
string marketing_strategy;
uint32 financial_prevision;
string distribution_strategy;
uint32 local_average_price;
string price_fixation_reason;
string[] benefits_means ;
uint32 expected_customer_per_year;
uint32 income_price;
uint32 benefits_marge;
uint32 ussd_average_price;
string business_file_url;
}
struct Charge {
RecetteCategory category;
string libelle ;
string reason;
uint32 amount;
}
struct Contrat {
string type_adhesion;
bytes32 entrepreneur_hash;
bytes32 investor_hash;
string refund_clauses;
uint32 refund_date_delay;
uint32 interest_rate;
string applicable_low;
string investor_rate;
string termination_conditions;
string major_force_clause;
bytes32 competent_juridiction;
string contrat_file;
string contrat_file_url;
bytes32 transaction_hash;
}
struct Project{
string name;
uint32 identifier;
bytes32 unique_hash;
string description;
string problem_to_solve ;
string pertinence;
ProjectStep step;
uint32 production_duration_in_year;
uint32 project_duration_in_year;
string total_amount;
string already_obtained_amount;
FinancialModal financialModal;
BusinessPlan businessPlan;
}
// TODO : Ecrire des fonctions qui les retourne
uint32 internal projet_count = 0;
uint32 internal document_count = 0;
uint32 internal transaction_count = 0;
uint32 internal user_count = 0;
struct UserObject {
string name;
bytes32 hash;
address adress;
string surname;
uint32 bithday;
string email;
string birth_place;
string phone_number;
//string profil_image;
Adress origin_adress;
Adress actual_adress;
AbonnementType abonnement;
uint32[] projectIndexes;
uint32[] documentIndexes;
uint32[] transactionIndexes;
}
//mapping(address => UserObject) internal Users;
mapping(bytes32 => UserObject) private users;
mapping(bytes32 => Project[]) private projects; //projects list
bytes32[] project_hashes ;
mapping(bytes32 => Project[]) private projets;
mapping(bytes32 => Document[]) private documents;
mapping(bytes32 => Adress[]) private addreses;
mapping(bytes32 => Transaction[]) private transactions;
mapping(bytes32 => Contrat) private adhesions;
// function to calculate the financial modal unique hash
function calculate_modal_hash(
bytes32 project_id,
string memory description,
string memory rentability_analysis,
uint32 objective_amount
) internal pure returns(bytes32)
{
return keccak256(abi.encodePacked(project_id, description, rentability_analysis,objective_amount));
}
/*------------ Repetition end ------------*/
// function to calculate the unique hash
function calculate_project_unique_hash(
string memory name,
string memory description,
string memory idea_source
) internal pure returns(bytes32)
{
return keccak256(abi.encodePacked(name, description, idea_source));
}
/**
* function that browse and verify if the project exists
**/
function getOrVerifyProject(bytes32 _address, bytes32 project_hash) internal view returns (bool success, Project memory retrievedProject ) {
(bool succes, ) = getOrVerifyUser(_address); // We verify if the user exists
require(succes, "Not found !");
Project[] memory userProjects = projets[_address];
bool isFound = false;
for (uint32 i = 0; i < userProjects.length; i++) {
if (userProjects[i].unique_hash == project_hash) {
retrievedProject = userProjects[i];
isFound = true;
break;
}
}
success = isFound;
return (success, retrievedProject);
}
function addUser(UserObject memory newUser) public {
bytes32 uniqueHash = keccak256(abi.encodePacked(newUser.hash));
users[uniqueHash] = newUser;
user_count++;
}
function createProject(
bytes32 user_address,
Project memory project
) public {
bytes32 projectHash = calculate_project_unique_hash(project.name, project.description, project.problem_to_solve);
(bool projectExists, ) = getOrVerifyProject(user_address, projectHash);
require(!projectExists, "Already exists !");
FinancialModal memory newModal = FinancialModal({
unique_hash: calculate_modal_hash(projectHash, project.description, "", 0),
description: "",
income_sources: new string[](0),
rentability_analysis: "",
evolutivity_strategy: "",
durability_strategy: "",
partenership: new string[](0),
modal_file_url: "",
objective_amount: 0
});
BusinessPlan memory business_plan = BusinessPlan({
unique_hash :0x0,
commercial_objectives : new string[](0),
marketing_strategy : "",
financial_prevision :0,
distribution_strategy:"",
local_average_price: 0,
price_fixation_reason :"",
benefits_means : new string[](0),
expected_customer_per_year:0,
income_price :0,
benefits_marge:0,
ussd_average_price:0,
business_file_url : ""
});
projects[user_address].push(Project({
name: project.name,
unique_hash: projectHash,
identifier : project.identifier,
description: project.description,
problem_to_solve: project.problem_to_solve,
pertinence: project.pertinence,
step: project.step,
production_duration_in_year : project.production_duration_in_year,
project_duration_in_year : project.project_duration_in_year,
total_amount: project.total_amount,
already_obtained_amount: project.already_obtained_amount,
financialModal: newModal,
businessPlan : business_plan
}));
(bool success, ) = getOrVerifyUser(user_address);
require(success, "Not found!");
UserObject storage userStorage = users[user_address];
projects[user_address] = projects[user_address];
projet_count++;
userStorage.projectIndexes.push(projet_count);
project_hashes.push(projectHash);
//emit ProjectCreated(projectHash, project.name, "Created successfully!!"); }
/**
* function that browse and verify if the user exists
* it return a tuple that contains a boolean indicatinf the existence et the Userobject if true
**/
function getOrVerifyUser(bytes32 _hash) public view returns (bool success, UserObject memory verifiedUser ) {
bool isFound = bytes(users[_hash].name).length > 0;
if(isFound)
{
verifiedUser = users[_hash];
success = isFound;
}
return (success, verifiedUser);
}
//===========================================
// Add the User Documents
function AddDocumentToUser(
bytes32 user_hash,
Document memory document
) public {
bytes32 doc_unique_hash = keccak256(abi.encodePacked(document.doc_type, document.recto_url,document.verso_url ));
(bool success, ) = getOrVerifyUser(user_hash);
require(success, "Not found !");
UserObject storage userStorage = users[user_hash];
documents[user_hash].push(Document({
unique_hash: doc_unique_hash,
doc_type : document.doc_type,
recto_url :document.recto_url,
verso_url : document.verso_url,
status : DocumentStatus.VALIDATED,
created_timestamp : 0
}));
document_count++;
userStorage.documentIndexes.push(document_count); // Add doc to user doc
}
function addAdhesion(
Contrat memory adhesion
) public {
bytes32 uniqueHash = keccak256(abi.encodePacked(adhesion.entrepreneur_hash, adhesion.investor_hash, adhesion.transaction_hash));
// Ajouter l'adhésion au mapping des adhésions
adhesions[uniqueHash] = Contrat({
type_adhesion: adhesion.type_adhesion,
entrepreneur_hash: adhesion.entrepreneur_hash,
investor_hash: adhesion.investor_hash,
refund_clauses: adhesion.refund_clauses,
refund_date_delay: adhesion.refund_date_delay,
interest_rate: adhesion.interest_rate,
applicable_low: adhesion.applicable_low,
investor_rate: adhesion.investor_rate,
termination_conditions: adhesion.termination_conditions,
major_force_clause: adhesion.major_force_clause,
competent_juridiction: adhesion.competent_juridiction,
contrat_file: adhesion.contrat_file,
contrat_file_url: adhesion.contrat_file_url,
transaction_hash: adhesion.transaction_hash
});
}
function getAdhesion(bytes32 contrat_hash) public view returns (Contrat memory) {
return adhesions[contrat_hash];
}
// Add the User Adresse
function AddAdressToUser(
bytes32 user_hash,
Adress memory adress,
uint _type
) public {
require(_type==0 || _type==1, "Not valid!");
(bool success, ) = getOrVerifyUser(user_hash);
require(success, "Not found!");
UserObject storage userStorage = users[user_hash];
if (_type==0)
{
userStorage.actual_adress = Adress({
country: adress.country,
departement :adress.departement,
township :adress.township,
dictrict : adress.dictrict
});
}
else {
userStorage.origin_adress = Adress({
country: adress.country,
departement :adress.departement,
township :adress.township,
dictrict : adress.dictrict
});
}
}
function setUserAbonnementType(bytes32 hash, AbonnementType _abonnement) public {
(bool success, ) = getOrVerifyUser(hash);
require(success, "Not found!");
UserObject storage userStorage = users[hash];
userStorage.abonnement = _abonnement;
}
// Add the Transaction Documents
function CreateUserTransaction(
bytes32 user_hash,
Transaction memory transaction
) public {
(bool success,) = getOrVerifyUser(user_hash);
require(success, "Not found!");
transactions[user_hash].push(Transaction({
sent_amount: transaction.sent_amount,
sent_amount_ussd: transaction.sent_amount_ussd,
deducted_amount: transaction.deducted_amount,
deducted_amount_ussd: transaction.deducted_amount_ussd,
slug: transaction.slug,
motif: transaction.motif,
gateway: transaction.gateway,
amount_with_fees: transaction.amount_with_fees,
network_fees_ussd: transaction.network_fees_ussd,
transactions_fees_ussd: transaction.transactions_fees_ussd,
tx_identifier: transaction.tx_identifier,
project_identifier: transaction.project_identifier,
sender: transaction.sender,
receiver: transaction.receiver
}));
}
function getUserDocuments(bytes32 userHash) public view returns (Document[] memory) {
(bool success,) = getOrVerifyUser(userHash);
require(success, "Not found !");
Document[] memory userDocuments = documents[userHash];
return userDocuments;
}
function getUserTransactions(bytes32 userHash) public view returns (Transaction[] memory) {
(bool success,) = getOrVerifyUser(userHash);
require(success, "Not found!");
Transaction[] memory userTransactions = transactions[userHash];
return userTransactions;
}
function getUserProjects(bytes32 userHash) public view returns (Project[] memory) {
(bool success,) = getOrVerifyUser(userHash);
require(success, "Not found!");
Project[] memory userProjects = projects[userHash];
return userProjects;
}
function getAllUsers(bytes32 user_hash) public view returns (UserObject memory) {
(bool success,) = getOrVerifyUser(user_hash);
require(success, "Not found !");
return users[user_hash];
}
function getUserSpecificProject(bytes32 userHash, uint32 projectId) public view returns (Project memory) {
(bool success,) = getOrVerifyUser(userHash);
require(success, "Not found !");
return projects[userHash][projectId];
}
function setProductionDuration(bytes32 userHash, uint32 projectId, uint32 _duration) public {
projects[userHash][projectId].production_duration_in_year = _duration;
}
function setProjectDuration(bytes32 userHash, uint32 projectId, uint32 _duration) public {
projects[userHash][projectId].project_duration_in_year = _duration;
}
function setProjectStep(bytes32 userHash, uint32 projectId, ProjectStep _step) public {
projects[userHash][projectId].step = _step;
}
function addIncomeSourceToModel(bytes32 userHash, uint32 projectId, string memory _source) public {
projects[userHash][projectId].financialModal.income_sources.push(_source);
}
function addIncomePartnerShipToMOdal(bytes32 userHash, uint32 projectId, string memory _partner) public {
projects[userHash][projectId].financialModal.partenership.push(_partner);
}
function AddFinancialModal(
bytes32 userHash,
uint32 projectId,
FinancialModal memory fiancial_model
) public {
// bytes32 uniqueHash = keccak256(abi.encodePacked(userHash, projectId, fiancial_model.objective_amount));
projects[userHash][projectId].financialModal = FinancialModal({
unique_hash: fiancial_model.unique_hash,
description: fiancial_model.description,
income_sources: fiancial_model.income_sources,
rentability_analysis: fiancial_model.rentability_analysis,
evolutivity_strategy: fiancial_model.evolutivity_strategy,
durability_strategy:fiancial_model.durability_strategy,
partenership: fiancial_model.partenership,
modal_file_url: fiancial_model.modal_file_url,
objective_amount: fiancial_model.objective_amount
});
}
}