From 676aa60e2bce93d45c44d564292aaa9c71521a02 Mon Sep 17 00:00:00 2001 From: Tibor Bossanyi Date: Sun, 5 Feb 2023 09:56:50 +0100 Subject: [PATCH 1/4] API 1.1 Dockerfile update openjdk:18 --- src/deploy/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deploy/Dockerfile b/src/deploy/Dockerfile index 6bd8c77..e8416ad 100644 --- a/src/deploy/Dockerfile +++ b/src/deploy/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:12 +FROM openjdk:18 RUN mkdir aitrainer_server RUN mkdir aitrainer_server/data RUN mkdir aitrainer_server/data/db From b33c8cbf7f948f0346086de0ff62423963b6c184 Mon Sep 17 00:00:00 2001 From: Tibor Bossanyi Date: Fri, 10 Feb 2023 19:10:02 +0100 Subject: [PATCH 2/4] API 1.2 Diet tables, Open AI API --- build.gradle.kts | 7 +- data/db/update_1_1_0.sql | 4 +- data/db/update_1_2_0.sql | 162 ++++++++++++++++ .../api/controller/ApplicationProperties.kt | 12 +- .../api/controller/CustomerController.kt | 15 +- .../CustomerConversationController.kt | 25 +++ .../controller/CustomerPackageController.kt | 67 +++++++ .../api/controller/EvaluationController.kt | 3 - .../api/controller/OpenAIController.kt | 30 +++ .../api/controller/PackageController.kt | 48 ++++- .../api/controller/diet/DietController.kt | 24 +++ .../controller/diet/DietCustomerController.kt | 142 ++++++++++++++ .../diet/DietRawMaterialController.kt | 24 +++ .../diet/DietSensitivityController.kt | 24 +++ .../diet/DietUserConsumptionController.kt | 43 +++++ .../api/controller/diet/DietUserController.kt | 24 +++ .../diet/DietUserPreferenceController.kt | 24 +++ .../diet/DietUserSensitivityController.kt | 24 +++ .../controller/diet/RawMaterialController.kt | 31 +++ .../api/controller/diet/RecipeController.kt | 58 ++++++ .../diet/RecipeRawMaterialController.kt | 17 ++ .../api/controller/diet/StoreController.kt | 32 ++++ .../api/model/CustomerConversation.kt | 17 ++ .../com/aitrainer/api/model/diet/Diet.kt | 27 +++ .../aitrainer/api/model/diet/DietCustomer.kt | 23 +++ .../api/model/diet/DietRawMaterial.kt | 22 +++ .../api/model/diet/DietSensitivity.kt | 14 ++ .../com/aitrainer/api/model/diet/DietUser.kt | 14 ++ .../api/model/diet/DietUserConsumption.kt | 24 +++ .../api/model/diet/DietUserPreference.kt | 16 ++ .../api/model/diet/DietUserSensitivity.kt | 15 ++ .../aitrainer/api/model/diet/RawMaterial.kt | 22 +++ .../com/aitrainer/api/model/diet/Recipe.kt | 26 +++ .../api/model/diet/RecipeRawMaterial.kt | 20 ++ .../com/aitrainer/api/model/diet/Store.kt | 13 ++ .../com/aitrainer/api/openai/OpenAIService.kt | 53 ++++++ .../CustomerConversationRepository.kt | 10 + .../diet/DietRawMaterialRepository.kt | 10 + .../api/repository/diet/DietRepository.kt | 10 + .../diet/DietSensitivityRepository.kt | 6 + .../diet/DietUserConsumptionRepository.kt | 10 + .../diet/DietUserPreferenceRepository.kt | 10 + .../api/repository/diet/DietUserRepository.kt | 10 + .../diet/DietUserSensitivityRepository.kt | 10 + .../repository/diet/RawMaterialRepository.kt | 12 ++ .../diet/RecipeRawMaterialRepository.kt | 9 + .../api/repository/diet/RecipeRepository.kt | 14 ++ .../api/repository/diet/StoreRepository.kt | 11 ++ .../kotlin/com/aitrainer/api/service/Email.kt | 21 +- .../api/service/EmailTemplateService.kt | 12 +- .../com/aitrainer/api/service/Encryptor.kt | 21 ++ .../resources/application-prod.properties | 2 +- src/main/resources/application.properties | 5 +- src/main/resources/logback-spring.xml | 2 +- .../templates/diet_registration_email.html | 25 +++ .../templates/diet_registration_subject.html | 1 + .../templates/registration_email.html | 6 +- .../api/test/AppCustomerPackageTest.kt | 123 +++++++++++- .../com/aitrainer/api/test/AppPackageTest.kt | 116 ++++++++++- .../com/aitrainer/api/test/CompletionTest.kt | 20 ++ .../api/test/CustomerConversationTest.kt | 76 ++++++++ .../api/test/CustomerMembershipTest.kt | 61 ++++-- .../com/aitrainer/api/test/CustomerTests.kt | 43 +++++ .../com/aitrainer/api/test/EmailTest.kt | 2 +- .../com/aitrainer/api/test/Tokenizer.kt | 38 ++++ .../api/test/diet/DietConsumptionTest.kt | 132 +++++++++++++ .../api/test/diet/DietRawMaterialTest.kt | 84 ++++++++ .../api/test/diet/DietSensitivityTest.kt | 70 +++++++ .../com/aitrainer/api/test/diet/DietTest.kt | 79 ++++++++ .../api/test/diet/DietUserPreferenceTest.kt | 93 +++++++++ .../api/test/diet/DietUserSensitivityTest.kt | 69 +++++++ .../aitrainer/api/test/diet/DietUserTest.kt | 55 ++++++ .../api/test/diet/RawMaterialTest.kt | 139 ++++++++++++++ .../com/aitrainer/api/test/diet/RecipeTest.kt | 180 ++++++++++++++++++ .../com/aitrainer/api/test/diet/StoreTest.kt | 138 ++++++++++++++ 75 files changed, 2812 insertions(+), 69 deletions(-) create mode 100644 data/db/update_1_2_0.sql create mode 100644 src/main/kotlin/com/aitrainer/api/controller/CustomerConversationController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/OpenAIController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietCustomerController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietRawMaterialController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietSensitivityController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietUserConsumptionController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietUserController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietUserPreferenceController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/DietUserSensitivityController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/RawMaterialController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/RecipeController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/RecipeRawMaterialController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/controller/diet/StoreController.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/CustomerConversation.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/Diet.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietCustomer.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietRawMaterial.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietSensitivity.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietUser.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietUserConsumption.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietUserPreference.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/DietUserSensitivity.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/RawMaterial.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/Recipe.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/RecipeRawMaterial.kt create mode 100644 src/main/kotlin/com/aitrainer/api/model/diet/Store.kt create mode 100644 src/main/kotlin/com/aitrainer/api/openai/OpenAIService.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/CustomerConversationRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietRawMaterialRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietSensitivityRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietUserConsumptionRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietUserPreferenceRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietUserRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/DietUserSensitivityRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/RawMaterialRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRawMaterialRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/repository/diet/StoreRepository.kt create mode 100644 src/main/kotlin/com/aitrainer/api/service/Encryptor.kt create mode 100644 src/main/resources/templates/diet_registration_email.html create mode 100644 src/main/resources/templates/diet_registration_subject.html create mode 100644 src/test/kotlin/com/aitrainer/api/test/CompletionTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/CustomerConversationTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/Tokenizer.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietConsumptionTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietRawMaterialTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietSensitivityTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietUserPreferenceTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietUserSensitivityTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/DietUserTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/RawMaterialTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/RecipeTest.kt create mode 100644 src/test/kotlin/com/aitrainer/api/test/diet/StoreTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 37cdf7d..a2eee37 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { } group = "com.aitrainer" -version = "1.1.0" +version = "1.2.0" java.sourceCompatibility = JavaVersion.VERSION_17 repositories { @@ -34,7 +34,7 @@ dependencies { implementation("org.apache.logging.log4j:log4j-core:2.19.0") implementation("org.apache.logging.log4j:log4j-api:2.19.0") implementation("org.slf4j:slf4j-api:2.0.6") - //implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:1.0-M1-1.4.0-rc") // JVM dependency + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.1") implementation("io.jsonwebtoken:jjwt:0.9.1") @@ -48,6 +48,9 @@ dependencies { implementation("jakarta.mail:jakarta.mail-api:2.1.1") implementation("org.eclipse.angus:angus-mail:2.0.1") + implementation ("com.aallam.openai:openai-client:2.1.3") + implementation("io.ktor:ktor-client-java:2.2.3") + runtimeOnly("mysql:mysql-connector-java") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") diff --git a/data/db/update_1_1_0.sql b/data/db/update_1_1_0.sql index bdcff28..5fafeaa 100644 --- a/data/db/update_1_1_0.sql +++ b/data/db/update_1_1_0.sql @@ -9,8 +9,8 @@ CREATE TABLE `membership` ( `duration_unit` ENUM('day','week','month','year') NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', `training_plan_id` INT(11) NULL DEFAULT '0', `training_plan_day_ids` CHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', - PRIMARY KEY (`membership_id`) USING BTREE - INDEX `training_plan_id` (`training_plan_id`) USING BTREE, + PRIMARY KEY (`membership_id`) USING BTREE, + INDEX `training_plan_id` (`training_plan_id`) USING BTREE ) ENGINE=InnoDB ; diff --git a/data/db/update_1_2_0.sql b/data/db/update_1_2_0.sql new file mode 100644 index 0000000..35e9262 --- /dev/null +++ b/data/db/update_1_2_0.sql @@ -0,0 +1,162 @@ +START TRANSACTION; + +CREATE TABLE `customer_conversation` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `customer_id` INT(11) NOT NULL DEFAULT '0', + `conversation_date` DATETIME NULL DEFAULT NULL, + `question` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `answer` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + + +CREATE TABLE `diet_user` ( + `diet_user_id` INT(11) NOT NULL AUTO_INCREMENT, + `customer_id` INT(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`diet_user_id`) USING BTREE +) +ENGINE=InnoDB +; + +CREATE TABLE `diet_raw_material` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `diet_id` INT(11) NOT NULL DEFAULT '0', + `raw_material_id` INT(11) NULL DEFAULT '0', + `kcal_min` INT(11) NULL DEFAULT '0', + `kcal_max` INT(11) NULL DEFAULT '0', + `protein_min` INT(11) NULL DEFAULT '0', + `protein_max` INT(11) NULL DEFAULT '0', + `ch_min` INT(11) NULL DEFAULT '0', + `ch_max` INT(11) NULL DEFAULT '0', + `fat_min` INT(11) NULL DEFAULT '0', + `fat_max` INT(11) NULL DEFAULT '0', + `sugar` INT(11) NULL DEFAULT '0', + `name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `diet_sensitivity` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `name` CHAR(100) NOT NULL DEFAULT '0' COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `diet_user_consumption` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `diet_user_id` INT(11) NOT NULL, + `raw_material_id` INT(11) NOT NULL DEFAULT '0', + `date_consumption` DATETIME NOT NULL, + `name` CHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `quantity` DOUBLE NOT NULL DEFAULT '0', + `quantity_unit` CHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `cal` INT(11) NULL DEFAULT NULL, + `protein` DOUBLE NULL DEFAULT NULL, + `fat` DOUBLE NULL DEFAULT NULL, + `ch` DOUBLE NULL DEFAULT NULL, + `sugar` DOUBLE NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `diet_user_id` (`diet_user_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `diet_user_preference` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `diet_user_id` INT(11) NOT NULL DEFAULT '0', + `raw_material_id` INT(11) NOT NULL DEFAULT '0', + `temperature` DECIMAL(1,0) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) USING BTREE, + INDEX `diet_user_id` (`diet_user_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `diet_user_sensitivity` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `sensitivity_id` INT(11) NOT NULL DEFAULT '0', + `diet_user_id` INT(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) USING BTREE, + INDEX `diet_user_id` (`diet_user_id`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + + + +CREATE TABLE `raw_material` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `name` CHAR(100) NOT NULL COLLATE 'utf8mb4_general_ci', + `description` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `kcal_min` INT(11) NULL DEFAULT '0', + `kcal_max` INT(11) NULL DEFAULT '0', + `protein_min` INT(11) NULL DEFAULT '0', + `protein_max` INT(11) NULL DEFAULT '0', + `ch_min` INT(11) NULL DEFAULT '0', + `ch_max` INT(11) NULL DEFAULT '0', + `fat_min` INT(11) NULL DEFAULT '0', + `fat_max` INT(11) NULL DEFAULT '0', + `sugar` INT(11) NULL DEFAULT '0', + `store_id` INT(11) NULL DEFAULT '0', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +ROW_FORMAT=DYNAMIC +; + +CREATE TABLE `recipe` ( + `recipe_id` INT(11) NOT NULL AUTO_INCREMENT, + `name` CHAR(250) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci', + `description` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + `cal` INT(11) NULL DEFAULT NULL, + `protein` DOUBLE NULL DEFAULT NULL, + `fat` DOUBLE NULL DEFAULT NULL, + `ch` DOUBLE NULL DEFAULT NULL, + `diet_user_id` INT(11) NULL DEFAULT '0', + PRIMARY KEY (`recipe_id`) USING BTREE, + INDEX `name` (`name`) USING BTREE, + INDEX `diet_user_id` (`diet_user_id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `store` ( + `store_id` INT(11) NOT NULL AUTO_INCREMENT, + `store_name` CHAR(50) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci', + `country` CHAR(4) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`store_id`) USING BTREE, + INDEX `store_name` (`store_name`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + +CREATE TABLE `recipe_raw_material` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `raw_material_id` INT(11) NOT NULL DEFAULT '0', + `recipe_id` INT(11) NOT NULL DEFAULT '0', + `quantity` INT(11) NULL DEFAULT '0', + `quantity_unit` CHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB +; + + +UPDATE configuration set config_value = "1.2.0", date_change=CURRENT_DATE WHERE config_key = "db_version"; + +COMMIT; diff --git a/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt b/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt index 927c727..3987d59 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt @@ -1,12 +1,14 @@ package com.aitrainer.api.controller import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping +@Component class ApplicationProperties { @Value("\${application.version}") @@ -21,7 +23,8 @@ class ApplicationProperties { @Value("\${spring.datasource.password}") private lateinit var datasourcePassword: String - + @Value("\${openai.key}") + private lateinit var apiKey: String @GetMapping("/version") fun getVersion(): String { @@ -42,4 +45,11 @@ class ApplicationProperties { fun getDatasourcePassword(): String { return this.datasourcePassword } + + @GetMapping("/openAIKey") + fun getOpenAIKey(): String { + return this.apiKey + } + + } \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt index c6f36cc..2f6063b 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerController.kt @@ -12,13 +12,9 @@ import org.springframework.http.HttpHeaders import org.springframework.http.ResponseEntity import org.springframework.security.access.annotation.Secured import org.springframework.web.bind.annotation.* -import java.io.ByteArrayOutputStream -import java.nio.charset.StandardCharsets.UTF_8 import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.* -import java.util.zip.GZIPInputStream -import java.util.zip.GZIPOutputStream import javax.validation.Valid @@ -159,15 +155,6 @@ class CustomerController ( private val customerRepository: CustomerRepository) { @PostMapping("/club_registration") fun clubRegistration(@Valid @RequestBody json: String): ResponseEntity<*> { - fun gzip(content: String): String { - val bos = ByteArrayOutputStream() - GZIPOutputStream(bos).bufferedWriter(UTF_8).use { it.write(content) } - return bos.toByteArray().toString() - } - - fun unzip(content: ByteArray): String = - GZIPInputStream(content.inputStream()).bufferedReader(UTF_8).use { it.readText() } - val newUser: ClubUser = ClubUser().fromJson(json) if ( newUser.email.isEmpty()) { @@ -252,7 +239,7 @@ class CustomerController ( private val customerRepository: CustomerRepository) { if ( emailTemplateService == null ) { emailTemplateService = EmailTemplateService() } - val html = emailTemplateService!!.getEmailBody(newUser.firstname, activationLink) + val html = emailTemplateService!!.getEmailBody(newUser.firstname, activationLink, "registration_email") val subject = emailTemplateService!!.getSubject() // send email diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerConversationController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerConversationController.kt new file mode 100644 index 0000000..130e7f4 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerConversationController.kt @@ -0,0 +1,25 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerConversation +import com.aitrainer.api.repository.CustomerConversationRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + + +@RestController +@RequestMapping("/api") +class CustomerConversationController (private val customerConversationRepository: CustomerConversationRepository +) { + + @PostMapping("/customer_conversation") + fun insert(@RequestBody customerConversation: CustomerConversation): ResponseEntity { + return ResponseEntity.ok().body(customerConversationRepository.save(customerConversation)) + } + + @GetMapping("/customer_conversation/{customerId}") + fun getByCustomerId(@PathVariable customerId: Long): ResponseEntity> { + val list = customerConversationRepository.findByCustomerId(customerId) + 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/CustomerPackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt index 45dd41b..3b879c3 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerPackageController.kt @@ -2,7 +2,9 @@ package com.aitrainer.api.controller import com.aitrainer.api.model.* import com.aitrainer.api.model.CustomerMembership +import com.aitrainer.api.model.diet.* import com.aitrainer.api.repository.* +import com.aitrainer.api.repository.diet.* import com.google.gson.GsonBuilder import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -21,8 +23,73 @@ class CustomerPackageController( private val customerRepository: CustomerReposit private val customerActivityRepository: CustomerActivityRepository, private val customerTrainingPlanRepository: CustomerTrainingPlanRepository, private val customerMembership: CustomerMembershipRepository, + private val dietRepository: DietRepository, + private val dietRawMaterialRepository: DietRawMaterialRepository, + private val dietUserConsumptionRepository: DietUserConsumptionRepository, + private val dietUserRepository: DietUserRepository, + private val dietUserPreferenceRepository: DietUserPreferenceRepository, + private val dietUserSensitivityRepository: DietUserSensitivityRepository + ) { + @GetMapping("/diet_customer_package/{id}") + fun getDietCustomerPackageData(@PathVariable(value = "id") dietUserId: Long): ResponseEntity { + if (dietUserId <= 0) { + return ResponseEntity.notFound().build() + } + + val gson = GsonBuilder() + .excludeFieldsWithoutExposeAnnotation() + .setPrettyPrinting() + .create() + + val dietUser: DietUser = dietUserRepository.findByDietUserId(dietUserId) + ?: return ResponseEntity.notFound().build() + + val customerId = dietUser.customerId + val customer: Customer = customerRepository.findByCustomerIdAndActive(customerId, "Y") + ?: return ResponseEntity.notFound().build() + + val customerJson: String = gson.toJson(customer) + val dietUserJson: String = gson.toJson(dietUser) + + val listCustomerProperty = customerPropertyRepository.findLastPropertiesByCustomerId(customerId) + val listCustomerPropertyJson = gson.toJson(listCustomerProperty) + + val listMembership = customerMembership.findAllByCustomer(customer) + val listMembershipJson = gson.toJson(listMembership) + + val listDiet = dietRepository.findByDietUserId(dietUserId) + val listDietJson = gson.toJson(listDiet) + + val listDietRawMaterial = dietRawMaterialRepository.findByDietId(dietUserId) + val listDietRawMaterialJson = gson.toJson(listDietRawMaterial) + + val listDietUserConsumption = dietUserConsumptionRepository.findByDietUserId(dietUserId) + val listDietUserConsumptionJson = gson.toJson(listDietUserConsumption) + + val listDietUserPreference = dietUserPreferenceRepository.findByDietUserId(dietUserId) + val listDietUserPreferenceJson = gson.toJson(listDietUserPreference) + + val listDietUserSensitivity = dietUserSensitivityRepository.findByDietUserId(dietUserId) + val listDietUserSensitivityJson = gson.toJson(listDietUserSensitivity) + + val packageJson: String = + getClassRecord(Customer::class.simpleName, customerJson) + + "|||" + getClassRecord(DietUser::class.simpleName, dietUserJson) + "|||" + getClassRecord(CustomerProperty::class.simpleName, listCustomerPropertyJson) + "|||" + getClassRecord(CustomerMembership::class.simpleName, listMembershipJson) + "|||" + getClassRecord(Diet::class.simpleName, listDietJson) + "|||" + getClassRecord(DietRawMaterial::class.simpleName, listDietRawMaterialJson) + "|||" + getClassRecord(DietUserConsumption::class.simpleName, listDietUserConsumptionJson) + "|||" + getClassRecord(DietUserPreference::class.simpleName, listDietUserPreferenceJson) + "|||" + getClassRecord(DietUserSensitivity::class.simpleName, listDietUserSensitivityJson) + + + return if (packageJson.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(packageJson) + } + @GetMapping("/club_customer_package/{id}") fun getCustomerClubPackageData(@PathVariable(value = "id") customerId: Long): ResponseEntity { if (customerId <= 0) { diff --git a/src/main/kotlin/com/aitrainer/api/controller/EvaluationController.kt b/src/main/kotlin/com/aitrainer/api/controller/EvaluationController.kt index 1adcf95..0b361cb 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/EvaluationController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/EvaluationController.kt @@ -1,10 +1,7 @@ package com.aitrainer.api.controller import com.aitrainer.api.model.Evaluation -import com.aitrainer.api.model.ExerciseTree import com.aitrainer.api.repository.EvaluationRepository -import com.aitrainer.api.repository.ExerciseTreeParentsRepository -import com.aitrainer.api.repository.ExerciseTreeRepository import org.slf4j.LoggerFactory import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping diff --git a/src/main/kotlin/com/aitrainer/api/controller/OpenAIController.kt b/src/main/kotlin/com/aitrainer/api/controller/OpenAIController.kt new file mode 100644 index 0000000..39a747c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/OpenAIController.kt @@ -0,0 +1,30 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.openai.OpenAIService +import kotlinx.coroutines.* +import org.slf4j.LoggerFactory +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 OpenAIController() { + private val logger = LoggerFactory.getLogger(javaClass) + + @OptIn(DelicateCoroutinesApi::class) + @GetMapping("/openai/completion") + fun getOpenAIResponse(question: String) : String { + var result = "" + val openAIService = OpenAIService() + val deferred = GlobalScope.async { + openAIService.completion(question) + } + runBlocking { + result = deferred.await() + //println("Result: $result" ) + } + return result + } +} + diff --git a/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt b/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt index ce181f2..8228615 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/PackageController.kt @@ -1,7 +1,12 @@ package com.aitrainer.api.controller import com.aitrainer.api.model.* +import com.aitrainer.api.model.diet.DietSensitivity +import com.aitrainer.api.model.diet.RawMaterial +import com.aitrainer.api.model.diet.Recipe +import com.aitrainer.api.model.diet.Store import com.aitrainer.api.repository.* +import com.aitrainer.api.repository.diet.* import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping @@ -29,9 +34,50 @@ class PackageController(private val exerciseAbilityRepository: ExerciseAbilityRe private val trainingPlanDayRepository: TrainingPlanDayRepository, private val appTextRepository: AppTextRepository, private val trainingProgramRepository: TrainingProgramRepository, - private val membershipRepository: MembershipRepository + private val membershipRepository: MembershipRepository, + private val storeRepository: StoreRepository, + private val recipeRepository: RecipeRepository, + private val rawMaterialRepository: RawMaterialRepository, + private val dietSensitivityRepository: DietSensitivityRepository ) { + @GetMapping("/diet_package") + fun getDietPackageData(): ResponseEntity { + val gson = GsonBuilder() + .excludeFieldsWithoutExposeAnnotation() + .setPrettyPrinting() + .create() + + val listProperty:List = propertyRepository.getProperties() + val listPropertyJson: String = gson.toJson(listProperty) + + val listMembership = membershipRepository.findAll() + val listMembershipJson = gson.toJson(listMembership) + + val listStore = storeRepository.findAll() + val listStoreJson = gson.toJson(listStore) + + val listRecipe = recipeRepository.findAll() + val listRecipeJson = gson.toJson(listRecipe) + + val listRawMaterial = rawMaterialRepository.findAll() + val listRawMaterialJson = gson.toJson(listRawMaterial) + + val listDietSensitivity = dietSensitivityRepository.findAll() + val listDietSensitivityJson = gson.toJson(listDietSensitivity) + + val packageJson: String = + getClassRecord(Property::class.simpleName, listPropertyJson) + + "|||" + getClassRecord(Membership::class.simpleName, listMembershipJson) + + "|||" + getClassRecord(Store::class.simpleName, listStoreJson) + + "|||" + getClassRecord(Recipe::class.simpleName, listRecipeJson) + + "|||" + getClassRecord(RawMaterial::class.simpleName, listRawMaterialJson) + + "|||" + getClassRecord(DietSensitivity::class.simpleName, listDietSensitivityJson) + + return if (packageJson.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(packageJson) + } + @GetMapping("/club_package") fun getClubPackageData(): ResponseEntity { diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/DietController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietController.kt new file mode 100644 index 0000000..6c68a84 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.Diet +import com.aitrainer.api.repository.diet.DietRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/api") +class DietController(private val dietRepository: DietRepository) { + + @PostMapping("/diet") + fun insert(@RequestBody diet: Diet): ResponseEntity<*> { + return ResponseEntity.ok().body(dietRepository.save(diet)) + } + + @GetMapping("/diet/{dietUserId}") + fun getByDietUserId(@PathVariable dietUserId: Long): ResponseEntity> { + val list = dietRepository.findByDietUserId(dietUserId) + 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/diet/DietCustomerController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietCustomerController.kt new file mode 100644 index 0000000..54fd3ff --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietCustomerController.kt @@ -0,0 +1,142 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.Customer +import com.aitrainer.api.model.CustomerMembership +import com.aitrainer.api.model.CustomerPropertyProperty +import com.aitrainer.api.model.diet.DietCustomer +import com.aitrainer.api.model.diet.DietUser +import com.aitrainer.api.repository.CustomerRepository +import com.aitrainer.api.repository.diet.DietUserRepository +import com.aitrainer.api.service.Email +import com.aitrainer.api.service.EmailTemplateService +import com.aitrainer.api.service.Firebase +import com.aitrainer.api.service.ServiceBeans +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.* + +@RestController +@RequestMapping("/api") +class DietCustomerController(private val dietUserRepository: DietUserRepository, private val customerRepository: CustomerRepository) { + + @Autowired + var serviceBeans: ServiceBeans? = null + + @Autowired + private var emailTemplateService: EmailTemplateService? = null + + @PostMapping("/diet_registration") + fun insert(@RequestBody dietCustomerJson: String): ResponseEntity<*> { + val newDietCustomer: DietCustomer = DietCustomer().fromJson(dietCustomerJson) + + if ( newDietCustomer.email.isEmpty()) { + return ResponseEntity.badRequest().body("No Email") + } + + val current = LocalDateTime.now() + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS") + val nowFormatted = current.format(formatter) + + val stringCharacters = ('0'..'z').toList().toTypedArray() + val genPassword = (1..10).map { stringCharacters.random() }.joinToString("") + + val idToken: String? + + var existingCustomer: Customer? = customerRepository.findByEmailAndActive(newDietCustomer.email, "Y") + + if (existingCustomer == null ) { + val firebase = Firebase() + val signupResponse = firebase.signUp(newDietCustomer.email, genPassword) + ?: return ResponseEntity.badRequest().body("Firebase exception ${firebase.error}") + idToken = signupResponse.idToken + + val savingCustomer = Customer() + + if ( serviceBeans == null ) { + serviceBeans = ServiceBeans() + } + with (savingCustomer) { + email = newDietCustomer.email + password = serviceBeans!!.passwordEncoder().encode(genPassword) + firebaseRegToken = signupResponse.idToken + firebaseUid = signupResponse.localId + dateAdd = nowFormatted + firstname = newDietCustomer.firstname + name = "" + goal = newDietCustomer.goal + fitnessLevel = newDietCustomer.fitnessLevel + birthYear = newDietCustomer.birthYear + sex = newDietCustomer.sex + } + + val newCustomer = customerRepository.save(savingCustomer) + + if ( newDietCustomer.weight != 0.0 ) { + val property = CustomerPropertyProperty() + with (property) { + propertyId = 1 + propertyValue = newDietCustomer.weight + dateAdd= nowFormatted + goal = false + customer = newCustomer + } + newCustomer.properties.add(property) + } + if ( newDietCustomer.height != 0.0 ) { + val property = CustomerPropertyProperty() + with (property) { + propertyId = 2 + propertyValue = newDietCustomer.height + dateAdd = nowFormatted + goal = false + customer = newCustomer + } + newCustomer.properties.add(property) + } + + val newMembershipId = newDietCustomer.membershipId + if ( newMembershipId != 0L) { + val membership = CustomerMembership() + with(membership) { + customer = newCustomer + membershipId = newMembershipId + startDate = nowFormatted + } + newCustomer.memberships.add(membership) + } + + customerRepository.save(newCustomer) + existingCustomer = newCustomer + } else { + val existingDietUser = dietUserRepository.findByCustomerId(existingCustomer.customerId) + if ( existingDietUser != null ) { + return ResponseEntity.badRequest().body("DietCustomer exists") + } else { + val newDietUser = DietUser( + customerId = existingCustomer.customerId + ) + dietUserRepository.save(newDietUser) + + } + idToken = existingCustomer.firebaseRegToken!! + } + + // create email link + val activationLink = "https://diet4you.andio.hu/welcome/id=$idToken" + if ( emailTemplateService == null ) { + emailTemplateService = EmailTemplateService() + } + val html = emailTemplateService!!.getEmailBody(newDietCustomer.firstname, activationLink, "diet_registration_email") + val subject = emailTemplateService!!.getSubjectDiet() + + // send email + val email = Email() + email.send(newDietCustomer.email, html, subject) + + return ResponseEntity.ok().body(existingCustomer) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/DietRawMaterialController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietRawMaterialController.kt new file mode 100644 index 0000000..c07e77b --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietRawMaterialController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietRawMaterial +import com.aitrainer.api.repository.diet.DietRawMaterialRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/api") +class DietRawMaterialController(private val dietRawMaterialRepository: DietRawMaterialRepository) { + + @PostMapping("/diet_raw_material") + fun insert(@RequestBody dietRawMaterial: DietRawMaterial): ResponseEntity<*> { + return ResponseEntity.ok().body(dietRawMaterialRepository.save(dietRawMaterial)) + } + + @GetMapping("/diet_raw_material/{dietId}") + fun getByDietUserId(@PathVariable dietId: Long): ResponseEntity> { + val list = dietRawMaterialRepository.findByDietId(dietId) + 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/diet/DietSensitivityController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietSensitivityController.kt new file mode 100644 index 0000000..1e98809 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietSensitivityController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietSensitivity +import com.aitrainer.api.repository.diet.DietSensitivityRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class DietSensitivityController(private val dietSensitivityRepository: DietSensitivityRepository) { + + @PostMapping ("/diet_sensitivity") + fun insert(@RequestBody dietSensitivity: DietSensitivity): ResponseEntity { + val newDietSensitivity = dietSensitivityRepository.save(dietSensitivity) + return ResponseEntity.ok().body(newDietSensitivity) + } + + @GetMapping("/diet_sensitivity") + fun getAll(): ResponseEntity> { + val list = dietSensitivityRepository.findAll() + 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/diet/DietUserConsumptionController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserConsumptionController.kt new file mode 100644 index 0000000..87c1f5d --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserConsumptionController.kt @@ -0,0 +1,43 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietUserConsumption +import com.aitrainer.api.repository.diet.DietUserConsumptionRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/api") +class DietUserConsumptionController(private val dietUserConsumptionRepository: DietUserConsumptionRepository) { + + @PostMapping("/diet_user_consumption") + fun insert(@RequestBody dietUserConsumption: DietUserConsumption): ResponseEntity<*> { + return ResponseEntity.ok().body(dietUserConsumptionRepository.save(dietUserConsumption)) + } + + @PostMapping("/diet_user_consumption/{id}") + fun update(@PathVariable(value = "id") id: Long, @RequestBody dietUserConsumption: DietUserConsumption): ResponseEntity<*> { + return dietUserConsumptionRepository.findById(id).map { existingConsumption -> + val updatedConsumption: DietUserConsumption = existingConsumption.copy( + rawMaterialId = dietUserConsumption.rawMaterialId, + dateConsumption = dietUserConsumption.dateConsumption, + name = dietUserConsumption.name, + quantity = dietUserConsumption.quantity, + quantityUnit = dietUserConsumption.quantityUnit, + cal = dietUserConsumption.cal, + protein = dietUserConsumption.protein, + fat = dietUserConsumption.fat, + ch = dietUserConsumption.ch, + sugar = dietUserConsumption.sugar + ) + ResponseEntity.ok().body(dietUserConsumptionRepository.save(updatedConsumption)) + }.orElse(ResponseEntity.notFound().build()) + } + + @GetMapping("/diet_user_consumption/{dietUserId}") + fun getByDietUserId(@PathVariable dietUserId: Long): ResponseEntity> { + val list = dietUserConsumptionRepository.findByDietUserId(dietUserId) + 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/diet/DietUserController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserController.kt new file mode 100644 index 0000000..0927d33 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietUser +import com.aitrainer.api.repository.diet.DietUserRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class DietUserController(private val dietUserRepository: DietUserRepository) { + + @PostMapping ("/diet_user") + fun insert(@RequestBody dietUser: DietUser): ResponseEntity { + val newDietUser = dietUserRepository.save(dietUser) + return ResponseEntity.ok().body(newDietUser) + } + + @GetMapping("/diet_user/{customerId}") + fun getByCustomerId(@PathVariable customerId: Long): ResponseEntity { + val dietUser = dietUserRepository.findByCustomerId(customerId) + return if (dietUser == null) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(dietUser) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserPreferenceController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserPreferenceController.kt new file mode 100644 index 0000000..1260c22 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserPreferenceController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietUserPreference +import com.aitrainer.api.repository.diet.DietUserPreferenceRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/api") +class DietUserPreferenceController(private val dietUserPreferenceRepository: DietUserPreferenceRepository) { + + @PostMapping("/diet_user_preference") + fun insert(@RequestBody dietUserPreference: DietUserPreference): ResponseEntity<*> { + return ResponseEntity.ok().body(dietUserPreferenceRepository.save(dietUserPreference)) + } + + @GetMapping("/diet_user_preference/{dietUserId}") + fun getByDietUserId(@PathVariable dietUserId: Long): ResponseEntity> { + val list = dietUserPreferenceRepository.findByDietUserId(dietUserId) + 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/diet/DietUserSensitivityController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserSensitivityController.kt new file mode 100644 index 0000000..a6e65b9 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/DietUserSensitivityController.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.DietUserSensitivity +import com.aitrainer.api.repository.diet.DietUserSensitivityRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/api") +class DietUserSensitivityController(private val dietUserSensitivityRepository: DietUserSensitivityRepository) { + + @PostMapping("/diet_user_sensitivity") + fun insert(@RequestBody dietUserSensitivity: DietUserSensitivity): ResponseEntity<*> { + return ResponseEntity.ok().body(dietUserSensitivityRepository.save(dietUserSensitivity)) + } + + @GetMapping("/diet_user_sensitivity/{dietUserId}") + fun getByDietUserId(@PathVariable dietUserId: Long): ResponseEntity> { + val list = dietUserSensitivityRepository.findByDietUserId(dietUserId) + 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/diet/RawMaterialController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/RawMaterialController.kt new file mode 100644 index 0000000..0a947ff --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/RawMaterialController.kt @@ -0,0 +1,31 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.RawMaterial +import com.aitrainer.api.repository.diet.RawMaterialRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class RawMaterialController(private val rawMaterialRepository: RawMaterialRepository) { + + @PostMapping ("/raw_material") + fun insert(@RequestBody rawMaterial: RawMaterial): ResponseEntity { + val newRawMaterial = rawMaterialRepository.save(rawMaterial) + return ResponseEntity.ok().body(newRawMaterial) + } + + @GetMapping("/raw_material") + fun getAll(): ResponseEntity> { + val list = rawMaterialRepository.findAll() + return if (list.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } + + @GetMapping("/raw_material/{id}") + fun getByRawMaterialId(@PathVariable id: Long): ResponseEntity { + val rawMaterial = rawMaterialRepository.findByRawMaterialId(id) + return if (rawMaterial == null) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(rawMaterial) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeController.kt new file mode 100644 index 0000000..4a5f4c5 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeController.kt @@ -0,0 +1,58 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.Recipe +import com.aitrainer.api.repository.diet.RecipeRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class RecipeController(private val recipeRepository: RecipeRepository) { + + @PostMapping ("/recipe") + fun insert(@RequestBody recipe: Recipe): ResponseEntity { + val newRecipe = recipeRepository.save(recipe) + return ResponseEntity.ok().body(newRecipe) + } + + @PostMapping("/recipe/{id}") + fun update(@PathVariable(value = "id") id: Long, @RequestBody recipe: Recipe): ResponseEntity { + val existingRecipe = recipeRepository.findByRecipeId(id) ?: return ResponseEntity.notFound().build() + + val updatedRecipe: Recipe = existingRecipe.copy( + name = recipe.name, + description = recipe.description, + cal = recipe.cal, + ch = recipe.ch, + fat = recipe.fat, + protein = recipe.protein, + dietUserId = recipe.dietUserId + ) + recipe.rawMaterials.forEach { + it.recipe = recipe + updatedRecipe.rawMaterials.add(it) + } + return ResponseEntity.ok().body(recipeRepository.save(updatedRecipe)) + } + + @GetMapping("/recipe") + fun getAll(): ResponseEntity> { + val list = recipeRepository.findAll() + return if (list.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } + + @GetMapping("/recipe/{dietUserId}") + fun getByDietUserId(@PathVariable dietUserId: Long): ResponseEntity> { + val list = recipeRepository.findByDietUserId(dietUserId) + return if (list == null) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } + + @GetMapping("/recipe/name/{name}") + fun getByName(@PathVariable name: String): ResponseEntity> { + val list = recipeRepository.findByName(name) + return if (list == null) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeRawMaterialController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeRawMaterialController.kt new file mode 100644 index 0000000..8a36598 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/RecipeRawMaterialController.kt @@ -0,0 +1,17 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.RecipeRawMaterial +import com.aitrainer.api.repository.diet.RecipeRawMaterialRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class RecipeRawMaterialController(private val recipeRawMaterialRepository: RecipeRawMaterialRepository) { + + @PostMapping ("/recipe_raw_material") + fun insert(@RequestBody recipeRawMaterial: RecipeRawMaterial): ResponseEntity { + val newRecipe = recipeRawMaterialRepository.save(recipeRawMaterial) + return ResponseEntity.ok().body(recipeRawMaterial) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/diet/StoreController.kt b/src/main/kotlin/com/aitrainer/api/controller/diet/StoreController.kt new file mode 100644 index 0000000..0a750e2 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/diet/StoreController.kt @@ -0,0 +1,32 @@ +package com.aitrainer.api.controller.diet + +import com.aitrainer.api.model.diet.Store +import com.aitrainer.api.repository.diet.StoreRepository +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("api") +class StoreController(private val storeRepository: StoreRepository) { + + @PostMapping ("/store") + fun insert(@RequestBody store: Store): ResponseEntity { + val newStore = storeRepository.save(store) + return ResponseEntity.ok().body(newStore) + } + + @GetMapping("/store") + fun getAll(): ResponseEntity> { + val list = storeRepository.findAll() + return if (list.isEmpty()) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(list) + } + + @GetMapping("/store/{name}/{country}") + fun getByNameAndCountry(@PathVariable name: String, @PathVariable country: String ): ResponseEntity { + val store = storeRepository.findByNameAndCountry(name, country) + return if (store == null) ResponseEntity.notFound().build() else + ResponseEntity.ok().body(store) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerConversation.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerConversation.kt new file mode 100644 index 0000000..158e3ec --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerConversation.kt @@ -0,0 +1,17 @@ +package com.aitrainer.api.model + +import com.google.gson.annotations.Expose +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import javax.validation.constraints.NotNull + +@Entity +data class CustomerConversation( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0, + @Expose @get: NotNull val customerId: Long, + @Expose @get: NotNull val conversationDate: String = "", + @Expose @get: NotNull val question: String = "", + @Expose @get: NotNull val answer: String = "" +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/Diet.kt b/src/main/kotlin/com/aitrainer/api/model/diet/Diet.kt new file mode 100644 index 0000000..20de8af --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/Diet.kt @@ -0,0 +1,27 @@ +package com.aitrainer.api.model.diet +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull + +@Entity +data class Diet ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val dietId: Long = 0, + + @Expose @get: NotNull val dietUserId: Long = 0, + + @Expose @get: NotNull val dietText: String = "", + + @Expose @get: NotNull val monday: String = "", + + @Expose @get: NotNull val tuesday: String = "", + + @Expose @get: NotNull val wednesday: String = "", + + @Expose @get: NotNull val thursday: String = "", + + @Expose @get: NotNull val friday: String = "", + + @Expose @get: NotNull val saturday: String = "", + + @Expose @get: NotNull val sunday: String = "" +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietCustomer.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietCustomer.kt new file mode 100644 index 0000000..fa1c8ec --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietCustomer.kt @@ -0,0 +1,23 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json + +@Serializable +data class DietCustomer( + @Expose var firstname: String = "", + @Expose var email: String = "", + @Expose var sex: String = "m", + @Expose var goal: String = "", + @Expose var fitnessLevel: String = "beginner", + @Expose var birthYear: Int = 0, + @Expose var weight: Double = 0.0, + @Expose var height: Double = 0.0, + @Expose var membershipId: Long = 0, + +){ + fun fromJson(json: String): DietCustomer { + return Json.decodeFromString(serializer(), json) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietRawMaterial.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietRawMaterial.kt new file mode 100644 index 0000000..0db7d9c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietRawMaterial.kt @@ -0,0 +1,22 @@ +package com.aitrainer.api.model.diet +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull + +@Entity +data class DietRawMaterial ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val id: Long = 0, + + @Expose @get: NotNull val dietId: Long = 0, + @Expose @get: NotNull val rawMaterialId: Long = 0, + @Expose @get: NotNull val name: String = "", + @Expose @get: NotNull val kcalMin: Int = 0, + @Expose @get: NotNull val kcalMax: Int = 0, + @Expose @get: NotNull val proteinMin: Int = 0, + @Expose @get: NotNull val proteinMax: Int = 0, + @Expose @get: NotNull val fatMin: Int = 0, + @Expose @get: NotNull val fatMax: Int = 0, + @Expose @get: NotNull val chMin: Int = 0, + @Expose @get: NotNull val chMax: Int = 0, + @Expose @get: NotNull val sugar: Int = 0, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietSensitivity.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietSensitivity.kt new file mode 100644 index 0000000..4327488 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietSensitivity.kt @@ -0,0 +1,14 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import javax.validation.constraints.NotNull + +@Entity +data class DietSensitivity( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0, + @Expose @get: NotNull val name: String = "", +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietUser.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietUser.kt new file mode 100644 index 0000000..dc787ac --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietUser.kt @@ -0,0 +1,14 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import javax.validation.constraints.NotNull + +@Entity +data class DietUser( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var dietUserId: Long = 0, + @Expose @get: NotNull val customerId: Long +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietUserConsumption.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserConsumption.kt new file mode 100644 index 0000000..5f9d935 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserConsumption.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.model.diet +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull +import org.springframework.lang.NonNull + +@Entity +data class DietUserConsumption( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val id: Long = 0, + + @Expose @get: NotNull val dietUserId: Long = 0, + @Expose @get: NotNull val rawMaterialId: Long = 0, + @Expose @get: NotNull val name: String = "", + @Expose @get: NonNull var dateConsumption: String = "", + + @Expose @get: NotNull val quantity: Double = 0.0, + @Expose @get: NotNull val quantityUnit: String = "", + + @Expose @get: NotNull val cal: Int = 0, + @Expose @get: NotNull val protein: Double = 0.0, + @Expose @get: NotNull val fat: Double = 0.0, + @Expose @get: NotNull val ch: Double = 0.0, + @Expose @get: NotNull val sugar: Double = 0.0, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietUserPreference.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserPreference.kt new file mode 100644 index 0000000..a66d8c2 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserPreference.kt @@ -0,0 +1,16 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import javax.validation.constraints.NotNull + +@Entity +data class DietUserPreference( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0, + @Expose @get: NotNull val dietUserId: Long = 0, + @Expose @get: NotNull val rawMaterialId: Long = 0, + @Expose @get: NotNull val temperature: Byte = 0, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/DietUserSensitivity.kt b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserSensitivity.kt new file mode 100644 index 0000000..d9aa84c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/DietUserSensitivity.kt @@ -0,0 +1,15 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import javax.validation.constraints.NotNull + +@Entity +data class DietUserSensitivity( + @Expose @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long = 0, + @Expose @get: NotNull val dietUserId: Long = 0, + @Expose @get: NotNull val sensitivityId: Long = 0, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/RawMaterial.kt b/src/main/kotlin/com/aitrainer/api/model/diet/RawMaterial.kt new file mode 100644 index 0000000..85ba350 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/RawMaterial.kt @@ -0,0 +1,22 @@ +package com.aitrainer.api.model.diet +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull + +@Entity +data class RawMaterial ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val id: Long = 0, + + @Expose @get: NotNull val name: String = "", + @Expose @get: NotNull val description: String = "", + @Expose @get: NotNull val kcalMin: Int = 0, + @Expose @get: NotNull val kcalMax: Int = 0, + @Expose @get: NotNull val proteinMin: Int = 0, + @Expose @get: NotNull val proteinMax: Int = 0, + @Expose @get: NotNull val fatMin: Int = 0, + @Expose @get: NotNull val fatMax: Int = 0, + @Expose @get: NotNull val chMin: Int = 0, + @Expose @get: NotNull val chMax: Int = 0, + @Expose @get: NotNull val sugar: Int = 0, + @Expose @get: NotNull val storeId: Long = 0, +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/Recipe.kt b/src/main/kotlin/com/aitrainer/api/model/diet/Recipe.kt new file mode 100644 index 0000000..87d68c6 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/Recipe.kt @@ -0,0 +1,26 @@ +package com.aitrainer.api.model.diet + + +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.hibernate.annotations.Fetch +import org.hibernate.annotations.FetchMode +import org.jetbrains.annotations.NotNull + +@Entity +data class Recipe ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val recipeId: Long = 0, + + @Expose @get: NotNull val name: String = "", + @Expose @get: NotNull val description: String = "", + + @Expose @get: NotNull val cal: Int = 0, + @Expose @get: NotNull val protein: Double = 0.0, + @Expose @get: NotNull val fat: Double = 0.0, + @Expose @get: NotNull val ch: Double = 0.0, + @Expose @get: NotNull val dietUserId: Long = 0, +) { + @OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.EAGER, mappedBy = "recipe") + @Fetch(value = FetchMode.SUBSELECT) + @Expose val rawMaterials: MutableList = mutableListOf() +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/RecipeRawMaterial.kt b/src/main/kotlin/com/aitrainer/api/model/diet/RecipeRawMaterial.kt new file mode 100644 index 0000000..7e8d62e --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/RecipeRawMaterial.kt @@ -0,0 +1,20 @@ +package com.aitrainer.api.model.diet + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull + +@Entity +data class RecipeRawMaterial ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val id: Long = 0, + + @Expose @get: NotNull var rawMaterialId: Int = 0, + @Expose @get: NotNull var quantity: Int = 0, + @Expose @get: NotNull var quantityUnit: String = "", +) { + @ManyToOne(fetch = FetchType.EAGER, optional = false) + @JoinColumn(name = "recipeId", nullable = false) + @JsonIgnore + var recipe: Recipe? = null +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/diet/Store.kt b/src/main/kotlin/com/aitrainer/api/model/diet/Store.kt new file mode 100644 index 0000000..4534b16 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/diet/Store.kt @@ -0,0 +1,13 @@ +package com.aitrainer.api.model.diet + +import com.google.gson.annotations.Expose +import jakarta.persistence.* +import org.jetbrains.annotations.NotNull + +@Entity +data class Store ( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Expose val storeId: Long = 0, + + @Expose @get: NotNull val storeName: String = "", + @Expose @get: NotNull val country: String = "", +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/openai/OpenAIService.kt b/src/main/kotlin/com/aitrainer/api/openai/OpenAIService.kt new file mode 100644 index 0000000..0bc6d4e --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/openai/OpenAIService.kt @@ -0,0 +1,53 @@ +package com.aitrainer.api.openai + +import com.aallam.openai.client.OpenAI +import com.aallam.openai.api.completion.CompletionRequest +import com.aallam.openai.api.completion.TextCompletion +import com.aallam.openai.api.model.Model +import com.aallam.openai.api.model.ModelId +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.util.Properties + +class OpenAIService { + + + private var openAI: OpenAI? = null + var model: Model? = null + private val properties = Properties() + + init { + val inputStream = ClassLoader.getSystemResourceAsStream("application.properties") + properties.load(inputStream) + inputStream?.close() + } + + private var modelId: ModelId? = null + private suspend fun connect(modelName: String) { + openAI = OpenAI(properties.getProperty("openai.key")) + modelId = ModelId(modelName) + model = openAI!!.model(modelId!!) + + } + + suspend fun completion(question: String): String { + return withContext(Dispatchers.IO) { + if (openAI == null) { + connect("text-davinci-003") + } + val completionRequest = CompletionRequest( + model = modelId!!, + prompt = question, + //echo = true, + maxTokens = 128, + temperature=0.1, + ) + val completion: TextCompletion = openAI!!.completion(completionRequest) + val result = completion.choices[0].text + + //println("Completion: $result") + result + } + } +} + diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerConversationRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerConversationRepository.kt new file mode 100644 index 0000000..ceaa384 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerConversationRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerConversation +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface CustomerConversationRepository : JpaRepository { + fun findByCustomerId(customerId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietRawMaterialRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietRawMaterialRepository.kt new file mode 100644 index 0000000..ca35269 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietRawMaterialRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietRawMaterial +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface DietRawMaterialRepository : JpaRepository { + fun findByDietId(dietId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietRepository.kt new file mode 100644 index 0000000..3678596 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.Diet +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface DietRepository : JpaRepository { + fun findByDietUserId(dietUserId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietSensitivityRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietSensitivityRepository.kt new file mode 100644 index 0000000..e4f3da6 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietSensitivityRepository.kt @@ -0,0 +1,6 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietSensitivity +import org.springframework.data.jpa.repository.JpaRepository + +interface DietSensitivityRepository : JpaRepository diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserConsumptionRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserConsumptionRepository.kt new file mode 100644 index 0000000..a25db25 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserConsumptionRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietUserConsumption +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface DietUserConsumptionRepository : JpaRepository { + fun findByDietUserId(dietUserId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserPreferenceRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserPreferenceRepository.kt new file mode 100644 index 0000000..aaa7fe9 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserPreferenceRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietUserPreference +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface DietUserPreferenceRepository : JpaRepository { + fun findByDietUserId(dietUserId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserRepository.kt new file mode 100644 index 0000000..b2accc3 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietUser +import org.springframework.data.jpa.repository.JpaRepository + +interface DietUserRepository : JpaRepository { + fun findByCustomerId(customerId: Long): DietUser? + + fun findByDietUserId(dietUserId: Long): DietUser? +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserSensitivityRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserSensitivityRepository.kt new file mode 100644 index 0000000..326a589 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/DietUserSensitivityRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.DietUserSensitivity +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface DietUserSensitivityRepository : JpaRepository { + fun findByDietUserId(dietUserId: Long): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/RawMaterialRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/RawMaterialRepository.kt new file mode 100644 index 0000000..1a543ae --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/RawMaterialRepository.kt @@ -0,0 +1,12 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.RawMaterial +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query + +interface RawMaterialRepository : JpaRepository { + @Query(" FROM RawMaterial " + + " WHERE id = :id" + ) + fun findByRawMaterialId(id: Long): RawMaterial? +} diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRawMaterialRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRawMaterialRepository.kt new file mode 100644 index 0000000..f892160 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRawMaterialRepository.kt @@ -0,0 +1,9 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.RecipeRawMaterial +import org.springframework.data.jpa.repository.JpaRepository + +interface RecipeRawMaterialRepository : JpaRepository { + + fun findByRawMaterialId(rawMaterialId: Long): List? +} diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRepository.kt new file mode 100644 index 0000000..5383261 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/RecipeRepository.kt @@ -0,0 +1,14 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.Recipe +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query + +interface RecipeRepository : JpaRepository { + @Query(" FROM Recipe WHERE name like %:name%") + fun findByName(name: String): List? + + fun findByDietUserId(dietUserId: Long): List? + @Query(" FROM Recipe WHERE recipeId = :recipeId") + fun findByRecipeId(recipeId: Long): Recipe? +} diff --git a/src/main/kotlin/com/aitrainer/api/repository/diet/StoreRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/diet/StoreRepository.kt new file mode 100644 index 0000000..1144a9a --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/diet/StoreRepository.kt @@ -0,0 +1,11 @@ +package com.aitrainer.api.repository.diet + +import com.aitrainer.api.model.diet.Store +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query + +interface StoreRepository : JpaRepository { + @Query(" FROM Store WHERE storeName = :name and country = :country") + fun findByNameAndCountry(name: String, country: String ): Store? + +} diff --git a/src/main/kotlin/com/aitrainer/api/service/Email.kt b/src/main/kotlin/com/aitrainer/api/service/Email.kt index a0abd67..ce54b31 100644 --- a/src/main/kotlin/com/aitrainer/api/service/Email.kt +++ b/src/main/kotlin/com/aitrainer/api/service/Email.kt @@ -3,9 +3,6 @@ package com.aitrainer.api.service import java.util.Properties import jakarta.mail.* import jakarta.mail.internet.* -import org.jasypt.encryption.StringEncryptor -import org.jasypt.encryption.pbe.PooledPBEStringEncryptor -import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig class Email { @@ -19,23 +16,9 @@ class Email { put("mail.smtp.port", "587") } - fun getEncryptor(): StringEncryptor { - val encryptor = PooledPBEStringEncryptor() - val config = SimpleStringPBEConfig() - config.password = "workouttest" - config.algorithm = "PBEWithMD5AndDES" - config.setKeyObtentionIterations("1000") - config.setPoolSize("1") - config.providerName = "SunJCE" - config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") - config.stringOutputType = "base64" - encryptor.setConfig(config) - return encryptor - } - val session: Session = Session.getInstance(properties, object : Authenticator() { override fun getPasswordAuthentication(): PasswordAuthentication { - return PasswordAuthentication("service@workouttest.com", getEncryptor().decrypt(encodedPassword)) + return PasswordAuthentication("service@workouttest.com", Encryptor.getEncryptor().decrypt(encodedPassword)) } }) @@ -47,7 +30,7 @@ class Email { } val bodyPart = MimeBodyPart().apply { - setContent(emailBody, "text/html") + setContent(emailBody, "text/html; charset=UTF-8") } val multipart = MimeMultipart().apply { diff --git a/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt b/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt index 5c74bcc..fe7ab78 100644 --- a/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt +++ b/src/main/kotlin/com/aitrainer/api/service/EmailTemplateService.kt @@ -10,14 +10,15 @@ class EmailTemplateService { @Autowired private var templateEngine: TemplateEngine? = null - fun getEmailBody(firstname: String, activationLink: String): String { + fun getEmailBody(firstname: String, activationLink: String, template: String): String { val context = Context() context.setVariable("firstname", firstname) context.setVariable("activationLink", activationLink) if ( templateEngine == null) { templateEngine = TemplateEngine() } - return templateEngine!!.process("registration_email", context) + + return templateEngine!!.process(template, context) } fun getSubject(): String { @@ -27,5 +28,12 @@ class EmailTemplateService { } return templateEngine!!.process("registration_subject", context) } + fun getSubjectDiet(): String { + val context = Context() + if ( templateEngine == null) { + templateEngine = TemplateEngine() + } + return templateEngine!!.process("diet_registration_subject", context) + } } diff --git a/src/main/kotlin/com/aitrainer/api/service/Encryptor.kt b/src/main/kotlin/com/aitrainer/api/service/Encryptor.kt new file mode 100644 index 0000000..8985943 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/service/Encryptor.kt @@ -0,0 +1,21 @@ +package com.aitrainer.api.service + +import org.jasypt.encryption.StringEncryptor +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig + +object Encryptor { + fun getEncryptor(): StringEncryptor { + val encryptor = PooledPBEStringEncryptor() + val config = SimpleStringPBEConfig() + config.password = "workouttest" + config.algorithm = "PBEWithMD5AndDES" + config.setKeyObtentionIterations("1000") + config.setPoolSize("1") + config.providerName = "SunJCE" + config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") + config.stringOutputType = "base64" + encryptor.setConfig(config) + return encryptor + } +} \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 4497da4..3fffd5b 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -14,6 +14,6 @@ logging.config=classpath:logback-spring.xml logging.file=logs # if the database structue has been changed, increment this version number -application.version=1.1.0 +application.version=1.2.0 jwt.secret=aitrainer \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7f5a994..0c644cf 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -17,6 +17,9 @@ logging.config=classpath:logback-spring.xml logging.file=logs # if the database structure has been changed, increment this version number -application.version=1.1.0 +application.version=1.2.0 jwt.secret=aitrainer + +openai.key=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 +spring.mail.properties.mail.mime.charset=UTF-8 diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 4c5614d..819a986 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -28,7 +28,7 @@ -