-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTrazabilidad.sol
259 lines (226 loc) · 10.5 KB
/
Trazabilidad.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// Version de solidity del Smart Contract
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.16;
// Informacion del Smart Contract
// Nombre: Trazabilidad
// Logica: Realiza un contral de entregas para una ruta preestablecida
// Declaracion del Smart Contract - Trazabilidad
contract Trazabilidad {
// ----------- Variables (datos) -----------
// Información de la Entrega
enum Status {ACCEPTED,READY,CLOK,RPOK,CLKO,RPKO,CANCEL,REALIZADA}
enum Role {CLIENTE,REPARTIDOR,VENDEDOR}
// Creamos la estructura de datos para la entrega
struct Entrega {
uint8 numEntrega;
string description;
uint price;
uint256 timestamp;
Status status;
mapping (Role => address) mapRole;
}
// Implementamos los datos de las transacciones para las firmas
uint priceTrasporte;
uint8 public numCalculado;
mapping (uint => Entrega) mapEntrega;
//Propietario y actores en el reparto
address payable public owner;
address payable public contractaddress;
uint fondostotales = address(this).balance;
//Constantes Status
string private ACCEPTED = "ACCEPTED";
string private READY = "READY";
string private CLOK = "CLOK";
string private RPOK = "RPOK";
string private CLKO = "CLKO";
string private RPKO = "RPKO";
string private CANCEL = "CANCEL";
string private REALIZADA = "REALIZADA";
//Eventos
// ----------- Eventos (pueden ser emitidos por el Smart Contract) -----------
event Msg(string _message);
event MsgEntrada (string _message ,address _repartidor, address _cliente,uint precio, string _descipcion);
event MsgEntradaXNumEnt (uint8 _numentrada ,string _descipcion,uint _precio, string _status, address _cliente, address _repartidor, address _vendedor);
event MsgPrecio(string _message, uint _precio);
// ----------- Constructor -----------
// Uso: Inicializa el Smart Contract - Inicio de Ruta
constructor() {
// Inicializo el valor a las variables (datos)
owner = payable(msg.sender);
contractaddress = payable(address(this));
numCalculado = 0;
priceTrasporte = 0.001 ether;
// Se emite un Evento
emit Msg("Contrato entrega creada sin Entregas");
}
// ------------ Modificadores ------------
// Modificador
// Nombre: isRepartidor
// Uso: Comprueba que es el repartidor de la entrega
modifier isRepartidor(uint numEnt) {
require(mapEntrega[numEnt].mapRole[Role.REPARTIDOR] == msg.sender ,"No tienes rol de repartidor o no estas signado como tal");
_;
}
// Modificador
// Nombre: isCliente
// Uso: Comprueba que es el cleinte de la entrega
modifier isCliente (uint numEnt){
require(mapEntrega[numEnt].mapRole[Role.CLIENTE] == msg.sender ,"No eres cliente de la entrega o no estas asignado como tal");
_;
}
// Modificador
// Nombre: isOwner
// Uso: Comprueba que es el owner del contrato
modifier isOwner {
require(msg.sender == owner,"No eres creador del contrato");
_;
}
// Modificador
// Nombre: isNot0x000000
// Uso: Comprueba que es 0x000000
modifier isNot0x000000 (address addr) {
require(addr != address(0), "Not valid address");
_;
}
// ------------ Funciones que modifican datos (set) ------------
// Funcion
// Nombre: repartidorFirmaSalida
// Uso: Repartidor firma la salida al contrato si se cumplen las conciciones
function repartidorFirmaSalida(uint numEnt) public isRepartidor(numEnt) {
require(numEnt > 0 && numEnt <= numCalculado,"El número de entrega no es correcto");
require(mapEntrega[numEnt].status == Status.ACCEPTED,"El estado de la entrega tiene que estar a ACCEPTED");
mapEntrega[numEnt].status = Status.READY;
mapEntrega[numEnt].timestamp = block.timestamp;
emit Msg("La entrega ha salido hacia su destino");
}
// Funcion
// Nombre: repartidorFirmaLLlegada
// Uso: Repartidor firma la llegada en contrato y se cumplen las condiciones
function repartidorFirmaLlegada(uint numEnt) public isRepartidor(numEnt) {
require(numEnt > 0 && numEnt <= numCalculado,"El número de entrega no es correcto");
require(mapEntrega[numEnt].status == Status.READY,"El estado de la entrega tiene que estar a READY");
mapEntrega[numEnt].status = Status.RPOK;
mapEntrega[numEnt].timestamp = block.timestamp;
emit Msg("El repartidor ha firmado la llega al destino");
}
// Funcion
// Nombre: clienteFirmaRecepcion
// Uso: cliente firma la recepcion del producto si se cumplen las conciciones y sus fondos se envian al contrato
function clienteFirmaRecepcion(uint numEnt) payable public isCliente(numEnt) {
require(numEnt > 0 && numEnt <= numCalculado,"El número de entrega no es correcto");
require(msg.value == mapEntrega[numEnt].price, "El precio introducido no se corresponde con el precio del producto");
mapEntrega[numEnt].status = Status.CLOK;
//Cuando el cliente da el Ok sus fondos se transfieren al contrato
emit Msg("El Cliente ha firmado la recepcion de Producto");
}
// Funcion
// Nombre: vendedorRecicePago
// Uso: vendedor Recoge el pago y se cumplen las conciciones
function vendedorRecibePago(uint _numEnt) payable public isOwner{
require(_numEnt > 0 && _numEnt <= numCalculado,"El Numero de entrega no es correcto");
//Si el status es CLOK y RPOK a REALIZADA
require(mapEntrega[_numEnt].status == Status.CLOK,"El Cliente no ha firmado la recepción");
mapEntrega[_numEnt].status = Status.REALIZADA;
mapEntrega[_numEnt].timestamp = block.timestamp;
//Pago al repartidor el precio
payable(mapEntrega[_numEnt].mapRole[Role.REPARTIDOR]).transfer(priceTrasporte);
//Pago al vendedor
payable(mapEntrega[_numEnt].mapRole[Role.VENDEDOR]).transfer(mapEntrega[_numEnt].price - priceTrasporte);
emit Msg("El vendedor recoje el pago y se paga el trasporte");
}
//Funcion cliente no firma recepcion se devuelve el dinero del contrato al vendedor menos la comison del repartidor
//Funcion repartidor no firma llegada se le penaliza al repartidor y se devuelve el dinero al vendedor
//Funcion cancelar solo cliente o vendedor y no estado Ready XXOK se devuelve la pasta
// Funcion
// Nombre: crearEntrega
// Uso: crear Entrega y añadir al mapping
function crearEntrega(
address repartidor,
address cliente,
uint precio,
string calldata description)
public payable isOwner {
numCalculado ++ ;
uint precioEther = precio * (10 ** 18);
mapEntrega[numCalculado].numEntrega = numCalculado;
mapEntrega[numCalculado].description = description;
mapEntrega[numCalculado].price = precioEther;
mapEntrega[numCalculado].timestamp = block.timestamp;
mapEntrega[numCalculado].status = Status.ACCEPTED;
mapEntrega[numCalculado].mapRole[Role.REPARTIDOR] = repartidor;
mapEntrega[numCalculado].mapRole[Role.CLIENTE] = cliente;
mapEntrega[numCalculado].mapRole[Role.VENDEDOR] = owner;
emit MsgEntrada ("Entrega creada: " ,repartidor, cliente, msg.value, description);
}
// Funcion
// Nombre: CanceladaEntrega
// Uso: Se cancela la entrega
function canceladaEntrega(uint numEnt) payable public isOwner(){
require(numEnt > 0 && numEnt <= numCalculado,"El Numero de entrega no es correcto");
require(mapEntrega[numEnt].status == Status.ACCEPTED, "El estado no es el adecuado para poder Cancelar la entrega");
mapEntrega[numEnt].status = Status.CANCEL;
mapEntrega[numEnt].timestamp = block.timestamp;
emit MsgEntrada ("Entrega Cancelada",
mapEntrega[numEnt].mapRole[Role.REPARTIDOR],
mapEntrega[numEnt].mapRole[Role.CLIENTE],
mapEntrega[numEnt].price,
mapEntrega[numEnt].description);
}
// Funcion
// Nombre: pánico
// Uso: Se devuelve el dinero del contrato al owner
function panico() public isOwner(){
owner.transfer(address(this).balance);
emit Msg("Funcion de pánico realizada se devuelven los fondos del Contrato al owner");
}
// Funcion get
// Nombre: viewEntrega
// Uso: Ver entrega por numEntrega
function viewEntrega(uint numEnt) public isOwner() {
require(numEnt > 0 && numEnt <= numCalculado,"El número de entrega no es correcto");
emit MsgEntradaXNumEnt (
mapEntrega[numEnt].numEntrega ,
mapEntrega[numEnt].description,
mapEntrega[numEnt].price,
viewEntregaStatus(numEnt),
mapEntrega[numEnt].mapRole[Role.CLIENTE],
mapEntrega[numEnt].mapRole[Role.REPARTIDOR],
mapEntrega[numEnt].mapRole[Role.VENDEDOR]);
}
// Funcion get
// Nombre: fondoscontratos
// Uso: Ver fondos contrato
function fondoscontratos() public view isOwner returns(uint){
return (address(this).balance);
}
// Funcion get
// Nombre: verPrecio
// Uso: Consultar el precio de un producto
function verPrecio(uint numEnt) public view isOwner returns(uint){
return mapEntrega[numEnt].price;
}
// Funcion view
// Nombre: viewEntregaStatus
// Uso: Ver El status de la entrega por numEntrega
// Status {ACCEPTED,READY,CLOK,RPOK,CLKO,RPKO,CANCEL,REALIZADA}
function viewEntregaStatus(uint numEnt) public view returns(string memory){
require(numEnt > 0 && numEnt <= numCalculado,"El Numero de entrega no es correcto");
if (mapEntrega[numEnt].status == Status.ACCEPTED){
return ACCEPTED;
}else if(mapEntrega[numEnt].status == Status.READY){
return READY;
}else if(mapEntrega[numEnt].status == Status.CLOK){
return CLOK;
}else if(mapEntrega[numEnt].status == Status.RPOK){
return RPOK;
}else if(mapEntrega[numEnt].status == Status.CLKO){
return CLKO;
}else if(mapEntrega[numEnt].status == Status.RPKO){
return RPKO;
}else if(mapEntrega[numEnt].status == Status.CANCEL){
return CANCEL;
}else{
return REALIZADA;
}
}
}