diff --git a/build.gradle.kts b/build.gradle.kts index 65b2860..08acfef 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } group = "com.aitrainer" -version = "1.0.40" +version = "1.0.41" java.sourceCompatibility = JavaVersion.VERSION_1_8 repositories { diff --git a/data/db/update_1_0_41.sql b/data/db/update_1_0_41.sql new file mode 100644 index 0000000..1b724e8 --- /dev/null +++ b/data/db/update_1_0_41.sql @@ -0,0 +1,36 @@ +START TRANSACTION; + +ALTER TABLE `customer_training_plan` + ADD COLUMN `active` TINYINT(1) NULL DEFAULT '0' AFTER `date_add`, + ADD COLUMN `status` CHAR(50) NULL DEFAULT NULL AFTER `active`; + +CREATE TABLE `customer_training_plan_exercise` ( + `customer_training_plan_exercise_id` INT(11) NOT NULL AUTO_INCREMENT, + `customer_training_plan_details_id` INT(11) NOT NULL DEFAULT '0', + `customer_id` INT NOT NULL, + `exercise_id` INT(11) NOT NULL DEFAULT '0', + `repeats` INT(11) NOT NULL DEFAULT '0', + `weight` DOUBLE NOT NULL DEFAULT '0', + PRIMARY KEY (`customer_training_plan_exercise_id`) USING BTREE, + INDEX `customer_id` (`customer_id`) +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + +CREATE TABLE `customer_training_plan_details` ( + `customer_training_plan_details_id` INT(11) NOT NULL AUTO_INCREMENT, + `customer_training_plan_id` INT(11) NOT NULL, + `exercise_type_id` INT(11) NOT NULL, + `set` INT(11) NOT NULL, + `repeats` INT(11) NOT NULL, + `weight` DOUBLE NOT NULL DEFAULT '0', + PRIMARY KEY (`customer_training_plan_detail_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + +UPDATE configuration set config_value = "1.0.41", date_change=CURRENT_DATE WHERE config_key = "db_version"; + +COMMIT; diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt index 9fc52d9..b523f37 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt @@ -19,7 +19,7 @@ class CustomerPackageController( private val customerRepository: CustomerReposit private val customerPropertyRepository: CustomerPropertyRepository, private val exerciseResultRepository: ExerciseResultRepository, private val customerActivityRepository: CustomerActivityRepository, - private val customerTrainingPlanRepository: CustomerTrainingPlanRepository + private val customerTrainingPlanRepository: CustomerTrainingPlanRepository, ) { @GetMapping("/app_customer_package/{id}") diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt index 98fc904..019e7af 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanController.kt @@ -1,8 +1,7 @@ package com.aitrainer.api.controller -import com.aitrainer.api.model.CustomerProperty import com.aitrainer.api.model.CustomerTrainingPlan -import com.aitrainer.api.repository.CustomerPropertyRepository +import com.aitrainer.api.model.CustomerTrainingPlanExercise import com.aitrainer.api.repository.CustomerTrainingPlanRepository import org.slf4j.LoggerFactory import org.springframework.http.ResponseEntity @@ -17,7 +16,7 @@ class CustomerTrainingPlanController(private val customerTrainingPlanRepository: @PostMapping("/customer_training_plan") fun createNewCustomerTrainingPlan(@Valid @RequestBody customerTrainingPlan: CustomerTrainingPlan): ResponseEntity { - logger.info("Create customer property: $customerTrainingPlan") + logger.info("Create customer training plan: $customerTrainingPlan") return ResponseEntity.ok().body(customerTrainingPlanRepository.save(customerTrainingPlan)) } diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanExerciseController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanExerciseController.kt new file mode 100644 index 0000000..83dcb60 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerTrainingPlanExerciseController.kt @@ -0,0 +1,31 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerTrainingPlanExercise +import com.aitrainer.api.repository.CustomerTrainingPlanExerciseRepository +import org.slf4j.LoggerFactory +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import javax.validation.Valid + +@RestController +@RequestMapping("/api") +class CustomerTrainingPlanExerciseController(private val customerTrainingPlanExerciseRepository: CustomerTrainingPlanExerciseRepository) { + private val logger = LoggerFactory.getLogger(javaClass) + + @PostMapping("/customer_training_plan_exercise") + fun createNewCustomerTrainingPlanExercise(@Valid @RequestBody customerTrainingPlanExercise: CustomerTrainingPlanExercise): ResponseEntity { + logger.info("Create customer property: $customerTrainingPlanExercise") + return ResponseEntity.ok().body(customerTrainingPlanExerciseRepository.save(customerTrainingPlanExercise)) + } + + @GetMapping("/customer_training_plan_exercise/{id}") + fun getAllByCustomerId(@PathVariable(value = "id") customerId: Long): ResponseEntity> { + + val exerciseList: List = customerTrainingPlanExerciseRepository.findAllByCustomerId(customerId) + logger.info("Get all training plan exercise list by customerId") + + return if(exerciseList.isNotEmpty()) + ResponseEntity.ok().body(exerciseList) else + ResponseEntity.notFound().build() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Customer.kt b/src/main/kotlin/com/aitrainer/api/model/Customer.kt index 6692302..8fc290d 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Customer.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Customer.kt @@ -7,6 +7,7 @@ import javax.persistence.* @Entity data class Customer ( + @Expose var name: String? = null, @Expose var firstname: String? = null, @Expose var email: String? = null, @@ -27,6 +28,5 @@ data class Customer ( @Expose var firebaseUid: String? = null, @Expose var sportId: Int? = null, @Expose var emailSubscription: Int? = 0, - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose var customerId: Long = 0 + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose var customerId: Long = 0, ) diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt index 93adf78..0d5ed86 100644 --- a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlan.kt @@ -1,16 +1,21 @@ package com.aitrainer.api.model import com.google.gson.annotations.Expose +import org.hibernate.annotations.Fetch +import org.hibernate.annotations.FetchMode import org.springframework.lang.NonNull -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id +import javax.persistence.* @Entity data class CustomerTrainingPlan ( @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerTrainingPlanId: Long = 0, @Expose @get: NonNull var customerId: Long = 0, @Expose @get: NonNull var trainingPlanId: Long = 0, - @Expose @get: NonNull var dateAdd: String? = null -) \ No newline at end of file + @Expose @get: NonNull var dateAdd: String? = null, + @Expose var active: Boolean?, + @Expose @get: NonNull var status: String? = null, +) { + @OneToMany(fetch = FetchType.EAGER, mappedBy = "customerTrainingPlan") + @Fetch(value = FetchMode.SUBSELECT) + @Expose val details: List = mutableListOf() +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt new file mode 100644 index 0000000..6b36b54 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanDetails.kt @@ -0,0 +1,22 @@ +package com.aitrainer.api.model + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.google.gson.annotations.Expose +import org.hibernate.annotations.Fetch +import org.hibernate.annotations.FetchMode +import org.springframework.lang.NonNull +import javax.persistence.* + +@Entity +data class CustomerTrainingPlanDetails ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerTrainingPlanDetailsId: Long = 0, + @Expose @get: NonNull var exerciseTypeId: Long = 0, + @Expose var set: Int?, + @Expose var repeats: Int?, + @Expose var weight: Double?, +) { + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "customerTrainingPlanId", nullable = false) + @JsonIgnore + val customerTrainingPlan: CustomerTrainingPlan? = null +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt new file mode 100644 index 0000000..9f07f93 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerTrainingPlanExercise.kt @@ -0,0 +1,15 @@ +package com.aitrainer.api.model + +import com.google.gson.annotations.Expose +import org.springframework.lang.NonNull +import javax.persistence.* + +@Entity +data class CustomerTrainingPlanExercise ( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerTrainingPlanExerciseId: Long = 0, + @Expose @get: NonNull var customerTrainingPlanDetailsId: Long = 0, + @Expose @get: NonNull var customerId: Long = 0, + @Expose @get: NonNull var exerciseId: Long = 0, + @Expose var repeats: Int?, + @Expose var weight: Double?, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanExerciseRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanExerciseRepository.kt new file mode 100644 index 0000000..1f77fcb --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerTrainingPlanExerciseRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerTrainingPlanExercise +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface CustomerTrainingPlanExerciseRepository: JpaRepository { + fun findAllByCustomerId(customerId: Long): List +} \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index ab0384d..94d16a5 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -17,6 +17,6 @@ logging.config=classpath:logback-spring.xml logging.file=logs # if the database structure has been changed, increment this version number -application.version=1.0.40 +application.version=1.0.41 jwt.secret=aitrainer \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d17420e..bd5308c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -17,7 +17,7 @@ logging.config=classpath:logback-spring.xml logging.file=logs # if the database structure has been changed, increment this version number -application.version=1.0.40 +application.version=1.0.41 jwt.secret=aitrainer jasypt.encryptor.password=Tibor diff --git a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt index 811d39c..22813c9 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AppCustomerPackageTest.kt @@ -128,6 +128,9 @@ class AppCustomerPackageTest { assertTrue(trainingPlanList.isNotEmpty()) assertEquals(trainingPlanList[0].customerId,91) assertEquals(trainingPlanList[0].trainingPlanId,2) + assertEquals(trainingPlanList[0].details.size,2) + assertEquals(trainingPlanList[0].details[0].exerciseTypeId,60) + assertEquals(trainingPlanList[0].details[0].weight,24.0) } } } diff --git a/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt b/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt index c244732..9ea3d23 100644 --- a/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/AppPackageTest.kt @@ -176,7 +176,7 @@ class AppPackageTest { assertEquals(plans[1].name, "Biceps") assertEquals(plans[1].internalName, "biceps_beginner") assertEquals(plans[1].free, true) - assertEquals(plans[1].treeId, 15) + assertEquals(plans[1].treeId, 3) assertEquals(plans[0].details[0].exerciseTypeId, 63) assertEquals(plans[0].details[1].weight, -1.0) } else if (record[0] == SplitTests::class.simpleName) { diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanExerciseTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanExerciseTest.kt new file mode 100644 index 0000000..2517c31 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanExerciseTest.kt @@ -0,0 +1,64 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.CustomerTrainingPlanExerciseController +import com.aitrainer.api.model.CustomerTrainingPlanExercise +import com.aitrainer.api.repository.CustomerTrainingPlanExerciseRepository +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.HttpStatus +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class CustomerTrainingPlanExerciseTest { + + @Autowired + private lateinit var customerTrainingPlanExerciseRepository: CustomerTrainingPlanExerciseRepository + + + + @Test + fun testInsert() { + val customerTrainingPlanExercise = CustomerTrainingPlanExercise( + customerId = 90, + exerciseId = 60, + repeats = 20, + weight = 50.0, + customerTrainingPlanDetailsId = 1 + ) + + val controller = CustomerTrainingPlanExerciseController(customerTrainingPlanExerciseRepository) + val response = controller.createNewCustomerTrainingPlanExercise(customerTrainingPlanExercise) + + val newCustomerTrainingPlanExercise = response.body + + assertTrue(newCustomerTrainingPlanExercise is CustomerTrainingPlanExercise) + assertEquals(newCustomerTrainingPlanExercise.exerciseId, 60) + assertEquals(newCustomerTrainingPlanExercise.repeats, 20) + assertEquals(newCustomerTrainingPlanExercise.weight, 50.0) + + customerTrainingPlanExerciseRepository.delete(newCustomerTrainingPlanExercise) + } + + @Test + fun testGet() { + val controller = CustomerTrainingPlanExerciseController(customerTrainingPlanExerciseRepository) + val response = controller.getAllByCustomerId(90) + + assertEquals(response.statusCode, HttpStatus.OK) + val exerciseList = response.body + + assertEquals(exerciseList!!.size, 3) + assertEquals(exerciseList[1].weight, 26.0) + assertEquals(exerciseList[1].repeats, 14) + assertEquals(exerciseList[2].weight, 30.0) + assertEquals(exerciseList[2].repeats, 11) + + + } + + +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt index 4de04e7..ed79805 100644 --- a/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerTrainingPlanTest.kt @@ -26,7 +26,8 @@ class CustomerTrainingPlanTest { customerId = 90, trainingPlanId = 1, dateAdd = "2021-05-12", - + active = true, + status = "open" ) val controller = CustomerTrainingPlanController(customerTrainingPlanRepository)