esoe 1 week ago
parent
commit
b2d4b8debd
  1. 2
      main/api-swagger/paths/api.v1.organizations.yaml
  2. 21
      main/api-swagger/paths/api.v1.positions.yaml
  3. 2
      main/pom.xml
  4. 16
      main/src/main/java/gsp/technologies/main/api/organization/OrganizationApiController.java
  5. 3
      main/src/main/java/gsp/technologies/main/api/organization/OrganizationEntity.java
  6. 23
      main/src/main/java/gsp/technologies/main/api/organization/OrganizationFaceController.java
  7. 10
      main/src/main/java/gsp/technologies/main/api/organization/OrganizationService.java
  8. 51
      main/src/main/java/gsp/technologies/main/api/position/PositionController.java
  9. 3
      main/src/main/java/gsp/technologies/main/api/position/PositionEntity.java
  10. 4
      main/src/main/java/gsp/technologies/main/api/position/PositionRepository.java
  11. 14
      main/src/main/java/gsp/technologies/main/api/position/PositionService.java
  12. 3
      main/src/main/java/gsp/technologies/main/mainframe/MainframeController.java
  13. BIN
      main/src/main/resources/static/hello/pictures/usecase.png
  14. 19
      main/src/main/resources/templates/organizations/main.html
  15. BIN
      out/docs/usecase/usecase.png

2
main/api-swagger/paths/api.v1.organizations.yaml

@ -3,7 +3,7 @@ paths:
get: get:
responses: responses:
'200': '200':
description: OK description: Получение перечня организаций
content: content:
application/json: application/json:
schema: schema:

21
main/api-swagger/paths/api.v1.positions.yaml

@ -1,15 +1,32 @@
paths: paths:
api.v1.positions: api.v1.positions:
get: get:
summary: repo.find() Возвращает полный список должностей summary: |-
description: Для разных организаций должности могут повторяться. Предусмотреть пагинацию при получении должностей, список может быть огромным repo.findByOrganization()
description: |-
__Возвращает перечень должностей по организации__
- можно получить из объекта Page
Для разных организаций должности могут повторяться.
- Не отправляет параметры с запросом.
parameters:
- name: id
in: query
required: false
schema:
type: integer
format: int64
default: 154
responses: responses:
'200': '200':
description: Получение списка должностей description: Получение списка должностей
content: content:
application/json: application/json:
schema: schema:
type: array
$ref: "../components.yaml#/components/schemas/position" $ref: "../components.yaml#/components/schemas/position"
400:
description: не верные параметры запроса
post: post:
summary: repo.create() Создает в базе запись о новой должности summary: repo.create() Создает в базе запись о новой должности
description: Предварительно должна существовать организация. Должность привязываетс для каждой организации, для разных организаций должности могут повторяться. description: Предварительно должна существовать организация. Должность привязываетс для каждой организации, для разных организаций должности могут повторяться.

2
main/pom.xml

@ -62,7 +62,7 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

16
main/src/main/java/gsp/technologies/main/api/organization/OrganizationController.java → main/src/main/java/gsp/technologies/main/api/organization/OrganizationApiController.java

