github.com/s7techlab/cckit@v0.10.5/examples/insurance/app/invoke_insurance.go (about) 1 package app 2 3 import ( 4 "encoding/json" 5 6 "strings" 7 8 "time" 9 10 "github.com/hyperledger/fabric-chaincode-go/shim" 11 pb "github.com/hyperledger/fabric-protos-go/peer" 12 ) 13 14 func listContractTypes(stub shim.ChaincodeStubInterface, args []string) pb.Response { 15 callingAsMerchant := len(args) == 1 16 input := struct { 17 ShopType string `json:"shop_type"` 18 }{} 19 if callingAsMerchant { 20 err := json.Unmarshal([]byte(args[0]), &input) 21 if err != nil { 22 return shim.Error(err.Error()) 23 } 24 } 25 26 resultsIterator, err := stub.GetStateByPartialCompositeKey(prefixContractType, []string{}) 27 if err != nil { 28 return shim.Error(err.Error()) 29 } 30 defer resultsIterator.Close() 31 32 results := []interface{}{} 33 for resultsIterator.HasNext() { 34 kvResult, err := resultsIterator.Next() 35 if err != nil { 36 return shim.Error(err.Error()) 37 } 38 39 ct := struct { 40 UUID string `json:"uuid"` 41 *ContractType 42 }{} 43 err = json.Unmarshal(kvResult.Value, &ct) 44 if err != nil { 45 return shim.Error(err.Error()) 46 } 47 prefix, keyParts, err := stub.SplitCompositeKey(kvResult.Key) 48 if err != nil { 49 return shim.Error(err.Error()) 50 } 51 if len(keyParts) > 0 { 52 ct.UUID = keyParts[0] 53 } else { 54 ct.UUID = prefix 55 } 56 57 // Apply proper filtering, merchants should only see active contracts 58 if !callingAsMerchant || 59 (strings.Contains(strings.ToTitle(ct.ShopType), strings.ToTitle(input.ShopType)) && ct.Active) { 60 results = append(results, ct) 61 } 62 } 63 64 returnBytes, err := json.Marshal(results) 65 return shim.Success(returnBytes) 66 } 67 68 func createContractType(stub shim.ChaincodeStubInterface, args []string) pb.Response { 69 if len(args) != 1 { 70 return shim.Error("Invalid argument count.") 71 } 72 73 partial := struct { 74 UUID string `json:"uuid"` 75 }{} 76 ct := ContractType{} 77 78 err := json.Unmarshal([]byte(args[0]), &partial) 79 if err != nil { 80 return shim.Error(err.Error()) 81 } 82 83 err = json.Unmarshal([]byte(args[0]), &ct) 84 if err != nil { 85 return shim.Error(err.Error()) 86 } 87 88 key, err := stub.CreateCompositeKey(prefixContractType, []string{partial.UUID}) 89 if err != nil { 90 return shim.Error(err.Error()) 91 } 92 93 value, err := json.Marshal(ct) 94 if err != nil { 95 return shim.Error(err.Error()) 96 } 97 98 err = stub.PutState(key, value) 99 if err != nil { 100 return shim.Error(err.Error()) 101 } 102 103 return shim.Success(nil) 104 } 105 106 func setActiveContractType(stub shim.ChaincodeStubInterface, args []string) pb.Response { 107 if len(args) != 1 { 108 return shim.Error("Invalid argument count.") 109 } 110 111 req := struct { 112 UUID string `json:"uuid"` 113 Active bool `json:"active"` 114 }{} 115 ct := ContractType{} 116 117 err := json.Unmarshal([]byte(args[0]), &req) 118 if err != nil { 119 return shim.Error(err.Error()) 120 } 121 122 key, err := stub.CreateCompositeKey(prefixContractType, []string{req.UUID}) 123 if err != nil { 124 return shim.Error(err.Error()) 125 } 126 127 valAsBytes, err := stub.GetState(key) 128 if err != nil { 129 return shim.Error(err.Error()) 130 } 131 if len(valAsBytes) == 0 { 132 return shim.Error("Contract Type could not be found") 133 } 134 err = json.Unmarshal(valAsBytes, &ct) 135 if err != nil { 136 return shim.Error(err.Error()) 137 } 138 139 ct.Active = req.Active 140 141 valAsBytes, err = json.Marshal(ct) 142 if err != nil { 143 return shim.Error(err.Error()) 144 } 145 146 err = stub.PutState(key, valAsBytes) 147 if err != nil { 148 return shim.Error(err.Error()) 149 } 150 151 return shim.Success(nil) 152 } 153 154 func listContracts(stub shim.ChaincodeStubInterface, args []string) pb.Response { 155 input := struct { 156 Username string `json:"username"` 157 }{} 158 if len(args) == 1 { 159 err := json.Unmarshal([]byte(args[0]), &input) 160 if err != nil { 161 return shim.Error(err.Error()) 162 } 163 } 164 filterByUsername := len(input.Username) > 0 165 166 var resultsIterator shim.StateQueryIteratorInterface 167 var err error 168 // Filtering by username if required 169 if filterByUsername { 170 resultsIterator, err = stub.GetStateByPartialCompositeKey(prefixContract, []string{input.Username}) 171 } else { 172 resultsIterator, err = stub.GetStateByPartialCompositeKey(prefixContract, []string{}) 173 } 174 if err != nil { 175 return shim.Error(err.Error()) 176 } 177 defer resultsIterator.Close() 178 179 results := []interface{}{} 180 // Iterate over the results 181 for resultsIterator.HasNext() { 182 kvResult, err := resultsIterator.Next() 183 if err != nil { 184 return shim.Error(err.Error()) 185 } 186 187 // Construct response struct 188 result := struct { 189 UUID string `json:"uuid"` 190 *Contract 191 Claims []Claim `json:"claims,omitempty"` 192 }{} 193 194 err = json.Unmarshal(kvResult.Value, &result) 195 if err != nil { 196 return shim.Error(err.Error()) 197 } 198 199 // Fetch key 200 prefix, keyParts, err := stub.SplitCompositeKey(kvResult.Key) 201 if len(keyParts) == 2 { 202 result.UUID = keyParts[1] 203 } else { 204 result.UUID = prefix 205 } 206 207 // Fetch the claims, if the the username parameter is specified 208 if len(input.Username) > 0 { 209 result.Claims, err = result.Contract.Claims(stub) 210 if err != nil { 211 return shim.Error(err.Error()) 212 } 213 } 214 result.ClaimIndex = []string{} // Remove internal data 215 results = append(results, result) 216 } 217 218 resultsAsBytes, err := json.Marshal(results) 219 if err != nil { 220 return shim.Error(err.Error()) 221 } 222 return shim.Success(resultsAsBytes) 223 } 224 225 func listClaims(stub shim.ChaincodeStubInterface, args []string) pb.Response { 226 var status ClaimStatus 227 if len(args) > 0 { 228 input := struct { 229 Status ClaimStatus `json:"status"` 230 }{} 231 err := json.Unmarshal([]byte(args[0]), &input) 232 if err != nil { 233 return shim.Error(err.Error()) 234 } 235 status = input.Status 236 } 237 238 results := []interface{}{} 239 resultsIterator, err := stub.GetStateByPartialCompositeKey(prefixClaim, []string{}) 240 if err != nil { 241 return shim.Error(err.Error()) 242 } 243 defer resultsIterator.Close() 244 245 for resultsIterator.HasNext() { 246 kvResult, err := resultsIterator.Next() 247 if err != nil { 248 return shim.Error(err.Error()) 249 } 250 251 result := struct { 252 UUID string `json:"uuid"` 253 *Claim 254 }{} 255 err = json.Unmarshal(kvResult.Value, &result) 256 if err != nil { 257 return shim.Error(err.Error()) 258 } 259 260 // Skip the processing of the result, if the status 261 // does not equal the query status; list all, if unknown 262 if result.Status != status && status != ClaimStatusUnknown { 263 continue 264 } 265 266 // Fetch key 267 prefix, keyParts, err := stub.SplitCompositeKey(kvResult.Key) 268 if len(keyParts) < 2 { 269 result.UUID = prefix 270 } else { 271 result.UUID = keyParts[1] 272 } 273 274 results = append(results, result) 275 } 276 277 claimsAsBytes, err := json.Marshal(results) 278 if err != nil { 279 return shim.Error(err.Error()) 280 } 281 return shim.Success(claimsAsBytes) 282 } 283 284 func fileClaim(stub shim.ChaincodeStubInterface, args []string) pb.Response { 285 if len(args) != 1 { 286 return shim.Error("Invalid argument count.") 287 } 288 289 dto := struct { 290 UUID string `json:"uuid"` 291 ContractUUID string `json:"contract_uuid"` 292 Date time.Time `json:"date"` 293 Description string `json:"description"` 294 IsTheft bool `json:"is_theft"` 295 }{} 296 err := json.Unmarshal([]byte(args[0]), &dto) 297 if err != nil { 298 return shim.Error(err.Error()) 299 } 300 301 claim := Claim{ 302 ContractUUID: dto.ContractUUID, 303 Date: dto.Date, 304 Description: dto.Description, 305 IsTheft: dto.IsTheft, 306 Status: ClaimStatusNew, 307 } 308 309 // Check if the contract exists 310 contract, err := claim.Contract(stub) 311 if err != nil { 312 return shim.Error(err.Error()) 313 } 314 if contract == nil { 315 return shim.Error("Contract could not be found.") 316 } 317 318 // Persist the claim 319 claimKey, err := stub.CreateCompositeKey(prefixClaim, 320 []string{dto.ContractUUID, dto.UUID}) 321 if err != nil { 322 return shim.Error(err.Error()) 323 } 324 claimBytes, err := json.Marshal(claim) 325 if err != nil { 326 return shim.Error(err.Error()) 327 } 328 329 err = stub.PutState(claimKey, claimBytes) 330 if err != nil { 331 return shim.Error(err.Error()) 332 } 333 334 // Update the claim index in the contract 335 contract.ClaimIndex = append(contract.ClaimIndex, claimKey) 336 contractKey, err := stub.CreateCompositeKey(prefixContract, 337 []string{contract.Username, claim.ContractUUID}) 338 339 if err != nil { 340 return shim.Error(err.Error()) 341 } 342 contractBytes, err := json.Marshal(contract) 343 if err != nil { 344 return shim.Error(err.Error()) 345 } 346 stub.PutState(contractKey, contractBytes) 347 if err != nil { 348 return shim.Error(err.Error()) 349 } 350 351 return shim.Success(nil) 352 } 353 354 func processClaim(stub shim.ChaincodeStubInterface, args []string) pb.Response { 355 if len(args) != 1 { 356 return shim.Error("Invalid argument count.") 357 } 358 359 input := struct { 360 UUID string `json:"uuid"` 361 ContractUUID string `json:"contract_uuid"` 362 Status ClaimStatus `json:"status"` 363 Reimbursable float32 `json:"reimbursable"` 364 }{} 365 err := json.Unmarshal([]byte(args[0]), &input) 366 if err != nil { 367 return shim.Error(err.Error()) 368 } 369 370 claimKey, err := stub.CreateCompositeKey(prefixClaim, []string{input.ContractUUID, input.UUID}) 371 if err != nil { 372 return shim.Error(err.Error()) 373 } 374 375 claimBytes, _ := stub.GetState(claimKey) 376 if len(claimBytes) == 0 { 377 return shim.Error("Claim cannot be found.") 378 } 379 380 claim := Claim{} 381 err = json.Unmarshal(claimBytes, &claim) 382 if err != nil { 383 return shim.Error(err.Error()) 384 } 385 386 if !claim.IsTheft && claim.Status != ClaimStatusNew { 387 // Check if altering claim is allowed 388 return shim.Error("Cannot change the status of a non-new claim.") 389 } 390 if claim.IsTheft && claim.Status == ClaimStatusNew { 391 return shim.Error("Theft must first be confirmed by authorities.") 392 } 393 394 claim.Status = input.Status // Assigning requested status 395 switch input.Status { 396 case ClaimStatusRepair: 397 // Approve and create a repair order 398 if claim.IsTheft { 399 return shim.Error("Cannot repair stolen items.") 400 } 401 claim.Reimbursable = 0 402 403 contract, err := claim.Contract(stub) 404 if err != nil { 405 return shim.Error(err.Error()) 406 } 407 // Create new repair order 408 repairOrder := RepairOrder{ 409 Item: contract.Item, 410 ClaimUUID: input.UUID, 411 ContractUUID: input.ContractUUID, 412 Ready: false, 413 } 414 repairOrderKey, err := stub.CreateCompositeKey(prefixRepairOrder, []string{input.UUID}) 415 if err != nil { 416 return shim.Error(err.Error()) 417 } 418 repairOrderBytes, err := json.Marshal(repairOrder) 419 if err != nil { 420 return shim.Error(err.Error()) 421 } 422 err = stub.PutState(repairOrderKey, repairOrderBytes) 423 if err != nil { 424 return shim.Error(err.Error()) 425 } 426 427 case ClaimStatusReimbursement: 428 // Approve reimbursement of item, and add the sum 429 claim.Reimbursable = input.Reimbursable 430 // If theft was involved, mark the contract as void 431 if claim.IsTheft { 432 contract, err := claim.Contract(stub) 433 if err != nil { 434 return shim.Error(err.Error()) 435 } 436 contract.Void = true 437 // Persist contract 438 contractKey, err := stub.CreateCompositeKey( 439 prefixContract, []string{contract.Username, claim.ContractUUID}) 440 if err != nil { 441 return shim.Error(err.Error()) 442 } 443 contractBytes, err := json.Marshal(contract) 444 if err != nil { 445 return shim.Error(err.Error()) 446 } 447 err = stub.PutState(contractKey, contractBytes) 448 if err != nil { 449 return shim.Error(err.Error()) 450 } 451 } 452 453 case ClaimStatusRejected: 454 // Mark as rejected 455 claim.Reimbursable = 0 456 default: 457 return shim.Error("Unknown status change.") 458 } 459 460 // Persist claim 461 claimBytes, err = json.Marshal(claim) 462 if err != nil { 463 return shim.Error(err.Error()) 464 } 465 err = stub.PutState(claimKey, claimBytes) 466 if err != nil { 467 return shim.Error(err.Error()) 468 } 469 470 return shim.Success(nil) 471 } 472 473 func authUser(stub shim.ChaincodeStubInterface, args []string) pb.Response { 474 if len(args) != 1 { 475 return shim.Error("Invalid argument count.") 476 } 477 478 input := struct { 479 Username string `json:"username"` 480 Password string `json:"password"` 481 }{} 482 483 authenticated := false 484 485 err := json.Unmarshal([]byte(args[0]), &input) 486 if err != nil { 487 return shim.Error(err.Error()) 488 } 489 490 userKey, err := stub.CreateCompositeKey(prefixUser, []string{input.Username}) 491 if err != nil { 492 return shim.Error(err.Error()) 493 } 494 userBytes, _ := stub.GetState(userKey) 495 if len(userBytes) == 0 { 496 authenticated = false 497 } else { 498 user := User{} 499 err := json.Unmarshal(userBytes, &user) 500 if err != nil { 501 return shim.Error(err.Error()) 502 } 503 authenticated = user.Password == input.Password 504 } 505 506 authBytes, _ := json.Marshal(authenticated) 507 return shim.Success(authBytes) 508 } 509 510 func getUser(stub shim.ChaincodeStubInterface, args []string) pb.Response { 511 if len(args) != 1 { 512 return shim.Error("Invalid argument count.") 513 } 514 515 input := struct { 516 Username string `json:"username"` 517 }{} 518 519 err := json.Unmarshal([]byte(args[0]), &input) 520 if err != nil { 521 return shim.Error(err.Error()) 522 } 523 524 userKey, err := stub.CreateCompositeKey(prefixUser, []string{input.Username}) 525 if err != nil { 526 return shim.Error(err.Error()) 527 } 528 userBytes, _ := stub.GetState(userKey) 529 if len(userBytes) == 0 { 530 return shim.Success(nil) 531 } 532 533 response := struct { 534 Username string `json:"username"` 535 FirstName string `json:"first_name"` 536 LastName string `json:"last_name"` 537 }{} 538 err = json.Unmarshal(userBytes, &response) 539 if err != nil { 540 return shim.Error(err.Error()) 541 } 542 responseBytes, err := json.Marshal(response) 543 if err != nil { 544 return shim.Error(err.Error()) 545 } 546 return shim.Success(responseBytes) 547 }