diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f6a4478..bb501b9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,9 @@ -name: test coverage +name: Test Coverage + on: pull_request: - branches: + branches: - 'dev' paths: - '**.java' @@ -12,6 +13,7 @@ permissions: pull-requests: write env: + APPLICATION: ${{ secrets.APPLICATION_TEST }} wd: ./backend jobs: @@ -20,25 +22,35 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up JDK 11 uses: actions/setup-java@v3 with: java-version: '11' distribution: 'temurin' + - name: Copy application.yml + working-directory: ${{ env.wd }} + run: | + touch ./src/test/resources/application.yml + echo "${{ secrets.APPLICATION_TEST }}" > ./src/test/resources/application.yml + - name: Setup Gradle uses: gradle/gradle-build-action@v2 - - name: Test with Gradle + - name: Run Coverage working-directory: ${{ env.wd }} - run: ./gradlew test - + run: | + chmod +x gradlew + ./gradlew testCoverage + - name: Add coverage to PR id: jacoco - uses: madrapps/jacoco-report@v1.2 + uses: madrapps/jacoco-report@v1.6.1 with: - paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml + paths: ${{ github.workspace }}/backend/build/reports/jacoco/test/jacocoTestReport.xml token: ${{ secrets.GITHUB_TOKEN }} title: ๐Ÿ“Š ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ๊ฒฐ๊ณผ min-coverage-overall: 80 - min-coverage-changed-files: 80 + update-comment: true + continue-on-error: true diff --git a/backend-recommend/recommend.py b/backend-recommend/recommend.py index 10e63cf..0460a72 100644 --- a/backend-recommend/recommend.py +++ b/backend-recommend/recommend.py @@ -25,7 +25,7 @@ def recByApriori(body): optionList = body['options'] for i in range(len(optionList)): - input.append(optionList[i]['subOptionId']) + input.append(str(optionList[i])) input = set(input) dataset = [] @@ -65,6 +65,9 @@ def recByApriori(body): response = [] for item in top_items: consequent = item[0] - response.append({"salesOptions": ",".join(consequent)}) + subResponse = [] + for option in consequent: + subResponse.append(int(option)) + response.append(subResponse) return jsonify(response) \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index 6c3f256..f2a5319 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -37,4 +37,5 @@ out/ .vscode/ ### yml files ### -src/main/resources/application.yml \ No newline at end of file +src/main/resources/application.yml +src/test/resources/application.yml \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle index a4e0ea3..29333fb 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -41,40 +41,26 @@ tasks.named('test') { } jacoco { - toolVersion = '0.8.9' -} - -test { - useJUnitPlatform() - finalizedBy jacocoTestReport + toolVersion = '0.8.9' } jacocoTestReport { - dependsOn test - reports { - xml.required = true - } - finalizedBy 'jacocoTestCoverageVerification' + dependsOn test + reports { + xml.required = true + html.required = true + csv.required = false + } } -jacocoTestCoverageVerification { - violationRules { - rule { - limit { - counter = 'LINE' - value = 'COVEREDRATIO' - minimum = 0.8 - } - limit { - counter = 'METHOD' - value = 'COVEREDRATIO' - minimum = 0.8 - } - } - } +tasks.register('testCoverage', Test) { + group 'verification' + description 'Runs the tests with covarage (Create JaCoCo report)' + + dependsOn test, jacocoTestReport + tasks['jacocoTestReport'].mustRunAfter(tasks['test']) } jar { enabled = false } - diff --git a/backend/src/main/java/autoever2/cartag/controller/CarController.java b/backend/src/main/java/autoever2/cartag/controller/CarController.java index 4538b1a..503cd12 100644 --- a/backend/src/main/java/autoever2/cartag/controller/CarController.java +++ b/backend/src/main/java/autoever2/cartag/controller/CarController.java @@ -1,10 +1,7 @@ package autoever2.cartag.controller; -import autoever2.cartag.domain.car.BoughtCarDto; import autoever2.cartag.domain.car.CarDefaultDto; import autoever2.cartag.domain.car.CarDto; -import autoever2.cartag.domain.share.QuoteIdList; -import autoever2.cartag.domain.share.QuoteInfoDto; import autoever2.cartag.domain.car.CarTypeDto; import autoever2.cartag.service.CarService; import io.swagger.v3.oas.annotations.Operation; @@ -15,7 +12,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -56,24 +52,4 @@ public List carTrimInfo(@Parameter(description = "์„ ํƒํ•œ car_type") @ public CarDefaultDto carDefaultDto(@Parameter(description = "์„ ํƒํ•œ car_id") @RequestParam("carid") int carId) { return service.findCarDefaultDtoByCarId(carId); } - - @Operation(summary = "์ฐจ๋Ÿ‰ ๊ตฌ๋งค ์ •๋ณด ๋ฐ˜ํ™˜ api", description = "์ฐจ๋Ÿ‰ ๊ตฌ๋งค ์ •๋ณด ์กฐํšŒ method") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "์กฐํšŒ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = BoughtCarDto.class))), - }) - @GetMapping("bought/infos") - public List boughtCarDtos() { - return service.findAllBoughInfos(); - } - - @Operation(summary = "์ฐจ๋Ÿ‰ ๊ณต์œ ํ•˜๊ธฐ๋ฅผ ์œ„ํ•œ api", description = "์ฐจ๋Ÿ‰ ๊ณต์œ ๋ฅผ ์œ„ํ•œ ์ •๋ณด ๋ฐ˜ํ™˜") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "์กฐํšŒ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = QuoteInfoDto.class))), - }) - @PostMapping("/infos/shares") - public QuoteInfoDto boughtCarDtos(@Parameter(description = "์„ ํƒํ•œ id ๋ฆฌ์ŠคํŠธ") @RequestBody QuoteIdList idList) { - return service.findShareInfoDto(idList); - } - - } diff --git a/backend/src/main/java/autoever2/cartag/controller/ModelController.java b/backend/src/main/java/autoever2/cartag/controller/ModelController.java index ce55de9..0a9fcac 100644 --- a/backend/src/main/java/autoever2/cartag/controller/ModelController.java +++ b/backend/src/main/java/autoever2/cartag/controller/ModelController.java @@ -3,7 +3,6 @@ import autoever2.cartag.domain.model.ModelDetailMappedDto; import autoever2.cartag.domain.model.ModelEfficiencyDataDto; import autoever2.cartag.domain.model.ModelShortDataDto; -import autoever2.cartag.domain.model.PowerTrainMappedDto; import autoever2.cartag.service.ModelService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -37,7 +36,8 @@ public class ModelController { }) @GetMapping("/list") public List getTrimModelType(@Parameter(description = "์„ ํƒํ•œ ์ฐจ๋Ÿ‰ ํŠธ๋ฆผID") @RequestParam("carid") int carId) { - return modelTypeService.getModelTypeData(carId); + List result = modelTypeService.getModelTypeData(carId); + return result; } @Operation(summary = "๋ชจ๋ธํƒ€์ž… ์ƒ์„ธ ๋ฐ์ดํ„ฐ ์กฐํšŒ", description = "๋ชจ๋ธ๋ช…๊ณผ ์„ค๋ช…, ์ด๋ฏธ์ง€ ๋ฐ˜ํ™˜ํ•˜๋Š” api") diff --git a/backend/src/main/java/autoever2/cartag/controller/QuoteController.java b/backend/src/main/java/autoever2/cartag/controller/QuoteController.java new file mode 100644 index 0000000..954ad33 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/controller/QuoteController.java @@ -0,0 +1,60 @@ +package autoever2.cartag.controller; + +import autoever2.cartag.domain.car.BoughtCarDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; +import autoever2.cartag.service.CarService; +import autoever2.cartag.service.QuoteService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/quote") +@RequiredArgsConstructor +public class QuoteController { + + private final CarService carService; + private final QuoteService quoteService; + + @Operation(summary = "์ถ”์ฒœ ๊ฒฌ์  ๊ทธ๋ž˜ํ”„ ์ œ๊ณต API", description = "์œ ์‚ฌ๊ฒฌ์ (์ตœ๋Œ€ 4๊ฐœ)์™€ ํŒ๋งคํšŸ์ˆ˜ ์ œ๊ณต") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "์กฐํšŒ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = HistoryShortDto.class))) + }) + @PostMapping("/list") + public HistoryShortDto getRecommendedList(@RequestBody QuoteDataDto quoteDataDto) { + HistoryShortDto myQuote = quoteService.findMyQuote(quoteDataDto); + List subList = quoteService.findTopHistory(quoteDataDto); + + myQuote.setHistories(subList); + + return myQuote; + } + + @Operation(summary = "์ฐจ๋Ÿ‰ ๊ตฌ๋งค ์ •๋ณด ๋ฐ˜ํ™˜ api", description = "์ฐจ๋Ÿ‰ ๊ตฌ๋งค ์ •๋ณด ์กฐํšŒ method") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "์กฐํšŒ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = BoughtCarDto.class))), + }) + @GetMapping("bought/infos") + public List getAllHistorySum() { + return carService.findAllBoughInfos(); + } + + @Operation(summary = "์ฐจ๋Ÿ‰ ๊ณต์œ ํ•˜๊ธฐ๋ฅผ ์œ„ํ•œ api", description = "์ฐจ๋Ÿ‰ ๊ณต์œ ๋ฅผ ์œ„ํ•œ ์ •๋ณด ๋ฐ˜ํ™˜") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "์กฐํšŒ ์„ฑ๊ณต", content = @Content(schema = @Schema(implementation = QuoteInfoDto.class))), + }) + @PostMapping("/infos/shares") + public QuoteInfoDto getQuoteDetail(@Parameter(description = "์„ ํƒํ•œ id ๋ฆฌ์ŠคํŠธ") @RequestBody QuoteDataDto idList) { + QuoteInfoDto data = carService.findShareInfoDto(idList); + return data; + } +} diff --git a/backend/src/main/java/autoever2/cartag/controller/RecommendController.java b/backend/src/main/java/autoever2/cartag/controller/RecommendController.java deleted file mode 100644 index 3d56738..0000000 --- a/backend/src/main/java/autoever2/cartag/controller/RecommendController.java +++ /dev/null @@ -1,21 +0,0 @@ -package autoever2.cartag.controller; - -import autoever2.cartag.service.RecommendService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api/recommend") -@RequiredArgsConstructor -public class RecommendController { - - private final RecommendService recommendService; - - @PostMapping("/list") - public ResponseEntity getRecommendedList() { - return ResponseEntity.ok(recommendService.getList()); - } -} diff --git a/backend/src/main/java/autoever2/cartag/domain/color/OuterColorDto.java b/backend/src/main/java/autoever2/cartag/domain/color/OuterColorDto.java index 0db211f..b2d4069 100644 --- a/backend/src/main/java/autoever2/cartag/domain/color/OuterColorDto.java +++ b/backend/src/main/java/autoever2/cartag/domain/color/OuterColorDto.java @@ -24,7 +24,8 @@ public class OuterColorDto { private String colorCarImage; @Builder - public OuterColorDto(String colorName, String colorImage, Long colorPrice, Long colorBoughtCount, String colorCarImage) { + public OuterColorDto(int colorId, String colorName, String colorImage, Long colorPrice, Long colorBoughtCount, String colorCarImage) { + this.colorId = colorId; this.colorName = colorName; this.colorImage = colorImage; this.colorPrice = colorPrice; diff --git a/backend/src/main/java/autoever2/cartag/domain/model/PowerTrainMappedDto.java b/backend/src/main/java/autoever2/cartag/domain/model/PowerTrainMappedDto.java deleted file mode 100644 index 93b7a55..0000000 --- a/backend/src/main/java/autoever2/cartag/domain/model/PowerTrainMappedDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package autoever2.cartag.domain.model; - -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.util.Objects; - -@Setter -@Getter -@NoArgsConstructor -public class PowerTrainMappedDto { - - private String maxPs; - private String maxKgfm; - - @Builder - public PowerTrainMappedDto(String maxPs, String maxKgfm) { - this.maxPs = maxPs; - this.maxKgfm = maxKgfm; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PowerTrainMappedDto that = (PowerTrainMappedDto) o; - return Objects.equals(maxPs, that.maxPs) && Objects.equals(maxKgfm, that.maxKgfm); - } -} diff --git a/backend/src/main/java/autoever2/cartag/domain/option/QuoteSubOptionDto.java b/backend/src/main/java/autoever2/cartag/domain/option/QuoteSubOptionDto.java index d1a3c65..bbed920 100644 --- a/backend/src/main/java/autoever2/cartag/domain/option/QuoteSubOptionDto.java +++ b/backend/src/main/java/autoever2/cartag/domain/option/QuoteSubOptionDto.java @@ -1,13 +1,25 @@ package autoever2.cartag.domain.option; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter +@NoArgsConstructor public class QuoteSubOptionDto { private int optionId; private String optionName; private Long optionPrice; private String optionTitle; private String optionImage; + + @Builder + public QuoteSubOptionDto(int optionId, String optionName, Long optionPrice, String optionTitle, String optionImage) { + this.optionId = optionId; + this.optionName = optionName; + this.optionPrice = optionPrice; + this.optionTitle = optionTitle; + this.optionImage = optionImage; + } } diff --git a/backend/src/main/java/autoever2/cartag/domain/option/SubOptionIdAndPriceDto.java b/backend/src/main/java/autoever2/cartag/domain/option/SubOptionIdAndPriceDto.java new file mode 100644 index 0000000..2a78c42 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/domain/option/SubOptionIdAndPriceDto.java @@ -0,0 +1,19 @@ +package autoever2.cartag.domain.option; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class SubOptionIdAndPriceDto { + private int optionId; + private Long optionPrice; + @Builder + public SubOptionIdAndPriceDto(int optionId, Long optionPrice) { + this.optionId = optionId; + this.optionPrice = optionPrice; + } +} diff --git a/backend/src/main/java/autoever2/cartag/domain/quote/HistorySearchDto.java b/backend/src/main/java/autoever2/cartag/domain/quote/HistorySearchDto.java new file mode 100644 index 0000000..42da0ec --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/domain/quote/HistorySearchDto.java @@ -0,0 +1,57 @@ +package autoever2.cartag.domain.quote; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@NoArgsConstructor +@Getter +public class HistorySearchDto { + + private int carId; + private int powerTrainId; + private int bodyTypeId; + private int operationId; + private List optionIds; + + @Builder + public HistorySearchDto(int carId, int powerTrainId, int bodyTypeId, int operationId, List optionIds) { + this.carId = carId; + this.powerTrainId = powerTrainId; + this.bodyTypeId = bodyTypeId; + this.operationId = operationId; + this.optionIds = new ArrayList<>(); + + this.optionIds.addAll(optionIds); + } + + public void addAllOption(List optionId) { + optionIds.addAll(optionId); + } + + public String getOptionIds() { + if(optionIds.isEmpty()) { + return ""; + } + + StringBuilder stringBuilder = new StringBuilder(); + for(int index = 0; index < optionIds.size() - 1; index++) { + stringBuilder.append(optionIds.get(index)).append(","); + } + stringBuilder.append(optionIds.get(optionIds.size()-1)); + + return stringBuilder.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HistorySearchDto that = (HistorySearchDto) o; + return carId == that.carId && powerTrainId == that.powerTrainId && bodyTypeId == that.bodyTypeId && operationId == that.operationId && Objects.equals(optionIds, that.optionIds); + } +} diff --git a/backend/src/main/java/autoever2/cartag/domain/quote/HistoryShortDto.java b/backend/src/main/java/autoever2/cartag/domain/quote/HistoryShortDto.java new file mode 100644 index 0000000..7ad1535 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/domain/quote/HistoryShortDto.java @@ -0,0 +1,31 @@ +package autoever2.cartag.domain.quote; + +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Schema(description = "์‹ค์ œ ํŒ๋งค๊ฒฌ์  ๊ฐ„๋žต ๋ฐ์ดํ„ฐ") +@Getter +@Setter +@NoArgsConstructor +public class HistoryShortDto { + + @Schema(description = "๊ฒฌ์ ์˜ ID, ๋˜๋Š” ๋‚ด ๊ฒฌ์ ์˜ ID") + private Long historyId; + @Schema(description = "๊ฒฌ์ ์˜ ํŒ๋งค ํšŸ์ˆ˜") + private int soldCount; + @ArraySchema(schema = @Schema(implementation = HistoryShortDto.class, description = "์œ ์‚ฌ๊ฒฌ์  ์ƒ์œ„ 4๊ฐœ ๋ฐ˜ํ™˜")) + List histories; + + @Builder + public HistoryShortDto(Long historyId, int soldCount, List histories) { + this.historyId = historyId; + this.soldCount = soldCount; + this.histories = histories; + } +} diff --git a/backend/src/main/java/autoever2/cartag/domain/quote/QuoteDataDto.java b/backend/src/main/java/autoever2/cartag/domain/quote/QuoteDataDto.java new file mode 100644 index 0000000..03b287a --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/domain/quote/QuoteDataDto.java @@ -0,0 +1,41 @@ +package autoever2.cartag.domain.quote; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Getter @Setter +@NoArgsConstructor +public class QuoteDataDto { + private int carId; + private int powerTrainId; + private int bodyTypeId; + private int operationId; + private int outerColorId; + private int innerColorId; + private List optionIdList = new ArrayList<>(); + + @Builder + public QuoteDataDto(int carId, int powerTrainId, int bodyTypeId, int operationId, int outerColorId, int innerColorId, List optionIdList) { + this.carId = carId; + this.powerTrainId = powerTrainId; + this.bodyTypeId = bodyTypeId; + this.operationId = operationId; + this.outerColorId = outerColorId; + this.innerColorId = innerColorId; + this.optionIdList = optionIdList; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + QuoteDataDto that = (QuoteDataDto) o; + return carId == that.carId && powerTrainId == that.powerTrainId && bodyTypeId == that.bodyTypeId && operationId == that.operationId && outerColorId == that.outerColorId && innerColorId == that.innerColorId && Objects.equals(optionIdList, that.optionIdList); + } +} diff --git a/backend/src/main/java/autoever2/cartag/domain/share/QuoteInfoDto.java b/backend/src/main/java/autoever2/cartag/domain/quote/QuoteInfoDto.java similarity index 98% rename from backend/src/main/java/autoever2/cartag/domain/share/QuoteInfoDto.java rename to backend/src/main/java/autoever2/cartag/domain/quote/QuoteInfoDto.java index 4f3770f..c831fdc 100644 --- a/backend/src/main/java/autoever2/cartag/domain/share/QuoteInfoDto.java +++ b/backend/src/main/java/autoever2/cartag/domain/quote/QuoteInfoDto.java @@ -1,4 +1,4 @@ -package autoever2.cartag.domain.share; +package autoever2.cartag.domain.quote; import autoever2.cartag.domain.car.TrimInfoDto; import autoever2.cartag.domain.color.InnerColorDto; @@ -22,6 +22,7 @@ public class QuoteInfoDto { private int carDefaultPrice; @Schema(description = "powerTrain์˜ id") private int powerTrainId; + @Schema(description = "ํŒŒ์›ŒํŠธ๋ ˆ์ธ ๋ช…") private String powerTrainTitle; @Schema(description = "๊ธฐ๋ณธ powerTrain์˜ ์ด๋ฆ„", example = "๋””์ ค 2.2") private String powerTrainName; diff --git a/backend/src/main/java/autoever2/cartag/domain/share/QuoteIdList.java b/backend/src/main/java/autoever2/cartag/domain/share/QuoteIdList.java deleted file mode 100644 index d84336a..0000000 --- a/backend/src/main/java/autoever2/cartag/domain/share/QuoteIdList.java +++ /dev/null @@ -1,17 +0,0 @@ -package autoever2.cartag.domain.share; - -import lombok.Getter; -import lombok.Setter; - -import java.util.ArrayList; -import java.util.List; -@Getter @Setter -public class QuoteIdList { - private int carId; - private int powerTrainId; - private int bodyTypeId; - private int operationId; - private int outerColorId; - private int innerColorId; - private List optionIdList = new ArrayList<>(); -} diff --git a/backend/src/main/java/autoever2/cartag/exception/ErrorCode.java b/backend/src/main/java/autoever2/cartag/exception/ErrorCode.java index d86cdb0..3432fdd 100644 --- a/backend/src/main/java/autoever2/cartag/exception/ErrorCode.java +++ b/backend/src/main/java/autoever2/cartag/exception/ErrorCode.java @@ -7,9 +7,11 @@ @Getter @RequiredArgsConstructor public enum ErrorCode { - INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "Invalid parameter included"), - RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND, "Resource not exists"), - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Unknown error"); + INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "์ž˜๋ชป๋œ ํŒŒ๋ผ๋ฏธํ„ฐ ํ˜•์‹์ž…๋‹ˆ๋‹ค."), + INVALID_OPTIONS_REQUEST(HttpStatus.BAD_REQUEST, "์ž˜๋ชป๋œ ์˜ต์…˜์œผ๋กœ ์ ‘๊ทผํ•˜์˜€์Šต๋‹ˆ๋‹ค."), + DATA_NOT_EXISTS(HttpStatus.NOT_FOUND, "๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "์„œ๋ฒ„์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ฌธ์˜ํ•˜์„ธ์š”."), + PARSE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."); private final HttpStatus httpStatus; private final String message; diff --git a/backend/src/main/java/autoever2/cartag/exception/GlobalExceptionHandler.java b/backend/src/main/java/autoever2/cartag/exception/GlobalExceptionHandler.java index 5868423..85a1962 100644 --- a/backend/src/main/java/autoever2/cartag/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/autoever2/cartag/exception/GlobalExceptionHandler.java @@ -1,10 +1,12 @@ package autoever2.cartag.exception; +import lombok.extern.log4j.Log4j2; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice +@Log4j2 public class GlobalExceptionHandler { @ExceptionHandler(EmptyDataException.class) @@ -15,4 +17,22 @@ public ResponseEntity handleEmptyDataException(EmptyDataException .message(errorCode.getMessage()) .build()); } + + @ExceptionHandler(InvalidDataException.class) + public ResponseEntity handleInvalidDataException(InvalidDataException e) { + ErrorCode errorCode = e.getErrorCode(); + return ResponseEntity.status(errorCode.getHttpStatus()).body(ErrorResponse.builder() + .code(errorCode.toString()) + .message(errorCode.getMessage()) + .build()); + } + + @ExceptionHandler(ServerException.class) + public ResponseEntity handleServerException(ServerException e) { + ErrorCode errorCode = e.getErrorCode(); + log.error("Server Error: " + errorCode.getMessage()); + return ResponseEntity.status(errorCode.getHttpStatus()).body(ErrorResponse.builder() + .code(errorCode.toString()) + .build()); + } } diff --git a/backend/src/main/java/autoever2/cartag/exception/InvalidDataException.java b/backend/src/main/java/autoever2/cartag/exception/InvalidDataException.java new file mode 100644 index 0000000..997122d --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/exception/InvalidDataException.java @@ -0,0 +1,11 @@ +package autoever2.cartag.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class InvalidDataException extends RuntimeException { + + private final ErrorCode errorCode; +} diff --git a/backend/src/main/java/autoever2/cartag/exception/ServerException.java b/backend/src/main/java/autoever2/cartag/exception/ServerException.java new file mode 100644 index 0000000..f7d5cd1 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/exception/ServerException.java @@ -0,0 +1,19 @@ +package autoever2.cartag.exception; + +import lombok.Getter; + +@Getter +public class ServerException extends RuntimeException { + private final ErrorCode errorCode; + private final String message; + + public ServerException(ErrorCode errorCode) { + this.errorCode = errorCode; + this.message = null; + } + + public ServerException(ErrorCode errorCode, String cause) { + this.errorCode = errorCode; + this.message = cause; + } +} diff --git a/backend/src/main/java/autoever2/cartag/recommend/RecommendConnector.java b/backend/src/main/java/autoever2/cartag/recommend/RecommendConnector.java new file mode 100644 index 0000000..c14d001 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/recommend/RecommendConnector.java @@ -0,0 +1,81 @@ +package autoever2.cartag.recommend; + +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.exception.ErrorCode; +import autoever2.cartag.exception.ServerException; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.List; + +@Component +public class RecommendConnector { + + @Value("${python.url}") + private String requestURL; + + public List> request(QuoteDataDto quoteDataDto) { + + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(requestURL)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(getJsonFromEstimate(quoteDataDto))).build(); + + HttpResponse response = null; + try { + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (InterruptedException e) { + throw new ServerException(ErrorCode.INTERNAL_SERVER_ERROR, e.getMessage()); + } catch (IOException e) { + throw new ServerException(ErrorCode.INTERNAL_SERVER_ERROR, e.getMessage()); + } + + return parseResponse(response.body()); + } + + + public String getJsonFromEstimate(QuoteDataDto quoteDataDto) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("carId", quoteDataDto.getCarId()); + jsonObject.put("powerTrain", quoteDataDto.getPowerTrainId()); + jsonObject.put("bodyType", quoteDataDto.getBodyTypeId()); + jsonObject.put("operation", quoteDataDto.getOperationId()); + jsonObject.put("options", quoteDataDto.getOptionIdList()); + + return jsonObject.toJSONString(); + } + + private List> parseResponse(String responseBody) { + JSONParser parser = new JSONParser(); + JSONArray resultArray = null; + try { + resultArray = (JSONArray) parser.parse(responseBody); + } catch (ParseException e) { + throw new ServerException(ErrorCode.PARSE_ERROR, e.getMessage()); + } + + List> result = new ArrayList<>(); + for (Object o : resultArray) { + JSONArray optionArray = (JSONArray) o; + List options = new ArrayList<>(); + + for (Object option : optionArray) { + options.add(Math.toIntExact((Long) option)); + } + + result.add(options); + } + return result; + } +} diff --git a/backend/src/main/java/autoever2/cartag/repository/CarRepository.java b/backend/src/main/java/autoever2/cartag/repository/CarRepository.java index 3c71ebb..2b6702e 100644 --- a/backend/src/main/java/autoever2/cartag/repository/CarRepository.java +++ b/backend/src/main/java/autoever2/cartag/repository/CarRepository.java @@ -68,8 +68,7 @@ public List findCarPriceAndCount() { String sql = "select SalesHistory.sold_options_id, (car_default_price + sum(model_price)) as sum from Model inner join HistoryModelMapper " + "on Model.model_id = HistoryModelMapper.model_id inner join SalesHistory " + "on SalesHistory.history_id = HistoryModelMapper.history_id inner join Car " + - "on Car.car_id = SalesHistory.car_id inner join SubOptionData " + - "on SubOptionData.car_id = Car.car_id group by SalesHistory.history_id"; + "on Car.car_id = SalesHistory.car_id group by SalesHistory.history_id"; return template.query(sql, carPriceRowMapper()); } diff --git a/backend/src/main/java/autoever2/cartag/repository/OptionRepository.java b/backend/src/main/java/autoever2/cartag/repository/OptionRepository.java index 079a4ab..2f8dcf1 100644 --- a/backend/src/main/java/autoever2/cartag/repository/OptionRepository.java +++ b/backend/src/main/java/autoever2/cartag/repository/OptionRepository.java @@ -4,6 +4,7 @@ import autoever2.cartag.domain.option.OptionDetailMappedDto; import autoever2.cartag.domain.option.OptionShortMappedDto; import autoever2.cartag.domain.option.QuoteSubOptionDto; +import autoever2.cartag.domain.option.SubOptionIdAndPriceDto; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.DataAccessUtils; import org.springframework.jdbc.core.BeanPropertyRowMapper; @@ -30,10 +31,10 @@ public List findOptionList(int carId, boolean isDefault) { StringBuilder query = new StringBuilder(); query.append("select o.option_id, o.option_name, oc.option_category_name, o.option_image, o.option_used_count "); - if(!isDefault) { + if (!isDefault) { query.append(", od.option_bought_count, od.option_price from SubOptionData od "); } - if(isDefault) { + if (isDefault) { query.append("from DefaultOptionData od "); } @@ -82,11 +83,11 @@ public Optional findOptionDetail(int carId, int optionId, StringBuilder query = new StringBuilder(); query.append("select oc.option_category_name as category_name, o.option_name, o.option_description, o.option_image, o.option_used_count "); - if(isDefault) { + if (isDefault) { query.append("from DefaultOptionData od "); } - if(!isDefault) { + if (!isDefault) { query.append(", od.option_bought_count from SubOptionData od "); } @@ -121,19 +122,7 @@ public List findPackageSubOptions(int optionId) { return template.query(sql, param, optionDetailRowMapper()); } - public Optional findOptionPriceByOptionId(int optionId) { - String sql = "select option_price from SubOptionData where option_id = :optionId"; - - try { - SqlParameterSource param = new MapSqlParameterSource() - .addValue("optionId", optionId); - return Optional.of(template.queryForObject(sql, param, Long.class)); - } catch (DataAccessException e) { - return Optional.empty(); - } - } - - public Optional findSubOptionByOptionId(int optionId){ + public Optional findSubOptionByOptionId(int optionId) { String sql = "select CarOption.option_id, option_name, option_image, option_price, option_category_name as optionTitle from CarOption inner join SubOptionData " + "on CarOption.option_id = SubOptionData.option_id inner join OptionCategory on " + "OptionCategory.option_category_id = CarOption.option_category_id where CarOption.option_id = :optionId"; @@ -146,8 +135,28 @@ public Optional findSubOptionByOptionId(int optionId){ } } + public List findAllSubOptionInfo() { + String sql = "select option_id, option_price from SubOptionData"; + return template.query(sql, subOptionIdAndPriceRowMapper()); + } + + private RowMapper subOptionIdAndPriceRowMapper() { + return BeanPropertyRowMapper.newInstance(SubOptionIdAndPriceDto.class); + } + private RowMapper shareSubOptionRowMapper() { return BeanPropertyRowMapper.newInstance(QuoteSubOptionDto.class); } + public Long countExistOptions(int carId, List optionIds) { + String sql = "select count(*) as totalCount " + + "from SubOptionData " + + "where car_id = :carId and option_id IN (:optionIds)"; + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("carId", carId) + .addValue("optionIds", optionIds); + + return template.queryForObject(sql, param, Long.class); + } } diff --git a/backend/src/main/java/autoever2/cartag/repository/QuoteRepository.java b/backend/src/main/java/autoever2/cartag/repository/QuoteRepository.java new file mode 100644 index 0000000..27f1a0a --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/repository/QuoteRepository.java @@ -0,0 +1,46 @@ +package autoever2.cartag.repository; + +import autoever2.cartag.domain.quote.HistorySearchDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import org.springframework.dao.support.DataAccessUtils; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; +import java.util.Optional; + +@Repository +public class QuoteRepository { + + private final NamedParameterJdbcTemplate template; + + public QuoteRepository(DataSource dataSource) { + this.template = new NamedParameterJdbcTemplate(dataSource); + } + + public Optional findShortData(HistorySearchDto historySearchDto) { + String sql = "select sh.history_id, sh.sold_count, sh.sold_options_id " + + "from SalesHistory sh " + + "inner join HistoryModelMapper hm " + + "on hm.history_id = sh.history_id " + + "where sh.car_id = :carId and sh.sold_options_id = :optionIds and hm.model_id in (:powerTrainId, :bodyTypeId, :operationId) " + + "group by sh.history_id having count(hm.model_id) = 3"; + + SqlParameterSource param = new MapSqlParameterSource() + .addValue("carId", historySearchDto.getCarId()) + .addValue("optionIds", historySearchDto.getOptionIds()) + .addValue("powerTrainId", historySearchDto.getPowerTrainId()) + .addValue("bodyTypeId", historySearchDto.getBodyTypeId()) + .addValue("operationId", historySearchDto.getOperationId()); + + return Optional.ofNullable(DataAccessUtils.singleResult(template.query(sql, param, historyShortRowMapper()))); + } + + private RowMapper historyShortRowMapper() { + return BeanPropertyRowMapper.newInstance(HistoryShortDto.class); + } +} diff --git a/backend/src/main/java/autoever2/cartag/service/CarService.java b/backend/src/main/java/autoever2/cartag/service/CarService.java index 9584a26..3c8686a 100644 --- a/backend/src/main/java/autoever2/cartag/service/CarService.java +++ b/backend/src/main/java/autoever2/cartag/service/CarService.java @@ -5,8 +5,9 @@ import autoever2.cartag.domain.color.OuterColorDto; import autoever2.cartag.domain.model.ModelDefaultDto; import autoever2.cartag.domain.option.QuoteSubOptionDto; -import autoever2.cartag.domain.share.QuoteIdList; -import autoever2.cartag.domain.share.QuoteInfoDto; +import autoever2.cartag.domain.option.SubOptionIdAndPriceDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; import autoever2.cartag.exception.EmptyDataException; import autoever2.cartag.exception.ErrorCode; import autoever2.cartag.repository.CarRepository; @@ -41,7 +42,7 @@ public List getAllCarTypes() { public List findCarByCarType(int carType) { List carInfos = carRepository.findCarByCarType(carType); if (carInfos.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } return carInfos.stream() @@ -54,12 +55,12 @@ public CarDefaultDto findCarDefaultDtoByCarId(int carId) { List innerColorList = colorRepository.findInnerColorCarByCarId(carId); List modelList = modelRepository.findModelDefaultDtoByCarId(carId); if (outerColorList.isEmpty() || innerColorList.isEmpty() || modelList.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } int colorId = outerColorList.get(0).getColorId(); Optional colorCarOuterImage = colorRepository.findOuterColorImagesByColorId(colorId); if (colorCarOuterImage.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } String value = colorCarOuterImage.get(); String outerImageUrl = value.substring(0, value.indexOf("*")) + 1 + value.substring(value.indexOf("*") + 1, value.length()); @@ -69,32 +70,30 @@ public CarDefaultDto findCarDefaultDtoByCarId(int carId) { public List findAllBoughInfos() { List carPriceAndCount = carRepository.findCarPriceAndCount(); - - return carPriceAndCount.stream() - .map(carPriceDto -> { - String optionList = carPriceDto.getOptionList(); - Long key = 0L; - if (optionList.isEmpty()) { - key = carPriceDto.getPrice() / 100000 * 100000; - } else { - String[] optionIdList = optionList.split(","); - - Long sum = Arrays.stream(optionIdList) - .mapToLong(s -> optionRepository.findOptionPriceByOptionId(Integer.parseInt(s)).get()) - .sum(); - - key = ((carPriceDto.getPrice() + sum) / 100000) * 1000000; - } - - return Map.entry(key, 1); - }) - .collect(Collectors.groupingByConcurrent(Map.Entry::getKey, Collectors.summingInt(Map.Entry::getValue))) - .entrySet().stream() - .map(entry -> BoughtCarDto.toBoughtCarDto(entry.getKey(), entry.getValue())) + List allSubOptionInfo = optionRepository.findAllSubOptionInfo(); + Map subOptionPrice = allSubOptionInfo.stream() + .collect(Collectors.toMap(SubOptionIdAndPriceDto::getOptionId, SubOptionIdAndPriceDto::getOptionPrice)); + Map map = new HashMap<>(); + for (int i = 0; i < carPriceAndCount.size(); i++) { + Long sum = 0L; + if(!carPriceAndCount.get(i).getOptionList().isEmpty()){ + String[] split = carPriceAndCount.get(i).getOptionList().split(","); + for (String s : split) { + sum += subOptionPrice.get(Integer.parseInt(s)); + } + } + long key = ((carPriceAndCount.get(i).getPrice() + sum) / 100000) * 100000; + map.put(key, map.getOrDefault(key, 0) + 1); + } + return map.entrySet().stream() + .map(entry -> BoughtCarDto.builder() + .totalPrice(entry.getKey()) + .count(entry.getValue()) + .build()) .collect(Collectors.toList()); } - public QuoteInfoDto findShareInfoDto(QuoteIdList idList) { + public QuoteInfoDto findShareInfoDto(QuoteDataDto idList) { int carId = idList.getCarId(); int powerTrainId = idList.getPowerTrainId(); int bodyTypeId = idList.getBodyTypeId(); @@ -108,13 +107,15 @@ public QuoteInfoDto findShareInfoDto(QuoteIdList idList) { Optional innerColorInfo = colorRepository.findInnerColorByColorId(innerColorId); Optional outerColorInfo = colorRepository.findOuterColorByColorId(outerColorId); List optionInfos = new ArrayList<>(); - for (Integer id : optionIdList) { - Optional optionInfo = optionRepository.findSubOptionByOptionId(id); - if (optionInfo.isPresent()) { - optionInfos.add(optionInfo.get()); - continue; + if(!optionIdList.isEmpty()) { + for (Integer id : optionIdList) { + Optional optionInfo = optionRepository.findSubOptionByOptionId(id); + if (optionInfo.isPresent()) { + optionInfos.add(optionInfo.get()); + continue; + } + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); } OuterColorDto outerColorDto = outerColorInfo.get(); String imageUrl = changeUrl(outerColorDto.getColorCarImage(), 1); diff --git a/backend/src/main/java/autoever2/cartag/service/ColorService.java b/backend/src/main/java/autoever2/cartag/service/ColorService.java index 0e4d343..b508afe 100644 --- a/backend/src/main/java/autoever2/cartag/service/ColorService.java +++ b/backend/src/main/java/autoever2/cartag/service/ColorService.java @@ -10,7 +10,6 @@ import autoever2.cartag.repository.ColorRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; import java.util.ArrayList; import java.util.List; @@ -30,7 +29,7 @@ public class ColorService { public List changeImageToImages(int colorId) { Optional images = colorRepository.findOuterColorImagesByColorId(colorId); if (images.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } List outerColorCarImages = new ArrayList<>(); String value = images.get(); @@ -44,7 +43,7 @@ public List changeImageToImages(int colorId) { public List findOuterColorByCarId(int carId) { List outerColors = colorRepository.findOuterColorCarByCarId(carId); if (outerColors.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } Optional totalCount = carRepository.findCarBoughtCountByCarId(carId); return outerColors.stream() @@ -56,7 +55,7 @@ public List findOuterColorByCarId(int carId) { public List findInnerColorByCarId(int carId) { List innerColors = colorRepository.findInnerColorCarByCarId(carId); if (innerColors.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } Optional totalCount = carRepository.findCarBoughtCountByCarId(carId); return innerColors.stream() diff --git a/backend/src/main/java/autoever2/cartag/service/ModelService.java b/backend/src/main/java/autoever2/cartag/service/ModelService.java index d2aca4d..bc6bf3b 100644 --- a/backend/src/main/java/autoever2/cartag/service/ModelService.java +++ b/backend/src/main/java/autoever2/cartag/service/ModelService.java @@ -21,7 +21,7 @@ public class ModelService { public List getModelTypeData(int carId) { List modelData = modelRepository.findAllModelTypeData(carId); if (modelData.isEmpty()) { - throw new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND); + throw new EmptyDataException(ErrorCode.DATA_NOT_EXISTS); } Long carBoughtCount = carRepository.findCarBoughtCountByCarId(carId).orElse(0L); List powerTrainData = modelData.stream().filter(modelShortMappedDto -> modelShortMappedDto.getModelTypeId() == 1).collect(Collectors.toList()); @@ -114,7 +114,7 @@ private Double calculateHmgString(String input) { //TODO: RuntimeException ์ฒ˜๋ฆฌ public ModelDetailMappedDto getModelDetail(int modelId) { - return modelRepository.findModelDetailData(modelId).orElseThrow(() -> new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); + return modelRepository.findModelDetailData(modelId).orElseThrow(() -> new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); } //TODO: RuntimeException ์ฒ˜๋ฆฌ diff --git a/backend/src/main/java/autoever2/cartag/service/OptionService.java b/backend/src/main/java/autoever2/cartag/service/OptionService.java index 9b3240a..11d5520 100644 --- a/backend/src/main/java/autoever2/cartag/service/OptionService.java +++ b/backend/src/main/java/autoever2/cartag/service/OptionService.java @@ -57,7 +57,7 @@ public List getDefaultOptionList(int carId) { //TODO: RuntimeException ์ฒ˜๋ฆฌ public OptionDetailDto getOptionDetailData(int carId, int optionId, boolean isDefault) { - OptionDetailMappedDto detail = optionRepository.findOptionDetail(carId, optionId, isDefault).orElseThrow(() -> new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); + OptionDetailMappedDto detail = optionRepository.findOptionDetail(carId, optionId, isDefault).orElseThrow(() -> new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); List packageSubOptions = optionRepository.findPackageSubOptions(optionId); diff --git a/backend/src/main/java/autoever2/cartag/service/QuoteService.java b/backend/src/main/java/autoever2/cartag/service/QuoteService.java new file mode 100644 index 0000000..1155179 --- /dev/null +++ b/backend/src/main/java/autoever2/cartag/service/QuoteService.java @@ -0,0 +1,64 @@ +package autoever2.cartag.service; + +import autoever2.cartag.domain.quote.HistorySearchDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.exception.ErrorCode; +import autoever2.cartag.exception.InvalidDataException; +import autoever2.cartag.recommend.RecommendConnector; +import autoever2.cartag.repository.OptionRepository; +import autoever2.cartag.repository.QuoteRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class QuoteService { + + private final OptionRepository optionRepository; + private final QuoteRepository quoteRepository; + private final RecommendConnector recommendConnector; + + public HistoryShortDto findMyQuote(QuoteDataDto quoteDataDto) { + List optionIds = quoteDataDto.getOptionIdList(); + + HistorySearchDto historyData = HistorySearchDto.builder() + .carId(quoteDataDto.getCarId()) + .powerTrainId(quoteDataDto.getPowerTrainId()) + .bodyTypeId(quoteDataDto.getBodyTypeId()) + .operationId(quoteDataDto.getOperationId()) + .optionIds(optionIds) + .build(); + return quoteRepository.findShortData(historyData).orElse(HistoryShortDto.builder().build()); + } + + public List findTopHistory(QuoteDataDto quoteDataDto) { + + List optionIds = quoteDataDto.getOptionIdList(); + if(optionIds.size() != optionRepository.countExistOptions(quoteDataDto.getCarId(), optionIds)) { + throw new InvalidDataException(ErrorCode.INVALID_OPTIONS_REQUEST); + } + + List> result = recommendConnector.request(quoteDataDto); + + List historyList = result.stream().map(options -> { + HistorySearchDto historyData = HistorySearchDto.builder() + .carId(quoteDataDto.getCarId()) + .powerTrainId(quoteDataDto.getPowerTrainId()) + .bodyTypeId(quoteDataDto.getBodyTypeId()) + .operationId(quoteDataDto.getOperationId()) + .optionIds(optionIds) + .build(); + historyData.addAllOption(options); + + return historyData; + }).collect(Collectors.toList()); + + return historyList.stream().map(historySearchDto -> + quoteRepository.findShortData(historySearchDto).orElse(null) + ).collect(Collectors.toList()); + } +} diff --git a/backend/src/main/java/autoever2/cartag/service/RecommendService.java b/backend/src/main/java/autoever2/cartag/service/RecommendService.java deleted file mode 100644 index 3860e10..0000000 --- a/backend/src/main/java/autoever2/cartag/service/RecommendService.java +++ /dev/null @@ -1,59 +0,0 @@ -package autoever2.cartag.service; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Service; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -@Service -public class RecommendService { - - @Value("${python.url}") - private String requestURL; - - //TODO: ์‘๋‹ต ์กด์žฌ ์•ˆํ•  ์‹œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ - public String getList() { - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(requestURL)) - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(getJsonFromEstimate())).build(); - - try { - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - String body = response.body(); - return body; - } catch (Exception e) { - e.getMessage(); - } - - return null; - } - - public String getJsonFromEstimate() { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("carId", 1); - jsonObject.put("powerTrain", 1); - jsonObject.put("bodyType", 3); - jsonObject.put("operation", 5); - - JSONArray jsonArray = new JSONArray(); - JSONObject subOption = new JSONObject(); - subOption.put("subOptionId", "69"); - jsonArray.add(subOption); - subOption = new JSONObject(); - subOption.put("subOptionId", "70"); - jsonArray.add(subOption); - - jsonObject.put("options", jsonArray); - - - return jsonObject.toJSONString(); - } -} diff --git a/backend/src/test/java/autoever2/cartag/controller/CarControllerTest.java b/backend/src/test/java/autoever2/cartag/controller/CarControllerTest.java index 2b55216..7ea364e 100644 --- a/backend/src/test/java/autoever2/cartag/controller/CarControllerTest.java +++ b/backend/src/test/java/autoever2/cartag/controller/CarControllerTest.java @@ -3,13 +3,18 @@ import autoever2.cartag.domain.car.CarDto; import autoever2.cartag.domain.car.CarTypeDto; import autoever2.cartag.domain.car.TrimDefaultOptionDto; +import autoever2.cartag.domain.option.QuoteSubOptionDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; import autoever2.cartag.service.CarService; +import autoever2.cartag.service.QuoteService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -23,6 +28,7 @@ @WebMvcTest(CarController.class) class CarControllerTest { + @Autowired MockMvc mockMvc; @@ -31,6 +37,7 @@ class CarControllerTest { private List carDtoList; private List defaultOptions; + @BeforeEach void setup() { carDtoList = new ArrayList<>(); @@ -38,10 +45,10 @@ void setup() { defaultOptions.add(TrimDefaultOptionDto .builder() - .optionName("์•ˆ์ „ ํ•˜์ฐจ ๋ณด์กฐ") - .optionImage("image_1") - .optionDescription("์ข‹์€ ๋ณด์กฐ ์žฅ์น˜") - .OptionUsedCount(42) + .optionName("์•ˆ์ „ ํ•˜์ฐจ ๋ณด์กฐ") + .optionImage("image_1") + .optionDescription("์ข‹์€ ๋ณด์กฐ ์žฅ์น˜") + .OptionUsedCount(42) .build()); defaultOptions.add(TrimDefaultOptionDto .builder() @@ -100,6 +107,7 @@ void setup() { .options(defaultOptions) .build() ); + } @Test diff --git a/backend/src/test/java/autoever2/cartag/controller/ModelControllerTest.java b/backend/src/test/java/autoever2/cartag/controller/ModelControllerTest.java index 6d24ebf..da67b29 100644 --- a/backend/src/test/java/autoever2/cartag/controller/ModelControllerTest.java +++ b/backend/src/test/java/autoever2/cartag/controller/ModelControllerTest.java @@ -3,9 +3,7 @@ import autoever2.cartag.domain.model.ModelDetailMappedDto; import autoever2.cartag.domain.model.ModelEfficiencyDataDto; import autoever2.cartag.domain.model.ModelShortDataDto; -import autoever2.cartag.domain.model.PowerTrainMappedDto; import autoever2.cartag.service.ModelService; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/backend/src/test/java/autoever2/cartag/controller/OptionControllerTest.java b/backend/src/test/java/autoever2/cartag/controller/OptionControllerTest.java index 43ad7c8..3fa8cb8 100644 --- a/backend/src/test/java/autoever2/cartag/controller/OptionControllerTest.java +++ b/backend/src/test/java/autoever2/cartag/controller/OptionControllerTest.java @@ -2,9 +2,6 @@ import autoever2.cartag.domain.option.*; import autoever2.cartag.service.OptionService; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Schema; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -15,7 +12,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static org.mockito.BDDMockito.given; diff --git a/backend/src/test/java/autoever2/cartag/controller/QuoteControllerTest.java b/backend/src/test/java/autoever2/cartag/controller/QuoteControllerTest.java new file mode 100644 index 0000000..3ea9644 --- /dev/null +++ b/backend/src/test/java/autoever2/cartag/controller/QuoteControllerTest.java @@ -0,0 +1,243 @@ +package autoever2.cartag.controller; + +import autoever2.cartag.domain.car.BoughtCarDto; +import autoever2.cartag.domain.option.QuoteSubOptionDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; +import autoever2.cartag.service.CarService; +import autoever2.cartag.service.QuoteService; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(QuoteController.class) +public class QuoteControllerTest { + + @Autowired + MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private QuoteService quoteService; + + @MockBean + private CarService carService; + + @Test + @DisplayName("์œ ์‚ฌ๊ฒฌ์  ๊ฐ„๋žต ๋ฐ์ดํ„ฐ ์ œ๊ณต API ํ…Œ์ŠคํŠธ") + void getRecommendedList() throws Exception { + //given + QuoteDataDto quoteDataDto = QuoteDataDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIdList(List.of(69)) + .build(); + + List expected = new ArrayList<>(); + expected.add(HistoryShortDto.builder() + .historyId(129L) + .soldCount(155) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(161L) + .soldCount(140) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(137L) + .soldCount(162) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(169L) + .soldCount(140) + .build()); + + HistoryShortDto myQuote = HistoryShortDto.builder() + .historyId(123L) + .soldCount(110) + .build(); + + String content = objectMapper.writeValueAsString(quoteDataDto); + given(quoteService.findTopHistory(quoteDataDto)).willReturn(expected); + given(quoteService.findMyQuote(quoteDataDto)).willReturn(myQuote); + //when + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/quote/list").content(content) + .contentType(MediaType.APPLICATION_JSON)); + + //then + resultActions.andExpect(status().isOk()) + .andExpect(jsonPath("$.historyId").value(123L)) + .andExpect(jsonPath("$.soldCount").value(110)) + .andExpect(jsonPath("$.histories[0].historyId").value(129)) + .andExpect(jsonPath("$.histories[1].soldCount").value(140)) + .andExpect(jsonPath("$.histories[2].soldCount").value(162)) + .andExpect(jsonPath("$.histories[3].historyId").value(169)); + } + + @Test + @DisplayName("id์— ๋”ฐ๋ฅธ ๊ณต์œ  ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜") + void getShareInfo() throws Exception { + + List quoteSubOptionDtoList = new ArrayList<>(); + + quoteSubOptionDtoList.add(QuoteSubOptionDto + .builder() + .optionId(69) + .optionPrice(123400L) + .optionTitle("์ƒ์„ธํ’ˆ๋ชฉ") + .optionImage("image_1.jpg") + .optionName("3์—ด ์—ด์„ ์‹œํŠธ") + .build()); + + quoteSubOptionDtoList.add(QuoteSubOptionDto + .builder() + .optionId(70) + .optionPrice(100L) + .optionTitle("ํœ ") + .optionImage("iamge_2.jpg") + .optionName("20์ธ์น˜ ๋‹คํฌ ์Šคํผํ„ฐ๋ง") + .build()); + + quoteSubOptionDtoList.add(QuoteSubOptionDto + .builder() + .optionId(71) + .optionPrice(8977L) + .optionTitle("์•…์„ธ์‚ฌ๋ฆฌ") + .optionImage("image_3.jpg") + .optionName("ํ›„์ง„๊ฐ€์ด๋“œ๋žจํ”„") + .build()); + + ArrayList optionIds = new ArrayList<>(); + optionIds.add(69); + optionIds.add(70); + optionIds.add(71); + QuoteDataDto quoteIdList = QuoteDataDto + .builder() + .carId(1) + .powerTrainId(1) + .operationId(3) + .bodyTypeId(5) + .innerColorId(1) + .outerColorId(4) + .optionIdList(optionIds) + .build(); + + QuoteInfoDto quoteInfoDto = QuoteInfoDto + .builder() + .carId(1) + .trim("Le Blanc") + .carDefaultPrice(40000000) + .powerTrainId(1) + .powerTrainTitle("ํŒŒ์›ŒํŠธ๋ ˆ์ธ") + .powerTrainImage("image_1.jpg") + .powerTrainName("๋””์ ค2.2") + .powerTrainPrice(0L) + .bodyTypeId(5) + .bodyTypeTitle("๋ฐ”๋””ํƒ€์ž…") + .bodyTypeImage("image_2.jpg") + .bodyTypeName("7์ธ์Šน") + .bodyTypePrice(1500L) + .operationTitle("๊ตฌ๋™๋ฐฉ์‹") + .operationId(3) + .operationImage("image_3.jpg") + .operationName("2WD") + .operationPrice(8900L) + .colorOuterTitle("์™ธ์žฅ์ƒ‰์ƒ") + .colorOuterId(4) + .colorOuterImage("red_1.jpg") + .colorOuterPrice(1500L) + .colorOuterImageName("ํผํ”Œ ํŽ„") + .colorCarOuterImage("outer_red.jpg") + .colorInnerTitle("๋‚ด์žฅ์ƒ‰์ƒ") + .colorInnerId(1) + .colorInnerImage("blue_1.jpg") + .colorInnerPrice(1220L) + .colorInnerImageName("ํ€„ํŒ… ์ฒœ์—ฐ(ํŒŒ๋ž‘)") + .colorCarInnerImage("inner_red.jpg") + .optionList(quoteSubOptionDtoList) + .build(); + + + given(carService.findShareInfoDto(quoteIdList)).willReturn(quoteInfoDto); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/quote/infos/shares") + .content("{\n" + + " \"carId\": 1,\n" + + " \"powerTrainId\": 1,\n" + + " \"bodyTypeId\": 5,\n" + + " \"operationId\": 3,\n" + + " \"outerColorId\": 4,\n" + + " \"innerColorId\": 1,\n" + + " \"optionIdList\": [69, 70, 71]\n" + + "}").contentType(MediaType.APPLICATION_JSON)); + resultActions.andExpect(status().isOk()) + .andExpect(jsonPath("$.carDefaultPrice").value(40000000)) + .andExpect(jsonPath("$.trim").value("Le Blanc")) + .andExpect(jsonPath("$.powerTrainImage").value("image_1.jpg")) + .andExpect(jsonPath("$.bodyTypeName").value("7์ธ์Šน")) + .andExpect(jsonPath("$.operationTitle").value("๊ตฌ๋™๋ฐฉ์‹")) + .andExpect(jsonPath("$.colorOuterPrice").value(1500L)) + .andExpect(jsonPath("$.colorCarInnerImage").value("inner_red.jpg")) + .andExpect(jsonPath("$.optionList.size()").value(3)); + } + + @Test + @DisplayName("์ฐจ๋Ÿ‰ ๊ตฌ๋งค ์ •๋ณด ๋ฐ˜ํ™˜ api") + void getBoughtInfos() throws Exception { + List boughtCarDtoList = new ArrayList<>(); + boughtCarDtoList.add(BoughtCarDto + .builder() + .totalPrice(4900000L) + .count(1900) + .build()); + boughtCarDtoList.add(BoughtCarDto + .builder() + .totalPrice(5100000L) + .count(2200) + .build()); + boughtCarDtoList.add(BoughtCarDto + .builder() + .totalPrice(6000000L) + .count(4300) + .build()); + boughtCarDtoList.add(BoughtCarDto + .builder() + .totalPrice(6700000L) + .count(1400) + .build()); + boughtCarDtoList.add(BoughtCarDto + .builder() + .totalPrice(7000000L) + .count(1200) + .build()); + + given(carService.findAllBoughInfos()).willReturn(boughtCarDtoList); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/quote/bought/infos")); + + //then + resultActions.andExpect(status().isOk()) + .andExpect(jsonPath("$[0].totalPrice").value(4900000L)) + .andExpect(jsonPath("$[1].count").value(2200)) + .andExpect(jsonPath("$[2].totalPrice").value(6000000L)) + .andExpect(jsonPath("$[3].count").value(1400)); + } +} diff --git a/backend/src/test/java/autoever2/cartag/integration/CarTest.java b/backend/src/test/java/autoever2/cartag/integration/CarTest.java index 83a441a..70d1116 100644 --- a/backend/src/test/java/autoever2/cartag/integration/CarTest.java +++ b/backend/src/test/java/autoever2/cartag/integration/CarTest.java @@ -1,16 +1,9 @@ package autoever2.cartag.integration; import autoever2.cartag.controller.CarController; -import autoever2.cartag.domain.car.CarDefaultDto; import autoever2.cartag.domain.car.CarDto; import autoever2.cartag.domain.car.CarTypeDto; import autoever2.cartag.exception.EmptyDataException; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -18,8 +11,6 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; import java.util.ArrayList; import java.util.List; @@ -70,4 +61,5 @@ void testCarTypeList() { assertThat(controller.getCarTypeList()).usingRecursiveComparison().isEqualTo(carTypeList); } + } diff --git a/backend/src/test/java/autoever2/cartag/integration/ModelTest.java b/backend/src/test/java/autoever2/cartag/integration/ModelTest.java index 9eccd3e..313e187 100644 --- a/backend/src/test/java/autoever2/cartag/integration/ModelTest.java +++ b/backend/src/test/java/autoever2/cartag/integration/ModelTest.java @@ -41,6 +41,9 @@ void getModelList() { PowerTrainDataDto hmgData = trimModels.get(0).getHmgData(); assertEquals("45.0/1750~2750", hmgData.getMaxKgfm()); + assertEquals("202/3800", hmgData.getMaxPs()); + assertEquals(1.0, hmgData.getRatioKgfm()); + assertEquals(1.0, hmgData.getRatioPs()); assertEquals(1.0, hmgData.getRatioKgfm()); } diff --git a/backend/src/test/java/autoever2/cartag/integration/QuoteTest.java b/backend/src/test/java/autoever2/cartag/integration/QuoteTest.java new file mode 100644 index 0000000..e3acfcd --- /dev/null +++ b/backend/src/test/java/autoever2/cartag/integration/QuoteTest.java @@ -0,0 +1,85 @@ +package autoever2.cartag.integration; + +import autoever2.cartag.controller.QuoteController; +import autoever2.cartag.domain.car.BoughtCarDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; +import autoever2.cartag.recommend.RecommendConnector; +import org.assertj.core.api.SoftAssertions; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import autoever2.cartag.controller.CarController; +import autoever2.cartag.domain.option.QuoteSubOptionDto; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +@ActiveProfiles("test") +@Transactional +public class QuoteTest { + + @Autowired + QuoteController quoteController; + + @Autowired + CarController carController; + + @Test + @DisplayName("/api/quote/infos/shares") + @Sql({"classpath:insert/insert-quote-h2.sql"}) + void testShare() { + ArrayList optionIds = new ArrayList<>(); + optionIds.add(1); + optionIds.add(2); + optionIds.add(3); + QuoteDataDto quoteIdList = QuoteDataDto + .builder() + .carId(1) + .powerTrainId(1) + .operationId(3) + .bodyTypeId(5) + .innerColorId(4) + .outerColorId(1) + .optionIdList(optionIds) + .build(); + + QuoteInfoDto quoteInfoDto = quoteController.getQuoteDetail(quoteIdList); + + assertEquals("๋ฅด๋ธ”๋ž‘", quoteInfoDto.getTrim()); + assertEquals(41980000, quoteInfoDto.getCarDefaultPrice()); + assertEquals("๋””์ ค2.2", quoteInfoDto.getPowerTrainName()); + assertEquals(0, quoteInfoDto.getBodyTypePrice()); + assertEquals("/model/2wd.png", quoteInfoDto.getOperationImage()); + assertEquals("์ฒœ์—ฐ ํ€„ํŒ…(๋ธ”๋ž™)", quoteInfoDto.getColorOuterImageName()); + assertEquals("๋‚ด์žฅ ์ƒ‰์ƒ", quoteInfoDto.getColorInnerTitle()); + + List optionList = quoteInfoDto.getOptionList(); + + assertEquals(3, optionList.size()); + assertEquals("2์—ด ํ†ตํ’ ์‹œํŠธ", optionList.get(0).getOptionName()); + assertEquals("/images/options/sub/warmer.jpg", optionList.get(1).getOptionImage()); + assertEquals("์•…์„ธ์‚ฌ๋ฆฌ", optionList.get(2).getOptionTitle()); + } + + @Test + @DisplayName("/api/quote/bought/infos") + @Sql({"classpath:insert/insert-boughtinfo-h2.sql"}) + void testBoughtInfo(){ + List allHistorySum = quoteController.getAllHistorySum(); + + assertEquals(6, allHistorySum.size()); + assertEquals(2, allHistorySum.get(0).getCount()); + assertEquals(42300000L, allHistorySum.get(1).getTotalPrice()); + } +} diff --git a/backend/src/test/java/autoever2/cartag/repository/CarRepositoryTest.java b/backend/src/test/java/autoever2/cartag/repository/CarRepositoryTest.java index 18dcca1..a058144 100644 --- a/backend/src/test/java/autoever2/cartag/repository/CarRepositoryTest.java +++ b/backend/src/test/java/autoever2/cartag/repository/CarRepositoryTest.java @@ -1,7 +1,9 @@ package autoever2.cartag.repository; import autoever2.cartag.domain.car.CarInfoDto; +import autoever2.cartag.domain.car.CarPriceDto; import autoever2.cartag.domain.car.CarTypeDto; +import autoever2.cartag.domain.car.TrimInfoDto; import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; @@ -16,12 +18,14 @@ import javax.sql.DataSource; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @JdbcTest @ActiveProfiles("test") -@Sql(scripts = {"classpath:/insert/insertCar-h2.sql"}) +@Sql(scripts = {"classpath:/insert/insert-boughtinfo-h2.sql"}) @ExtendWith(SoftAssertionsExtension.class) class CarRepositoryTest { @@ -84,4 +88,34 @@ void findAllCarTypeList() { //then softAssertions.assertThat(result).usingRecursiveComparison().isEqualTo(expected); } + + @Test + @DisplayName("์ฐจ๋Ÿ‰ ํŠธ๋ฆผ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜") + void getTrimInfo() { + Optional trimInfo = carRepository.findTrimInfoByCarId(1); + assertTrue(trimInfo.isPresent()); + + TrimInfoDto infoDto = trimInfo.get(); + assertEquals("Le Blanc", infoDto.getTrim()); + assertEquals(40000000, infoDto.getCarDefaultPrice()); + + Optional trimNoFoundInfo = carRepository.findTrimInfoByCarId(7); + assertTrue(trimNoFoundInfo.isEmpty()); + } + + @Test + @DisplayName("์ฐจ๋Ÿ‰ ๊ฐ€๊ฒฉ ์ •๋ณด์™€ optionIdList๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋กœ์ง") + void getPriceAndOptionList(){ + List totalInfo = carRepository.findCarPriceAndCount(); + + assertEquals(11, totalInfo.size()); + assertEquals(41480000L, totalInfo.get(0).getPrice()); + + String emptyOptionList = totalInfo.get(0).getOptionList(); + assertTrue(emptyOptionList.isEmpty()); + + String optionList = totalInfo.get(10).getOptionList(); + assertTrue(!optionList.isEmpty()); + assertEquals(69, Integer.parseInt(optionList)); + } } \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/repository/ColorRepositoryTest.java b/backend/src/test/java/autoever2/cartag/repository/ColorRepositoryTest.java index 84975e5..8223e3e 100644 --- a/backend/src/test/java/autoever2/cartag/repository/ColorRepositoryTest.java +++ b/backend/src/test/java/autoever2/cartag/repository/ColorRepositoryTest.java @@ -19,6 +19,7 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @JdbcTest @ActiveProfiles("test") @@ -52,8 +53,34 @@ void findOuterColor() { @Test @DisplayName("carId์— ๋”ฐ๋ฅธ ์ƒ‰์ƒ์ด ์ ์šฉ๋œ ์ฐจ๋Ÿ‰ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.") - void findOuterImages(){ + void findOuterImages() { String image = repository.findOuterColorImagesByColorId(1).get(); assertEquals("red_image_*.jpg", image); } + + @Test + @DisplayName("color_id์— ๋”ฐ๋ฅธ ์™ธ์žฅ์ƒ‰์ƒ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.") + void getOuterColorInfo() { + Optional outerColorInfo = repository.findOuterColorByColorId(1); + assertTrue(outerColorInfo.isPresent()); + + OuterColorDto outerColorDto = outerColorInfo.get(); + assertEquals("์ฒœ์—ฐ ํ€„ํŒ…(๋ธ”๋ž™)", outerColorDto.getColorName()); + assertEquals(1234, outerColorDto.getColorPrice()); + assertEquals("red_image_*.jpg", outerColorDto.getColorCarImage()); + assertEquals("image_1", outerColorDto.getColorImage()); + } + + @Test + @DisplayName("color_id์— ๋”ฐ๋ฅธ ๋‚ด์žฅ์ƒ‰์ƒ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.") + void getInnerColorInfo() { + Optional innerColorInfo = repository.findInnerColorByColorId(3); + assertTrue(innerColorInfo.isPresent()); + + InnerColorDto innerColorDto = innerColorInfo.get(); + assertEquals("ํผํ”Œ ๊ทธ๋ ˆ์ด ํŽ„", innerColorDto.getColorName()); + assertEquals(154, innerColorDto.getColorPrice()); + assertEquals("black_image_*.jpg", innerColorDto.getColorCarImage()); + assertEquals("image_3", innerColorDto.getColorImage()); + } } \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/repository/ModelRepositoryTest.java b/backend/src/test/java/autoever2/cartag/repository/ModelRepositoryTest.java index 5aa4146..de95587 100644 --- a/backend/src/test/java/autoever2/cartag/repository/ModelRepositoryTest.java +++ b/backend/src/test/java/autoever2/cartag/repository/ModelRepositoryTest.java @@ -130,7 +130,7 @@ void getPowerTrainOperationEfficiency() { @Test @DisplayName("ํ•ด๋‹น carId์— ๋”ฐ๋ผ์„œ default model๋“ค์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.") - void getDefaultModelList(){ + void getDefaultModelList() { List modelDefaultDtos = modelRepository.findModelDefaultDtoByCarId(1); assertEquals(3, modelDefaultDtos.size()); @@ -150,4 +150,27 @@ void getDefaultModelList(){ assertEquals("/model/2wd.png", bodyType.getModelImage()); assertEquals("/model/7seats.jpg", operation.getModelImage()); } + + @Test + @DisplayName("๊ณต์œ ๋ฅผ ์œ„ํ•œ model ๋ฐ์ดํ„ฐ ์ถ”์ถœ") + void getModelInfo(){ + List modelInfos = modelRepository.findModelListByModelId(1, 5, 3); + assertTrue(modelInfos.size() == 3); + + ModelDefaultDto powerTrainInfo = modelInfos.get(0); + ModelDefaultDto operationInfo = modelInfos.get(1); + ModelDefaultDto bodyTypeInfo = modelInfos.get(2); + + assertEquals("๋””์ ค2.2", powerTrainInfo.getModelName()); + assertEquals("ํŒŒ์›ŒํŠธ๋ ˆ์ธ", powerTrainInfo.getModelTitle()); + assertEquals(1480000, powerTrainInfo.getModelPrice()); + + assertEquals("2WD", operationInfo.getModelName()); + assertEquals("๊ตฌ๋™๋ฐฉ์‹", operationInfo.getModelTitle()); + assertEquals(0, operationInfo.getModelPrice()); + + assertEquals("/model/7seats.jpg", bodyTypeInfo.getModelImage()); + assertEquals("๋ฐ”๋””ํƒ€์ž…", bodyTypeInfo.getModelTitle()); + assertEquals("7์ธ์Šน", bodyTypeInfo.getModelName()); + } } \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/repository/OptionRepositoryTest.java b/backend/src/test/java/autoever2/cartag/repository/OptionRepositoryTest.java index 93e6dca..00bd913 100644 --- a/backend/src/test/java/autoever2/cartag/repository/OptionRepositoryTest.java +++ b/backend/src/test/java/autoever2/cartag/repository/OptionRepositoryTest.java @@ -3,6 +3,8 @@ import autoever2.cartag.domain.car.TrimDefaultOptionDto; import autoever2.cartag.domain.option.OptionDetailMappedDto; import autoever2.cartag.domain.option.OptionShortMappedDto; +import autoever2.cartag.domain.option.QuoteSubOptionDto; +import autoever2.cartag.domain.option.SubOptionIdAndPriceDto; import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; @@ -230,4 +232,40 @@ void findDefaultOptionList() { softAssertions.assertThat(data).usingRecursiveComparison().isEqualTo(expectedList); } + + @Test + @DisplayName("๊ณต์œ ๋ฅผ ์œ„ํ•œ optionInfo ์ถ”์ถœ") + void getOptionInfo() { + Optional subOptionInfoV1 = optionRepository.findSubOptionByOptionId(1); + assertTrue(subOptionInfoV1.isPresent()); + + QuoteSubOptionDto subOptionV1 = subOptionInfoV1.get(); + assertEquals("2์—ด ํ†ตํ’ ์‹œํŠธ", subOptionV1.getOptionName()); + assertEquals("/images/options/sub/2seats.jpg", subOptionV1.getOptionImage()); + assertEquals("์ƒ์„ธํ’ˆ๋ชฉ", subOptionV1.getOptionTitle()); + assertEquals(100000, subOptionV1.getOptionPrice()); + + Optional subOptionInfoV2 = optionRepository.findSubOptionByOptionId(100); + assertTrue(subOptionInfoV2.isEmpty()); + } + + @Test + @DisplayName("์˜ต์…˜์ด ์‹ค์ œ๋กœ ์กด์žฌํ•˜๋Š”์ง€ ๊ฒ€์ฆ") + void countExistOptions() { + int carId = 1; + List optionIds = List.of(69); + + assertEquals(1, optionRepository.countExistOptions(carId, optionIds)); + } + + @Test + @DisplayName("๋ชจ๋“  subOptionData๋ฅผ ์ถ”์ถœ") + void findAllSubOptionInfos(){ + List allSubOptionInfo = optionRepository.findAllSubOptionInfo(); + assertEquals(6, allSubOptionInfo.size()); + + SubOptionIdAndPriceDto subOptionIdAndPriceDto = allSubOptionInfo.get(0); + assertEquals(1, subOptionIdAndPriceDto.getOptionId()); + assertEquals(100000L, subOptionIdAndPriceDto.getOptionPrice()); + } } \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/repository/QuoteRepositoryTest.java b/backend/src/test/java/autoever2/cartag/repository/QuoteRepositoryTest.java new file mode 100644 index 0000000..e2e4ae9 --- /dev/null +++ b/backend/src/test/java/autoever2/cartag/repository/QuoteRepositoryTest.java @@ -0,0 +1,68 @@ +package autoever2.cartag.repository; + +import autoever2.cartag.domain.quote.HistorySearchDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import org.assertj.core.api.SoftAssertions; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +import javax.sql.DataSource; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@ActiveProfiles("test") +@JdbcTest +@Sql({"classpath:insert/insert-sales-h2.sql"}) +@ExtendWith(SoftAssertionsExtension.class) +class QuoteRepositoryTest { + + @InjectSoftAssertions + SoftAssertions softAssertions; + + private final QuoteRepository quoteRepository; + + @Autowired + public QuoteRepositoryTest(DataSource dataSource) { + quoteRepository = new QuoteRepository(dataSource); + } + + @Test + void findShortData() { + HistorySearchDto search1 = HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 70)) + .build(); + HistorySearchDto search2 = HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 74)) + .build(); + + HistoryShortDto expected1 = HistoryShortDto.builder() + .historyId(129L) + .soldCount(155) + .build(); + HistoryShortDto expected2 = HistoryShortDto.builder() + .historyId(161L) + .soldCount(140) + .build(); + + assertTrue(quoteRepository.findShortData(search1).isPresent()); + assertTrue(quoteRepository.findShortData(search2).isPresent()); + softAssertions.assertThat(quoteRepository.findShortData(search1).get()).usingRecursiveComparison().isEqualTo(expected1); + softAssertions.assertThat(quoteRepository.findShortData(search2).get()).usingRecursiveComparison().isEqualTo(expected2); + } +} \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/service/CarServiceTest.java b/backend/src/test/java/autoever2/cartag/service/CarServiceTest.java index a070cb4..f3a53ea 100644 --- a/backend/src/test/java/autoever2/cartag/service/CarServiceTest.java +++ b/backend/src/test/java/autoever2/cartag/service/CarServiceTest.java @@ -1,12 +1,18 @@ package autoever2.cartag.service; -import autoever2.cartag.domain.car.CarDto; -import autoever2.cartag.domain.car.CarInfoDto; -import autoever2.cartag.domain.car.CarTypeDto; -import autoever2.cartag.domain.car.TrimDefaultOptionDto; +import autoever2.cartag.domain.car.*; +import autoever2.cartag.domain.color.InnerColorDto; +import autoever2.cartag.domain.color.OuterColorDto; +import autoever2.cartag.domain.model.ModelDefaultDto; +import autoever2.cartag.domain.option.QuoteSubOptionDto; +import autoever2.cartag.domain.option.SubOptionIdAndPriceDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.domain.quote.QuoteInfoDto; import autoever2.cartag.exception.EmptyDataException; import autoever2.cartag.exception.ErrorCode; import autoever2.cartag.repository.CarRepository; +import autoever2.cartag.repository.ColorRepository; +import autoever2.cartag.repository.ModelRepository; import autoever2.cartag.repository.OptionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -18,6 +24,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -31,9 +38,12 @@ class CarServiceTest { @Mock private CarRepository carRepository; - @Mock private OptionRepository optionRepository; + @Mock + private ModelRepository modelRepository; + @Mock + private ColorRepository colorRepository; private List carInfoDtoList; @@ -120,7 +130,7 @@ void getCarType() { when(carRepository.findCarByCarType(carType)).thenReturn(carInfoDtoList); when(optionRepository.findDefaultOptionByCarId(carId)).thenReturn(trimDefaultOptionDtoList); - when(carRepository.findCarByCarType(2)).thenThrow(new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); + when(carRepository.findCarByCarType(2)).thenThrow(new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); List carByCarType = carService.findCarByCarType(carType); @@ -129,13 +139,6 @@ void getCarType() { assertThatThrownBy(() -> carService.findCarByCarType(2)).isInstanceOf(EmptyDataException.class); } - @Test - @DisplayName("์ฐจ๋Ÿ‰์˜ ๊ธฐ๋ณธ์ •๋ณด๋“ค์„ ๋ฐ˜ํ™˜") - void carDefaultInfo(){ - - - } - @Test @DisplayName("DB์—์„œ ๋ฐ›์•„์˜จ ์ฐจ์ข…์„ Controller๋กœ ์ „๋‹ฌ") void carTypeList() { @@ -160,4 +163,174 @@ void carTypeList() { assertEquals(carTypeList, carService.getAllCarTypes()); } + + @Test + @DisplayName("service์—์„œ ๊ณต์œ  ์ •๋ณด๋ฅผ ํ†ตํ•ฉํ•ฉ๋‹ˆ๋‹ค.") + void integrateAllInfo() { + + TrimInfoDto trimInfo = TrimInfoDto + .builder() + .carId(1) + .carDefaultPrice(4000000) + .trim("Le Blanc") + .build(); + when(carRepository.findTrimInfoByCarId(1)).thenReturn(Optional.of(trimInfo)); + + List modelList = new ArrayList<>(); + modelList.add(ModelDefaultDto + .builder() + .modelId(1) + .modelName("๋””์ ค2.2") + .modelImage("/model/diesel2-2.jpg") + .modelTitle("ํŒŒ์›ŒํŠธ๋ ˆ์ธ") + .modelPrice(12999L) + .build()); + modelList.add(ModelDefaultDto + .builder() + .modelId(3) + .modelName("2WD") + .modelImage("/model/2wd.png") + .modelTitle("๊ตฌ๋™๋ฐฉ์‹") + .modelPrice(0L) + .build()); + modelList.add(ModelDefaultDto + .builder() + .modelId(5) + .modelName("7์ธ์Šน") + .modelImage("/model/7seats.jpg") + .modelTitle("๋ฐ”๋”” ํƒ€์ž…") + .modelPrice(9999L) + .build()); + when(modelRepository.findModelListByModelId(1, 3, 5)).thenReturn(modelList); + + + OuterColorDto outerColor = OuterColorDto + .builder() + .colorId(4) + .colorCarImage("red_*.jpg") + .colorPrice(1500L) + .colorImage("ํผํ”Œ ํŽ„") + .build(); + + InnerColorDto innerColor = InnerColorDto + .builder() + .colorId(1) + .colorCarImage("black_1.jpg") + .colorPrice(2000L) + .colorImage("ํ€„ํŒ… ์ฒœ์—ฐ(๋ธ”๋ž™)") + .build(); + when(colorRepository.findInnerColorByColorId(1)).thenReturn(Optional.of(innerColor)); + when(colorRepository.findOuterColorByColorId(4)).thenReturn(Optional.of(outerColor)); + + + ArrayList idList = new ArrayList<>(); + idList.add(1); + + QuoteSubOptionDto subOption = QuoteSubOptionDto + .builder() + .optionId(1) + .optionName("2์—ด ํ†ตํ’ ์‹œํŠธ") + .optionPrice(14999L) + .optionTitle("์ƒ์„ธํ’ˆ๋ชฉ") + .optionImage("/images/options/sub/2seats.jpg") + .build(); + + when(optionRepository.findSubOptionByOptionId(1)).thenReturn(Optional.of(subOption)); + + QuoteInfoDto shareInfoDto = carService.findShareInfoDto(QuoteDataDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .innerColorId(1) + .outerColorId(4) + .optionIdList(idList) + .build()); + + assertEquals(1, shareInfoDto.getCarId()); + assertEquals("๋‚ด์žฅ ์ƒ‰์ƒ", shareInfoDto.getColorInnerTitle()); + assertEquals(9999L, shareInfoDto.getBodyTypePrice()); + assertEquals(1, shareInfoDto.getOptionList().size()); + assertEquals("ํผํ”Œ ํŽ„", shareInfoDto.getColorOuterImage()); + assertEquals("red_1.jpg", shareInfoDto.getColorCarOuterImage()); + } + + @Test + @DisplayName("service ์˜์—ญ์—์„œ ์กฐํ•ฉ์„ ํ†ตํ•œ ์ •๋ณด ํ†ตํ•ฉ") + void getTotalInfo() { + List carPriceDtos = new ArrayList<>(); + carPriceDtos.add(CarPriceDto + .builder() + .price(43000000L) + .optionList("12,14") + .build()); + carPriceDtos.add(CarPriceDto + .builder() + .price(45660000L) + .optionList("22,25") + .build()); + carPriceDtos.add(CarPriceDto + .builder() + .price(51200000L) + .optionList("30,33") + .build()); + carPriceDtos.add(CarPriceDto + .builder() + .price(59900000L) + .optionList("41,42") + .build()); + + List subOptionIdAndPriceDtos = new ArrayList<>(); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(12) + .optionPrice(1000L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(14) + .optionPrice(0L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(22) + .optionPrice(1000L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(25) + .optionPrice(9000L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(30) + .optionPrice(45000L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(33) + .optionPrice(3000L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(41) + .optionPrice(1200L) + .build()); + subOptionIdAndPriceDtos.add(SubOptionIdAndPriceDto + .builder() + .optionId(42) + .optionPrice(90000L) + .build()); + when(carRepository.findCarPriceAndCount()).thenReturn(carPriceDtos); + when(optionRepository.findAllSubOptionInfo()).thenReturn(subOptionIdAndPriceDtos); + + List allBoughInfos = carService.findAllBoughInfos(); + + assertEquals(4, allBoughInfos.size()); + + BoughtCarDto boughtCarDto = allBoughInfos.get(0); + assertEquals(43000000L, boughtCarDto.getTotalPrice()); + assertEquals(1, boughtCarDto.getCount()); + } + } \ No newline at end of file diff --git a/backend/src/test/java/autoever2/cartag/service/ColorServiceTest.java b/backend/src/test/java/autoever2/cartag/service/ColorServiceTest.java index 3135bf6..95dd477 100644 --- a/backend/src/test/java/autoever2/cartag/service/ColorServiceTest.java +++ b/backend/src/test/java/autoever2/cartag/service/ColorServiceTest.java @@ -138,9 +138,9 @@ void getModelTypeData() { when(colorRepository.findOuterColorCarByCarId(carId)).thenReturn(outerColors); when(colorRepository.findOuterColorImagesByColorId(colorId)).thenReturn(Optional.of("red_image_*.jpg")); when(carRepository.findCarBoughtCountByCarId(carId)).thenReturn(Optional.of(10000L)); - when(colorRepository.findOuterColorImagesByColorId(2)).thenThrow(new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); - when(colorRepository.findOuterColorCarByCarId(2)).thenThrow(new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); - when(colorRepository.findInnerColorCarByCarId(2)).thenThrow(new EmptyDataException(ErrorCode.RESOURCE_NOT_FOUND)); + when(colorRepository.findOuterColorImagesByColorId(2)).thenThrow(new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); + when(colorRepository.findOuterColorCarByCarId(2)).thenThrow(new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); + when(colorRepository.findInnerColorCarByCarId(2)).thenThrow(new EmptyDataException(ErrorCode.DATA_NOT_EXISTS)); //when diff --git a/backend/src/test/java/autoever2/cartag/service/QuoteServiceTest.java b/backend/src/test/java/autoever2/cartag/service/QuoteServiceTest.java new file mode 100644 index 0000000..433b65d --- /dev/null +++ b/backend/src/test/java/autoever2/cartag/service/QuoteServiceTest.java @@ -0,0 +1,132 @@ +package autoever2.cartag.service; + +import autoever2.cartag.domain.quote.HistorySearchDto; +import autoever2.cartag.domain.quote.HistoryShortDto; +import autoever2.cartag.domain.quote.QuoteDataDto; +import autoever2.cartag.recommend.RecommendConnector; +import autoever2.cartag.repository.OptionRepository; +import autoever2.cartag.repository.QuoteRepository; +import org.assertj.core.api.SoftAssertions; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.mockito.Mockito.when; + +@ExtendWith({MockitoExtension.class, SoftAssertionsExtension.class}) +class QuoteServiceTest { + + @InjectSoftAssertions + private SoftAssertions softAssertions; + + @InjectMocks + private QuoteService quoteService; + + @Mock + private OptionRepository optionRepository; + + @Mock + private QuoteRepository quoteRepository; + + @Mock + private RecommendConnector recommendConnector; + + @Test + void findTopHistory() { + //given + QuoteDataDto quoteDataDto = QuoteDataDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIdList(List.of(69)) + .build(); + + List> response = new ArrayList<>(); + response.add(List.of(70)); + response.add(List.of(74)); + response.add(List.of(71)); + response.add(List.of(84)); + + List expected = new ArrayList<>(); + expected.add(HistoryShortDto.builder() + .historyId(129L) + .soldCount(155) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(161L) + .soldCount(140) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(137L) + .soldCount(162) + .build()); + expected.add(HistoryShortDto.builder() + .historyId(169L) + .soldCount(140) + .build()); + + + when(optionRepository.countExistOptions(quoteDataDto.getCarId(), quoteDataDto.getOptionIdList())).thenReturn(1L); + when(recommendConnector.request(quoteDataDto)).thenReturn(response); + + when(quoteRepository.findShortData(HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 70)) + .build())) + .thenReturn(Optional.of(HistoryShortDto.builder() + .historyId(129L) + .soldCount(155) + .build())); + when(quoteRepository.findShortData(HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 74)) + .build())) + .thenReturn(Optional.of(HistoryShortDto.builder() + .historyId(161L) + .soldCount(140) + .build())); + when(quoteRepository.findShortData(HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 71)) + .build())) + .thenReturn(Optional.of(HistoryShortDto.builder() + .historyId(137L) + .soldCount(162) + .build())); + when(quoteRepository.findShortData(HistorySearchDto.builder() + .carId(1) + .powerTrainId(1) + .bodyTypeId(3) + .operationId(5) + .optionIds(List.of(69, 84)) + .build())) + .thenReturn(Optional.of(HistoryShortDto.builder() + .historyId(169L) + .soldCount(140) + .build())); + + //when + List result = quoteService.findTopHistory(quoteDataDto); + + //then + softAssertions.assertThat(result).usingRecursiveComparison().isEqualTo(expected); + } +} \ No newline at end of file diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml deleted file mode 100644 index a3374c9..0000000 --- a/backend/src/test/resources/application.yml +++ /dev/null @@ -1,19 +0,0 @@ -spring: - config: - activate: - on-profile: test - h2: - console: - enabled: true - datasource: - url: jdbc:h2:mem:test;MODE=MySQL; - username: sa - password: - driver-class-name: org.h2.Driver - sql: - init: - mode: always - schema-locations: classpath:schema-h2.sql - -python: - url: http://localhost:5001/test diff --git a/backend/src/test/resources/insert/insert-boughtinfo-h2.sql b/backend/src/test/resources/insert/insert-boughtinfo-h2.sql new file mode 100644 index 0000000..7d32ebe --- /dev/null +++ b/backend/src/test/resources/insert/insert-boughtinfo-h2.sql @@ -0,0 +1,110 @@ +INSERT INTO CarType (car_type_id, car_type_image, car_type_name) VALUES (1, 'image_1', 'ํŽ ๋ฆฌ์„ธ์ด๋“œ'); +INSERT INTO CarType (car_type_id, car_type_image, car_type_name) VALUES (2, '/cartype/santafe.png', '์‹ผํƒ€ํŽ˜'); +INSERT INTO CarType (car_type_id, car_type_image, car_type_name) VALUES (3, '/cartype/the-all-new-kona-hybrid.png', '๋”” ์˜ฌ ๋‰ด ์ฝ”๋‚˜ Hybrid'); + +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (1, 1, 'Le Blanc', 40000000, 'image_1', 'image_2', 'image_3', 234, 'Good'); +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (2, 1, 'Exclusive', 40000000, 'image_1', 'image_2', 'image_3', 24, 'Good'); +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (3, 1, 'Prestige', 40000000, 'image_1', 'image_2', 'image_3', 34, 'Good'); +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (4, 1, 'Calligraphy', 40000000, 'image_1', 'image_2', 'image_3', 23499, 'Good'); +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (5, 2, 'Exclusive', 35460000, '/cartype/santafe.png', '/cartype/santafe.png', '', 150000, '์‚ฐํƒ€ํŽ˜'); +INSERT INTO Car (car_id, car_type_id, trim, car_default_price, outer_image, inner_image, wheel_image, bought_count, car_description) VALUES (6, 3, 'Inspiration', 36380000, '/cartype/the-all-new-kona-hybrid.png', '/cartype/the-all-new-kona-hybrid.png', '', 150000, '๋”” ์˜ฌ ๋‰ด ์ฝ”๋‚˜ Hybrid์ž…๋‹ˆ๋‹ค.'); + +insert into OptionCategory (option_category_id, option_category_name) VALUES (1, '์ƒ์„ธํ’ˆ๋ชฉ'); +insert into OptionCategory (option_category_id, option_category_name) VALUES (2, '์•…์„ธ์‚ฌ๋ฆฌ'); +insert into OptionCategory (option_category_id, option_category_name) VALUES (3, 'ํœ '); +insert into OptionCategory (option_category_id, option_category_name) VALUES (4, '์™ธ๊ด€'); +insert into OptionCategory (option_category_id, option_category_name) values (9, '์ƒ์„ธํ’ˆ๋ชฉ'); + +insert into caroption values (1, 1, '2์—ด ํ†ตํ’ ์‹œํŠธ', '/images/options/sub/2seats.jpg', '์‹œ๋™์ด ๊ฑธ๋ฆฐ ์ƒํƒœ์—์„œ ํ•ด๋‹น ์ขŒ์„์˜ ํ†ตํ’ ์Šค์œ„์น˜๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ‘œ์‹œ๋“ฑ์ด ์ผœ์ง€๋ฉด์„œ ํ•ด๋‹น ์ขŒ์„์— ๋ฐ”๋žŒ์ด ๋‚˜์˜ค๋Š” ํŽธ์˜์žฅ์น˜์ž…๋‹ˆ๋‹ค.', 38); +insert into caroption values (2, 2, '์ ์™ธ์„  ๋ฌด๋ฆŽ ์›Œ๋จธ', '/images/options/sub/warmer.jpg', '์›Œ๋จธ์ž…๋‹ˆ๋‹ค.', 42); +insert into caroption values (3, 2, '๋“€์–ผ ๋จธํ”Œ๋Ÿฌ ํŒจํ‚ค์ง€', '/images/options/sub/murfler.jpg', '๋จธํ”Œ๋Ÿฌ์ž…๋‹ˆ๋‹ค.', 55); +insert into caroption values (4, 3, '20์ธ์น˜ ๋‹คํฌ ์Šคํผํ„ฐ๋ง ํœ ', '/images/options/sub/darkwheel.jpg', '๋‹คํฌ ํœ ์ž…๋‹ˆ๋‹ค.', 12); +insert into CarOption (option_id, option_category_id, option_name, option_image, option_description) values (72, 9, '๋นŒํŠธ์ธ ์บ ', '/options/builtincam.png', '๋นŒํŠธ์ธ ์ ์šฉ๋œ ์˜์ƒ๊ธฐ๋ก์žฅ์น˜๋กœ, ๋‚ด๋น„๊ฒŒ์ด์…˜ ํ™”๋ฉด์„ ํ†ตํ•ด ์˜์ƒ ํ™•์ธ ๋ฐ ์•ฑ ์—ฐ๋™์„ ํ†ตํ•ด ์˜์ƒ ํ™•์ธ ๋ฐ SNS ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.'); +insert into CarOption values (75, 2, 'ํ›„์„ ์Šน๊ฐ์•Œ๋ฆผ', '/options/rear-passenger.png', '์ดˆ์ŒํŒŒ ์„ผ์„œ๋ฅผ ํ†ตํ•ด ๋’ท์ขŒ์„์— ๋‚จ์•„์žˆ๋Š” ์Šน๊ฐ์˜ ์›€์ง์ž„์„ ๊ฐ์ง€ํ•˜์—ฌ ์šด์ „์ž์—๊ฒŒ ๊ฒฝ๊ณ ํ•จ์œผ๋กœ์จ ๋ถ€์ฃผ์˜์— ์˜ํ•œ ์œ ์•„ ๋˜๋Š” ๋ฐ˜๋ ค ๋™๋ฌผ ๋“ฑ์˜ ๋ฐฉ์น˜ ์‚ฌ๊ณ ๋ฅผ ์˜ˆ๋ฐฉํ•˜๋Š” ์‹ ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.', 82); +insert into CarOption (option_id, option_category_id, option_name, option_image, option_description) values (76, 4, '๋ฉ”ํƒˆ ๋ฆฌ์–ด๋ฒ”ํผ์Šคํ…', '/options/metalrearbumper.png', '๋Ÿฌ๊ธฐ์ง€ ๋ฃธ ์•ž์ชฝ ํ•˜๋‹จ๋ถ€๋ฅผ ๋ฉ”ํƒˆ๋กœ ๋งŒ๋“ค์–ด ๋ฌผ๊ฑด์„ ์‹ฃ๊ณ  ๋‚ด๋ฆด ๋•Œ๋‚˜ ์‚ฌ๋žŒ์ด ์˜ฌ๋ผ๊ฐˆ ๋•Œ ์ฐจ์ฒด๋ฅผ ๋ณดํ˜ธํ•ด์ค๋‹ˆ๋‹ค.'); +insert into CarOption(option_id, option_category_id, option_name, option_image) values (69, 9, '์ปดํฌํŠธ2', '/options/rear-passenger.png'); + +insert into SubOptionData values (1, 1, 1, 2800, 100000); +insert into SubOptionData values (2, 1, 2, 4200, 130000); +insert into SubOptionData values (3, 1, 3, 1300, 870000); +insert into SubOptionData values (4, 1, 4, 3850, 50000); +insert into SubOptionData values (5, 1, 72, 133980, 690000); +insert into SubOptionData values (6, 1, 69, 48015, 1090000); + +insert into Hashtag values (1, '๋ ˆ์ €'); +insert into Hashtag values (2, '์Šคํฌ์ธ '); +insert into Hashtag values (3, '์บ ํ•‘'); +insert into Hashtag values (4, '์žฅ๊ฑฐ๋ฆฌ ์šด์ „'); +insert into Hashtag values (5, '์ฃผ์ฐจ'); + +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (1, 1, 1); +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (2, 1, 2); +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (3, 1, 3); +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (4, 2, 1); +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (5, 2, 4); +insert into OptionHashtag (option_hashtag_id, option_id, hashtag_id) values (6, 2, 5); + +insert into defaultOptionData values(1, 1, 1); +insert into defaultOptionData values(2, 1, 2); +insert into defaultOptionData values(3, 1, 3); + +insert into SubOptionPackage values (69, 75); +insert into SubOptionPackage values (69, 76); + +insert into ModelType (model_type_id, model_type_name) VALUES (1, 'ํŒŒ์›ŒํŠธ๋ ˆ์ธ'); +insert into ModelType (model_type_id, model_type_name) VALUES (2, '๊ตฌ๋™๋ฐฉ์‹'); +insert into ModelType (model_type_id, model_type_name) VALUES (3, '๋ฐ”๋””ํƒ€์ž…'); + +INSERT INTO Model VALUES (1,'๋””์ ค2.2',1,'๋†’์€ ํ† ํฌ๋กœ ํŒŒ์›Œํ’€ํ•œ ๋“œ๋ผ์ด๋น™์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ฐจ๊ธ‰๋Œ€๋น„ ์—ฐ๋น„ ํšจ์œจ์ด ์šฐ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค',1480000,'/model/diesel2-2.jpg'); +INSERT INTO Model VALUES (2,'๊ฐ€์†”๋ฆฐ3.8',1,'๊ณ ๋งˆ๋ ฅ์˜ ์šฐ์ˆ˜ํ•œ ๊ฐ€์† ์„ฑ๋Šฅ์„ ํ™•๋ณดํ•˜์—ฌ, ๋„‰๋„‰ํ•˜๊ณ  ์•ˆ์ •๊ฐ ์žˆ๋Š” ์ฃผํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.' || CHR(10) || '์—”์ง„์˜ ์ง„๋™์ด ์ ์–ด ํŽธ์•ˆํ•˜๊ณ  ์กฐ์šฉํ•œ ๋“œ๋ผ์ด๋น™ ๊ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.',0,'/model/gasoline3-8.jpg'); +INSERT INTO Model VALUES (3,'2WD',2,'์—”์ง„์—์„œ ์ „๋‹ฌ๋˜๋Š” ๋™๋ ฅ์ด ์ „/ํ›„๋ฅœ ๋ฐ”ํ€ด ์ค‘ ํ•œ์ชฝ์œผ๋กœ๋งŒ ์ „๋‹ฌ๋˜์–ด ์ฐจ๋Ÿ‰์„ ์›€์ง์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.' || CHR(10) || '์ฐจ์ฒด๊ฐ€ ๊ฐ€๋ฒผ์›Œ ์—ฐ๋ฃŒ ํšจ์œจ์ด ๋†’์Šต๋‹ˆ๋‹ค.',0,'/model/2wd.png'); +INSERT INTO Model VALUES (4,'4WD',2,'์ „์ž์‹ ์ƒ์‹œ 4๋ฅœ ๊ตฌ๋™ ์‹œ์Šคํ…œ ์ž…๋‹ˆ๋‹ค.' || CHR(10) || '๋„๋กœ์˜ ์ƒํ™ฉ์ด๋‚˜ ์ฃผํ–‰ ํ™˜๊ฒฝ์— ๋งž์ถฐ ์ „ํ›„๋ฅœ ๊ตฌ๋™๋ ฅ์„ ์ž๋™๋ฐฐ๋ถ„ํ•˜์—ฌ ์ฃผํ–‰ ์•ˆ์ „์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค',2370000,'/model/4wd.png'); +INSERT INTO Model VALUES (5,'7์ธ์Šน',3,'๊ธฐ์กด 8์ธ์Šน ์‹œํŠธ(1์—ด 2๋ช…, 2์—ด 3๋ช…, 3์—ด 3๋ช…)์—์„œ 2์—ด ๊ฐ€์šด๋ฐ ์‹œํŠธ๋ฅผ ์—†์•  2์—ด ํƒ‘์Šน๊ฐ์˜ ํŽธ์˜๋Š” ๋ฌผ๋ก , 3์—ด ํƒ‘์Šน๊ฐ์˜ ์Šนํ•˜์ฐจ๊ฐ€ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค',0,'/model/7seats.jpg'); +INSERT INTO Model VALUES (6,'8์ธ์Šน',3,'1์—ด 2๋ช…, 2์—ด 3๋ช…, 3์—ด 3๋ช…์ด ํƒ‘์Šนํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ, ๋งŽ์€ ์ธ์›์ด ํƒ‘์Šนํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐ๋ คํ•˜์˜€์Šต๋‹ˆ๋‹ค',0,'/model/8seats.jpg'); + +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (1, 1, 91, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (2, 1, 71, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (3, 1, 84, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (4, 1, 96, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (5, 1, 81, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (6, 1, 69, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (7, 1, 67, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (8, 1, 87, ''); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (9, 1, 82, '69'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (10, 1, 99, '69'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (11, 1, 77, '69'); + + +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (0, 1, 1); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (1, 3, 1); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (2, 5, 1); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (3, 1, 2); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (4, 3, 2); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (5, 6, 2); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (6, 1, 3); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (7, 4, 3); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (8, 5, 3); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (10, 4, 4); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (9, 1, 4); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (11, 6, 4); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (12, 2, 5); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (13, 3, 5); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (14, 5, 5); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (15, 2, 6); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (16, 3, 6); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (17, 6, 6); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (18, 2, 7); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (19, 4, 7); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (20, 5, 7); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (21, 2, 8); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (22, 4, 8); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (23, 6, 8); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (24, 1, 9); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (25, 3, 9); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (26, 5, 9); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (27, 1, 10); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (28, 3, 10); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (29, 6, 10); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (30, 1, 11); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (31, 4, 11); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (32, 5, 11); \ No newline at end of file diff --git a/backend/src/test/resources/insert/insert-quote-h2.sql b/backend/src/test/resources/insert/insert-quote-h2.sql new file mode 100644 index 0000000..24a8eb8 --- /dev/null +++ b/backend/src/test/resources/insert/insert-quote-h2.sql @@ -0,0 +1,45 @@ +insert into CarType (car_type_id, car_type_image, car_type_name) values (1, '/cartype/palisade/palisade-thumbnail.png', 'ํŒฐ๋ฆฌ์„ธ์ด๋“œ'); +insert into Car values (1, 1, '๋ฅด๋ธ”๋ž‘', 41980000, '/cartype/palisade/leblanc-outer.png', '/cartype/palisade/palisade-inner.png', '/cartype/palisade/leblanc-wheel.png', 150000, 'ํ•ฉ๋ฆฌ์ ์ธ ์กฐํ•ฉ์˜ ์ ˆ์ •'); + +insert into ModelType (model_type_id, model_type_name) VALUES (1, 'ํŒŒ์›ŒํŠธ๋ ˆ์ธ'); +insert into ModelType (model_type_id, model_type_name) VALUES (2, '๊ตฌ๋™๋ฐฉ์‹'); +insert into ModelType (model_type_id, model_type_name) VALUES (3, '๋ฐ”๋””ํƒ€์ž…'); + +INSERT INTO Model VALUES (1,'๋””์ ค2.2',1,'๋†’์€ ํ† ํฌ๋กœ ํŒŒ์›Œํ’€ํ•œ ๋“œ๋ผ์ด๋น™์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ฐจ๊ธ‰๋Œ€๋น„ ์—ฐ๋น„ ํšจ์œจ์ด ์šฐ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค',1480000,'/model/diesel2-2.jpg'); +INSERT INTO Model VALUES (2,'๊ฐ€์†”๋ฆฐ3.8',1,'๊ณ ๋งˆ๋ ฅ์˜ ์šฐ์ˆ˜ํ•œ ๊ฐ€์† ์„ฑ๋Šฅ์„ ํ™•๋ณดํ•˜์—ฌ, ๋„‰๋„‰ํ•˜๊ณ  ์•ˆ์ •๊ฐ ์žˆ๋Š” ์ฃผํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.' || CHR(10) || '์—”์ง„์˜ ์ง„๋™์ด ์ ์–ด ํŽธ์•ˆํ•˜๊ณ  ์กฐ์šฉํ•œ ๋“œ๋ผ์ด๋น™ ๊ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.',0,'/model/gasoline3-8.jpg'); +INSERT INTO Model VALUES (3,'2WD',2,'์—”์ง„์—์„œ ์ „๋‹ฌ๋˜๋Š” ๋™๋ ฅ์ด ์ „/ํ›„๋ฅœ ๋ฐ”ํ€ด ์ค‘ ํ•œ์ชฝ์œผ๋กœ๋งŒ ์ „๋‹ฌ๋˜์–ด ์ฐจ๋Ÿ‰์„ ์›€์ง์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.' || CHR(10) || '์ฐจ์ฒด๊ฐ€ ๊ฐ€๋ฒผ์›Œ ์—ฐ๋ฃŒ ํšจ์œจ์ด ๋†’์Šต๋‹ˆ๋‹ค.',0,'/model/2wd.png'); +INSERT INTO Model VALUES (4,'4WD',2,'์ „์ž์‹ ์ƒ์‹œ 4๋ฅœ ๊ตฌ๋™ ์‹œ์Šคํ…œ ์ž…๋‹ˆ๋‹ค.' || CHR(10) || '๋„๋กœ์˜ ์ƒํ™ฉ์ด๋‚˜ ์ฃผํ–‰ ํ™˜๊ฒฝ์— ๋งž์ถฐ ์ „ํ›„๋ฅœ ๊ตฌ๋™๋ ฅ์„ ์ž๋™๋ฐฐ๋ถ„ํ•˜์—ฌ ์ฃผํ–‰ ์•ˆ์ „์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค',2370000,'/model/4wd.png'); +INSERT INTO Model VALUES (5,'7์ธ์Šน',3,'๊ธฐ์กด 8์ธ์Šน ์‹œํŠธ(1์—ด 2๋ช…, 2์—ด 3๋ช…, 3์—ด 3๋ช…)์—์„œ 2์—ด ๊ฐ€์šด๋ฐ ์‹œํŠธ๋ฅผ ์—†์•  2์—ด ํƒ‘์Šน๊ฐ์˜ ํŽธ์˜๋Š” ๋ฌผ๋ก , 3์—ด ํƒ‘์Šน๊ฐ์˜ ์Šนํ•˜์ฐจ๊ฐ€ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค',0,'/model/7seats.jpg'); +INSERT INTO Model VALUES (6,'8์ธ์Šน',3,'1์—ด 2๋ช…, 2์—ด 3๋ช…, 3์—ด 3๋ช…์ด ํƒ‘์Šนํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ, ๋งŽ์€ ์ธ์›์ด ํƒ‘์Šนํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐ๋ คํ•˜์˜€์Šต๋‹ˆ๋‹ค',0,'/model/8seats.jpg'); + +insert into Color values(1, '์ฒœ์—ฐ ํ€„ํŒ…(๋ธ”๋ž™)', 'image_1', 1); +insert into Color values(2, '์ฒœ์—ฐ ํ€„ํŒ…(ํ™”์ดํŠธ)', 'image_2', 1); +insert into Color values(3, 'ํผํ”Œ ๊ทธ๋ ˆ์ด ํŽ„', 'image_3', 0); +insert into Color values(4, '์ฝ”๋ฐœํŠธ ๋ธ”๋ฃจ', 'image_4', 0); + +insert into ColorCarMapper values(1, 1, 1, 'red_image_*.jpg', 1234, 12348); +insert into ColorCarMapper values(2, 1, 2, 'white_image_*.jpg', 555, 12346); +insert into ColorCarMapper values(3, 1, 3, 'black_image_*.jpg', 154, 12354); +insert into ColorCarMapper values(4, 1, 4, 'blue_image_*.jpg', 1734, 1234); + +insert into OptionCategory (option_category_id, option_category_name) VALUES (1, '์ƒ์„ธํ’ˆ๋ชฉ'); +insert into OptionCategory (option_category_id, option_category_name) VALUES (2, '์•…์„ธ์‚ฌ๋ฆฌ'); +insert into OptionCategory (option_category_id, option_category_name) VALUES (3, 'ํœ '); +insert into OptionCategory (option_category_id, option_category_name) VALUES (4, '์™ธ๊ด€'); +insert into OptionCategory (option_category_id, option_category_name) values (9, '์ƒ์„ธํ’ˆ๋ชฉ'); + +insert into caroption values (1, 1, '2์—ด ํ†ตํ’ ์‹œํŠธ', '/images/options/sub/2seats.jpg', '์‹œ๋™์ด ๊ฑธ๋ฆฐ ์ƒํƒœ์—์„œ ํ•ด๋‹น ์ขŒ์„์˜ ํ†ตํ’ ์Šค์œ„์น˜๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ‘œ์‹œ๋“ฑ์ด ์ผœ์ง€๋ฉด์„œ ํ•ด๋‹น ์ขŒ์„์— ๋ฐ”๋žŒ์ด ๋‚˜์˜ค๋Š” ํŽธ์˜์žฅ์น˜์ž…๋‹ˆ๋‹ค.', 38); +insert into caroption values (2, 2, '์ ์™ธ์„  ๋ฌด๋ฆŽ ์›Œ๋จธ', '/images/options/sub/warmer.jpg', '์›Œ๋จธ์ž…๋‹ˆ๋‹ค.', 42); +insert into caroption values (3, 2, '๋“€์–ผ ๋จธํ”Œ๋Ÿฌ ํŒจํ‚ค์ง€', '/images/options/sub/murfler.jpg', '๋จธํ”Œ๋Ÿฌ์ž…๋‹ˆ๋‹ค.', 55); +insert into caroption values (4, 3, '20์ธ์น˜ ๋‹คํฌ ์Šคํผํ„ฐ๋ง ํœ ', '/images/options/sub/darkwheel.jpg', '๋‹คํฌ ํœ ์ž…๋‹ˆ๋‹ค.', 12); +insert into CarOption (option_id, option_category_id, option_name, option_image, option_description) values (72, 9, '๋นŒํŠธ์ธ ์บ ', '/options/builtincam.png', '๋นŒํŠธ์ธ ์ ์šฉ๋œ ์˜์ƒ๊ธฐ๋ก์žฅ์น˜๋กœ, ๋‚ด๋น„๊ฒŒ์ด์…˜ ํ™”๋ฉด์„ ํ†ตํ•ด ์˜์ƒ ํ™•์ธ ๋ฐ ์•ฑ ์—ฐ๋™์„ ํ†ตํ•ด ์˜์ƒ ํ™•์ธ ๋ฐ SNS ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.'); +insert into CarOption values (75, 2, 'ํ›„์„ ์Šน๊ฐ์•Œ๋ฆผ', '/options/rear-passenger.png', '์ดˆ์ŒํŒŒ ์„ผ์„œ๋ฅผ ํ†ตํ•ด ๋’ท์ขŒ์„์— ๋‚จ์•„์žˆ๋Š” ์Šน๊ฐ์˜ ์›€์ง์ž„์„ ๊ฐ์ง€ํ•˜์—ฌ ์šด์ „์ž์—๊ฒŒ ๊ฒฝ๊ณ ํ•จ์œผ๋กœ์จ ๋ถ€์ฃผ์˜์— ์˜ํ•œ ์œ ์•„ ๋˜๋Š” ๋ฐ˜๋ ค ๋™๋ฌผ ๋“ฑ์˜ ๋ฐฉ์น˜ ์‚ฌ๊ณ ๋ฅผ ์˜ˆ๋ฐฉํ•˜๋Š” ์‹ ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.', 82); +insert into CarOption (option_id, option_category_id, option_name, option_image, option_description) values (76, 4, '๋ฉ”ํƒˆ ๋ฆฌ์–ด๋ฒ”ํผ์Šคํ…', '/options/metalrearbumper.png', '๋Ÿฌ๊ธฐ์ง€ ๋ฃธ ์•ž์ชฝ ํ•˜๋‹จ๋ถ€๋ฅผ ๋ฉ”ํƒˆ๋กœ ๋งŒ๋“ค์–ด ๋ฌผ๊ฑด์„ ์‹ฃ๊ณ  ๋‚ด๋ฆด ๋•Œ๋‚˜ ์‚ฌ๋žŒ์ด ์˜ฌ๋ผ๊ฐˆ ๋•Œ ์ฐจ์ฒด๋ฅผ ๋ณดํ˜ธํ•ด์ค๋‹ˆ๋‹ค.'); +insert into CarOption(option_id, option_category_id, option_name, option_image) values (69, 9, '์ปดํฌํŠธ2', '/options/rear-passenger.png'); + +insert into SubOptionData values (1, 1, 1, 2800, 100000); +insert into SubOptionData values (2, 1, 2, 4200, 130000); +insert into SubOptionData values (3, 1, 3, 1300, 870000); +insert into SubOptionData values (4, 1, 4, 3850, 50000); +insert into SubOptionData values (5, 1, 72, 133980, 690000); +insert into SubOptionData values (6, 1, 69, 48015, 1090000); \ No newline at end of file diff --git a/backend/src/test/resources/insert/insert-sales-h2.sql b/backend/src/test/resources/insert/insert-sales-h2.sql new file mode 100644 index 0000000..d889878 --- /dev/null +++ b/backend/src/test/resources/insert/insert-sales-h2.sql @@ -0,0 +1,177 @@ +SET REFERENTIAL_INTEGRITY FALSE; + +INSERT INTO SubOptionData (sub_option_data_id, car_id, option_id, option_bought_count, option_price) VALUES (1, 1, 69, 48015, 1090000); +INSERT INTO SubOptionData (sub_option_data_id, car_id, option_id, option_bought_count, option_price) VALUES (2, 1, 70, 121380, 790000); + +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (129, 1, 155, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (130, 1, 165, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (131, 1, 152, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (132, 1, 139, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (133, 1, 135, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (134, 1, 164, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (135, 1, 153, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (136, 1, 143, '69,70'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (137, 1, 162, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (138, 1, 148, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (139, 1, 138, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (140, 1, 159, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (141, 1, 156, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (142, 1, 150, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (143, 1, 154, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (144, 1, 145, '69,71'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (145, 1, 144, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (146, 1, 157, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (147, 1, 150, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (148, 1, 162, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (149, 1, 145, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (150, 1, 155, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (151, 1, 162, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (152, 1, 158, '69,72'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (153, 1, 149, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (154, 1, 145, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (155, 1, 150, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (156, 1, 164, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (157, 1, 163, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (158, 1, 152, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (159, 1, 143, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (160, 1, 142, '69,73'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (161, 1, 140, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (162, 1, 138, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (163, 1, 151, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (164, 1, 159, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (165, 1, 144, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (166, 1, 139, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (167, 1, 144, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (168, 1, 149, '69,74'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (169, 1, 140, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (170, 1, 150, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (171, 1, 152, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (172, 1, 143, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (173, 1, 162, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (174, 1, 151, '69,84'); +INSERT INTO SalesHistory (history_id, car_id, sold_count, sold_options_id) VALUES (175, 1, 149, '69,84'); + + +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (384, 1, 129); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (385, 3, 129); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (386, 5, 129); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (387, 1, 130); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (388, 3, 130); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (389, 6, 130); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (390, 1, 131); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (391, 4, 131); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (392, 5, 131); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (393, 1, 132); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (394, 4, 132); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (395, 6, 132); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (396, 2, 133); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (397, 3, 133); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (398, 5, 133); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (399, 2, 134); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (400, 3, 134); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (401, 6, 134); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (402, 2, 135); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (403, 4, 135); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (404, 5, 135); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (405, 2, 136); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (406, 4, 136); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (407, 6, 136); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (408, 1, 137); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (409, 3, 137); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (410, 5, 137); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (411, 1, 138); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (412, 3, 138); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (413, 6, 138); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (414, 1, 139); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (415, 4, 139); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (416, 5, 139); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (417, 1, 140); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (418, 4, 140); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (419, 6, 140); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (420, 2, 141); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (421, 3, 141); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (422, 5, 141); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (423, 2, 142); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (424, 3, 142); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (425, 6, 142); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (426, 2, 143); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (427, 4, 143); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (428, 5, 143); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (429, 2, 144); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (430, 4, 144); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (431, 6, 144); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (432, 1, 145); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (433, 3, 145); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (434, 5, 145); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (435, 1, 146); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (436, 3, 146); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (437, 6, 146); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (438, 1, 147); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (439, 4, 147); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (440, 5, 147); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (441, 1, 148); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (442, 4, 148); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (443, 6, 148); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (444, 2, 149); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (445, 3, 149); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (446, 5, 149); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (447, 2, 150); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (448, 3, 150); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (449, 6, 150); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (450, 2, 151); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (451, 4, 151); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (452, 5, 151); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (453, 2, 152); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (454, 4, 152); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (455, 6, 152); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (456, 1, 153); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (457, 3, 153); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (458, 5, 153); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (459, 1, 154); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (460, 3, 154); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (461, 6, 154); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (462, 1, 155); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (463, 4, 155); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (464, 5, 155); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (465, 1, 156); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (466, 4, 156); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (467, 6, 156); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (468, 2, 157); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (469, 3, 157); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (470, 5, 157); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (471, 2, 158); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (472, 3, 158); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (473, 6, 158); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (474, 2, 159); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (475, 4, 159); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (476, 5, 159); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (477, 2, 160); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (478, 4, 160); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (479, 6, 160); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (480, 1, 161); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (481, 3, 161); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (482, 5, 161); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (483, 1, 162); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (484, 3, 162); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (485, 6, 162); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (486, 1, 163); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (487, 4, 163); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (488, 5, 163); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (489, 1, 164); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (490, 4, 164); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (491, 6, 164); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (492, 2, 165); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (493, 3, 165); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (494, 5, 165); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (495, 2, 166); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (496, 3, 166); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (497, 6, 166); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (498, 2, 167); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (499, 4, 167); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (500, 5, 167); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (501, 2, 168); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (502, 4, 168); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (503, 6, 168); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (504, 1, 169); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (505, 3, 169); +INSERT INTO HistoryModelMapper (history_model_mapper_id, model_id, history_id) VALUES (506, 5, 169);