Last active
June 23, 2024 15:09
-
-
Save asaidimu/827194698cf2d1f7adfe1e2995a3cd02 to your computer and use it in GitHub Desktop.
Tracking a project with blockchain.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { v4 as uuidv4 } from 'uuid'; | |
| // UUID generation function | |
| const generateUUID = (): string => { | |
| return uuidv4(); | |
| }; | |
| // User interface | |
| interface User { | |
| userId: string; | |
| name: string; | |
| department: string; | |
| email: string; | |
| } | |
| // Internal Department interface | |
| interface InternalDepartment { | |
| departmentId: string; | |
| name: string; | |
| manager: string; // UUID of User | |
| } | |
| // Contractor interface | |
| interface Contractor { | |
| contractorId: string; | |
| name: string; | |
| contactPerson: string; // UUID of User | |
| company: string; | |
| } | |
| // Financial Officer interface | |
| interface FinancialOfficer { | |
| officerId: string; | |
| name: string; | |
| department: string; | |
| email: string; | |
| } | |
| // Task interface | |
| interface Task { | |
| taskId: string; | |
| createdBy: string; // UUID of User | |
| createdTimestamp: string; // ISO string | |
| description: string; | |
| function: string; | |
| policy: string; | |
| proposer: string; // UUID of User | |
| thesis: string; | |
| currentStage: TaskStage; | |
| stages: TaskStage[]; | |
| approvals: Approval[]; | |
| budget?: Budget; // Optional budget information | |
| handler?: string; // UUID of InternalDepartment or Contractor | |
| reason?: string; // Reason for hiring contractor or internal handling | |
| financialApprovals?: FinancialApproval[]; // Array of FinancialApprovals | |
| totalEstimatedCost?: number; // Total estimated cost for the task | |
| performanceReview?: PerformanceReview; // Performance review by committee | |
| financialReceipts?: FinancialReceipt[]; // Array of FinancialReceipts | |
| completionStatus: 'Pending' | 'Completed'; // Task completion status | |
| } | |
| // TaskStage interface | |
| interface TaskStage { | |
| stageId: string; | |
| taskId: string; // UUID of Task | |
| stageName: string; | |
| startDate: string; // ISO string | |
| endDate?: string; // ISO string | |
| comments?: string; | |
| } | |
| // Approval interface | |
| interface Approval { | |
| approvalId: string; | |
| approver: string; // UUID of User or FinancialOfficer | |
| timestamp: string; // ISO string | |
| status: 'Pending' | 'Approved' | 'Rejected'; | |
| comments?: string; | |
| } | |
| // Budget interface | |
| interface Budget { | |
| taskId: string; // UUID of Task | |
| subcommittee: string; // UUID of committee or subcommittee | |
| resources: BudgetResource[]; | |
| } | |
| // BudgetResource interface | |
| interface BudgetResource { | |
| resourceId: string; // UUID of Resource | |
| reason: string; // Reason for resource allocation | |
| cost: number; // Cost of resource | |
| } | |
| // FinancialApproval interface | |
| interface FinancialApproval { | |
| approvalId: string; | |
| taskId: string; // UUID of Task | |
| approver: string; // UUID of FinancialOfficer | |
| timestamp: string; // ISO string | |
| status: 'Pending' | 'Approved' | 'Rejected'; | |
| comments?: string; | |
| } | |
| // PerformanceReview interface | |
| interface PerformanceReview { | |
| taskId: string; // UUID of Task | |
| committee: string; // UUID of committee or subcommittee | |
| comments: string; // Review comments | |
| } | |
| // FinancialReceipt interface | |
| interface FinancialReceipt { | |
| receiptId: string; | |
| taskId: string; // UUID of Task | |
| resourceId: string; // UUID of Resource | |
| approvedBy: string; // UUID of FinancialOfficer | |
| approvalTimestamp: string; // ISO string | |
| receiptDetails: string; | |
| } | |
| // Block interface for blockchain | |
| interface Block { | |
| index: number; | |
| previousHash: string; | |
| timestamp: number; | |
| data: Task; | |
| hash: string; | |
| } | |
| // Blockchain class | |
| class Blockchain { | |
| chain: Block[]; | |
| constructor() { | |
| this.chain = []; | |
| // Genesis block creation (initial block in the blockchain) | |
| this.createGenesisBlock(); | |
| } | |
| // Create genesis block | |
| private createGenesisBlock() { | |
| const genesisBlock: Block = { | |
| index: 0, | |
| previousHash: '0', | |
| timestamp: Date.now(), | |
| data: null, // No data for genesis block | |
| hash: '' | |
| }; | |
| genesisBlock.hash = this.calculateHash(genesisBlock); | |
| this.chain.push(genesisBlock); | |
| } | |
| // Calculate hash for a block | |
| private calculateHash(block: Block): string { | |
| const { index, previousHash, timestamp, data } = block; | |
| const blockString = `${index}${previousHash}${timestamp}${JSON.stringify(data)}`; | |
| return uuidv4(); // Placeholder for actual hash calculation, using UUID for simplicity | |
| } | |
| // Get latest block in the chain | |
| private getLatestBlock(): Block { | |
| return this.chain[this.chain.length - 1]; | |
| } | |
| // Add a new block to the chain | |
| addBlock(data: Task): void { | |
| const previousBlock = this.getLatestBlock(); | |
| const newIndex = previousBlock.index + 1; | |
| const newBlock: Block = { | |
| index: newIndex, | |
| previousHash: previousBlock.hash, | |
| timestamp: Date.now(), | |
| data, | |
| hash: '' | |
| }; | |
| newBlock.hash = this.calculateHash(newBlock); | |
| this.chain.push(newBlock); | |
| } | |
| // Validate blockchain integrity (simple check) | |
| isChainValid(): boolean { | |
| for (let i = 1; i < this.chain.length; i++) { | |
| const currentBlock = this.chain[i]; | |
| const previousBlock = this.chain[i - 1]; | |
| // Check if hashes are correct | |
| if (currentBlock.previousHash !== previousBlock.hash) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| } | |
| // Example Usage | |
| const blockchain = new Blockchain(); | |
| // Example data creation | |
| const user1: User = { | |
| userId: generateUUID(), | |
| name: 'Alice', | |
| department: 'IT', | |
| email: '[email protected]' | |
| }; | |
| const committee: string = generateUUID(); // UUID for committee | |
| const taskProposal: Task = { | |
| taskId: generateUUID(), | |
| createdBy: user1.userId, | |
| createdTimestamp: new Date().toISOString(), | |
| description: 'Build a school in Maralal', | |
| function: 'Education', | |
| policy: 'Education Policy 2024', | |
| proposer: user1.userId, | |
| thesis: 'A school in Maralal will provide access to education for children in the region.', | |
| currentStage: { | |
| stageId: generateUUID(), | |
| taskId: '', // To be filled later during insertion | |
| stageName: 'Proposal', | |
| startDate: new Date().toISOString() | |
| }, | |
| stages: [], | |
| approvals: [], | |
| completionStatus: 'Pending' | |
| }; | |
| // Add initial proposal to blockchain | |
| blockchain.addBlock(taskProposal); | |
| // Committee reviews the proposal and moves to deliberation stage | |
| const taskWithDeliberation: Task = { | |
| ...taskProposal, | |
| currentStage: { | |
| stageId: generateUUID(), | |
| taskId: taskProposal.taskId, | |
| stageName: 'Deliberation', | |
| startDate: new Date().toISOString() | |
| } | |
| }; | |
| blockchain.addBlock(taskWithDeliberation); | |
| // Committee approves the proposal | |
| const approvedTask: Task = { | |
| ...taskWithDeliberation, | |
| currentStage: { | |
| ...taskWithDeliberation.currentStage, | |
| endDate: new Date().toISOString() | |
| }, | |
| approvals: [ | |
| { | |
| approvalId: generateUUID(), | |
| approver: committee, | |
| timestamp: new Date().toISOString(), | |
| status: 'Approved', | |
| comments: 'Approved for building the school in Maralal.' | |
| } | |
| ] | |
| }; | |
| blockchain.addBlock(approvedTask); | |
| // Subcommittee develops budget and decides on handling | |
| const budget: Budget = { | |
| taskId: approvedTask.taskId, | |
| subcommittee: committee, | |
| resources: [ | |
| { | |
| resourceId: generateUUID(), | |
| reason: 'Construction materials', | |
| cost: 50000 | |
| }, | |
| { | |
| resourceId: generateUUID(), | |
| reason: 'Labor costs', | |
| cost: 80000 | |
| } | |
| ] | |
| }; | |
| const taskWithBudget: Task = { | |
| ...approvedTask, | |
| budget, | |
| handler: generateUUID(), // Assuming hiring contractor | |
| reason: 'Contractor selected for construction' | |
| }; | |
| blockchain.addBlock(taskWithBudget); | |
| // Financial officer approves funds | |
| const financialApproval: FinancialApproval = { | |
| approvalId: generateUUID(), | |
| taskId: taskWithBudget.taskId, | |
| approver: generateUUID(), // UUID of financial officer | |
| timestamp: new Date().toISOString(), | |
| status: 'Approved', | |
| comments: 'Approved funds allocation for school construction in Maralal.' | |
| }; | |
| const taskWithFinancialApproval: Task = { | |
| ...taskWithBudget, | |
| financialApprovals: [financialApproval], | |
| totalEstimatedCost: budget.resources.reduce((total, resource) => total + resource.cost, 0) | |
| }; | |
| blockchain.addBlock(taskWithFinancialApproval); | |
| // Performance review and financial receipts | |
| const performanceReview: PerformanceReview = { | |
| taskId: taskWithFinancialApproval.taskId, | |
| committee, | |
| comments: 'Construction completed on time and within budget.' | |
| }; | |
| const financialReceipts: FinancialReceipt[] = [ | |
| { | |
| receiptId: generateUUID(), | |
| taskId: taskWithFinancialApproval.taskId, | |
| resourceId: budget.resources[0].resourceId, // Assuming first resource for example | |
| approvedBy: financialApproval.approver, | |
| approvalTimestamp: new Date().toISOString(), | |
| receiptDetails: 'Receipt for construction materials' | |
| }, | |
| { | |
| receiptId: generateUUID(), | |
| taskId: taskWithFinancialApproval.taskId, | |
| resourceId: budget.resources[1].resourceId, // Assuming second resource for | |
| approvedBy: financialApproval.approver, | |
| approvalTimestamp: new Date().toISOString(), | |
| receiptDetails: 'Receipt for labor costs' | |
| } | |
| ]; | |
| const taskCompleted: Task = { | |
| ...taskWithFinancialApproval, | |
| performanceReview, | |
| financialReceipts, | |
| completionStatus: 'Completed' | |
| }; | |
| blockchain.addBlock(taskCompleted); | |
| // Example of validating the blockchain | |
| console.log('Is blockchain valid?', blockchain.isChainValid()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment