From 32652ee3a2b4721024eb9f40f9109e569c14060f Mon Sep 17 00:00:00 2001 From: Dmitry Kutuzov Date: Mon, 26 Jun 2023 22:02:23 +0300 Subject: [PATCH 1/3] done hw12 --- dev/docker-compose.yml | 2 + handyman-service/build.gradle | 4 + .../handyman/HandymanController.java | 8 ++ .../handyman/HandymanRepository.java | 5 ++ .../handyman/HandymanService.java | 48 ++++++++++- .../handymanservice/landscape/Order.java | 25 ++++++ .../landscape/OrderClient.java | 31 +++++++ .../handymanservice/landscape/WorkStatus.java | 8 ++ .../handymanservice/landscape/WorkType.java | 8 ++ .../landscape/dto/CreatingOrderDto.java | 24 ++++++ .../handymanservice/landscape/dto/Field.java | 22 +++++ .../landscape/dto/FieldDto.java | 21 +++++ .../landscape/dto/OrderDto.java | 27 +++++++ landscape-service/build.gradle | 4 + .../LandscapeApplication.java | 3 + .../LandscapeConfiguration.java | 2 + .../archie/landscapeservice/field/Field.java | 2 + .../gardener/GardenerClient.java | 21 +++++ .../handyman/HandymanClient.java | 15 ++++ .../handyman/HandymanRepository.java | 12 +++ .../handyman/HandymanService.java | 7 ++ .../archie/landscapeservice/order/Order.java | 17 +++- .../order/OrderRepository.java | 31 ++++--- .../landscapeservice/order/OrderResolver.java | 80 +++++++++++++++++++ .../landscapeservice/order/OrderService.java | 29 ++++++- .../order/dto/CreatingOrderDto.java | 4 + .../archie/landscapeservice/user/User.java | 9 +++ .../src/main/resources/application.properties | 5 +- .../rancherservice/landscape/OrderClient.java | 39 +++++++++ .../landscape/dto/CreatingOrderDto.java | 24 ++++++ .../landscape/dto/OrderDto.java | 25 ++++++ .../landscape/dto/SkillDto.java | 12 +++ .../landscape/dto/WorkStatus.java | 8 ++ .../landscape/dto/WorkType.java | 8 ++ .../rancherservice/order/OrderController.java | 42 ++++++++++ .../rancherservice/order/OrderService.java | 30 +++++++ .../rancher/GardenerController.java | 12 +++ .../rancher/GardenerService.java | 45 +++++++++++ 38 files changed, 704 insertions(+), 15 deletions(-) create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/Order.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkStatus.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkType.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/CreatingOrderDto.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java create mode 100644 handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/OrderDto.java create mode 100644 landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java create mode 100644 landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanClient.java create mode 100644 landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/OrderClient.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/CreatingOrderDto.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/SkillDto.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkStatus.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkType.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/order/OrderController.java create mode 100644 rancher-service/src/main/java/dev/archie/rancherservice/order/OrderService.java diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index b64a903..7b36e47 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -36,6 +36,8 @@ services: - DB_URL=jdbc:postgresql://postgres:5432/postgres?currentSchema=public&stringtype=unspecified - DB_USERNAME=postgres - DB_PASSWORD=123 + - RANCHER_REST_URL=http://rancher-service:8082 + - HANDYMAN_REST_URL=http://handyman-service:8080 depends_on: - rancher-service - handyman-service diff --git a/handyman-service/build.gradle b/handyman-service/build.gradle index c0ac897..93afae0 100644 --- a/handyman-service/build.gradle +++ b/handyman-service/build.gradle @@ -64,6 +64,10 @@ ext { } dependencies { + implementation 'org.n52.jackson:jackson-datatype-jts:1.2.10' + implementation 'org.locationtech.jts:jts-io:1.18.2' + implementation 'org.locationtech.jts:jts-core:1.18.2' + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java index 05f22eb..e6c36ff 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java @@ -1,6 +1,7 @@ package dev.archie.handymanservice.handyman; import dev.archie.handymanservice.handyman.dto.CreatingHandymanDto; +import dev.archie.handymanservice.landscape.Order; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -11,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.UUID; + @RestController @RequiredArgsConstructor @RequestMapping("/handymen") @@ -53,4 +56,9 @@ public Handyman update(@PathVariable String id, @RequestBody CreatingHandymanDto public void delete(@PathVariable String id) { handymanService.delete(id); } + + @PostMapping("/order/{innerId}") + public boolean orderAJob(@PathVariable UUID innerId, @RequestBody Order order) { + return handymanService.orderAJob(innerId, order); + } } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java index 8a95f4c..99e5d07 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java @@ -2,5 +2,10 @@ import org.springframework.data.mongodb.repository.MongoRepository; +import java.util.Optional; +import java.util.UUID; + public interface HandymanRepository extends MongoRepository { + boolean existsByInnerId(UUID innerId); + Optional findByInnerId(UUID innerId); } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java index 97c1439..4ad1694 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java @@ -8,14 +8,24 @@ import dev.archie.handymanservice.handyman.skill.SkillRepository; import dev.archie.handymanservice.landscape.HandymanClient; import dev.archie.handymanservice.landscape.LandscapeService; +import dev.archie.handymanservice.landscape.Order; +import dev.archie.handymanservice.landscape.OrderClient; +import dev.archie.handymanservice.landscape.WorkStatus; +import dev.archie.handymanservice.landscape.dto.CreatingOrderDto; import dev.archie.handymanservice.landscape.dto.HandymanDto; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @Service @RequiredArgsConstructor +@Slf4j public class HandymanService { private final HandymanRepository handymanRepository; @@ -27,6 +37,7 @@ public class HandymanService { private final AccountService accountService; private final HandymanClient handymanClient; + private final OrderClient orderClient; /** * @param creatingHandymanDto handyman dto create. Email should not exist @@ -62,7 +73,7 @@ public Handyman getById(String id) { } /** - * @param id of existing profile + * @param id of existing profile * @param creatingHandymanDto of new fields. New email should not exist * @return Profile od updated handyman */ @@ -114,4 +125,39 @@ private Handyman mapUserToHandyman(HandymanDto createdUser, CreatingHandymanDto .phone(creatingHandymanDto.getPhoneNumber()) .build(); } + + public boolean orderAJob(UUID innerId, Order order) { + if (!handymanRepository.existsByInnerId(innerId)) { + throw new NoSuchUserException(innerId.toString()); + } + boolean acceptedTheJob = order.getSkills().stream() + .noneMatch(skill -> skill.getName().contains("поливать")); + if (acceptedTheJob) { + CompletableFuture.runAsync(() -> getTheJobDone(order, innerId)); + log.info(innerId + " принял работу"); + } else { + log.info(innerId + " отказался от работы"); + } + return acceptedTheJob; + } + + public void getTheJobDone(Order order, UUID innerId) { + Random random = new Random(); + try { + Thread.sleep(random.nextLong(4000) + 3000); + } catch (InterruptedException e) { + throw new RuntimeException("Execution was interrupted" + e); + } + order.setStatus(WorkStatus.DONE); + CreatingOrderDto updatingDto = CreatingOrderDto.builder() + .status(order.getStatus()) + .fieldId(order.getField().getId()) + .userId(innerId) + .workType(order.getWorkType()) + .skills(order.getSkills().stream().map(Skill::getName).toList()) + .build(); + orderClient.update(order.getId(), updatingDto); + log.info(innerId + " выполнил работу"); + } + } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/Order.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/Order.java new file mode 100644 index 0000000..188ca71 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/Order.java @@ -0,0 +1,25 @@ +package dev.archie.handymanservice.landscape; + + +import dev.archie.handymanservice.handyman.skill.Skill; +import dev.archie.handymanservice.landscape.dto.Field; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Set; + +@Data +public class Order { + private Long id; + + private WorkType workType; + + private WorkStatus status; + + private LocalDateTime createdAt; + + private Field field; + + private Set skills; + +} diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java new file mode 100644 index 0000000..75e7d7e --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java @@ -0,0 +1,31 @@ +package dev.archie.handymanservice.landscape; + +import dev.archie.handymanservice.landscape.dto.CreatingOrderDto; +import dev.archie.handymanservice.landscape.dto.OrderDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.UUID; + +@FeignClient(name = "order-client", path = "/orders", url = "${application.landscape.rest.url}") +public interface OrderClient { + + @PostMapping + OrderDto create(@RequestBody CreatingOrderDto orderDto); + + @GetMapping("/{id}") + OrderDto getById(@PathVariable Long id); + @PutMapping("/{id}") + OrderDto update(@PathVariable Long id, @RequestBody CreatingOrderDto orderDto); + + @DeleteMapping("/{id}") + void delete(@PathVariable Long id); + +} + diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkStatus.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkStatus.java new file mode 100644 index 0000000..a744435 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkStatus.java @@ -0,0 +1,8 @@ +package dev.archie.handymanservice.landscape; + +public enum WorkStatus { + CREATED, + IN_PROGRESS, + DONE, + APPROVED +} diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkType.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkType.java new file mode 100644 index 0000000..d5ee208 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/WorkType.java @@ -0,0 +1,8 @@ +package dev.archie.handymanservice.landscape; + +public enum WorkType { + SHOVEL, + PLANT, + WATER, + SOW +} diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/CreatingOrderDto.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/CreatingOrderDto.java new file mode 100644 index 0000000..8b0ca11 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/CreatingOrderDto.java @@ -0,0 +1,24 @@ +package dev.archie.handymanservice.landscape.dto; + +import dev.archie.handymanservice.landscape.WorkStatus; +import dev.archie.handymanservice.landscape.WorkType; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +@Builder +public class CreatingOrderDto { + + private WorkType workType; + + private WorkStatus status; + + private Long fieldId; + + private UUID userId; + + private List skills; +} diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java new file mode 100644 index 0000000..a8b4107 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java @@ -0,0 +1,22 @@ +package dev.archie.handymanservice.landscape.dto; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; +import org.n52.jackson.datatype.jts.GeometryDeserializer; +import org.n52.jackson.datatype.jts.GeometrySerializer; + +@Data +public class Field { + + private Long id; + + private String address; + + private Double latitude; + + private Double longitude; + +} + diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java new file mode 100644 index 0000000..48b4613 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java @@ -0,0 +1,21 @@ +package dev.archie.handymanservice.landscape.dto; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import lombok.Data; +import org.locationtech.jts.geom.Geometry; +import org.n52.jackson.datatype.jts.GeometryDeserializer; +import org.n52.jackson.datatype.jts.GeometrySerializer; + +@Data +public class FieldDto { + + private Long id; + + private String address; + + private Double latitude; + + private Double longitude; + +} diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/OrderDto.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/OrderDto.java new file mode 100644 index 0000000..9d7f7cc --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/OrderDto.java @@ -0,0 +1,27 @@ +package dev.archie.handymanservice.landscape.dto; + + +import dev.archie.handymanservice.landscape.User; +import dev.archie.handymanservice.landscape.WorkStatus; +import dev.archie.handymanservice.landscape.WorkType; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class OrderDto { + private Long id; + + private WorkType workType; + + private WorkStatus status; + + private LocalDateTime createdAt; + + private FieldDto field; + + private User user; + + private List skills; +} diff --git a/landscape-service/build.gradle b/landscape-service/build.gradle index bbeb5fd..2e1580c 100644 --- a/landscape-service/build.gradle +++ b/landscape-service/build.gradle @@ -45,6 +45,7 @@ repositories { ext { set('testcontainersVersion', "1.17.6") + set('springCloudVersion', "2021.0.6") } jar { @@ -52,6 +53,8 @@ jar { } dependencies { + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' + implementation 'org.hibernate:hibernate-spatial' implementation 'org.n52.jackson:jackson-datatype-jts:1.2.10' implementation 'org.locationtech.jts:jts-io:1.18.2' @@ -86,6 +89,7 @@ dependencies { dependencyManagement { imports { mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}" + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } } diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java index 580e185..3700847 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java @@ -2,8 +2,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignClient; @SpringBootApplication +@EnableFeignClients public class LandscapeApplication { public static void main(String[] args) { diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeConfiguration.java b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeConfiguration.java index a557338..0129d4b 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeConfiguration.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeConfiguration.java @@ -3,8 +3,10 @@ import org.n52.jackson.datatype.jts.JtsModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; @Configuration +@EnableScheduling public class LandscapeConfiguration { @Bean diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java index ab6f22e..073bf9b 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java @@ -1,5 +1,6 @@ package dev.archie.landscapeservice.field; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import dev.archie.landscapeservice.gardener.Gardener; @@ -47,6 +48,7 @@ public class Field { @JsonDeserialize(contentUsing = GeometryDeserializer.class) private Geometry area; + @JsonIgnoreProperties("fields") @ManyToOne @JoinColumn(name = "gardener_id") private Gardener gardener; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java b/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java new file mode 100644 index 0000000..454ba65 --- /dev/null +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java @@ -0,0 +1,21 @@ +package dev.archie.landscapeservice.gardener; + +import dev.archie.landscapeservice.order.Order; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@FeignClient(name = "gardener-client", url = "${application.rancher.rest.url}", path = "/gardeners") +public interface GardenerClient { + + @PostMapping("/notify/missingWorkers") + void notifyAboutMissingWorkers(@RequestBody Order order); + + @PostMapping("/notify/orderUpdate") + void notifyAboutOrderUpdate(@RequestBody Order orderDto); +} diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanClient.java b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanClient.java new file mode 100644 index 0000000..375492b --- /dev/null +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanClient.java @@ -0,0 +1,15 @@ +package dev.archie.landscapeservice.handyman; + +import dev.archie.landscapeservice.order.Order; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.UUID; + +@FeignClient(url = "${application.handyman.rest.url}", path = "/handymen", name = "handyman-client") +public interface HandymanClient { + @PostMapping("/order/{innerId}") + boolean orderAJob(@PathVariable UUID innerId, @RequestBody Order order); +} diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java index ab0696f..2e1772e 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java @@ -1,8 +1,20 @@ package dev.archie.landscapeservice.handyman; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import java.util.List; import java.util.UUID; public interface HandymanRepository extends JpaRepository { + @Query(""" + select h + from Handyman h + join User u on u.id = h.id + where u.orders.size = 0 + order by ST_Distance(ST_Point(?1, ?2), ST_Point(u.latitude, u.longitude)) + """) + List findNearestNotBusyHandyman(Double latitude, Double longitude); } \ No newline at end of file diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanService.java b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanService.java index 1f608a0..beeef01 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanService.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanService.java @@ -1,5 +1,7 @@ package dev.archie.landscapeservice.handyman; +import dev.archie.landscapeservice.account.skill.Skill; +import dev.archie.landscapeservice.account.skill.SkillRepository; import dev.archie.landscapeservice.handyman.dto.CreatingHandymanDto; import dev.archie.landscapeservice.user.exceptions.NoSuchUserException; import dev.archie.landscapeservice.user.type.UserType; @@ -16,11 +18,16 @@ public class HandymanService { private final HandymanRepository handymanRepository; private final UserTypeRepository userTypeRepository; + private final SkillRepository skillRepository; public Handyman create(CreatingHandymanDto creatingHandymanDto) { Handyman handyman = mapCreatingHandymanDtoToHandyman(creatingHandymanDto); handyman.setCreatedAt(LocalDateTime.now()); handyman.setLastUpdatedAt(LocalDateTime.now()); + handyman.setSkills(creatingHandymanDto.getSkills().stream() + .map(skillName -> Skill.builder().name(skillName).build()) + .map(skillRepository::save) + .toList()); return handymanRepository.save(handyman); } diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java index ea8311a..ccaa7c8 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java @@ -1,6 +1,8 @@ package dev.archie.landscapeservice.order; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import dev.archie.landscapeservice.account.skill.Skill; import dev.archie.landscapeservice.field.Field; import dev.archie.landscapeservice.user.User; import lombok.AllArgsConstructor; @@ -17,9 +19,13 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; import java.time.LocalDateTime; +import java.util.LinkedHashSet; +import java.util.Set; @Builder @AllArgsConstructor @@ -49,8 +55,17 @@ public class Order { @JoinColumn(name = "field_id") private Field field; - @OneToOne + + @JsonIgnoreProperties("orders") + @ManyToOne @JoinColumn(name = "user_id") private User user; + @OneToMany + @JoinColumn(name = "order_id") + private Set skills = new LinkedHashSet<>(); + + @Column(name = "grade", nullable = false) + private int grade; + } diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderRepository.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderRepository.java index 87e4fd9..5b4071d 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderRepository.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderRepository.java @@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query; import java.util.List; +import java.util.Optional; import java.util.UUID; public interface OrderRepository extends JpaRepository { @@ -22,20 +23,30 @@ public interface OrderRepository extends JpaRepository { List findDistinctByField_Id(Long id); @Query(""" - SELECT h - FROM Order o JOIN o.user u - JOIN Handyman h ON u.id = h.id - WHERE o.field.id = ?1 + select h + from Order o join o.user u + join Handyman h on u.id = h.id + where o.field.id = ?1 """) List findHandymenByField_Id(Long id); @Query(""" - SELECT COUNT(DISTINCT s) < COUNT(DISTINCT o.workType) - FROM Order o JOIN o.user u - JOIN Handyman h ON u.id = h.id - JOIN h.skills s - JOIN o.field f - WHERE f.id = ?1 + select count(distinct s) < count(distinct o.workType) + from Order o join o.user u + join Handyman h on u.id = h.id + join h.skills s + join o.field f + where f.id = ?1 """) Boolean isWorkDeficit(Long id); + + @Query(""" + select o + from Order o + where o.createdAt = ( + select min(o1.createdAt) from Order o1 + where o1.status = 'CREATED' + ) + """) + Optional findFirstCreatedOrder(); } \ No newline at end of file diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java new file mode 100644 index 0000000..f2eaf79 --- /dev/null +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java @@ -0,0 +1,80 @@ +package dev.archie.landscapeservice.order; + +import dev.archie.landscapeservice.account.skill.Skill; +import dev.archie.landscapeservice.field.Field; +import dev.archie.landscapeservice.gardener.GardenerClient; +import dev.archie.landscapeservice.handyman.Handyman; +import dev.archie.landscapeservice.handyman.HandymanClient; +import dev.archie.landscapeservice.handyman.HandymanRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +@Service +@RequiredArgsConstructor +@Slf4j +public class OrderResolver { + + private static final int PAGE_SIZE = 10; + private final OrderRepository orderRepository; + private final HandymanRepository handymanRepository; + private final HandymanClient handymanClient; + private final GardenerClient gardenerClient; + + @Transactional + @Scheduled(initialDelay = 5000, fixedDelay = 2000) + public void sceduledResolver() { + resolve(); + } + + @Transactional + public void resolve() { + Optional firstCreatedOrder = orderRepository.findFirstCreatedOrder(); + if (firstCreatedOrder.isEmpty()) { + return; + } + Order order = firstCreatedOrder.get(); + + List threeNearestSuitableHandymen = findThreeNearestSuitableHandymen(order); + if (threeNearestSuitableHandymen.size() == 3) { + log.info("notifying handymen"); + notifyFoundHandymen(threeNearestSuitableHandymen, order); + } else { + log.info("notifying rancher"); + notifyRancher(order); + } + } + + private List findThreeNearestSuitableHandymen(Order order) { + Field field = order.getField(); + Set requiredSkills = order.getSkills(); + List foundHandymen = new ArrayList<>(); + List nearestNotBusyHandyman = handymanRepository.findNearestNotBusyHandyman(field.getLatitude(), field.getLongitude()); + nearestNotBusyHandyman.forEach(handyman -> { + if (requiredSkills.containsAll(handyman.getSkills())) { + foundHandymen.add(handyman); + } + }); + return foundHandymen.stream().limit(3).toList(); + } + + private void notifyFoundHandymen(List threeNearestSuitableHandymen, Order order) { + if (threeNearestSuitableHandymen.stream().allMatch(handyman -> handymanClient.orderAJob(handyman.getId(), order))) { + order.setStatus(WorkStatus.APPROVED); + } + } + + private void notifyRancher(Order order) { + gardenerClient.notifyAboutMissingWorkers(order); + } + +} diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java index 3c9a45f..7340cdb 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java @@ -1,22 +1,31 @@ package dev.archie.landscapeservice.order; +import dev.archie.landscapeservice.account.skill.Skill; +import dev.archie.landscapeservice.account.skill.SkillRepository; import dev.archie.landscapeservice.field.Field; import dev.archie.landscapeservice.field.FieldService; +import dev.archie.landscapeservice.gardener.GardenerClient; import dev.archie.landscapeservice.order.dto.CreatingOrderDto; import dev.archie.landscapeservice.order.exception.DirectionIsNotSpecifiedException; import dev.archie.landscapeservice.order.exception.NoSuchOrderException; import dev.archie.landscapeservice.user.User; import dev.archie.landscapeservice.user.UserService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor +@Slf4j public class OrderService { public static final String DEFAULT_DIRECTION = "ASC"; @@ -24,6 +33,8 @@ public class OrderService { private final UserService userService; private final FieldService fieldService; private final OrderRepository orderRepository; + private final SkillRepository skillRepository; + private final GardenerClient gardenerClient; public Order create(CreatingOrderDto orderDto) { User user = userService.getById(orderDto.getUserId()); @@ -51,9 +62,23 @@ public Page getAllSorted(int pageNumber, int size, UUID userId, String di public Order update(CreatingOrderDto creatingOrderDto, Long id) { Order order = getById(id); - order.setStatus(creatingOrderDto.getStatus()); + WorkStatus status = creatingOrderDto.getStatus(); + order.setStatus(status != null && status.equals(WorkStatus.DONE) ? WorkStatus.DONE : WorkStatus.CREATED); order.setWorkType(creatingOrderDto.getWorkType()); - return orderRepository.save(order); + Set skills = creatingOrderDto.getSkills().stream() + .map(skillName -> Skill.builder() + .name(skillName) + .build()) + .map(skillRepository::save) + .collect(Collectors.toSet()); + order.setSkills(skills); + order.setGrade(creatingOrderDto.getGrade()); + Order save = orderRepository.save(order); + log.info(order.toString()); + if (order.getStatus().equals(WorkStatus.DONE)) { + gardenerClient.notifyAboutOrderUpdate(save); + } + return save; } public void delete(Long id) { diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java index a95eb16..61f0161 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java @@ -4,6 +4,7 @@ import dev.archie.landscapeservice.order.WorkType; import lombok.Data; +import java.util.List; import java.util.UUID; @Data @@ -17,4 +18,7 @@ public class CreatingOrderDto { private UUID userId; + private List skills; + + private int grade; } diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java index 7f58473..52161aa 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java @@ -1,5 +1,7 @@ package dev.archie.landscapeservice.user; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import dev.archie.landscapeservice.order.Order; import dev.archie.landscapeservice.user.type.UserType; import lombok.AllArgsConstructor; import lombok.Builder; @@ -17,8 +19,11 @@ import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.Table; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -69,6 +74,10 @@ public class User { @Column(name = "last_name") private String lastName; + @JsonIgnoreProperties({"user", "field"}) + @OneToMany(mappedBy = "user") + private List orders = new ArrayList<>(); + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/landscape-service/src/main/resources/application.properties b/landscape-service/src/main/resources/application.properties index 8822738..f665a3a 100644 --- a/landscape-service/src/main/resources/application.properties +++ b/landscape-service/src/main/resources/application.properties @@ -16,4 +16,7 @@ spring.datasource.username=${DB_USERNAME} spring.datasource.password=${DB_PASSWORD} spring.jpa.hibernate.ddl-auto=update -spring.liquibase.enabled=true \ No newline at end of file +spring.liquibase.enabled=true + +application.rancher.rest.url=${RANCHER_REST_URL:http://localhost:8082} +application.handyman.rest.url=${HANDYMAN_REST_URL:http://localhost:8080} \ No newline at end of file diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/OrderClient.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/OrderClient.java new file mode 100644 index 0000000..9d09612 --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/OrderClient.java @@ -0,0 +1,39 @@ +package dev.archie.rancherservice.landscape; + +import dev.archie.rancherservice.landscape.dto.CreatingOrderDto; +import dev.archie.rancherservice.landscape.dto.OrderDto; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.UUID; + +@FeignClient(name = "order-client", path = "/orders", url = "${application.landscape.rest.url}") +public interface OrderClient { + + @PostMapping + OrderDto create(@RequestBody CreatingOrderDto orderDto); + + @GetMapping("/{id}") + OrderDto getById(@PathVariable Long id); + + @GetMapping + Page getAllSorted(@RequestParam(name = "page") int pageNumber, + @RequestParam(name = "size") int size, + @RequestParam(name = "id") UUID userId, + @RequestParam(name = "direction", required = false) String direction); + + @PutMapping("/{id}") + OrderDto update(@PathVariable Long id, @RequestBody CreatingOrderDto orderDto); + + @DeleteMapping("/{id}") + void delete(@PathVariable Long id); + +} + diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/CreatingOrderDto.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/CreatingOrderDto.java new file mode 100644 index 0000000..8ed895f --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/CreatingOrderDto.java @@ -0,0 +1,24 @@ +package dev.archie.rancherservice.landscape.dto; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +@Builder +public class CreatingOrderDto { + + private WorkType workType; + + private WorkStatus status; + + private Long fieldId; + + private UUID userId; + + private List skills; + + private int grade; +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java new file mode 100644 index 0000000..78f7d4e --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java @@ -0,0 +1,25 @@ +package dev.archie.rancherservice.landscape.dto; + + +import dev.archie.rancherservice.landscape.User; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class OrderDto { + private Long id; + + private WorkType workType; + + private WorkStatus status; + + private LocalDateTime createdAt; + + private FieldDto field; + + private User user; + + private List skills; +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/SkillDto.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/SkillDto.java new file mode 100644 index 0000000..723f2f9 --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/SkillDto.java @@ -0,0 +1,12 @@ +package dev.archie.rancherservice.landscape.dto; + +import lombok.Data; + +@Data +public class SkillDto { + + private Long id; + + private String name; + +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkStatus.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkStatus.java new file mode 100644 index 0000000..9906394 --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkStatus.java @@ -0,0 +1,8 @@ +package dev.archie.rancherservice.landscape.dto; + +public enum WorkStatus { + CREATED, + IN_PROGRESS, + DONE, + APPROVED +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkType.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkType.java new file mode 100644 index 0000000..4774d8c --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/WorkType.java @@ -0,0 +1,8 @@ +package dev.archie.rancherservice.landscape.dto; + +public enum WorkType { + SHOVEL, + PLANT, + WATER, + SOW +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderController.java b/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderController.java new file mode 100644 index 0000000..ee5ba09 --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderController.java @@ -0,0 +1,42 @@ +package dev.archie.rancherservice.order; + +import dev.archie.rancherservice.landscape.dto.CreatingOrderDto; +import dev.archie.rancherservice.landscape.dto.OrderDto; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/orders") +@RequiredArgsConstructor +public class OrderController { + + private final OrderService orderService; + + @PostMapping + public OrderDto create(@RequestBody CreatingOrderDto orderDto) { + return orderService.create(orderDto); + } + + @GetMapping("/{id}") + public OrderDto getById(@PathVariable Long id) { + return orderService.getById(id); + } + + @PutMapping("/{id}") + public OrderDto update(@PathVariable Long id, @RequestBody CreatingOrderDto orderDto) { + return orderService.update(orderDto, id); + } + + @DeleteMapping("/{id}") + public void delete(@PathVariable Long id) { + orderService.delete(id); + } + +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderService.java b/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderService.java new file mode 100644 index 0000000..3218eab --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/rancherservice/order/OrderService.java @@ -0,0 +1,30 @@ +package dev.archie.rancherservice.order; + +import dev.archie.rancherservice.landscape.OrderClient; +import dev.archie.rancherservice.landscape.dto.CreatingOrderDto; +import dev.archie.rancherservice.landscape.dto.OrderDto; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class OrderService { + + private final OrderClient orderClient; + + public OrderDto create(CreatingOrderDto creatingOrderDto) { + return orderClient.create(creatingOrderDto); + } + + public OrderDto update(CreatingOrderDto creatingOrderDto, Long id) { + return orderClient.update(id, creatingOrderDto); + } + + public OrderDto getById(Long id) { + return orderClient.getById(id); + } + + public void delete(Long id) { + orderClient.delete(id); + } +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java index 1a26dd1..add01a8 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java @@ -1,7 +1,10 @@ package dev.archie.rancherservice.rancher; +import dev.archie.rancherservice.landscape.dto.OrderDto; import dev.archie.rancherservice.rancher.dto.CreatingGardenerDto; import lombok.RequiredArgsConstructor; +import org.aspectj.weaver.ast.Or; +import org.hibernate.criterion.Order; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -54,4 +57,13 @@ public void delete(@PathVariable String id) { gardenerService.delete(id); } + @PostMapping("/notify/missingWorkers") + public void notifyAboutMissingWorkers(@RequestBody OrderDto orderDto) { + gardenerService.notifyAboutMissingWorkers(orderDto); + } + + @PostMapping("/notify/orderUpdate") + public void notifyAboutOrderUpdate(@RequestBody OrderDto orderDto) { + gardenerService.notifyAboutOrderUpdate(orderDto); + } } diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java index a78595b..25453c3 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java @@ -1,18 +1,31 @@ package dev.archie.rancherservice.rancher; import dev.archie.rancherservice.landscape.GardenerClient; +import dev.archie.rancherservice.landscape.dto.CreatingOrderDto; import dev.archie.rancherservice.landscape.dto.GardenerDto; +import dev.archie.rancherservice.landscape.dto.OrderDto; +import dev.archie.rancherservice.landscape.dto.SkillDto; +import dev.archie.rancherservice.landscape.dto.WorkStatus; +import dev.archie.rancherservice.landscape.dto.WorkType; +import dev.archie.rancherservice.order.OrderService; import dev.archie.rancherservice.rancher.dto.CreatingGardenerDto; import dev.archie.rancherservice.rancher.exception.NoSuchUserException; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CompletableFuture; + @Service @RequiredArgsConstructor +@Slf4j public class GardenerService { private final GardenerRepository gardenerRepository; private final GardenerClient gardenerClient; + private final OrderService orderService; /** * @param creatingGardenerDto rancher to create @@ -67,4 +80,36 @@ private static Gardener mapGardenerDtoToGardener(CreatingGardenerDto creatingGar .build(); } + public void notifyAboutMissingWorkers(OrderDto orderDto) { + log.info("По данному запросу копателей не нашлось. Измените объем работ."); + // по-хорошему тут нужно держать соединение с клиентом, но представим, что мы его уведомили + CreatingOrderDto updatingOrderDto = CreatingOrderDto.builder() + .fieldId(orderDto.getField().getId()) + .workType(WorkType.SHOVEL) + .skills(List.of("сажать")) + .build(); + orderService.update(updatingOrderDto, orderDto.getId()); + } + + public void notifyAboutOrderUpdate(OrderDto orderDto) { + log.info("Order updated: " + orderDto); + if (orderDto.getStatus().equals(WorkStatus.DONE)) { + CompletableFuture.runAsync(() -> evaluateTheOrder(orderDto)); + } + } + + public void evaluateTheOrder(OrderDto orderDto) { + log.info("По данному запросу копателей не нашлось. Измените объем работ."); + // по-хорошему тут нужно держать соединение с клиентом, но представим, что мы его уведомили + Random random = new Random(); + CreatingOrderDto updatingOrderDto = CreatingOrderDto.builder() + .status(orderDto.getStatus()) + .userId(orderDto.getUser().getId()) + .fieldId(orderDto.getField().getId()) + .skills(orderDto.getSkills().stream().map(SkillDto::getName).toList()) + .workType(orderDto.getWorkType()) + .grade(random.nextInt(10)) + .build(); + orderService.update(updatingOrderDto, orderDto.getId()); + } } From a11066e396ea096a2ad5e1fa81cae6b7c3b0a53d Mon Sep 17 00:00:00 2001 From: Dmitry Kutuzov Date: Mon, 26 Jun 2023 22:04:06 +0300 Subject: [PATCH 2/3] delete unused imports --- .../archie/handymanservice/handyman/HandymanRepository.java | 1 - .../dev/archie/handymanservice/handyman/HandymanService.java | 1 - .../dev/archie/handymanservice/landscape/OrderClient.java | 3 --- .../java/dev/archie/handymanservice/landscape/dto/Field.java | 5 ----- .../dev/archie/handymanservice/landscape/dto/FieldDto.java | 5 ----- .../dev/archie/landscapeservice/LandscapeApplication.java | 1 - .../dev/archie/landscapeservice/gardener/GardenerClient.java | 5 ----- .../archie/landscapeservice/handyman/HandymanRepository.java | 2 -- .../dev/archie/landscapeservice/order/OrderResolver.java | 3 --- .../java/dev/archie/landscapeservice/order/OrderService.java | 2 -- .../archie/rancherservice/rancher/GardenerController.java | 2 -- 11 files changed, 30 deletions(-) diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java index 99e5d07..9224951 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanRepository.java @@ -7,5 +7,4 @@ public interface HandymanRepository extends MongoRepository { boolean existsByInnerId(UUID innerId); - Optional findByInnerId(UUID innerId); } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java index 4ad1694..bf1a4b8 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java @@ -21,7 +21,6 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; @Service @RequiredArgsConstructor diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java index 75e7d7e..306ea48 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/OrderClient.java @@ -9,9 +9,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.UUID; @FeignClient(name = "order-client", path = "/orders", url = "${application.landscape.rest.url}") public interface OrderClient { diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java index a8b4107..c1bb7ac 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/Field.java @@ -1,11 +1,6 @@ package dev.archie.handymanservice.landscape.dto; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; -import org.locationtech.jts.geom.Geometry; -import org.n52.jackson.datatype.jts.GeometryDeserializer; -import org.n52.jackson.datatype.jts.GeometrySerializer; @Data public class Field { diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java index 48b4613..4684cf2 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/dto/FieldDto.java @@ -1,11 +1,6 @@ package dev.archie.handymanservice.landscape.dto; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; -import org.locationtech.jts.geom.Geometry; -import org.n52.jackson.datatype.jts.GeometryDeserializer; -import org.n52.jackson.datatype.jts.GeometrySerializer; @Data public class FieldDto { diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java index 3700847..237f3d5 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/LandscapeApplication.java @@ -3,7 +3,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.cloud.openfeign.FeignClient; @SpringBootApplication @EnableFeignClients diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java b/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java index 454ba65..6b09e9f 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/gardener/GardenerClient.java @@ -2,13 +2,8 @@ import dev.archie.landscapeservice.order.Order; import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "gardener-client", url = "${application.rancher.rest.url}", path = "/gardeners") public interface GardenerClient { diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java index 2e1772e..83caceb 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java @@ -1,7 +1,5 @@ package dev.archie.landscapeservice.handyman; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java index f2eaf79..c1559b2 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java @@ -8,8 +8,6 @@ import dev.archie.landscapeservice.handyman.HandymanRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,7 +22,6 @@ @Slf4j public class OrderResolver { - private static final int PAGE_SIZE = 10; private final OrderRepository orderRepository; private final HandymanRepository handymanRepository; private final HandymanClient handymanClient; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java index 7340cdb..9435e6e 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java @@ -17,8 +17,6 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java index add01a8..4763c03 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java @@ -3,8 +3,6 @@ import dev.archie.rancherservice.landscape.dto.OrderDto; import dev.archie.rancherservice.rancher.dto.CreatingGardenerDto; import lombok.RequiredArgsConstructor; -import org.aspectj.weaver.ast.Or; -import org.hibernate.criterion.Order; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; From 162a04e272efdeda95a3d6fcf5aba36abe68967f Mon Sep 17 00:00:00 2001 From: Dmitry Kutuzov Date: Mon, 26 Jun 2023 22:06:39 +0300 Subject: [PATCH 3/3] add hw log --- docs/homeworks-logs/hw12.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 docs/homeworks-logs/hw12.md diff --git a/docs/homeworks-logs/hw12.md b/docs/homeworks-logs/hw12.md new file mode 100644 index 0000000..72a886f --- /dev/null +++ b/docs/homeworks-logs/hw12.md @@ -0,0 +1,16 @@ + - [X] Сервис после получения запроса на создание работы, должен сохранить его в таблице. + - [X] Сервис должен найти копателей для всех заказов, которые имеют статус created. Копатели должны иметь подходящие навыки для выполнения заказа (навыки, указанные в запросе от копателей, должны совпадать с теми, что указал огородник). + - [X] Если копатели с похожими навыками найдены, то необходимо отсортировать самых ближайших к огороду и выделить первых трех копателей и создать запрос к системе HandymanService, указав необходимых копателей. + - [X] Иначе - уведомляем сервис RancherService: "По данному запросу копателей не нашлось. Измените объем работ". + - [X] Новый запрос на изменение объема работ должен обновить данные ранее созданого запроса + + - [X] В сервисе при получении запроса на работу, копатель может либо принять, либо отклонить заказ. (Для тестирования можете захардкодить ответ. Например, если приходит запрос с копанием огорода, ъ копатель отклоняет его, а если с поливанием - принимает) + - [X] Если заказ принят, в сервисе LandscapeService должны обновить статус заказа. + - [X] Если заказ отклонен - ничего не делаем. + - [X] После того, как копатель принял заказа, необходимо через рандомное время отправить запрос в LandscapeService о том, что работа проделана. Статус заказа должен измениться. + - [X] LandscapeService информирует RancherService об изменении статуса заказа. + - [X] Через рандомное время огородник отправляет запрос в LandscapeService о подтверждении заказа и выставляет оценку работы. + + - [ ] При отправке запроса из сервиса RancherService в LandscapeService возникнет ситуация, когда LandscapeService не обработал запрос. (сетевые проблемы, приложение упало и тд). Необходимо повторно выслать запроса из сервиса RancherService и записать данные в таблицу сервиса LandscapeService. + - [ ] Создав запрос из сервиса LandscapeService в HandymanService, у копателя может возникнуть проблема с соединением. Тогда попробовать заново отправить запрос, если запрос не был обработан то, следует создать новый запрос другому копателю. + - [ ] При отправке запроса из сервиса HandymanService в LandscapeService необходимо убедиться в том, что данные записались корретно. Если LandscapeService в момент получения запроса упадет, то необходимо инициировать новый запрос. \ No newline at end of file