This commit is contained in:
AnnZhimol 2023-04-16 01:33:20 +04:00
parent eb03fcc404
commit 9730c77ed5
38 changed files with 32357 additions and 168 deletions

View File

@ -1,10 +1,10 @@
plugins { plugins {
id 'java' id 'java'
id 'org.springframework.boot' version '2.7.8' id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.0.15.RELEASE' id 'io.spring.dependency-management' version '1.1.0'
} }
group = 'ru.ulstu.is' group = 'com.example'
version = '0.0.1-SNAPSHOT' version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17' sourceCompatibility = '17'
@ -12,20 +12,12 @@ repositories {
mavenCentral() mavenCentral()
} }
jar {
enabled = false
}
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.1.210' implementation 'com.h2database:h2:2.1.210'
implementation 'org.hibernate.validator:hibernate-validator'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-starter-test'
} }

31166
front/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

48
front/package.json Normal file
View File

@ -0,0 +1,48 @@
{
"name": "pages_react",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^6.2.1",
"axios": "^1.1.3",
"bootstrap": "^5.2.3",
"react": "^18.2.0",
"react-bootstrap": "^2.7.2",
"react-dom": "^18.2.0",
"react-router-dom": "^6.6.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"@types/react": "^18.0.24",
"@types/react-dom": "^18.0.8",
"@vitejs/plugin-react": "^2.2.0",
"json-server": "^0.17.1",
"npm-run-all": "^4.1.5",
"vite": "^3.2.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

14
front/public/index.html Normal file
View File

@ -0,0 +1,14 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/node_modules/@fortawesome/fontawesome-free/css/all.min.css">
<title>Сеть автошкол</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

44
front/src/App.js Normal file
View File

@ -0,0 +1,44 @@
import React from "react";
import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom';
import Students from './components/Students.jsx';
import Header from "./components/commons/Header.jsx"
import 'bootstrap/dist/css/bootstrap.min.css';
import DrivingSchools from './components/DrivingSchools.jsx';
import Categories from './components/Categories.jsx';
import OneDrivingSchool from './components/OneDrivingSchool.jsx';
function Router(props) {
return useRoutes(props.rootRoute);
}
function App() {
const routes = [
{ index: true, element: <DrivingSchools /> },
{ path: '/', element: <DrivingSchools />, label: 'Сеть Автошкол' },
{ path: '/students', element: <Students />, label: 'Студенты' },
{ path: '/drivingSchools', element: <DrivingSchools />, label: 'Автошколы' },
{ path: '/categories', element: <Categories />, label: 'Категории' },
{ path: '/drivingSchool/:id', element: <OneDrivingSchool />},
];
const links = routes.filter(route => route.hasOwnProperty('label'));
const rootRoute = [
{ path: '/', element: render(links), children: routes }
];
function render(links) {
return (
<div className="App">
<Header links={links} />
<div className="w-100">
<Outlet />
</div>
</div>
);
}
return (
<BrowserRouter>
<Router rootRoute={ rootRoute } />
</BrowserRouter>
);
}
export default App;

View File

@ -0,0 +1,50 @@
import Button from 'react-bootstrap/Button';
import Table from "./commons/Table.jsx";
import { useState} from 'react';
import ModalForm from './commons/ModalForm.jsx';
// это абстрактный компонент для всех справочников
export default function Catalog(props) {
const [show, setShow] = useState(false);
const [modalTitle, setModalTitle] = useState("");
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
function handleAdd() {
setModalTitle("Добавление");
props.onBtnAdd();
handleShow();
}
function handleEdit(itemId) {
setModalTitle("Редактирование");
props.onEdit(itemId);
handleShow();
}
function handleRemove(item) {
props.onDelete(item);
}
function changeData(event) {
props.onFormChanged(event);
}
return <>
<div>{props.name}</div>
<Button variant="success" onClick={handleAdd}>Добавить</Button>
<Table
headers={props.headers}
items={props.items}
onEdit={handleEdit}
onDelete={handleRemove}
/>
<ModalForm
show={show}
onClose={handleClose}
modalTitle={modalTitle}
// onSubmit={submitForm}
onChange={changeData}
form={props.form}
/></>
}

View File

@ -0,0 +1,108 @@
import Category from "../models/Category";
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import { useState, useEffect } from 'react';
import DataService from '../services/DataService';
import Catalog from "./Catalog.jsx";
export default function Categories(props) {
const headers = [
{name: 'name', label: "Название"},
];
const nameCatalog = "Категории";
const url = '/category';
const requestParams = '?name=nameData';
const [items, setItems] = useState([]);
const [data, setData] = useState(new Category());
const [isEditing, setEditing] = useState(false);
useEffect(() => {
loadItems();
}, []);
function loadItems() {
DataService.readAll(url, (data) => new Category(data))
.then(data => setItems(data));
}
function handleAdd() {
DataService.create(url +requestParams
.replace("nameData", data.name))
.then(() => loadItems());
}
function handleEdit(editedId) {
DataService.read(url + "/" + editedId, (e) => new Category(e))
.then(data => {
setData(new Category(data));
});
setEditing(true);
}
function handleEditIsDone() {
DataService.update(url + "/" + data.id + requestParams
.replace("nameData", data.name)).then(() => loadItems());
}
function handleDelete(item) {
if (window.confirm('Удалить выбранный элемент?')) {
const promises = [];
promises.push(DataService.delete(url + "/" + item));
Promise.all(promises).then(() => {
loadItems();
});
}
}
// при каждом изменении поля формы происходит вызов этого метода, обновляя данные объекта
function handleFormChange(event) {
setData({ ...data, [event.target.name]: event.target.value });
}
// определяет действия формы по нажатию Отправить
function submitForm() {
if (!isEditing) {
// если добавление элемента
handleAdd();
} else {
// если редактирование элемента;
handleEditIsDone();
setEditing(false);
}
}
// вызывается при закрытии модального окна или по нажатию кнопки Добавить и очищает данные объекта
function reset() {
setData(new Category());
setEditing(false);
}
// для каждого типа сущности своя форма,
// которая передается дальше в абстрактный компонент Catalog в качестве props.form
const form = <Form onSubmit={submitForm}>
<Form.Group className="mb-3" controlId="name">
<Form.Label>Название</Form.Label>
<Form.Control name="name" value={data.name} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>
return <div className="container-lg pt-5 min-vh-100">
<Catalog name={nameCatalog}
headers={headers}
items={items}
onAdd={handleAdd}
onEdit={handleEdit}
onDelete={handleDelete}
onClose={reset}
onBtnAdd={reset}
form={form}>
</Catalog>
</div>
}

View File

@ -0,0 +1,153 @@
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import { useState, useEffect } from 'react';
import DataService from '../services/DataService';
import Catalog from "./Catalog.jsx";
import DrivingSchool from "../models/DrivingSchool";
import ModalForm from './commons/ModalForm';
import { useNavigate } from "react-router-dom";
export default function DrivingSchools(props) {
const headers = [
{name: 'name', label: "Название"},
{name: 'countStudents', label: "Студенты"},
];
const nameCatalog = "Автошколы";
const url = '/drivingSchool';
const requestParams = '?name=nameData';
const [items, setItems] = useState([]);
const [data, setData] = useState(new DrivingSchool());
const [isEditing, setEditing] = useState(false);
useEffect(() => {
loadItems();
}, []);
function loadItems() {
DataService.readAll(url, (data) => new DrivingSchool(data))
.then(data => setItems(data));
}
function handleAdd() {
DataService.create(url +requestParams
.replace("nameData", data.name))
.then(() => loadItems());
}
function handleEdit(editedId) {
DataService.read(url + "/" + editedId, (e) => new DrivingSchool(e))
.then(data => {
setData(new DrivingSchool(data));
});
setEditing(true);
}
function handleEditIsDone() {
DataService.update(url + "/" + data.id + requestParams
.replace("nameData", data.name))
.then(() => loadItems());
}
function handleDelete(item) {
if (window.confirm('Удалить выбранный элемент?')) {
const promises = [];
promises.push(DataService.delete(url + "/" + item));
Promise.all(promises).then(() => {
loadItems();
});
}
}
// при каждом изменении поля формы происходит вызов этого метода, обновляя данные объекта
function handleFormChange(event) {
setData({ ...data, [event.target.name]: event.target.value });
}
// определяет действия формы по нажатию Отправить
function submitForm() {
if (!isEditing) {
// если добавление элемента
handleAdd();
} else {
// если редактирование элемента;
handleEditIsDone();
setEditing(false);
}
}
// вызывается при закрытии модального окна или по нажатию кнопки Добавить и очищает данные объекта
function reset() {
setData(new DrivingSchool());
setEditing(false);
}
// для каждого типа сущности своя форма,
// которая передается дальше в абстрактный компонент Catalog в качестве props.form
const form = <Form onSubmit={submitForm}>
<Form.Group className="mb-3" controlId="name">
<Form.Label>Название</Form.Label>
<Form.Control name="name" value={data.name} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>;
const [showModalForm, setShowChoosing] = useState(false);
const formChooseDrivingSchool = <Form onSubmit={redirectToDrivingSchool}>
<Form.Group className="mb-3" controlId="name">
<Form.Label>Автошкола</Form.Label>
<Form.Select name="name_select" type="input" onChange={(e) => {setChosenDrivingSchool(e.target.value)}} required>
<option selected disabled>Выберите автошколу</option>
{
items.map((drivingSchool) => <option key={`drivingSchool_${drivingSchool.id}`} value={`${drivingSchool.id}`}>{`${drivingSchool.name}`}</option>)
}
</Form.Select>
</Form.Group>
<Button variant="primary" type="submit">
Перейти
</Button>
</Form>;
function showModalFormChoosing() {
setShowChoosing(true);
}
function unshowModalFormChoosing() {
setShowChoosing(false);
}
const [chosenDrivingSchool, setChosenDrivingSchool] = useState(0);
const navigate = useNavigate();
function redirectToDrivingSchool() {
if (chosenDrivingSchool !== 0) {
navigate(`/drivingSchool/${chosenDrivingSchool}`);
}
}
return <div className="container-lg pt-5 min-vh-100">
<Button onClick={showModalFormChoosing} variant="info">Перейти к автошколе</Button>
<ModalForm show={showModalForm} onClose={unshowModalFormChoosing} modalTitle={"Выбор автошколы"} form={formChooseDrivingSchool}></ModalForm>
<Catalog name={nameCatalog}
headers={headers}
items={items}
onAdd={handleAdd}
onEdit={handleEdit}
onDelete={handleDelete}
onClose={reset}
onBtnAdd={reset}
form={form}>
</Catalog>
</div>
}

View File

@ -0,0 +1,256 @@
import DrivingSchool from "../models/DrivingSchool";
import { useState, useEffect } from 'react';
import { Link, useParams } from "react-router-dom";
import DataService from '../services/DataService';
import Student from '../models/Student';
import Category from '../models/Category';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import ModalForm from './commons/ModalForm';
import styles from "./OneDrivingSchool.module.css";
export default function OneDrivingSchool(props) {
const { id } = useParams();
const url = '/drivingSchool/id';
const urlDrivingSchoolStud = '/drivingSchool/id/students';
const urlStud = '/student/free';
const urlCat = '/category';
const urlHire = '/drivingSchool/id/hire';
const urlDismiss = '/drivingSchool/id/dismiss';
const urlAddCat = '/student/id/addCat';
const urlDelCat = '/student/id/delCat';
const requestParamsCategory = '?category=catId';
const requestParamsHire = '?studentId=studId';
const [drivingSchool, setDrivingSchool] = useState(new DrivingSchool());
const [itemsStudFree, setItemsStudFree] = useState([]);
const [itemsStudDrivingSchool, setItemsStudDrivingSchool] = useState([]);
const [itemsCat, setItemsCat] = useState([]);
const headersStud = [
{name: 'surname', label: "Фамилия"},
{name: 'name', label: "Имя"},
{name: 'categoriesString', label: 'Категории'},
{name: 'phoneNumber', label: "Номер телефона"}
];
useEffect(() => {
loadDrivingSchool();
}, []);
function loadDrivingSchool() {
DataService.read(url.replace("id", id), (data) => new DrivingSchool(data)).then((data) => setDrivingSchool(new DrivingSchool(data)));
}
function loadItemsStudents() {
DataService.readAll(urlStud, (data) => new Student(data))
.then(data => setItemsStudFree(data));
}
function loadItemsCategories() {
DataService.readAll(urlCat, (data) => new Category(data))
.then(data => setItemsCat(data));
}
function loadItemsStudentsDrivingSchool() {
DataService.readAll(urlDrivingSchoolStud.replace("id", drivingSchool.id), (data) => new Student(data))
.then(data => setItemsStudDrivingSchool(data));
}
// логика для найма или увольнения
const [isShowHire, setShowHire] = useState(false);
function showModalFormHire() {
loadItemsStudents();
setShowHire(true);
}
function unshowModalFormHire() {
setShowHire(false);
}
const [isShowDismiss, setShowDismiss] = useState(false);
function showModalFormDismiss(e) {
loadItemsStudentsDrivingSchool();
setShowDismiss(true);
}
function unshowModalFormDismiss() {
setShowDismiss(false);
}
const [student, setStudent] = useState(new Student());
function studentChosenFree(e) {
setStudent(itemsStudFree.filter((stud) => stud.id == e.target.value)[0]);
}
function studentChosenBusy(e) {
setStudent(Array.from(drivingSchool.students).filter((stud) => stud.id == e.target.value)[0]);
}
function formHireSubmit() {
DataService.update(urlHire.replace("id",drivingSchool.id) + requestParamsHire
.replace("studId", student.id))
.then(() => loadDrivingSchool());
setStudent(new Student());
}
function formDismissSubmit() {
DataService.update(urlDismiss.replace("id",drivingSchool.id) + requestParamsHire
.replace("studId", student.id))
.then(() => loadDrivingSchool());
setStudent(new Student());
}
const [isShowChooseCategory, setShowChooseCategory] = useState(false);
function showModalFormChooseCategory() {
loadItemsCategories();
loadItemsStudentsDrivingSchool();
setShowChooseCategory(true);
}
function unshowModalFormChooseCategory() {
setShowChooseCategory(false);
setCategoryStud([]);
}
const [categoriesChosen, setCategoryStud] = useState([]);
function checkBoxChanged(e) {
// если чекбокс был выбран, то добавляем в массив категорию
if (e.target.checked)
{
categoriesChosen.push(e.target.value);
} // если чекбокс был убран, то исключаем его значение из массива
else
{
let i = categoriesChosen.indexOf(e.target.value);
if(i >= 0) {
categoriesChosen.splice(i,1);
}
}
}
function formChooseCategoriesSubmit() {
for (let i = 0; i < categoriesChosen.length; i++) {
DataService.update(urlAddCat.replace("id",student.id) + requestParamsCategory
.replace("catId", categoriesChosen[i]))
.then(() => loadDrivingSchool());
}
let categoriesStud = student.categories;
for (let i = 0; i < categoriesStud.length; i++) {
if (categoriesChosen.indexOf(''+categoriesStud[i].id) == -1) {
// удаление категории
DataService.update(urlDelCat.replace("id",student.id) + requestParamsCategory
.replace("catId", categoriesStud[i].id))
.then(() => loadDrivingSchool());
}
}
}
const formHire = <Form onSubmit={formHireSubmit}>
<Form.Group className="mb-3" controlId="student">
<Form.Label>Студент</Form.Label>
<Form.Select name="student_select" type="input" onChange={studentChosenFree} required>
<option selected disabled>Выберите студента</option>
{
itemsStudFree.map((e) => <option key={`stud_${e.id}`} value={`${e.id}`}>{`${e.surname} ${e.name}`}</option>)
}
</Form.Select>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>;
const formDismiss = <Form onSubmit={formDismissSubmit}>
<Form.Group className="mb-3" controlId="student">
<Form.Label>Студент</Form.Label>
<Form.Select name="student_select" type="input" onChange={studentChosenBusy} required>
<option selected disabled>Выберите студента</option>
{
itemsStudDrivingSchool.map((e) => <option key={`stud_${e.id}`} value={`${e.id}`}>{`${e.surname} ${e.name}`}</option>)
}
</Form.Select>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>;
const formCheckBoxesCategory = <Form onSubmit={formChooseCategoriesSubmit}>
<Form.Group className="mb-3" controlId="student">
<Form.Label>Студент</Form.Label>
<Form.Select name="student_select" type="input" onChange={studentChosenBusy} required>
<option selected disabled>Выберите студента</option>
{
itemsStudDrivingSchool.map((e) => <option key={`stud_${e.id}`} value={`${e.id}`}>{`${e.surname} ${e.name}`}</option>)
}
</Form.Select>
</Form.Group>
<Form.Group className="mb-3" controlId="category">
<Form.Label>Категории</Form.Label>
<div className={`${styles.prokrutka}`}>
{
itemsCat.map((p) => <div style={{width: `150 px`}}>
<input type="checkbox" key={`${p.id}`} value={`${p.id}`} onChange={checkBoxChanged}/>
{/* {!studentHasCategory(p) && <input type="checkbox" key={`${p.id}`} value={`${p.id}`} onChange={checkBoxChanged}/>}
{studentHasCategory(p) && <input type="checkbox" key={`${p.id}`} value={`${p.id}`} checked onChange={checkBoxChanged}/>} */}
{`${p.name}`}
</div>)
}
</div>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>
if (!drivingSchool) {
return <div><h1>Автошкола не найдена</h1>
<Link to='/drivingSchools'>
<Button variant="info">Назад</Button>
</Link>
</div>
}
return <div className="container-lg pt-5 min-vh-100">
<Link to='/drivingSchools'>
<Button variant="info">Назад</Button>
</Link>
<h1>Название: {drivingSchool.name}</h1>
<h2>Количество студентов: {drivingSchool.countStudents}</h2>
<Button name="Зачисление" onClick={showModalFormHire} variant="success">Зачислить студента</Button>
<Button name='Отчисление' onClick={showModalFormDismiss} variant="danger">Отчислить студента</Button>
<Button name='Выбор категории' onClick={showModalFormChooseCategory} variant="info">Выбор категории</Button>
<div >
<table className={`table table-hover`}>
<thead>
<tr>
{
headersStud.map((header) => <th key={header.name}>{header.label}</th>)
}
</tr>
</thead>
<tbody>
{
Array.from(drivingSchool.students).map((item, index) => <tr key={item.id}>
{
headersStud.map((header) => <td key={`${header.name}_${item.id}`}>{item[header.name]}</td>)
}
</tr>)
}
</tbody>
</table>
</div>
<ModalForm show={isShowHire} onClose={unshowModalFormHire} modalTitle={"Зачисление"} form={formHire}></ModalForm>
<ModalForm show={isShowDismiss} onClose={unshowModalFormDismiss} modalTitle={"Отчисление"} form={formDismiss}></ModalForm>
<ModalForm show={isShowChooseCategory} onClose={unshowModalFormChooseCategory} modalTitle={"Управление категориями"} form={formCheckBoxesCategory}></ModalForm>
</div>
}

View File

@ -0,0 +1,7 @@
.prokrutka {
background: #fff; /* цвет фона, белый */
border: 1px solid #C1C1C1; /* размер и цвет границы блока */
overflow: auto;
width:200px;
height:100px;
}

View File

@ -0,0 +1,115 @@
import Student from "../models/Student";
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import { useState, useEffect } from 'react';
import DataService from '../services/DataService';
import Catalog from "./Catalog.jsx";
export default function Students(props) {
const headers = [
{name: 'surname', label: "Фамилия"},
{name: 'name', label: "Имя"},
{name: 'phoneNumber', label: "Номер телефона"},
{name: 'categoriesString', label: 'Категории'}
];
const nameCatalog = "Студенты";
const [items, setItems] = useState([]);
const url = '/student';
const requestParams = '?name=nameData&surname=surnameData&phoneNumber=phoneNameData';
const [data, setData] = useState(new Student());
const [isEditing, setEditing] = useState(false);
useEffect(() => {
loadItems();
}, []);
function loadItems() {
DataService.readAll(url, (data) => new Student(data))
.then(data => setItems(data));
}
function handleAdd() {
DataService.create(url +requestParams
.replace("nameData", data.name)
.replace("surnameData", data.surname)
.replace("phoneNameData", data.phoneNumber))
.then(() => loadItems());
}
function handleEdit(editedId) {
DataService.read(url + "/" + editedId, (e) => new Student(e))
.then(data => {
setData(new Student(data));
});
setEditing(true);
}
function handleEditIsDone() {
DataService.update(url + "/" + data.id + requestParams
.replace("nameData", data.name)
.replace("surnameData", data.surname)
.replace("phoneNameData", data.phoneNumber)).then(() => loadItems());
}
function handleDelete(item) {
if (window.confirm('Удалить выбранный элемент?')) {
const promises = [];
promises.push(DataService.delete(url + "/" + item));
Promise.all(promises).then(() => {
loadItems();
});
}
}
// при каждом изменении поля формы происходит вызов этого метода, обновляя данные объекта
function handleFormChange(event) {
setData({ ...data, [event.target.name]: event.target.value });
}
// определяет действия формы по нажатию Отправить
function submitForm() {
if (!isEditing) {
// если добавление элемента
handleAdd();
} else {
// если редактирование элемента;
handleEditIsDone();
setEditing(false);
}
}
// вызывается при закрытии модального окна или по нажатию кнопки Добавить и очищает данные объекта
function reset() {
setData(new Student());
setEditing(false);
}
// для каждого типа сущности своя форма,
// которая передается дальше в абстрактный компонент Catalog в качестве props.form
const form = <Form onSubmit={submitForm}>
<Form.Group className="mb-3" controlId="name">
<Form.Label>Фамилия</Form.Label>
<Form.Control name="surname" value={data.surname} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
<Form.Label>Имя</Form.Label>
<Form.Control name="name" value={data.name} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
<Form.Label>Номер телефона</Form.Label>
<Form.Control name="phoneNumber" value={data.phoneNumber} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
</Form.Group>
<Button variant="primary" type="submit">
Отправить
</Button>
</Form>
return <div className="container-lg pt-5 min-vh-100">
<Catalog name={nameCatalog}
headers={headers}
items={items}
onAdd={handleAdd}
onEdit={handleEdit}
onDelete={handleDelete}
onClose={reset}
onBtnAdd={reset}
form={form}>
</Catalog>
</div>
}

View File

@ -0,0 +1,25 @@
import { NavLink } from 'react-router-dom';
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
export default function Header(props) {
return (
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
<Container className='lg justify-content-center'>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
{
props.links.map(route =>
<NavLink key={route.path} className="nav-link" to={route.path}>
<div>{route.label}</div>
</NavLink>
)
}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}

View File

@ -0,0 +1,18 @@
import Button from 'react-bootstrap/Button';
export default function ItemTable(props) {
function edit() {
props.onEdit(props.item.id);
}
function remove() {
props.onDelete(props.item.id);
}
return <tr key={props.item.id}>
{
props.headers.map((header) => <td key={`${header.name}_${props.item.id}`}>{props.item[header.name]}</td>)
}
{props.isOnlyView || <td key={`controls_${props.item.id}`}>
<Button variant="info" onClick={edit}>Редактировать</Button>
<Button variant="danger" onClick={remove}>Удалить</Button></td>}
</tr>
}

View File

@ -0,0 +1,14 @@
import Form from 'react-bootstrap/Form';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
import { React} from 'react';
export default function ModalForm(props) {
return <Modal show={props.show} onHide={props.onClose}>
<Modal.Header closeButton>
<Modal.Title>{props.modalTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
{props.form}
</Modal.Body>
</Modal>
}

View File

@ -0,0 +1,34 @@
import ItemTable from './ItemTable';
export default function Table(props) {
function edit(itemId) {
props.onEdit(itemId)
}
function remove(itemId) {
props.onDelete(itemId);
}
return <div >
<table className={`table table-hover`}>
<thead>
<tr>
{
props.headers.map((header) => <th key={header.name}>{header.label}</th>)
}
{props.isOnlyView || <th key='controls'>Элементы управления</th>}
</tr>
</thead>
<tbody>
{
props.items.map((item, index) =>
<ItemTable
key={index}
headers={props.headers}
item={item}
onDelete={remove}
onEdit={edit}
isOnlyView={props.isOnlyView}/>)
}
</tbody>
</table>
</div>
}

8
front/src/index.js Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);

View File

@ -0,0 +1,6 @@
export default class Category {
constructor(data) {
this.id = data?.id;
this.name = data?.name || '';
}
}

View File

@ -0,0 +1,13 @@
import Student from "./Student";
export default class DrivingSchool {
constructor(data) {
this.id = data?.id;
this.name = data?.name || '';
this.students = data?.students.map((e) => new Student(e)) || '';
this.countStudents = '';
if (this.students !== '') {
this.countStudents = this.students.length;
}
}
}

View File

@ -0,0 +1,25 @@
import Category from "./Category";
export default class Student {
constructor(data) {
this.id = data?.id;
this.surname = data?.surname || '';
this.name = data?.name || '';
this.phoneNumber = data?.phoneNumber || '';
this.categories = data?.categories.map((p) => new Category(p)) || '';
this.categoriesString = '';
if (this.categories !== '') {
this.categories.forEach((p) => {this.categoriesString += p.name + " "});
}
this.drivingSchool = data?.drivingSchool || '';
}
}
Student.prototype.equals = function (obj){
if(typeof obj != typeof this)
return false;
if (this.id === obj.id) {
return true;
}
return false;
}

View File

@ -0,0 +1,42 @@
import axios from 'axios';
function toJSON(data) {
const jsonObj = {};
const fields = Object.getOwnPropertyNames(data);
for (const field of fields) {
if (data[field] === undefined) {
continue;
}
jsonObj[field] = data[field];
}
return jsonObj;
}
export default class DataService {
static dataUrlPrefix = 'http://localhost:8080';
static async readAll(url, transformer) {
const response = await axios.get(this.dataUrlPrefix + url);
return response.data.map(item => transformer(item));
}
static async read(url, transformer) {
const response = await axios.get(this.dataUrlPrefix + url);
return transformer(response.data);
}
static async create(url, data) {
const response = await axios.post(this.dataUrlPrefix + url);
return true;
}
static async update(url, data) {
const response = await axios.put(this.dataUrlPrefix + url);
return true;
}
static async delete(url) {
const response = await axios.delete(this.dataUrlPrefix + url);
return response.data.id;
}
}

View File

@ -0,0 +1,12 @@
package ru.ulstu.is.cbapp;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}

View File

@ -1,8 +1,8 @@
package ru.ulstu.is.cbapp.controller; package ru.ulstu.is.cbapp.controller;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.cbapp.dto.CategoryDto; import ru.ulstu.is.cbapp.dto.CategoryDto;
import ru.ulstu.is.cbapp.service.CategoryService; import ru.ulstu.is.cbapp.service.CategoryService;
import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -16,12 +16,12 @@ public class CategoryController {
} }
@GetMapping("/{id}") @GetMapping("/{id}")
public CategoryDto getCategory(@PathVariable long id) { public CategoryDto getDrivingSchool(@PathVariable long id) {
return new CategoryDto(categoryService.findCategory(id)); return new CategoryDto(categoryService.findCategory(id));
} }
@GetMapping @GetMapping
public List<CategoryDto> getAllCategories() { public List<CategoryDto> getAllDrivingSchools() {
return categoryService.findAllCategories().stream() return categoryService.findAllCategories().stream()
.map(CategoryDto::new) .map(CategoryDto::new)
.toList(); .toList();

View File

@ -1,18 +1,17 @@
package ru.ulstu.is.cbapp.controller; package ru.ulstu.is.cbapp.controller;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.cbapp.dto.DrivingSchoolDto; import ru.ulstu.is.cbapp.dto.DrivingSchoolDto;
import ru.ulstu.is.cbapp.dto.StudentDto; import ru.ulstu.is.cbapp.dto.StudentDto;
import ru.ulstu.is.cbapp.models.Student; import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.service.DrivingSchoolService; import ru.ulstu.is.cbapp.service.DrivingSchoolService;
import ru.ulstu.is.cbapp.service.StudentService; import ru.ulstu.is.cbapp.service.StudentService;
import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/drivingSchool") @RequestMapping("/drivingSchool")
public class DrivingSchoolController { public class DrivingSchoolController {
private final DrivingSchoolService drivingSchoolService; private final DrivingSchoolService drivingSchoolService;
private final StudentService studentService; private final StudentService studentService;
@ -26,6 +25,11 @@ public class DrivingSchoolController {
return new DrivingSchoolDto(drivingSchoolService.findDrivingSchool(id)); return new DrivingSchoolDto(drivingSchoolService.findDrivingSchool(id));
} }
@GetMapping("/{id}/students")
public List<StudentDto> getDrivingSchoolStudents(@PathVariable long id) {
return drivingSchoolService.findDrivingSchool(id).getStudents().stream().map(StudentDto::new).toList();
}
@GetMapping @GetMapping
public List<DrivingSchoolDto> getAllDrivingSchools() { public List<DrivingSchoolDto> getAllDrivingSchools() {
return drivingSchoolService.findAllDrivingSchools().stream() return drivingSchoolService.findAllDrivingSchools().stream()
@ -51,13 +55,14 @@ public class DrivingSchoolController {
@PutMapping("/{id}/hire") @PutMapping("/{id}/hire")
public StudentDto hire(@PathVariable Long id, @RequestParam Long studentId) { public StudentDto hire(@PathVariable Long id, @RequestParam Long studentId) {
Student s = studentService.findStudent(studentId); Student e = studentService.findStudent(studentId);
return new StudentDto(drivingSchoolService.addNewStudent(id, s)); return new StudentDto(drivingSchoolService.addNewStudent(id, e));
} }
@PutMapping("/{id}/dismiss") @PutMapping("/{id}/dismiss")
public StudentDto dismiss(@PathVariable Long id, @RequestParam Long studentId) { public StudentDto dismiss(@PathVariable Long id, @RequestParam Long studentId) {
Student s = studentService.findStudent(studentId); Student e = studentService.findStudent(studentId);
return new StudentDto(drivingSchoolService.deleteStudent(id, s)); return new StudentDto(drivingSchoolService.deleteStudent(id, e));
} }
} }

View File

@ -1,10 +1,10 @@
package ru.ulstu.is.cbapp.controller; package ru.ulstu.is.cbapp.controller;
import org.springframework.web.bind.annotation.*;
import ru.ulstu.is.cbapp.dto.StudentDto; import ru.ulstu.is.cbapp.dto.StudentDto;
import ru.ulstu.is.cbapp.models.Category; import ru.ulstu.is.cbapp.models.Category;
import ru.ulstu.is.cbapp.service.CategoryService;
import ru.ulstu.is.cbapp.service.StudentService; import ru.ulstu.is.cbapp.service.StudentService;
import ru.ulstu.is.cbapp.service.CategoryService;
import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -50,24 +50,43 @@ public class StudentController {
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public StudentDto deleteEmployee(@PathVariable Long id) { public StudentDto deleteStudent(@PathVariable Long id) {
return new StudentDto(studentService.deleteStudent(id)); return new StudentDto(studentService.deleteStudent(id));
} }
@PutMapping("/{id}/addCat") @PutMapping("/{id}/addCat")
public StudentDto addCategory(@PathVariable Long id, public StudentDto addCategory(@PathVariable Long id,
@RequestParam("category") Long category) { @RequestParam("category") Long category) {
Category c = categoryService.findCategory(category); Category p = categoryService.findCategory(category);
if (c == null) if (p == null)
return null; return null;
return new StudentDto(studentService.addCategory(id, c)); return new StudentDto(studentService.addCategory(id, p));
} }
@PutMapping("/{id}/delCat") @PutMapping("/{id}/delCat")
public StudentDto delCategory(@PathVariable Long id, public StudentDto delCategory(@PathVariable Long id,
@RequestParam("category") Long category) { @RequestParam("category") Long category) {
Category c = categoryService.findCategory(category); Category p = categoryService.findCategory(category);
if (c == null) if (p == null)
return null; return null;
return new StudentDto(studentService.deleteCategory(id, c)); return new StudentDto(studentService.deleteCategory(id, p));
}
@GetMapping("/free")
public List<StudentDto> getAllFreeStudents() {
return studentService.findAllFreeStudents().stream()
.map(StudentDto::new)
.toList();
}
@GetMapping("/category")
public List<StudentDto> getStudentsByCategory(@RequestParam Long cat) {
Category p = categoryService.findCategory(cat);
if (p == null) {
return null;
}
return studentService.getStudentsByCategory(p).stream()
.map(StudentDto::new)
.toList();
} }
} }

View File

@ -1,7 +1,7 @@
package ru.ulstu.is.cbapp.dao; package ru.ulstu.is.cbapp.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.is.cbapp.models.Category; import ru.ulstu.is.cbapp.models.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional; import java.util.Optional;

View File

@ -1,7 +1,7 @@
package ru.ulstu.is.cbapp.dao; package ru.ulstu.is.cbapp.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.is.cbapp.models.DrivingSchool; import ru.ulstu.is.cbapp.models.DrivingSchool;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional; import java.util.Optional;

View File

@ -1,10 +1,13 @@
package ru.ulstu.is.cbapp.dao; package ru.ulstu.is.cbapp.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.is.cbapp.models.Student; import ru.ulstu.is.cbapp.models.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface StudentRepository extends JpaRepository<Student, Long> { public interface StudentRepository extends JpaRepository<Student, Long> {
Optional<Student> findById(Long id); Optional<Student> findById(Long id);
List<Student> findByCategories_Id(Long p_id);
List<Student> findByDrivingSchoolIsNull();
} }

View File

@ -0,0 +1,21 @@
package ru.ulstu.is.cbapp.dto;
import ru.ulstu.is.cbapp.models.DrivingSchool;
public class DrivingSchoolWithoutStudDto {
private final Long Id;
private final String name;
public DrivingSchoolWithoutStudDto(DrivingSchool drivingSchool) {
this.Id = drivingSchool.getId();
this.name = drivingSchool.getName();
}
public Long getId() {
return Id;
}
public String getName() {
return name;
}
}

View File

@ -11,12 +11,15 @@ public class StudentDto {
private final String surname; private final String surname;
private final List<CategoryDto> categories; private final List<CategoryDto> categories;
private final DrivingSchoolWithoutStudDto drivingSchool;
public StudentDto(Student student) { public StudentDto(Student student) {
Id = student.getId(); Id = student.getId();
this.name = student.getName(); this.name = student.getName();
this.phoneNumber = student.getPhoneNumber(); this.phoneNumber = student.getPhoneNumber();
this.surname = student.getSurname(); this.surname = student.getSurname();
this.categories = student.getCategories().stream().map(CategoryDto::new).toList(); this.categories = student.getCategories().stream().map(CategoryDto::new).toList();
this.drivingSchool = student.getDrivingSchool() != null ? new DrivingSchoolWithoutStudDto(student.getDrivingSchool()) : null;
} }
public Long getId() { public Long getId() {
@ -38,4 +41,8 @@ public class StudentDto {
public List<CategoryDto> getCategories() { public List<CategoryDto> getCategories() {
return categories; return categories;
} }
public DrivingSchoolWithoutStudDto getDrivingSchool() {
return drivingSchool;
}
} }

View File

@ -1,6 +1,6 @@
package ru.ulstu.is.cbapp.models; package ru.ulstu.is.cbapp.models;
import javax.persistence.*; import jakarta.persistence.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -11,10 +11,11 @@ public class Category {
@Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
private Long Id; private Long Id;
private String name; private String name;
//mappedBy - атрибут, указывающий, что классом-владельцем отношений является другой класс //mappedBy - атрибут, указывающий, что классом-владельцем отношений является другой класс
@ManyToMany(mappedBy = "categories", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @ManyToMany(mappedBy = "categories", cascade = {CascadeType.REMOVE}, fetch = FetchType.EAGER)
private List<Student> students = new ArrayList<>(); private List<Student> students = new ArrayList<>();
public Category() { public Category() {

View File

@ -1,22 +1,19 @@
package ru.ulstu.is.cbapp.models; package ru.ulstu.is.cbapp.models;
import javax.persistence.*; import jakarta.persistence.*;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Entity @Entity
public class DrivingSchool { public class DrivingSchool {
@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;
@OneToMany(mappedBy = "drivingSchool", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(mappedBy = "drivingSchool", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Student> students = new ArrayList<>(); private Set<Student> students = new HashSet<>();
public DrivingSchool(String name, List<Student> students) { public DrivingSchool(String name, Set<Student> students) {
this.name = name; this.name = name;
this.students = students; this.students = students;
} }
@ -51,11 +48,11 @@ public class DrivingSchool {
return Id; return Id;
} }
public List<Student> getStudents() { public Set<Student> getStudents() {
return students; return students;
} }
public void setStudents(List<Student> students) { public void setStudents(Set<Student> students) {
this.students = students; this.students = students;
} }

View File

@ -1,6 +1,6 @@
package ru.ulstu.is.cbapp.models; package ru.ulstu.is.cbapp.models;
import javax.persistence.*; import jakarta.persistence.*;
import java.util.*; import java.util.*;
@ -13,14 +13,14 @@ public class Student {
private String name; private String name;
private String surname; private String surname;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
private DrivingSchool drivingSchool; private DrivingSchool drivingSchool;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Category> categories = new HashSet<>(); private Set<Category> categories = new HashSet<>();
public Student(String phoneNumber, String name, String surname) { public Student(String surname, String name, String phoneNumber) {
this.phoneNumber = phoneNumber; this.phoneNumber = phoneNumber;
this.name = name; this.name = name;
this.surname = surname; this.surname = surname;
@ -77,6 +77,7 @@ public class Student {
drivingSchool.deleteStudent(this); drivingSchool.deleteStudent(this);
} }
this.drivingSchool = null; this.drivingSchool = null;
this.categories.clear();
} }
public void addNewCategory(Category p) { public void addNewCategory(Category p) {

View File

@ -2,7 +2,7 @@ package ru.ulstu.is.cbapp.service;
import ru.ulstu.is.cbapp.dao.CategoryRepository; import ru.ulstu.is.cbapp.dao.CategoryRepository;
import ru.ulstu.is.cbapp.models.Category; import ru.ulstu.is.cbapp.models.Category;
import javax.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -17,6 +17,7 @@ public class CategoryService {
public CategoryService(CategoryRepository categoryRepository) { public CategoryService(CategoryRepository categoryRepository) {
this.categoryRepository = categoryRepository; this.categoryRepository = categoryRepository;
} }
@Transactional @Transactional
public Category addCategory(String name) { public Category addCategory(String name) {
if (!StringUtils.hasText(name)) { if (!StringUtils.hasText(name)) {
@ -44,7 +45,7 @@ public class CategoryService {
@Transactional @Transactional
public Category updateCategory(Long id, String name) { public Category updateCategory(Long id, String name) {
if (!StringUtils.hasText(name)) { if (!StringUtils.hasText(name)) {
throw new IllegalArgumentException("Category's data is null or empty"); throw new IllegalArgumentException("Student's data is null or empty");
} }
final Category currentCategory = findCategory(id); final Category currentCategory = findCategory(id);
currentCategory.setName(name); currentCategory.setName(name);

View File

@ -1,19 +1,18 @@
package ru.ulstu.is.cbapp.service; package ru.ulstu.is.cbapp.service;
import javax.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import ru.ulstu.is.cbapp.dao.DrivingSchoolRepository; import ru.ulstu.is.cbapp.dao.DrivingSchoolRepository;
import ru.ulstu.is.cbapp.dao.StudentRepository; import ru.ulstu.is.cbapp.dao.StudentRepository;
import ru.ulstu.is.cbapp.models.DrivingSchool; import ru.ulstu.is.cbapp.models.DrivingSchool;
import ru.ulstu.is.cbapp.models.Student; import ru.ulstu.is.cbapp.models.Student;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List; import java.util.List;
@Service @Service
public class DrivingSchoolService { public class DrivingSchoolService {
private DrivingSchoolRepository drivingSchoolRepository; private DrivingSchoolRepository drivingSchoolRepository;
private StudentRepository studentRepository; private StudentRepository studentRepository;
public DrivingSchoolService(DrivingSchoolRepository drivingSchoolRepository, StudentRepository studentRepository) { public DrivingSchoolService(DrivingSchoolRepository drivingSchoolRepository, StudentRepository studentRepository) {
@ -76,15 +75,6 @@ public class DrivingSchoolService {
return student; return student;
} }
@Transactional
public void addAllStudent(Long id, List<Student> students) {
DrivingSchool currentDrivingSchool = findDrivingSchool(id);
for(int i=0; i<students.size(); i++) {
currentDrivingSchool.addNewStudent(students.get(i));
drivingSchoolRepository.save(currentDrivingSchool);
}
}
@Transactional @Transactional
public Student deleteStudent(Long id, Student student) { public Student deleteStudent(Long id, Student student) {
DrivingSchool currentDrivingSchool = findDrivingSchool(id); DrivingSchool currentDrivingSchool = findDrivingSchool(id);

View File

@ -1,19 +1,18 @@
package ru.ulstu.is.cbapp.service; package ru.ulstu.is.cbapp.service;
import javax.persistence.EntityNotFoundException; import ru.ulstu.is.cbapp.dao.StudentRepository;
import ru.ulstu.is.cbapp.models.Category;
import ru.ulstu.is.cbapp.models.DrivingSchool;
import ru.ulstu.is.cbapp.models.Student;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import ru.ulstu.is.cbapp.dao.StudentRepository;
import ru.ulstu.is.cbapp.models.DrivingSchool;
import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.models.Category;
import java.util.List; import java.util.List;
@Service @Service
public class StudentService { public class StudentService {
private StudentRepository studentRepository; private StudentRepository studentRepository;
public StudentService(StudentRepository studentRepository) { public StudentService(StudentRepository studentRepository) {
this.studentRepository = studentRepository; this.studentRepository = studentRepository;
@ -42,6 +41,10 @@ public class StudentService {
public List<Student> findAllStudents() { public List<Student> findAllStudents() {
return studentRepository.findAll(); return studentRepository.findAll();
} }
@Transactional(readOnly = true)
public List<Student> findAllFreeStudents() {
return studentRepository.findByDrivingSchoolIsNull();
}
@Transactional @Transactional
public Student updateStudent(Long id, String surname, String name, String phoneNumber) { public Student updateStudent(Long id, String surname, String name, String phoneNumber) {
@ -69,9 +72,9 @@ public class StudentService {
} }
@Transactional @Transactional
public void addDrivingSchool(Long id, DrivingSchool d) { public void addDrivingSchool(Long id, DrivingSchool c) {
final Student student = findStudent(id); final Student student = findStudent(id);
student.setDrivingSchool(d); student.setDrivingSchool(c);
studentRepository.save(student); studentRepository.save(student);
} }
@ -97,4 +100,9 @@ public class StudentService {
return studentRepository.save(e); return studentRepository.save(e);
} }
@Transactional
public List<Student> getStudentsByCategory(Category p) {
List<Student> students = studentRepository.findByCategories_Id(p.getId());
return students;
}
} }

View File

@ -1,13 +1,13 @@
package ru.ulstu.is.cbapp; package ru.ulstu.is.cbapp;
import ru.ulstu.is.cbapp.models.Category;
import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.service.StudentService;
import ru.ulstu.is.cbapp.service.CategoryService;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.models.Category;
import ru.ulstu.is.cbapp.service.StudentService;
import ru.ulstu.is.cbapp.service.CategoryService;
@SpringBootTest @SpringBootTest
public class CategoryServiceTests { public class CategoryServiceTests {
@ -41,12 +41,12 @@ public class CategoryServiceTests {
categoryService.deleteAllCategories(); categoryService.deleteAllCategories();
Category p = categoryService.addCategory("Category"); Category p = categoryService.addCategory("Category");
Student e1 = studentService.addStudent("1", "2", "33"); Student e = studentService.addStudent("1", "2", "33");
studentService.addCategory(e1.getId(), p); studentService.addCategory(e.getId(), p);
studentService.deleteCategory(e1.getId(), p); studentService.deleteCategory(e.getId(), p);
Assertions.assertFalse(studentService.findStudent(e1.getId()).getCategories().contains(p)); Assertions.assertFalse(studentService.findStudent(e.getId()).getCategories().contains(p));
Assertions.assertFalse(categoryService.findCategory(p.getId()).getStudents().contains(e1)); Assertions.assertFalse(categoryService.findCategory(p.getId()).getStudents().contains(e));
studentService.deleteAllStudents(); studentService.deleteAllStudents();
categoryService.deleteAllCategories(); categoryService.deleteAllCategories();

View File

@ -1,17 +1,14 @@
package ru.ulstu.is.cbapp; package ru.ulstu.is.cbapp;
import javax.persistence.EntityNotFoundException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.ulstu.is.cbapp.models.DrivingSchool; import ru.ulstu.is.cbapp.models.DrivingSchool;
import ru.ulstu.is.cbapp.models.Student; import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.service.DrivingSchoolService; import ru.ulstu.is.cbapp.service.DrivingSchoolService;
import ru.ulstu.is.cbapp.service.StudentService; import ru.ulstu.is.cbapp.service.StudentService;
import jakarta.persistence.EntityNotFoundException;
import java.util.ArrayList; import org.junit.jupiter.api.Assertions;
import java.util.List; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest @SpringBootTest
public class DrivingSchoolServiceTests { public class DrivingSchoolServiceTests {
@ -21,7 +18,6 @@ public class DrivingSchoolServiceTests {
@Autowired @Autowired
private StudentService studentService; private StudentService studentService;
@Test @Test
public void testDeleteAllDrivingSchools() { public void testDeleteAllDrivingSchools() {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
@ -38,18 +34,18 @@ public class DrivingSchoolServiceTests {
public void testDeleteDrivingSchool() { public void testDeleteDrivingSchool() {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
String name = "DrivingSchool1"; String name = "DrivingSchool1";
DrivingSchool d = drivingSchoolService.addDrivingSchool(name); DrivingSchool c = drivingSchoolService.addDrivingSchool(name);
drivingSchoolService.deleteDrivingSchool(d.getId()); drivingSchoolService.deleteDrivingSchool(c.getId());
Assertions.assertThrows(EntityNotFoundException.class, () -> { Assertions.assertThrows(EntityNotFoundException.class, () -> {
drivingSchoolService.findDrivingSchool(d.getId());}); drivingSchoolService.findDrivingSchool(c.getId());});
} }
@Test @Test
public void testAddDrivingSchool() { public void testAddDrivingSchool() {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
String name = "DrivingSchool1"; String name = "DrivingSchool1";
DrivingSchool d = drivingSchoolService.addDrivingSchool(name); DrivingSchool c = drivingSchoolService.addDrivingSchool(name);
Assertions.assertNotNull(drivingSchoolService.findDrivingSchool(d.getId())); Assertions.assertNotNull(drivingSchoolService.findDrivingSchool(c.getId()));
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
} }
@ -57,10 +53,10 @@ public class DrivingSchoolServiceTests {
public void testUpdateDrivingSchool() { public void testUpdateDrivingSchool() {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
String name = "DrivingSchool1"; String name = "DrivingSchool1";
DrivingSchool ds = drivingSchoolService.addDrivingSchool(name); DrivingSchool c = drivingSchoolService.addDrivingSchool(name);
String name2 = "DrivingSchool2"; String name2 = "DrivingSchool2";
drivingSchoolService.updateDrivingSchool(ds.getId(), name2); drivingSchoolService.updateDrivingSchool(c.getId(), name2);
Assertions.assertNotNull(drivingSchoolService.findDrivingSchool(ds.getId())); Assertions.assertNotNull(drivingSchoolService.findDrivingSchool(c.getId()));
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
} }
@ -84,23 +80,14 @@ public class DrivingSchoolServiceTests {
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
final String name = "DrivingSchool"; final String name = "DrivingSchool";
DrivingSchool d = drivingSchoolService.addDrivingSchool(name); DrivingSchool c = drivingSchoolService.addDrivingSchool(name);
Student newStudent = studentService.addStudent("cha", "chacha", "111");
drivingSchoolService.addNewStudent(c.getId(), newStudent);
Student s1 = studentService.addStudent("cha", "chacha", "111"); Assertions.assertTrue(drivingSchoolService.findDrivingSchool(c.getId()).getStudents().contains(newStudent));
Student s2 = studentService.addStudent("cha", "chacha", "111");
Student s3 = studentService.addStudent("cha", "chacha", "111");
List<Student> studs = new ArrayList<>();
studs.add(s1);
studs.add(s2);
studs.add(s3);
drivingSchoolService.addAllStudent(d.getId(), studs);
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(s1));
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(s2));
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(s3));
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
@ -111,51 +98,19 @@ public class DrivingSchoolServiceTests {
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
final String name = "DrivingSchool"; final String name = "DrivingSchool";
DrivingSchool d = drivingSchoolService.addDrivingSchool(name); DrivingSchool c = drivingSchoolService.addDrivingSchool(name);
Student student1 = studentService.addStudent("cha1", "chacha1", "111"); Student newStudent = studentService.addStudent("cha", "chacha", "111");
Student student2 = studentService.addStudent("cha2", "chacha2", "1111");
Student student3 = studentService.addStudent("cha3", "chacha3", "11111");
drivingSchoolService.addNewStudent(d.getId(), student1); drivingSchoolService.addNewStudent(c.getId(), newStudent);
drivingSchoolService.addNewStudent(d.getId(), student2); Assertions.assertTrue(drivingSchoolService.findDrivingSchool(c.getId()).getStudents().contains(newStudent));
drivingSchoolService.addNewStudent(d.getId(), student3);
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student1)); drivingSchoolService.deleteStudent(c.getId(), newStudent);
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student2)); Assertions.assertFalse(drivingSchoolService.findDrivingSchool(c.getId()).getStudents().contains(newStudent));
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student3));
DrivingSchool ds=drivingSchoolService.findDrivingSchool(d.getId());
Assertions.assertNotNull(ds);
Assertions.assertTrue(ds.getStudents().contains(student1));
Assertions.assertTrue(ds.getStudents().contains(student2));
Assertions.assertTrue(ds.getStudents().contains(student3));
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
}
@Test
public void testFindAllStudent(){
studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools();
DrivingSchool d = drivingSchoolService.addDrivingSchool("ds");
Student student1 = studentService.addStudent("cha1", "chacha1", "1111");
Student student2 = studentService.addStudent("cha2", "chacha2", "11111");
Student student3 = studentService.addStudent("cha3", "chacha3", "111111");
drivingSchoolService.addNewStudent(d.getId(), student1);
drivingSchoolService.addNewStudent(d.getId(), student2);
drivingSchoolService.addNewStudent(d.getId(), student3);
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student1));
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student2));
Assertions.assertTrue(drivingSchoolService.findDrivingSchool(d.getId()).getStudents().contains(student3));
studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools();
} }
} }

View File

@ -1,13 +1,15 @@
package ru.ulstu.is.cbapp; package ru.ulstu.is.cbapp;
import org.junit.jupiter.api.Assertions; import ru.ulstu.is.cbapp.models.Category;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.ulstu.is.cbapp.models.DrivingSchool; import ru.ulstu.is.cbapp.models.DrivingSchool;
import ru.ulstu.is.cbapp.models.Student; import ru.ulstu.is.cbapp.models.Student;
import ru.ulstu.is.cbapp.service.DrivingSchoolService; import ru.ulstu.is.cbapp.service.DrivingSchoolService;
import ru.ulstu.is.cbapp.service.StudentService; import ru.ulstu.is.cbapp.service.StudentService;
import ru.ulstu.is.cbapp.service.CategoryService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest @SpringBootTest
public class StudentServiceTests { public class StudentServiceTests {
@ -17,6 +19,9 @@ public class StudentServiceTests {
@Autowired @Autowired
private DrivingSchoolService drivingSchoolService; private DrivingSchoolService drivingSchoolService;
@Autowired
private CategoryService categoryService;
@Test @Test
public void testAddStudent() { public void testAddStudent() {
studentService.deleteAllStudents(); studentService.deleteAllStudents();
@ -64,9 +69,9 @@ public class StudentServiceTests {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
Student e = studentService.addStudent("name", "surname", "111"); Student e = studentService.addStudent("name", "surname", "111");
DrivingSchool d = drivingSchoolService.addDrivingSchool("Comp"); DrivingSchool c = drivingSchoolService.addDrivingSchool("Comp");
drivingSchoolService.addNewStudent(d.getId(), e); drivingSchoolService.addNewStudent(c.getId(), e);
Assertions.assertEquals(d, studentService.findStudent(e.getId()).getDrivingSchool()); Assertions.assertEquals(c, studentService.findStudent(e.getId()).getDrivingSchool());
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
@ -78,10 +83,10 @@ public class StudentServiceTests {
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
Student e = studentService.addStudent("name", "surname", "111"); Student e = studentService.addStudent("name", "surname", "111");
DrivingSchool d = drivingSchoolService.addDrivingSchool("Comp"); DrivingSchool c = drivingSchoolService.addDrivingSchool("Comp");
studentService.addDrivingSchool(e.getId(), d); studentService.addDrivingSchool(e.getId(), c);
Assertions.assertEquals(d, studentService.findStudent(e.getId()).getDrivingSchool()); Assertions.assertEquals(c, studentService.findStudent(e.getId()).getDrivingSchool());
studentService.deleteDrivingSchool(e.getId()); studentService.deleteDrivingSchool(e.getId());
Assertions.assertNull(studentService.findStudent(e.getId()).getDrivingSchool()); Assertions.assertNull(studentService.findStudent(e.getId()).getDrivingSchool());
@ -89,4 +94,30 @@ public class StudentServiceTests {
studentService.deleteAllStudents(); studentService.deleteAllStudents();
drivingSchoolService.deleteAllDrivingSchools(); drivingSchoolService.deleteAllDrivingSchools();
} }
@Test
public void testGetByCategory() {
studentService.deleteAllStudents();
categoryService.deleteAllCategories();
Category p = categoryService.addCategory("Category 1");
Category p2 = categoryService.addCategory("Category 2");
final int n = 10;
for (int i = 0; i < n; i++) {
Student e = studentService.addStudent("1111", "name" + i, "surname");
if (i % 2 == 0) {
studentService.addCategory(e.getId(), p);
}
else {
studentService.addCategory(e.getId(), p2);
}
}
Assertions.assertEquals(n / 2, studentService.getStudentsByCategory(p).size());
Assertions.assertEquals(n / 2, studentService.getStudentsByCategory(p2).size());
studentService.deleteAllStudents();
categoryService.deleteAllCategories();
}
} }