@ -13,21 +13,23 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import gsp.technologies.main.api.position.PositionEntity;
@RestController @RestController
@RequestMapping(path = "/api/v1/organizations") @RequestMapping(path = "/api/v1/organizations")
public class OrganizationController { public class OrganizationApiController {
private static final Logger log = LoggerFactory.getLogger(OrganizationController.class); private static final Logger log = LoggerFactory.getLogger(OrganizationApiController.class);
@Autowired @Autowired
private OrganizationRepository organizationRepo; private OrganizationService organizationService;
public OrganizationApiController(OrganizationService organizationService) {
this.organizationService = organizationService;
}
@CrossOrigin @CrossOrigin
@GetMapping("") @GetMapping("")
public ResponseEntity<?> getOrganizations() { public ResponseEntity<?> getOrganizations() {
log.info("GET /organizations"); log.info("GET /organizations");
return new ResponseEntity<>(organizationRepo.findAll(), HttpStatus.OK); return new ResponseEntity<>(organizationService.findAll(), HttpStatus.OK);
} }
@CrossOrigin @CrossOrigin
@ -36,7 +38,7 @@ public class OrganizationController {
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveOrganization(@RequestBody OrganizationEntity organization) { public ResponseEntity<?> saveOrganization(@RequestBody OrganizationEntity organization) {
log.info("POST /organization, organization: {}", organization); log.info("POST /organization, organization: {}", organization);
organizationRepo.save(organization); organizationService.save(organization);
return new ResponseEntity<>(organization, HttpStatus.CREATED); return new ResponseEntity<>(organization, HttpStatus.CREATED);
} }

3
main/src/main/java/gsp/technologies/main/api/organization/OrganizationEntity.java

@ -1,5 +1,6 @@
package gsp.technologies.main.api.organization; package gsp.technologies.main.api.organization;
import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
@ -18,5 +19,7 @@ public class OrganizationEntity {
@Id @Id
@GeneratedValue(strategy=GenerationType.AUTO) @GeneratedValue(strategy=GenerationType.AUTO)
private Long id; private Long id;
@Column(unique = true)
private String name; //наименование организации private String name; //наименование организации
} }

23
main/src/main/java/gsp/technologies/main/api/organization/OrganizationFaceController.java

@ -0,0 +1,23 @@
package gsp.technologies.main.api.organization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(path = "/organizations")
public class OrganizationFaceController {
private static final Logger log = LoggerFactory.getLogger(OrganizationFaceController.class);
/**
* Главная страница для работы с перечнем организаций
* @return
*/
@GetMapping("")
public String organizations() {
log.info("GET /organizations");
return "organizations/main";
}
}

10
main/src/main/java/gsp/technologies/main/api/organization/OrganizationService.java

@ -1,5 +1,7 @@
package gsp.technologies.main.api.organization; package gsp.technologies.main.api.organization;
import java.util.Collection;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@ -9,4 +11,12 @@ public class OrganizationService {
public OrganizationService(OrganizationRepository repo) { public OrganizationService(OrganizationRepository repo) {
this.repo = repo; this.repo = repo;
} }
public Collection<OrganizationEntity> findAll() {
return repo.findAll();
}
public OrganizationEntity save(OrganizationEntity organization) {
return repo.save(organization);
}
} }

51
main/src/main/java/gsp/technologies/main/api/position/PositionController.java

@ -3,6 +3,10 @@ package gsp.technologies.main.api.position;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -11,6 +15,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@ -18,22 +23,58 @@ import org.springframework.web.bind.annotation.RestController;
public class PositionController { public class PositionController {
private static final Logger log = LoggerFactory.getLogger(PositionController.class); private static final Logger log = LoggerFactory.getLogger(PositionController.class);
@Autowired @Autowired
private PositionRepository positionRepo; private PositionService positionService;
public PositionController(PositionService positionService) {
this.positionService = positionService;
}
/**
* Получение перечня должностей
* @param number
* @param size
* @param sortBy
* @return
*/
@CrossOrigin @CrossOrigin
@GetMapping("") @GetMapping("")
public ResponseEntity<?> getPositions() { public ResponseEntity<?> getPositions(
@RequestParam(name = "id", required = false, defaultValue = "0") Long id,
@RequestParam(name = "number", required = false, defaultValue = "0") int number,
@RequestParam(name = "size", required = false, defaultValue = "10") int size,
@RequestParam(name = "sortBy", required = false, defaultValue = "name") String sortBy) {
log.info("GET /positions"); log.info("GET /positions");
return new ResponseEntity<>(positionRepo.findAll(), HttpStatus.OK);
Sort sort = Sort.by(sortBy);
Pageable of = PageRequest.of(number, size, sort);
if (id != 0) {
log.info("GET /positions, organizationId: {}", id);
Page<PositionEntity> page = positionService.findByOrganizationId(of, id);
return new ResponseEntity<>(page, HttpStatus.OK);
// return new ResponseEntity<PagedModel<EntityModel<PositionEntity>>>(assembler.toModel(page), HttpStatus.OK);
}
Page<PositionEntity> page = positionService.findAll(of);
return new ResponseEntity<>(page, HttpStatus.OK);
} }
/**
* Добавление новой должности
* @param position
* @return
*/
@CrossOrigin @CrossOrigin
@PostMapping(path = "", @PostMapping(path = "",
consumes = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> savePosition(@RequestBody PositionEntity position) { public ResponseEntity<?> savePosition(@RequestBody PositionEntity position) {
log.info("POST /position, position: {}", position); log.info("POST /positions, position: {}", position);
positionRepo.save(position); try {
positionService.save(position);
} catch (Exception e) {
log.error("POST /positions", e.getMessage());
return new ResponseEntity<>(e.getMessage(), HttpStatus.OK);
}
return new ResponseEntity<>(position, HttpStatus.CREATED); return new ResponseEntity<>(position, HttpStatus.CREATED);
} }
} }

3
main/src/main/java/gsp/technologies/main/api/position/PositionEntity.java

@ -6,6 +6,7 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne; import jakarta.persistence.OneToOne;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@ -29,7 +30,7 @@ public class PositionEntity {
private Long id; private Long id;
private String name; //наименование должности работника private String name; //наименование должности работника
@OneToOne(fetch = FetchType.EAGER, optional = false) @ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "organization", referencedColumnName = "id") @JoinColumn(name = "organization", referencedColumnName = "id")
@OnDelete(action = OnDeleteAction.CASCADE) @OnDelete(action = OnDeleteAction.CASCADE)
private OrganizationEntity organization; private OrganizationEntity organization;

4
main/src/main/java/gsp/technologies/main/api/position/PositionRepository.java

@ -1,9 +1,13 @@
package gsp.technologies.main.api.position; package gsp.technologies.main.api.position;
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.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
public interface PositionRepository extends JpaRepository<PositionEntity, Long> { public interface PositionRepository extends JpaRepository<PositionEntity, Long> {
Page<PositionEntity> findByOrganizationId(Pageable of, long organizationId);
} }

14
main/src/main/java/gsp/technologies/main/api/position/PositionService.java

@ -1,5 +1,7 @@
package gsp.technologies.main.api.position; package gsp.technologies.main.api.position;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@ -9,4 +11,16 @@ public class PositionService {
public PositionService(PositionRepository repo) { public PositionService(PositionRepository repo) {
this.repo = repo; this.repo = repo;
} }
public Page<PositionEntity> findByOrganizationId(Pageable of, Long id) {
return repo.findByOrganizationId(of, id);
}
public Page<PositionEntity> findAll(Pageable of) {
return repo.findAll(of);
}
public void save(PositionEntity position) {
repo.save(position);
}
} }

3
main/src/main/java/gsp/technologies/main/mainframe/MainframeController.java

@ -5,9 +5,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.ServletException;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

BIN
main/src/main/resources/static/hello/pictures/usecase.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 215 KiB

19
main/src/main/resources/templates/organizations/main.html

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>exam-main-hello</title>
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2/webcomponents-loader.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@1/src/zero-md.min.js"></script>
</head>
<header>
</header>
<body>
<h1>organizations</h1>
</body>
<footer>
<div th:insert="~{fragments/common/footer :: copy}"></div>
</footer>
</html>

BIN
out/docs/usecase/usecase.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 215 KiB

Loading…
Cancel
Save