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  }