github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/blockapps-ba-master/server/lib/project/contracts/ProjectManager.sol (about) 1 import "./Project.sol"; 2 import "./ProjectState.sol"; 3 import "./ProjectEvent.sol"; 4 import "../../bid/contracts/Bid.sol"; 5 import "../../bid/contracts/BidState.sol"; 6 import "../../common/ErrorCodes.sol"; 7 import "../../common/Util.sol"; 8 9 /** 10 * Interface for Project data contracts 11 */ 12 contract ProjectManager is ErrorCodes, Util, ProjectState, ProjectEvent, BidState { 13 14 Project[] projects; 15 uint bidId; // unique identifier for bids 16 17 /* 18 note on mapping to array index: 19 a non existing mapping will return 0, so 0 should not be a valid value in a map, 20 otherwise exists() will not work 21 */ 22 mapping (bytes32 => uint) nameToIndexMap; 23 24 /** 25 * Constructor 26 */ 27 function ProjectManager() { 28 projects.length = 1; // see above note 29 bidId = block.number; 30 } 31 32 function exists(string name) returns (bool) { 33 return nameToIndexMap[b32(name)] != 0; 34 } 35 36 function getProject(string name) returns (address) { 37 uint index = nameToIndexMap[b32(name)]; 38 return projects[index]; 39 } 40 41 /* 42 string addressStreet, 43 string addressCity, 44 string addressState, 45 string addressZip 46 */ 47 // addressStreet, 48 // addressCity, 49 // addressState, 50 // addressZip 51 52 function createProject( 53 string name, 54 string buyer, 55 string description, 56 string spec, 57 uint price, 58 uint created, 59 uint targetDelivery 60 ) returns (ErrorCodes) { 61 // name must be < 32 bytes 62 if (bytes(name).length > 32) return ErrorCodes.ERROR; 63 // fail if username exists 64 if (exists(name)) return ErrorCodes.EXISTS; 65 // add project 66 uint index = projects.length; 67 nameToIndexMap[b32(name)] = index; 68 projects.push(new Project( 69 name, 70 buyer, 71 description, 72 spec, 73 price, 74 created, 75 targetDelivery 76 )); 77 return ErrorCodes.SUCCESS; 78 } 79 80 function createBid(string name, string supplier, uint amount) returns (ErrorCodes, uint) { 81 // fail if project name not found 82 if (!exists(name)) return (ErrorCodes.NOT_FOUND, 0); 83 // create bid 84 bidId++; // increment the unique id 85 Bid bid = new Bid(bidId, name, supplier, amount); 86 return (ErrorCodes.SUCCESS, bidId); 87 } 88 89 function settleProject(string name, address supplierAddress, address bidAddress) returns (ErrorCodes) { 90 // validity 91 if (!exists(name)) return (ErrorCodes.NOT_FOUND); 92 // set project state 93 address projectAddress = getProject(name); 94 var (errorCode, state) = handleEvent(projectAddress, ProjectEvent.RECEIVE); 95 if (errorCode != ErrorCodes.SUCCESS) return errorCode; 96 // settle 97 Bid bid = Bid(bidAddress); 98 return bid.settle(supplierAddress); 99 } 100 101 /** 102 * handleEvent - transition project to a new state based on incoming event 103 */ 104 function handleEvent(address projectAddress, ProjectEvent projectEvent) returns (ErrorCodes, ProjectState) { 105 Project project = Project(projectAddress); 106 ProjectState state = project.getState(); 107 // check transition 108 var (errorCode, newState) = fsm(state, projectEvent); 109 // event is not valid in current state 110 if (errorCode != ErrorCodes.SUCCESS) { 111 return (errorCode, state); 112 } 113 // use the new state 114 project.setState(newState); 115 return (ErrorCodes.SUCCESS, newState); 116 } 117 118 function fsm(ProjectState state, ProjectEvent projectEvent) returns (ErrorCodes, ProjectState) { 119 // NULL 120 if (state == ProjectState.NULL) 121 return (ErrorCodes.ERROR, state); 122 // OPEN 123 if (state == ProjectState.OPEN) { 124 if (projectEvent == ProjectEvent.ACCEPT) 125 return (ErrorCodes.SUCCESS, ProjectState.PRODUCTION); 126 } 127 // PRODUCTION 128 if (state == ProjectState.PRODUCTION) { 129 if (projectEvent == ProjectEvent.DELIVER) 130 return (ErrorCodes.SUCCESS, ProjectState.INTRANSIT); 131 } 132 // INTRANSIT 133 if (state == ProjectState.INTRANSIT) { 134 if (projectEvent == ProjectEvent.RECEIVE) 135 return (ErrorCodes.SUCCESS, ProjectState.RECEIVED); 136 } 137 return (ErrorCodes.ERROR, state); 138 } 139 }