From fd10f40306b56975c9a12abb05eacb2a508bc96b Mon Sep 17 00:00:00 2001 From: Bossanyi Tibor Date: Mon, 9 Nov 2020 22:49:15 +0100 Subject: [PATCH] Property, CustomerProperty --- build.gradle.kts | 2 +- data/db/install.sql | 42 +++++++ data/db/update_1_0_12.sql | 41 +++++++ readme.MD | 6 + .../api/controller/ControllerAspect.kt | 106 ++++++++++++++++++ .../controller/CustomerControllerAspect.kt | 30 ----- .../CustomerInformationControllerAspect.kt | 35 ------ .../controller/CustomerPropertyController.kt | 43 +++++++ .../controller/ExerciseControllerAspect.kt | 35 ------ .../ExercisePlanControllerAspect.kt | 33 ------ .../ExercisePlanDetailControllerAspect.kt | 33 ------ .../ExerciseTreeControllerAspect.kt | 33 ------ .../ExerciseTypeControllerAspect.kt | 33 ------ .../api/controller/ProductControllerAspect.kt | 33 ------ .../controller/ProductTestControllerAspect.kt | 33 ------ .../api/controller/PropertyController.kt | 24 ++++ .../controller/PurchaseControllerAspect.kt | 33 ------ .../aitrainer/api/model/CustomerProperty.kt | 16 +++ .../com/aitrainer/api/model/Property.kt | 19 ++++ .../api/model/PropertyTranslation.kt | 21 ++++ .../repository/CustomerPropertyRepository.kt | 19 ++++ .../api/repository/PropertyRepository.kt | 14 +++ .../resources/application-prod.properties | 2 +- src/main/resources/application.properties | 2 +- .../api/test/CustomerPropertyTest.kt | 70 ++++++++++++ .../com/aitrainer/api/test/PropertyTest.kt | 35 ++++++ .../com/aitrainer/api/test/PurchaseTest.kt | 2 +- 27 files changed, 460 insertions(+), 335 deletions(-) create mode 100644 data/db/update_1_0_12.sql create mode 100644 src/main/kotlin/com/aitrainer/api/controller/ControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/CustomerInformationControllerAspect.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ExercisePlanControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ExercisePlanDetailControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ExerciseTreeControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ProductControllerAspect.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/ProductTestControllerAspect.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/PropertyController.kt delete mode 100644 src/main/kotlin/com/aitrainer/api/controller/PurchaseControllerAspect.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/Property.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/CustomerPropertyRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/PropertyRepository.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/PropertyTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index d33fb83..a3f333e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } group = "com.aitrainer" -version = "1.0.11" +version = "1.0.12" java.sourceCompatibility = JavaVersion.VERSION_1_8 repositories { diff --git a/data/db/install.sql b/data/db/install.sql index 6dac830..506b115 100644 --- a/data/db/install.sql +++ b/data/db/install.sql @@ -339,6 +339,48 @@ INSERT INTO `purchase` (`purchase_id`, `customer_id`, `product_id`, `date_add`, INSERT INTO `purchase` (`purchase_id`, `customer_id`, `product_id`, `date_add`, `purchase_sum`, `currency`) VALUES (2, 62, 1, '2020-11-05 15:45:08', 1000, 'HUF'); INSERT INTO `purchase` (`purchase_id`, `customer_id`, `product_id`, `date_add`, `purchase_sum`, `currency`) VALUES (3, 2, 1, '2020-11-05 15:45:30', 1000, 'HUF'); +CREATE TABLE `property` ( + `property_id` INT(11) NOT NULL AUTO_INCREMENT, + `property_name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + `property_unit` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + PRIMARY KEY (`property_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + + +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (1, 'Weight', 'kg'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (2, 'Height', 'cm'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (3, 'Chest', 'cm'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (4, 'Biceps', 'cm'); + + +CREATE TABLE `property_translation` ( + `translation_id` INT(13) NOT NULL AUTO_INCREMENT, + `language_code` CHAR(2) NOT NULL DEFAULT 'en' COLLATE 'utf8mb4_general_ci', + `property_id` INT(13) NOT NULL DEFAULT '0', + `property_name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`translation_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +ROW_FORMAT=DYNAMIC +; + +CREATE TABLE `customer_property` ( + `customer_property_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `customer_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `property_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `property_value` DOUBLE UNSIGNED NOT NULL DEFAULT '0', + `date_add` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`customer_property_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + + /*!40000 ALTER TABLE `exercise_type` ENABLE KEYS */; diff --git a/data/db/update_1_0_12.sql b/data/db/update_1_0_12.sql new file mode 100644 index 0000000..9297b6a --- /dev/null +++ b/data/db/update_1_0_12.sql @@ -0,0 +1,41 @@ +CREATE TABLE `property` ( + `property_id` INT(11) NOT NULL AUTO_INCREMENT, + `property_name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + `property_unit` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + PRIMARY KEY (`property_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + + +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (1, 'Weight', 'kg'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (2, 'Height', 'cm'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (3, 'Chest', 'cm'); +INSERT INTO `property` (`property_id`, `property_name`, `property_unit`) VALUES (4, 'Biceps', 'cm'); + + +CREATE TABLE `property_translation` ( + `translation_id` INT(13) NOT NULL AUTO_INCREMENT, + `language_code` CHAR(2) NOT NULL DEFAULT 'en' COLLATE 'utf8mb4_general_ci', + `property_id` INT(13) NOT NULL DEFAULT '0', + `property_name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`translation_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `customer_property` ( + `customer_property_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `customer_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `property_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `property_value` DOUBLE UNSIGNED NOT NULL DEFAULT '0', + `date_add` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`customer_property_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + +UPDATE configuration set config_value = "1.0.12", date_change=CURRENT_DATE WHERE config_key = "db_version"; \ No newline at end of file diff --git a/readme.MD b/readme.MD index 2c55e6e..84894c8 100644 --- a/readme.MD +++ b/readme.MD @@ -16,5 +16,11 @@ provide a RESTful API for the mobile app * customer_information * exercise_plan * exercise_plan_detail +* product +* product_test +* purchase +* property +* property_translation +* customer_property with automatic database update diff --git a/src/main/kotlin/com/aitrainer/api/controller/ControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ControllerAspect.kt new file mode 100644 index 0000000..65b847d --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/ControllerAspect.kt @@ -0,0 +1,106 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.ApiApplication +import com.aitrainer.api.repository.ConfigurationRepository +import org.aspectj.lang.JoinPoint +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.annotation.Before +import org.aspectj.lang.annotation.Pointcut +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Suppress("unused") +@Aspect +@Component +class ControllerAspect { + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + @Autowired + private lateinit var properties: ApplicationProperties + + /* @Suppress("unused") + @Pointcut("execution(* com.aitrainer.api.controller.*.*())") + fun controllerAspect() { + } + + @Before("controllerAspect()") + fun loggingAop() { + Singleton.checkDBUpdate(configurationRepository, properties) + }*/ + + @Before("execution(* com.aitrainer.api.controller.CustomerController.*(..))") + fun customerControllerAspect(joinPoint: JoinPoint) { + println("customer controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.CustomerInformationController.*(..))") + fun customerInformationControllerAspect(joinPoint: JoinPoint) { + println("customer information controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.CustomerPropertyController.*(..))") + fun customerPropertyControllerAspect(joinPoint: JoinPoint) { + println("customer property controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ExerciseController.*(..))") + fun exerciseControllerAspect(joinPoint: JoinPoint) { + println("exercise controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ExercisePlanController.*(..))") + fun exercisePlanControllerAspect(joinPoint: JoinPoint) { + println("exercise plan controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ExercisePlanDetailController.*(..))") + fun exercisePlanDetailControllerAspect(joinPoint: JoinPoint) { + println("exercise plan detail controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ExerciseTreeController.*(..))") + fun exerciseTreeControllerAspect(joinPoint: JoinPoint) { + println("exercise tree controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ExerciseTypeController.*(..))") + fun exerciseTypeControllerAspect(joinPoint: JoinPoint) { + println("exercise type controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ProductController.*(..))") + fun productControllerAspect(joinPoint: JoinPoint) { + println("product controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.ProductTestController.*(..))") + fun productTestControllerAspect(joinPoint: JoinPoint) { + println("product test controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.PropertyController.*(..))") + fun propertyControllerAspect(joinPoint: JoinPoint) { + println("property controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + + @Before("execution(* com.aitrainer.api.controller.PurchaseController.*(..))") + fun purchaseControllerAspect(joinPoint: JoinPoint) { + println("purchase controller") + Singleton.checkDBUpdate(configurationRepository, properties) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt deleted file mode 100644 index 656fb28..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.JoinPoint -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class CustomerControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Before("execution(* com.aitrainer.api.controller.CustomerController.*(..))") - fun customerControllerAspect(joinPoint: JoinPoint) { - println("customer controller") - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} - diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationControllerAspect.kt deleted file mode 100644 index 93b3a09..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationControllerAspect.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Aspect -@Component -@Suppress("unused") -class CustomerInformationControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.CustomerInformationController.*())") - fun customerInformationAspect() { - } - - @Suppress("unused") - @Before("customerInformationAspect()") - fun dbCheckAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt new file mode 100644 index 0000000..040b218 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPropertyController.kt @@ -0,0 +1,43 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerProperty +import com.aitrainer.api.model.ExercisePlanDetail +import com.aitrainer.api.model.Purchase +import com.aitrainer.api.repository.CustomerPropertyRepository +import org.slf4j.LoggerFactory +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import javax.validation.Valid + +@RestController +@RequestMapping("/api") +class CustomerPropertyController(private val customerPropertyRepository: CustomerPropertyRepository) { + private val logger = LoggerFactory.getLogger(javaClass) + + @PostMapping("/customer_property") + fun createNewCustomerProperty(@Valid @RequestBody customerProperty: CustomerProperty): ResponseEntity { + logger.info("Create customer property: $customerProperty") + return ResponseEntity.ok().body(customerPropertyRepository.save(customerProperty)) + } + + @GetMapping("/customer_property/{id}") + fun getAllByCustomerId(@PathVariable(value = "id") customerId: Long): ResponseEntity> { + + val propertyList: List = customerPropertyRepository.findAllByCustomerId(customerId) + logger.info("Get all customer_property by customerId") + + return if(propertyList.isNotEmpty()) + ResponseEntity.ok().body(propertyList) else + ResponseEntity.notFound().build() + } + + @GetMapping( "/customer_property/last/{id}") + fun getLastPropertiesByCustomerId(@PathVariable(value = "id") customerId: Long): ResponseEntity> { + val propertyList = customerPropertyRepository.findLastPropertiesByCustomerId(customerId) + logger.info("Get last customer_property by customerId $propertyList") + + return if (propertyList.isNotEmpty()) + ResponseEntity.ok().body(propertyList) else + ResponseEntity.notFound().build() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt deleted file mode 100644 index 02089ed..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Component -@Suppress("unused") -@Aspect -class ExerciseControllerAspect { - - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ExerciseController.*())") - fun exerciseControllerAspect() { - } - - @Before("exerciseControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanControllerAspect.kt deleted file mode 100644 index 84a6fe3..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ExercisePlanControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ExercisePlanController.*())") - fun exercisePlanControllerAspect() { - } - - @Before("exercisePlanControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanDetailControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanDetailControllerAspect.kt deleted file mode 100644 index 5d06300..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ExercisePlanDetailControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ExercisePlanDetailControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ExercisePlanDetailController.*())") - fun exercisePlanDetailControllerAspect() { - } - - @Before("exercisePlanDetailControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciseTreeControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseTreeControllerAspect.kt deleted file mode 100644 index fa2ee4d..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ExerciseTreeControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ExerciseTreeControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ExerciseTreeController.*())") - fun exerciseTreeControllerAspect() { - } - - @Before("exerciseTreeControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt deleted file mode 100644 index acbb9ca..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ExerciseTypeControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ExerciseTypeController.*())") - fun exerciseTypeControllerAspect() { - } - - @Before("exerciseTypeControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ProductControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ProductControllerAspect.kt deleted file mode 100644 index 04014b7..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ProductControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ProductControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ProductController.*())") - fun productControllerAspect() { - } - - @Before("productControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ProductTestControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ProductTestControllerAspect.kt deleted file mode 100644 index 03fe875..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/ProductTestControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class ProductTestControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.ProductTestController.*())") - fun productTestControllerAspect() { - } - - @Before("productTestControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/PropertyController.kt b/src/main/kotlin/com/aitrainer/api/controller/PropertyController.kt new file mode 100644 index 0000000..d311201 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/PropertyController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.Property +import com.aitrainer.api.repository.PropertyRepository +import org.slf4j.LoggerFactory +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api") +class PropertyController(private val propertyRepository: PropertyRepository) { + private val logger = LoggerFactory.getLogger(javaClass) + + @GetMapping("/property") + fun getPropertiesWithTranslation(): ResponseEntity> { + val list = propertyRepository.getProperties() + + logger.info(" -- Get All properties $list") + return if (list.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/PurchaseControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/PurchaseControllerAspect.kt deleted file mode 100644 index fca8066..0000000 --- a/src/main/kotlin/com/aitrainer/api/controller/PurchaseControllerAspect.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.aitrainer.api.controller - -import com.aitrainer.api.ApiApplication -import com.aitrainer.api.repository.ConfigurationRepository -import org.aspectj.lang.annotation.Aspect -import org.aspectj.lang.annotation.Before -import org.aspectj.lang.annotation.Pointcut -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component - -@Suppress("unused") -@Aspect -@Component -class PurchaseControllerAspect { - private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) - - @Autowired - private lateinit var configurationRepository: ConfigurationRepository - @Autowired - private lateinit var properties: ApplicationProperties - - @Suppress("unused") - @Pointcut("execution(* com.aitrainer.api.controller.PurchaseController.*())") - fun purchaseControllerAspect() { - } - - @Before("purchaseControllerAspect()") - fun loggingAop() { - Singleton.checkDBUpdate(configurationRepository, properties) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt new file mode 100644 index 0000000..554f1e9 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerProperty.kt @@ -0,0 +1,16 @@ +package com.aitrainer.api.model + +import org.springframework.lang.NonNull +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id + +@Entity +data class CustomerProperty ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var customerPropertyId: Long = 0, + @get: NonNull var customerId: Long = 0, + @get: NonNull var propertyId: Long = 0, + @get: NonNull var propertyValue: Double? = null, + @get: NonNull var dateAdd: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Property.kt b/src/main/kotlin/com/aitrainer/api/model/Property.kt new file mode 100644 index 0000000..2672dd0 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/Property.kt @@ -0,0 +1,19 @@ +package com.aitrainer.api.model + +import org.hibernate.annotations.Fetch +import org.hibernate.annotations.FetchMode +import org.springframework.lang.NonNull +import javax.persistence.* +import javax.validation.constraints.NotBlank + +@Entity +data class Property ( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) @get: NonNull var propertyId: Long = 0, + @get: NotBlank var propertyName: String = "", + @get: NotBlank var propertyUnit: String = "" +) { + @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "property") + @Fetch(value = FetchMode.SUBSELECT) + val translations: List = mutableListOf().toList() +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt b/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt new file mode 100644 index 0000000..b863e9c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/PropertyTranslation.kt @@ -0,0 +1,21 @@ +package com.aitrainer.api.model + +import com.fasterxml.jackson.annotation.JsonIgnore +import javax.persistence.* +import javax.validation.constraints.NotBlank + +@Entity +data class PropertyTranslation ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val translationId: Long = 0, + + @get: NotBlank var languageCode: String?, + @get: NotBlank var propertyName: String = "" + + +) { + @ManyToOne(fetch = FetchType.EAGER, optional = false) + @JoinColumn(name = "propertyId", nullable = false) + @JsonIgnore + val property: Property? = null + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerPropertyRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerPropertyRepository.kt new file mode 100644 index 0000000..32b8f90 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerPropertyRepository.kt @@ -0,0 +1,19 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerProperty +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.stereotype.Repository + +@Repository +interface CustomerPropertyRepository: JpaRepository { + + fun findAllByCustomerId(customerId: Long): List + + @Query(" FROM CustomerProperty a " + + " WHERE customerId = :customerId" + + " AND dateAdd in (select MAX(dateAdd) from CustomerProperty b " + + " WHERE customerId = :customerId and a.propertyId = b.propertyId ) " + ) + fun findLastPropertiesByCustomerId(customerId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/PropertyRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/PropertyRepository.kt new file mode 100644 index 0000000..cd9c357 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/PropertyRepository.kt @@ -0,0 +1,14 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.Property +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.stereotype.Repository + +@Repository +interface PropertyRepository: JpaRepository { + @Query("FROM Property as e " + + "LEFT JOIN PropertyTranslation as t ON e.propertyId = t.property AND t.languageCode = 'hu' " + + "ORDER BY e.propertyId ") + fun getProperties(): List +} \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 367e1a2..275db0d 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -16,6 +16,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.11 +application.version=1.0.12 jwt.secret=aitrainer \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9799eb1..82c52d9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,6 +16,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.11 +application.version=1.0.12 jwt.secret=aitrainer \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt new file mode 100644 index 0000000..2ebb2c8 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerPropertyTest.kt @@ -0,0 +1,70 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.CustomerPropertyController +import com.aitrainer.api.model.CustomerProperty +import com.aitrainer.api.repository.CustomerPropertyRepository +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.TestInstance +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class CustomerPropertyTest { + + @Autowired + private lateinit var customerPropertyRepository: CustomerPropertyRepository + + + @Test + fun testGetAllCustomerProperties() { + val controller = CustomerPropertyController(customerPropertyRepository ) + val response = controller.getAllByCustomerId(90) + + val properties = response.body + + assertTrue(properties is List) + assertTrue(properties.isNotEmpty()) + assertEquals(properties.size, 4) + assertEquals(properties[0].propertyValue, 81.0) + assertEquals(properties[1].propertyValue, 82.0) + assertEquals(properties[3].propertyId, 4) + } + + @Test + fun testGetLastCustomerProperties() { + val controller = CustomerPropertyController(customerPropertyRepository) + val response = controller.getLastPropertiesByCustomerId(90) + + val properties = response.body + assertTrue(properties is List) + assertTrue(properties.isNotEmpty()) + assertEquals(properties.size, 3) + assertEquals(properties[0].propertyValue, 82.0) + assertEquals(properties[1].propertyValue, 172.0) + } + + @Test + fun testInsert() { + val customerProperty = CustomerProperty( + customerId = 90, + propertyId = 1, + dateAdd = "2020-11-10", + propertyValue = 81.5 + ) + + val controller = CustomerPropertyController(customerPropertyRepository) + val response = controller.createNewCustomerProperty(customerProperty) + + val newCustomerProperty = response.body + + assertTrue(newCustomerProperty is CustomerProperty) + assertEquals(newCustomerProperty.propertyValue, 81.5) + + customerPropertyRepository.delete(customerProperty) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/PropertyTest.kt b/src/test/kotlin/com/aitrainer/api/test/PropertyTest.kt new file mode 100644 index 0000000..2938454 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/PropertyTest.kt @@ -0,0 +1,35 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.PropertyController +import com.aitrainer.api.repository.PropertyRepository +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 kotlin.test.assertEquals +import kotlin.test.assertTrue + +@SpringBootTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class PropertyTest { + + @Autowired + private lateinit var propertyRepository: PropertyRepository + + + @Test + fun testGetProperties() { + val controller = PropertyController(propertyRepository ) + val response = controller.getPropertiesWithTranslation() + + val properties = response.body + + assertTrue(properties is List) + assertTrue(properties.isNotEmpty()) + assertEquals(properties.size, 4) + assertEquals(properties[0].propertyName, "Weight") + assertEquals(properties[0].translations[0].propertyName, "Tömeg") + assertEquals(properties[1].propertyName, "Height") + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/PurchaseTest.kt b/src/test/kotlin/com/aitrainer/api/test/PurchaseTest.kt index 146acc0..ec9eb02 100644 --- a/src/test/kotlin/com/aitrainer/api/test/PurchaseTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/PurchaseTest.kt @@ -50,7 +50,7 @@ class PurchaseTest { assertEquals(purchaseNew!!.productId, 2) assertEquals(purchaseNew.customerId, 1) - //purchaseRepository.delete(purchaseNew) + purchaseRepository.delete(purchaseNew) }