github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/examples/student/student.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "github.com/inklabsfoundation/inkchain/core/chaincode/shim" 6 pb "github.com/inklabsfoundation/inkchain/protos/peer" 7 "strings" 8 "strconv" 9 "encoding/json" 10 ) 11 12 const ( 13 SCHOOL_TYPE_FULL_TIME = 1 14 SCHOOL_TYPE_PART_TIME = 2 15 SEX_MALE = 1 16 SEX_FAMEL = 2 17 SCHOOL_PREFIX = "school" 18 STUDENT_PREFIX = "student" 19 ) 20 21 const ( 22 SPECIALTY_DEGREE = iota 23 BACHELOR_DEGREE 24 MASTER_DEGREE 25 DOCTOR_DEGREE 26 ) 27 28 const ( 29 STUDY_LOG_KEY = "studyLog" 30 GRADUATION_LOG_KEY = "graduationLog" 31 ) 32 33 type School struct { 34 Number string `json:"number"` //school number 35 Name string `json:"name"` //school name 36 Address string `json:"address"` //school address 37 CreateAt string `json:"createAt"` //school create date 38 Manager string `json:"manager"` //school manager 39 SchoolLevel int `json:"schoolLevel"` //school level 40 RegisterTime string `json:"registerTime"` 41 } 42 43 type Student struct { 44 Number string `json:"number"` //personal card number 45 StudentNumber string `json:"studentNumber"` //student number 46 Name string `json:"name"` //student name 47 Age int `json:"age"` //student age 48 Sex int `json:"sex"` //student sex 49 Credit int `json:"credit"` //academic credit number 50 Grade string `json:"grade"` //student grade 51 Class string `json:"class"` //student class 52 CurrentSchool string `json:"currentSchool"` //student current school 53 CurrentSchoolName string `json:"currentSchoolName"` //student current school name 54 CurrentLevel int `json:"currentLevel"` //student current level 55 AdmissionTime string `json:"admissionTime"` //student admission time 56 GraduationSchool string `json:"graduationSchool"` //graduation school number 57 GraduationSchoolName string `json:"graduationSchoolName"` //graduation school name 58 GraduationTime string `json:"graduationTime"` //student graduation time 59 GraduationLevel int `json:"graduationLevel"` //student graduation level 60 RegisterTime string `json:"registerTime"` 61 } 62 63 type StudyLog struct { 64 SchoolName string `json:"schoolName"` //study school name 65 SchoolNumber string `json:"schoolNumber"` //study school number 66 StudentName string `json:"studentName"` //student name 67 StudentNumber string `json:"studentNumber"` //student number 68 Level int `json:"level"` //student study level 69 Class string `json:"class"` //student study class 70 Grade string `json:"grade"` //student study grade 71 DateTime string `json:"dateTime"` 72 } 73 74 type GraduationInfo struct { 75 SchoolName string `json:"schoolName"` //school name 76 SchoolNumber string `json:"schoolNumber"` //school number 77 StudentName string `json:"studentName"` //student name 78 StudentNumber string `json:"studentNumber"` //student number 79 GraduationLevel int `json:"graduationLevel"` //student graduation level 80 Description string `json:"description"` //description 81 Class string `json:"class"` //student class 82 Grade string `json:"grade"` //student grade 83 Credit string `json:"credit"` //credit number 84 DateTime string `json:"dateTime"` 85 } 86 87 const ( 88 RegisterSchool = "registerSchool" 89 RegisterStudent = "registerStudent" 90 Enrolment = "enrolment" 91 Graduate = "graduate" 92 QuerySchoolInfo = "querySchoolInfo" 93 QueryStudentInfo = "queryStudentInfo" 94 QueryStudentStudyLog = "queryStudentStudyLog" 95 QueryStudentGraduationLog = "queryStudentGraduationLog" 96 ) 97 98 type StudentChaincode struct { 99 } 100 101 func (s *StudentChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { 102 return shim.Success(nil) 103 } 104 105 func (s *StudentChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { 106 function, args := stub.GetFunctionAndParameters() 107 switch function { 108 case RegisterSchool: 109 if len(args) < 4 { 110 return shim.Error("RegisterSchool, Incorrect number of arguments. Expecting 4") 111 } 112 return s.registerSchool(stub, args) 113 case RegisterStudent: 114 if len(args) < 4 { 115 return shim.Error("RegisterStudent, Incorrect number of arguments. Expecting 3") 116 } 117 return s.registerStudent(stub, args) 118 case Enrolment: 119 if len(args) < 6 { 120 return shim.Error("Enrolment, Incorrect number of arguments. Expecting 6") 121 } 122 return s.enrolment(stub, args) 123 case Graduate: 124 if len(args) < 5 { 125 return shim.Error("Graduate, Incorrect number of arguments. Expecting 5") 126 } 127 return s.graduate(stub, args) 128 case QuerySchoolInfo: 129 if len(args) < 1 { 130 return shim.Error("QuerySchoolInfo, Incorrect number of arguments. Expecting 1") 131 } 132 return s.querySchoolInfo(stub, args) 133 case QueryStudentInfo: 134 if len(args) < 1 { 135 return shim.Error("QueryStudentInfo, Incorrect number of arguments. Expecting 1") 136 } 137 return s.queryStudentInfo(stub, args) 138 case QueryStudentStudyLog: 139 if len(args) < 1 { 140 return shim.Error("QueryStudentStudyLog, Incorrect number of arguments. At least 1") 141 } 142 return s.queryStudentStudyLog(stub, args) 143 case QueryStudentGraduationLog: 144 if len(args) < 1 { 145 return shim.Error("QueryStudentGraduationLog, Incorrect number of arguments. At least 1") 146 } 147 return s.queryStudentGraduationLog(stub, args) 148 } 149 return shim.Error("Function not found") 150 } 151 152 //school register 153 func (s *StudentChaincode) registerSchool(stub shim.ChaincodeStubInterface, args []string) pb.Response { 154 //get transaction time 155 timeStamp, err := stub.GetTxTimestamp() 156 if err != nil { 157 return shim.Error("Failed to get transaction timestamp : " + err.Error()) 158 } 159 registerTime := fmt.Sprintf("%d", timeStamp.GetSeconds()) 160 //get sender 161 sender, err := stub.GetSender() 162 if err != nil { 163 return shim.Error("Failed to get sender info : " + err.Error()) 164 } 165 //validate args 166 number := strings.TrimSpace(strings.ToLower(args[0])) 167 if len(number) <= 0 { 168 return shim.Error("1st arg must be non-empty string") 169 } 170 name := strings.TrimSpace(strings.ToLower(args[1])) 171 if len(name) <= 0 { 172 return shim.Error("2st arg must be non-empty string") 173 } 174 address := strings.TrimSpace(strings.ToLower(args[2])) 175 if len(address) <= 0 { 176 return shim.Error("3st arg must be non-empty string") 177 } 178 level, err := strconv.Atoi(args[3]) 179 if err != nil { 180 return shim.Error("3st arg failed to parse int : " + err.Error()) 181 } 182 if level != SCHOOL_TYPE_FULL_TIME && level != SCHOOL_TYPE_PART_TIME { 183 return shim.Error("3st arg must be 1 or 2") 184 } 185 createTime := strings.TrimSpace(strings.ToLower(args[4])) 186 if len(createTime) <= 0 { 187 return shim.Error("4st arg must be non-empty string") 188 } 189 //build school record 190 school := &School{ 191 Number: number, 192 Name: name, 193 Address: address, 194 SchoolLevel: level, 195 Manager: sender, 196 CreateAt: createTime, 197 RegisterTime: registerTime, 198 } 199 schoolKey := SCHOOL_PREFIX + number 200 //validate school exists 201 old, err := stub.GetState(schoolKey) 202 if err != nil { 203 return shim.Error("Failed to check school info : " + err.Error()) 204 } else if old != nil { 205 return shim.Error("School exists") 206 } 207 //marshal to json 208 schoolJson, err := json.Marshal(school) 209 if err != nil { 210 return shim.Error("Failed to marshal school : " + err.Error()) 211 } 212 err = stub.PutState(schoolKey, schoolJson) 213 if err != nil { 214 return shim.Error("Failed to save school data : " + err.Error()) 215 } 216 return shim.Success(nil) 217 } 218 219 //student register 220 func (s *StudentChaincode) registerStudent(stub shim.ChaincodeStubInterface, args []string) pb.Response { 221 //get transaction time 222 timeStamp, err := stub.GetTxTimestamp() 223 if err != nil { 224 return shim.Error("Failed to get transaction timestamp : " + err.Error()) 225 } 226 registerTime := fmt.Sprintf("%d", timeStamp.GetSeconds()) 227 //get sender 228 sender, err := stub.GetSender() 229 if err != nil { 230 return shim.Error("Failed to get sender info : " + err.Error()) 231 } 232 //validate args 233 number := strings.TrimSpace(strings.ToLower(args[0])) 234 if len(number) <= 0 { 235 return shim.Error("1st arg must be non-empty") 236 } 237 name := strings.TrimSpace(strings.ToLower(args[1])) 238 if len(name) <= 0 { 239 return shim.Error("2st arg must be non-empty") 240 } 241 age, err := strconv.Atoi(args[2]) 242 if err != nil { 243 return shim.Error("3st arg parse to int failed : " + err.Error()) 244 } 245 if age <= 0 { 246 return shim.Error("3st arg must be more than 0") 247 } 248 sex, err := strconv.Atoi(args[3]) 249 if err != nil { 250 return shim.Error("4st arg parse to int failed : " + err.Error()) 251 } 252 if sex != SEX_FAMEL && sex != SEX_MALE { 253 return shim.Error("4st arg must be 0 or 1") 254 } 255 //build student struct 256 student := &Student{ 257 Number: number, 258 Name: name, 259 Age: age, 260 Sex: sex, 261 RegisterTime: registerTime, 262 } 263 //check sender exists 264 studentKey := STUDENT_PREFIX + sender 265 old, err := stub.GetState(studentKey) 266 if err != nil { 267 return shim.Error("Failed to validate sender register status : " + err.Error()) 268 } else if old != nil { 269 return shim.Error("Sender has registered") 270 } 271 //marshal json 272 studentJson, err := json.Marshal(student) 273 if err != nil { 274 return shim.Error("Marshal student info error : " + err.Error()) 275 } 276 err = stub.PutState(studentKey, studentJson) 277 if err != nil { 278 return shim.Error("Failed to save student info : " + err.Error()) 279 } 280 return shim.Success(nil) 281 } 282 283 //student enrolment 284 func (s *StudentChaincode) enrolment(stub shim.ChaincodeStubInterface, args []string) pb.Response { 285 //get transaction time 286 timeStamp, err := stub.GetTxTimestamp() 287 if err != nil { 288 return shim.Error("Failed to get transaction timestamp : " + err.Error()) 289 } 290 admissionTime := fmt.Sprintf("%d", timeStamp.GetSeconds()) 291 //get sender 292 sender, err := stub.GetSender() 293 if err != nil { 294 return shim.Error("Failed to get sender info : " + err.Error()) 295 } 296 //validate args 297 schoolNumber := strings.TrimSpace(strings.ToLower(args[0])) 298 if len(schoolNumber) <= 0 { 299 return shim.Error("1st arg must be non-empty string") 300 } 301 studentAddr := strings.TrimSpace(strings.ToLower(args[1])) 302 if len(studentAddr) <= 0 { 303 return shim.Error("2st arg must be non-empty string") 304 } 305 grade := strings.TrimSpace(strings.ToLower(args[2])) 306 if len(grade) <= 0 { 307 return shim.Error("3st arg must be non-empty string") 308 } 309 class := strings.TrimSpace(strings.ToLower(args[3])) 310 if len(class) <= 0 { 311 return shim.Error("4st arg must be non-empty string") 312 } 313 studentNumber := strings.TrimSpace(strings.ToLower(args[4])) 314 if len(studentNumber) <= 0 { 315 return shim.Error("5st arg must be non-empty string") 316 } 317 level, err := strconv.Atoi(args[5]) 318 if err != nil { 319 return shim.Error("6st parse int failed : " + err.Error()) 320 } 321 if level < SPECIALTY_DEGREE && level > DOCTOR_DEGREE { 322 return shim.Error("6st must be 0 , 1 , 2 , 3") 323 } 324 //check school info 325 schoolJson, err := stub.GetState(SCHOOL_PREFIX + schoolNumber) 326 if err != nil { 327 return shim.Error("Failed to get school info : " + err.Error()) 328 } else if schoolJson == nil { 329 return shim.Error("School not exists") 330 } 331 //unmarshal school info 332 school := &School{} 333 err = json.Unmarshal(schoolJson, school) 334 if err != nil { 335 return shim.Error("Failed unmarshal school info : " + err.Error()) 336 } 337 //check sender 338 if school.Manager != sender { 339 return shim.Error("Authority failed") 340 } 341 //check student info 342 studentKey := STUDENT_PREFIX + studentAddr 343 studentJson, err := stub.GetState(studentKey) 344 if err != nil { 345 return shim.Error("Failed to get student info : " + err.Error()) 346 } else if studentJson == nil { 347 return shim.Error("Student not exists") 348 } 349 //unmarshal student info 350 student := &Student{} 351 err = json.Unmarshal(studentJson, student) 352 if err != nil { 353 return shim.Error("Failed unmarshal student info : " + err.Error()) 354 } 355 if student.CurrentSchool != "" { 356 return shim.Error("Student has study at another school") 357 } 358 //update school info 359 student.StudentNumber = studentNumber 360 student.CurrentSchool = schoolNumber 361 student.CurrentSchoolName = school.Name 362 student.AdmissionTime = admissionTime 363 student.Class = class 364 student.Grade = grade 365 student.CurrentLevel = level 366 studentJson, err = json.Marshal(student) 367 if err != nil { 368 return shim.Error("Marshal student info to json failed : " + err.Error()) 369 } 370 //update student info 371 err = stub.PutState(studentKey, studentJson) 372 if err != nil { 373 return shim.Error("Failed to save student info : " + err.Error()) 374 } 375 //save study log 376 err = s.saveStudyLog(stub, student, school, admissionTime) 377 if err != nil { 378 return shim.Error("Failed to save study log : " + err.Error()) 379 } 380 return shim.Success(nil) 381 } 382 383 //student graduate 384 func (s *StudentChaincode) graduate(stub shim.ChaincodeStubInterface, args []string) pb.Response { 385 //get transaction time 386 timeStamp, err := stub.GetTxTimestamp() 387 if err != nil { 388 return shim.Error("Failed to get transaction timestamp : " + err.Error()) 389 } 390 graduateTime := fmt.Sprintf("%d", timeStamp.GetSeconds()) 391 //get sender 392 sender, err := stub.GetSender() 393 if err != nil { 394 return shim.Error("Failed to get sender info : " + err.Error()) 395 } 396 //check args 397 schoolNumber := strings.TrimSpace(strings.ToLower(args[0])) 398 if len(schoolNumber) <= 0 { 399 return shim.Error("1st arg must be non-empty string") 400 } 401 studentAddr := strings.TrimSpace(strings.ToLower(args[1])) 402 if len(studentAddr) <= 0 { 403 return shim.Error("2st arg must be non-empty string") 404 } 405 description := strings.TrimSpace(strings.ToLower(args[2])) 406 if len(description) <= 0 { 407 return shim.Error("3st arg must be non-empty string") 408 } 409 creditNum := strings.TrimSpace(strings.ToLower(args[3])) 410 if len(creditNum) <= 0 { 411 return shim.Error("4st arg must be non-empty string") 412 } 413 credit, err := strconv.Atoi(args[4]) 414 if err != nil { 415 return shim.Error("5st arg parse int failed : " + err.Error()) 416 } 417 if credit <= 0 { 418 return shim.Error("5st arg must be more than 0") 419 } 420 //check school 421 schoolJson, err := stub.GetState(SCHOOL_PREFIX + schoolNumber) 422 if err != nil { 423 return shim.Error("Failed to get school info : " + err.Error()) 424 } 425 school := &School{} 426 err = json.Unmarshal(schoolJson, school) 427 if err != nil { 428 return shim.Error("Unmarshal school info failed : " + err.Error()) 429 } 430 //check sender 431 if school.Manager != sender { 432 return shim.Error("Authority failed") 433 } 434 //check student info 435 studentKey := STUDENT_PREFIX + studentAddr 436 studentJson, err := stub.GetState(studentKey) 437 if err != nil { 438 return shim.Error("Failed to get student info : " + err.Error()) 439 } 440 student := &Student{} 441 err = json.Unmarshal(studentJson, student) 442 if err != nil { 443 return shim.Error("Unmarshal student info error : " + err.Error()) 444 } 445 if student.CurrentSchool != school.Number { 446 return shim.Error("Student not study at your school") 447 } 448 //update student info 449 student.GraduationLevel = student.CurrentLevel 450 student.GraduationSchool = school.Number 451 student.GraduationSchoolName = school.Name 452 student.GraduationTime = graduateTime 453 student.Credit = credit 454 student.CurrentSchool = "" 455 studentJson, err = json.Marshal(student) 456 if err != nil { 457 return shim.Error("Student marshal to json failed : " + err.Error()) 458 } 459 //update student state 460 err = stub.PutState(studentKey, studentJson) 461 if err != nil { 462 return shim.Error("Failed to update student info : " + err.Error()) 463 } 464 //save graduate log 465 err = s.saveGraduateLog(stub, school, student, description, creditNum) 466 if err != nil { 467 return shim.Error("Failed to save graduate log : " + err.Error()) 468 } 469 return shim.Success(nil) 470 } 471 472 //query school info 473 func (s *StudentChaincode) querySchoolInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response { 474 number := strings.TrimSpace(strings.ToLower(args[0])) 475 if len(number) <= 0 { 476 return shim.Error("1st arg must be non-empty string") 477 } 478 schoolKey := SCHOOL_PREFIX + number 479 schoolJson, err := stub.GetState(schoolKey) 480 if err != nil { 481 return shim.Error("Failed to get school info : " + err.Error()) 482 } else if schoolJson == nil { 483 return shim.Error("School not exists") 484 } 485 return shim.Success(schoolJson) 486 } 487 488 //query student info 489 func (s *StudentChaincode) queryStudentInfo(stub shim.ChaincodeStubInterface, args []string) pb.Response { 490 //check args 491 studentAddr := strings.TrimSpace(strings.ToLower(args[0])) 492 if len(studentAddr) <= 0 { 493 return shim.Error("1st arg must be non-empty string") 494 } 495 //get student info 496 studentKey := STUDENT_PREFIX + studentAddr 497 studentJson, err := stub.GetState(studentKey) 498 if err != nil { 499 return shim.Error("Failed to get student info : " + err.Error()) 500 } else if studentJson == nil { 501 return shim.Error("Student not exists") 502 } 503 //unmarshal student info 504 student := &Student{} 505 err = json.Unmarshal(studentJson, student) 506 if err != nil { 507 return shim.Error("Failed to unmarshal student info : " + err.Error()) 508 } 509 result := map[string]interface{}{ 510 "studentInfo": student, 511 } 512 //get study log 513 studentStudyLog, err := s.getStudentStudyLog(stub, []string{student.StudentNumber}) 514 if err == nil { 515 result["studyLog"] = studentStudyLog 516 } 517 //get graduation info log 518 graduationInfoLog, err := s.getStudentGraduationLog(stub, []string{student.StudentNumber}) 519 if err == nil { 520 result["graduationLog"] = graduationInfoLog 521 } 522 //marshal result 523 resultJson, err := json.Marshal(result) 524 if err != nil { 525 return shim.Error("Failed to marshal result : " + err.Error()) 526 } 527 return shim.Success(resultJson) 528 } 529 530 //query student study log 531 func (s *StudentChaincode) queryStudentStudyLog(stub shim.ChaincodeStubInterface, args []string) pb.Response { 532 studentAddr := strings.TrimSpace(strings.ToLower(args[0])) 533 if len(studentAddr) <= 0 { 534 return shim.Error("1st arg must be non-empty string") 535 } 536 studentJson, err := stub.GetState(STUDENT_PREFIX + studentAddr) 537 if err != nil { 538 return shim.Error("Failed to get student info : " + err.Error()) 539 } else if studentJson == nil { 540 return shim.Error("Student not exists") 541 } 542 student := &Student{} 543 err = json.Unmarshal(studentJson, student) 544 if err != nil { 545 return shim.Error("Unmarshal student info failed : " + err.Error()) 546 } 547 keyArg := []string{student.StudentNumber} 548 549 if len(args)>1 { 550 schoolNumber := strings.TrimSpace(strings.ToLower(args[1])) 551 if len(schoolNumber)>0{ 552 keyArg = append(keyArg, schoolNumber) 553 }else{ 554 return shim.Error("1st arg must be non-empty string") 555 } 556 } 557 result, err := s.getStudentStudyLog(stub, keyArg) 558 if err != nil { 559 return shim.Error("Failed to get student study log : " + err.Error()) 560 } 561 resultJson, err := json.Marshal(result) 562 if err != nil { 563 return shim.Error("Failed to marshal result : " + err.Error()) 564 } 565 return shim.Success(resultJson) 566 } 567 568 //query student graduation log 569 func (s *StudentChaincode) queryStudentGraduationLog(stub shim.ChaincodeStubInterface, args []string) pb.Response { 570 studentAddr := strings.TrimSpace(strings.ToLower(args[0])) 571 if len(studentAddr) <= 0 { 572 return shim.Error("1st arg must be non-empty string") 573 } 574 studentJson, err := stub.GetState(STUDENT_PREFIX + studentAddr) 575 if err != nil { 576 return shim.Error("Failed to get student info : " + err.Error()) 577 } else if studentJson == nil { 578 return shim.Error("Student not exists") 579 } 580 student := &Student{} 581 err = json.Unmarshal(studentJson, student) 582 if err != nil { 583 return shim.Error("Unmarshal student info failed : " + err.Error()) 584 } 585 keyArg := []string{student.StudentNumber} 586 if len(args)>1 { 587 schoolNumber := strings.TrimSpace(strings.ToLower(args[1])) 588 if len(schoolNumber)>0{ 589 keyArg = append(keyArg, schoolNumber) 590 }else{ 591 return shim.Error("1st arg must be non-empty string") 592 } 593 } 594 result, err := s.getStudentGraduationLog(stub, keyArg) 595 if err != nil { 596 return shim.Error("Failed to get student study log : " + err.Error()) 597 } 598 resultJson, err := json.Marshal(result) 599 if err != nil { 600 return shim.Error("Failed to marshal result : " + err.Error()) 601 } 602 return shim.Success(resultJson) 603 } 604 605 //get student study log 606 func (s *StudentChaincode) getStudentStudyLog(stub shim.ChaincodeStubInterface, keyArg []string) ([]StudyLog, error) { 607 //get study log key 608 resultsIterator, err := stub.GetStateByPartialCompositeKey(STUDY_LOG_KEY, keyArg) 609 if err != nil { 610 return nil, err 611 } 612 defer resultsIterator.Close() 613 resultList := make([]StudyLog, 0) 614 for i := 0; resultsIterator.HasNext(); i++ { 615 responseRange, err := resultsIterator.Next() 616 if err != nil { 617 return nil, err 618 } 619 value := responseRange.Value 620 tmp := StudyLog{} 621 err = json.Unmarshal(value, &tmp) 622 if err == nil { 623 resultList = append(resultList, tmp) 624 } 625 } 626 return resultList, nil 627 } 628 629 //get student graduation log 630 func (s *StudentChaincode) getStudentGraduationLog(stub shim.ChaincodeStubInterface, keyArg []string) ([]GraduationInfo, error) { 631 //get graduation key 632 resultsIterator, err := stub.GetStateByPartialCompositeKey(GRADUATION_LOG_KEY, keyArg) 633 if err != nil { 634 return nil, err 635 } 636 defer resultsIterator.Close() 637 resultList := make([]GraduationInfo, 0) 638 for i := 0; resultsIterator.HasNext(); i++ { 639 responseRange, err := resultsIterator.Next() 640 if err != nil { 641 return nil, err 642 } 643 value := responseRange.Value 644 tmp := GraduationInfo{} 645 err = json.Unmarshal(value, &tmp) 646 if err == nil { 647 resultList = append(resultList, tmp) 648 } 649 } 650 return resultList, nil 651 } 652 653 //save study log 654 func (s *StudentChaincode) saveStudyLog(stub shim.ChaincodeStubInterface, student *Student, school *School, enrolTime string) error { 655 log := &StudyLog{ 656 SchoolName: school.Name, 657 SchoolNumber: school.Number, 658 StudentName: student.Name, 659 StudentNumber: student.StudentNumber, 660 Level: student.CurrentLevel, 661 Class: student.Class, 662 Grade: student.Grade, 663 DateTime: enrolTime, 664 } 665 //marshal study log data 666 logJson, err := json.Marshal(log) 667 if err != nil { 668 return err 669 } 670 //create composite key 671 compositeKey, err := stub.CreateCompositeKey(STUDY_LOG_KEY, []string{student.StudentNumber, school.Number, enrolTime}) 672 if err != nil { 673 return err 674 } 675 err = stub.PutState(compositeKey, logJson) 676 if err != nil { 677 return err 678 } 679 return nil 680 } 681 682 //save graduate log 683 func (s *StudentChaincode) saveGraduateLog(stub shim.ChaincodeStubInterface, school *School, student *Student, description string, creditNumber string) error { 684 graduateLog := &GraduationInfo{ 685 SchoolNumber: school.Number, 686 SchoolName: school.Name, 687 StudentNumber: student.StudentNumber, 688 StudentName: student.Name, 689 GraduationLevel: student.CurrentLevel, 690 Description: description, 691 Class: student.Class, 692 Grade: student.Grade, 693 Credit: creditNumber, 694 DateTime: student.GraduationTime, 695 } 696 //marshal graduate log data 697 graduationJson, err := json.Marshal(graduateLog) 698 if err != nil { 699 return err 700 } 701 //create composite key 702 compositeKey, err := stub.CreateCompositeKey(GRADUATION_LOG_KEY, []string{student.StudentNumber, school.Number, student.GraduationTime}) 703 if err != nil { 704 return err 705 } 706 err = stub.PutState(compositeKey, graduationJson) 707 if err != nil { 708 return err 709 } 710 return nil 711 } 712 713 func main() { 714 err := shim.Start(new(StudentChaincode)) 715 if err == nil { 716 fmt.Printf("Error starting WorkChaincode: %s", err) 717 } 718 }