-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathSourceTracker.sol
165 lines (144 loc) · 4.07 KB
/
SourceTracker.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
pragma solidity ^0.5.0;
// @title a simple tracker for a supply chain product from source to consumer
// @author Blockchain at Michigan
contract SourceTracker
{
string internal ProductName;
uint internal NumItemsOriginal; // how many total items should be in shipment
uint internal NumNodes; // number of nodes in supply chain
struct Node
{
string BusinessName; // name of the business representing this node
string DateReceived; // date that shipment was received, in form mm/dd/yyyy
uint NumItemsReceived; // how many total items were received
uint NodeIndex; // index of this node in chain array
bool PerfectCondition; // true if all items received are in perfect condition
}
Node[] internal SupplyChain;
mapping (string => uint) internal BusinessNameLookup; // maps name of business to index of its node in supply chain
// when a new node is added to supply chain
event NewNode
(
string BusinessName,
uint NumItemsReceived
);
// when a new node is added to supply chain and reports imperfect items
event ProductDamage
(
string BusinessName,
uint NodeIndex
);
// @param name of the product
// @param total number of items that are expected in shipment
// NOTE: Data location (memory, calldata, storage) can only be specified for array, struct or mapping types
constructor (string memory productName, uint numItemsOriginal)
public
{
ProductName = productName;
NumItemsOriginal = numItemsOriginal;
NumNodes = 0;
}
// @returns name of product this supply chain tracks
function GetProductName()
external
view
returns (string memory)
{
return ProductName;
}
// @returns total number of items that should be in each shipment
function GetOriginalNumberOfItems()
external
view
returns (uint)
{
return NumItemsOriginal;
}
// @returns number of nodes in supply chain
function GetNumberOfNodes()
external
view
returns (uint)
{
return NumNodes;
}
// adds a new node to the end of the supply chain
// @param name of business representing this node
// @param date that this node received shipment
// @param total number of items received in this shipment at this node
// @param whether every item in the shipment was in perfect condition
// NOTE: Data location must be "calldata" for parameter in external function
function AddNode
(
string calldata businessName,
string calldata dateReceived,
uint numItemsReceived,
bool perfectCondition
)
external
{
// push new struct into array
SupplyChain.push(Node(businessName, dateReceived, numItemsReceived, NumNodes, perfectCondition));
// update BusinessNameLookup mapping
BusinessNameLookup[businessName] = NumNodes;
// emit NewNode event
emit NewNode(businessName, numItemsReceived);
// check if ProductDamage event should be emitted
if (!perfectCondition)
{
emit ProductDamage(businessName, NumNodes);
}
// increase numNodes
++NumNodes;
}
// finds the first node to report damage
// @returns name of a business in the supply chain or empty string
function FindDamage()
external
view
returns (string memory)
{
// look for business that reported damage
for (uint i = 0; i < NumNodes; ++i)
{
if (!(SupplyChain[i].PerfectCondition))
{
return SupplyChain[i].BusinessName;
}
}
// or return an empty string
return "";
}
// determines what date the company received their shipment
// @param name of a business
// @returns date or empty string
function DateBusinessReceivedShipment(string calldata businessName)
external
view
returns (string memory)
{
// get index of business
uint idx = BusinessNameLookup[businessName];
// make sure returned index wasn't just a default value
if (
(idx == 0) &&
(!compareStrings(SupplyChain[idx].BusinessName, businessName))
)
{
return "";
} else
{
return SupplyChain[idx].DateReceived;
}
}
// helper function that compares strings
// @param 2 strings
// @returns true if the strings match
function compareStrings(string memory a, string memory b)
internal
pure
returns (bool)
{
return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))) );
}
}