сделал допку

This commit is contained in:
2025-12-13 20:30:16 +04:00
parent 1fcb355ba3
commit ea4012112b
52 changed files with 2105 additions and 195 deletions

View File

@@ -1,7 +1,5 @@
server.port=8080
# БД
spring.datasource.url=jdbc:h2:file:./data;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
@@ -11,15 +9,17 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
# Liquibase
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.h2.console.settings.web-allow-others=true
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml
spring.web.resources.static-locations=classpath:/static/
spring.web.resources.add-mappings=true
spring.mvc.throw-exception-if-no-handler-found=true
spring.thymeleaf.enabled=false
logging.level.org.springframework.web=DEBUG
logging.level.com.example=DEBUG
logging.level.org.springframework.web=INFO
logging.level.com.example=INFO

View File

@@ -12,7 +12,6 @@ if (!frontDir.exists()) {
} else {
logger.quiet("Webapp dir is {}", frontDir.toString())
// Настраиваем node
node {
version = "22.17.1"
npmVersion = "10.9.2"
@@ -22,7 +21,6 @@ if (!frontDir.exists()) {
nodeProjectDir = file("${frontDir}")
}
// Задача для npm install
task frontNpmInstall(type: NpmTask) {
group = "front"
description = "Installs npm dependencies"
@@ -30,7 +28,6 @@ if (!frontDir.exists()) {
args = ["install"]
}
// Задача для npm build
task frontNpmBuild(type: NpmTask) {
group = "front"
description = "Builds React app"
@@ -43,7 +40,6 @@ if (!frontDir.exists()) {
outputs.dir(frontDistDir)
}
// Задача для копирования в ресурсы
task copyFrontendToResources(type: Copy) {
group = "front"
description = "Copies built frontend to static resources"
@@ -57,13 +53,10 @@ if (!frontDir.exists()) {
}
}
// Настраиваем зависимости
copyFrontendToResources.dependsOn frontNpmBuild
frontNpmBuild.dependsOn frontNpmInstall
// Интеграция со сборкой
processResources.dependsOn copyFrontendToResources
// Для bootJar
bootJar.dependsOn copyFrontendToResources
}

View File

@@ -3,7 +3,7 @@ plugins {
id 'org.springframework.boot' version '3.5.5'
id 'io.spring.dependency-management' version '1.1.7'
id 'org.liquibase.gradle' version '2.2.0'
id 'com.github.node-gradle.node' version '7.0.2' // Для React
id 'com.github.node-gradle.node' version '7.0.2'
}
group = 'com.example'
@@ -25,7 +25,6 @@ ext {
h2Version = "2.3.232"
postgresVersion = "42.7.3"
// НАСТРОЙКА ПРОФИЛЕЙ
springProfiles = []
if (project.hasProperty("front")) {
springProfiles.add("front")
@@ -49,16 +48,12 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0'
// Liquibase
implementation "org.liquibase:liquibase-core:${liquibaseVersion}"
// БД в зависимости от профиля
if (springProfiles.contains("prod")) {
// Prod профиль - ТОЛЬКО PostgreSQL
implementation "org.postgresql:postgresql:${postgresVersion}"
logger.quiet("→ Added PostgreSQL dependency for PROD")
} else {
// Dev/Front профили - ТОЛЬКО H2
implementation "com.h2database:h2:${h2Version}"
logger.quiet("→ Added H2 dependency for DEV/FRONT")
}
@@ -67,7 +62,6 @@ dependencies {
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
// НАСТРОЙКА ПРОФИЛЕЙ ДЛЯ ЗАПУСКА
bootRun {
systemProperty "spring.profiles.active", currentProfiles
}
@@ -77,7 +71,6 @@ test {
systemProperty "spring.profiles.active", currentProfiles
}
// ПРАВКА application.properties ДЛЯ ПРОФИЛЕЙ
processResources {
filesMatching("**/application.properties") {
filter { line ->
@@ -86,17 +79,14 @@ processResources {
}
}
// ПОДКЛЮЧЕНИЕ МИГРАЦИЙ ТОЛЬКО ДЛЯ DEV
if (springProfiles.contains("dev")) {
apply from: "build.migrations.gradle"
}
// НАСТРОЙКА ДЛЯ REACT (FRONT ПРОФИЛЬ)
if (springProfiles.contains("front")) {
apply from: "build.front.gradle"
}
// ЗАДАЧИ ДЛЯ СБОРКИ JAR
jar {
enabled = true
archiveFileName = "delivery-app.jar"

View File

@@ -8,25 +8,20 @@ ext {
timestamp = new Date().format("yyyy-MM-dd-HHmmss")
}
// ОСНОВНАЯ КОНФИГУРАЦИЯ
liquibase {
activities {
main {
changelogFile "src/main/resources/db/changelog/db.changelog-master.yaml"
// Используем параметры URL для передачи пароля
url "jdbc:h2:file:./data;user=sa;password="
driver "org.h2.Driver"
logLevel "info"
// Не передаем username и password отдельно
// Они уже в URL
}
}
}
// ЗАВИСИМОСТИ
dependencies {
liquibaseRuntime "org.liquibase:liquibase-core:${liquibaseVersion}"
liquibaseRuntime "info.picocli:picocli:${picocliVersion}"
@@ -36,7 +31,6 @@ dependencies {
liquibaseRuntime sourceSets.main.output
}
// ЗАДАЧА generateFull
task generateFull {
group = "migrations"
description = "Generate changelog from existing database"
@@ -54,7 +48,6 @@ task generateFull {
finalizedBy generateChangelog
}
// ЗАДАЧА generateDiff
task generateDiff {
group = "migrations"
description = "Generate diff between DB and JPA entities"
@@ -72,7 +65,6 @@ task generateDiff {
finalizedBy diffChangelog
}
// ЗАДАЧА ДЛЯ СТАТУСА - ИСПРАВЛЕННАЯ
task migrationStatus {
group = "migrations"
description = "Show migration status"
@@ -81,17 +73,15 @@ task migrationStatus {
println "Checking migration status..."
}
finalizedBy 'liquibaseStatus' // ИСПОЛЬЗУЕМ СТАНДАРТНУЮ ЗАДАЧУ LIQUIBASE
finalizedBy 'liquibaseStatus'
}
// ЗАДАЧА ДЛЯ SQL
task updateSQL {
group = "migrations"
description = "Generate SQL without executing"
finalizedBy 'updateSQL' // СТАНДАРТНАЯ ЗАДАЧА LIQUIBASE
finalizedBy 'updateSQL'
}
// ВАЖНЫЕ ЗАВИСИМОСТИ
diffChangelog.dependsOn compileJava
update.dependsOn processResources

BIN
build/libs/delivery-app.jar Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="x-ua-compatible" content="IE=edge"/>
<title>Test results - CustomerServiceTest</title>
<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
<script src="../js/report.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<h1>CustomerServiceTest</h1>
<div class="breadcrumbs">
<a href="../index.html">all</a> &gt;
<a href="../packages/com.example.service.html">com.example.service</a> &gt; CustomerServiceTest</div>
<div id="summary">
<table>
<tr>
<td>
<div class="summaryGroup">
<table>
<tr>
<td>
<div class="infoBox" id="tests">
<div class="counter">2</div>
<p>tests</p>
</div>
</td>
<td>
<div class="infoBox" id="failures">
<div class="counter">0</div>
<p>failures</p>
</div>
</td>
<td>
<div class="infoBox" id="ignored">
<div class="counter">0</div>
<p>ignored</p>
</div>
</td>
<td>
<div class="infoBox" id="duration">
<div class="counter">0.559s</div>
<p>duration</p>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
<div class="infoBox success" id="successRate">
<div class="percent">100%</div>
<p>successful</p>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-container">
<ul class="tabLinks">
<li>
<a href="#">Tests</a>
</li>
<li>
<a href="#">Standard error</a>
</li>
</ul>
<div class="tab">
<h2>Tests</h2>
<table>
<thead>
<tr>
<th>Test</th>
<th>Duration</th>
<th>Result</th>
</tr>
</thead>
<tr>
<td class="success">create_WhenValidData_ShouldCreateCustomer()</td>
<td class="success">0.556s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findById_WhenCustomerExists_ShouldReturnCustomer()</td>
<td class="success">0.003s</td>
<td class="success">passed</td>
</tr>
</table>
</div>
<div class="tab">
<h2>Standard error</h2>
<span class="code">
<pre>Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
WARNING: A Java agent has been loaded dynamically (/Users/floom/.gradle/caches/modules-2/files-2.1/net.bytebuddy/byte-buddy-agent/1.17.7/fbf3d6d649ed37fc9e9c59480a05be0a26e3c2da/byte-buddy-agent-1.17.7.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
</pre>
</span>
</div>
</div>
<div id="footer">
<p>
<div>
<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label>
</div>Generated by
<a href="https://www.gradle.org">Gradle 8.14.3</a> at 13 дек. 2025г., 19:44:16</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="x-ua-compatible" content="IE=edge"/>
<title>Test results - DeliveryServiceTest</title>
<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
<script src="../js/report.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<h1>DeliveryServiceTest</h1>
<div class="breadcrumbs">
<a href="../index.html">all</a> &gt;
<a href="../packages/com.example.service.html">com.example.service</a> &gt; DeliveryServiceTest</div>
<div id="summary">
<table>
<tr>
<td>
<div class="summaryGroup">
<table>
<tr>
<td>
<div class="infoBox" id="tests">
<div class="counter">6</div>
<p>tests</p>
</div>
</td>
<td>
<div class="infoBox" id="failures">
<div class="counter">0</div>
<p>failures</p>
</div>
</td>
<td>
<div class="infoBox" id="ignored">
<div class="counter">0</div>
<p>ignored</p>
</div>
</td>
<td>
<div class="infoBox" id="duration">
<div class="counter">0.051s</div>
<p>duration</p>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
<div class="infoBox success" id="successRate">
<div class="percent">100%</div>
<p>successful</p>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-container">
<ul class="tabLinks">
<li>
<a href="#">Tests</a>
</li>
</ul>
<div class="tab">
<h2>Tests</h2>
<table>
<thead>
<tr>
<th>Test</th>
<th>Duration</th>
<th>Result</th>
</tr>
</thead>
<tr>
<td class="success">create_WhenValidData_ShouldCreateDelivery()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">delete_WhenDeliveryExists_ShouldDeleteDelivery()</td>
<td class="success">0.001s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">delete_WhenDeliveryNotExists_ShouldReturnFalse()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findAll_ShouldReturnAllDeliveries()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findById_WhenDeliveryExists_ShouldReturnDelivery()</td>
<td class="success">0.042s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">update_WhenDeliveryExists_ShouldUpdateDelivery()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
</table>
</div>
</div>
<div id="footer">
<p>
<div>
<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label>
</div>Generated by
<a href="https://www.gradle.org">Gradle 8.14.3</a> at 13 дек. 2025г., 19:44:16</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,136 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="x-ua-compatible" content="IE=edge"/>
<title>Test results - OrderServiceTest</title>
<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
<script src="../js/report.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<h1>OrderServiceTest</h1>
<div class="breadcrumbs">
<a href="../index.html">all</a> &gt;
<a href="../packages/com.example.service.html">com.example.service</a> &gt; OrderServiceTest</div>
<div id="summary">
<table>
<tr>
<td>
<div class="summaryGroup">
<table>
<tr>
<td>
<div class="infoBox" id="tests">
<div class="counter">9</div>
<p>tests</p>
</div>
</td>
<td>
<div class="infoBox" id="failures">
<div class="counter">0</div>
<p>failures</p>
</div>
</td>
<td>
<div class="infoBox" id="ignored">
<div class="counter">0</div>
<p>ignored</p>
</div>
</td>
<td>
<div class="infoBox" id="duration">
<div class="counter">0.053s</div>
<p>duration</p>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
<div class="infoBox success" id="successRate">
<div class="percent">100%</div>
<p>successful</p>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-container">
<ul class="tabLinks">
<li>
<a href="#">Tests</a>
</li>
</ul>
<div class="tab">
<h2>Tests</h2>
<table>
<thead>
<tr>
<th>Test</th>
<th>Duration</th>
<th>Result</th>
</tr>
</thead>
<tr>
<td class="success">create_WhenCustomerNotFound_ShouldThrowException()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">create_WhenValidData_ShouldCreateOrder()</td>
<td class="success">0.041s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">delete_WhenOrderExists_ShouldDeleteOrder()</td>
<td class="success">0.001s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">delete_WhenOrderNotExists_ShouldReturnFalse()</td>
<td class="success">0.001s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findAll_ShouldReturnAllOrders()</td>
<td class="success">0.001s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findByCustomerId_ShouldReturnCustomerOrders()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findById_WhenOrderExists_ShouldReturnOrder()</td>
<td class="success">0.001s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">findByStatus_ShouldReturnOrdersByStatus()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
<tr>
<td class="success">update_WhenOrderExists_ShouldUpdateOrder()</td>
<td class="success">0.002s</td>
<td class="success">passed</td>
</tr>
</table>
</div>
</div>
<div id="footer">
<p>
<div>
<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label>
</div>Generated by
<a href="https://www.gradle.org">Gradle 8.14.3</a> at 13 дек. 2025г., 19:44:16</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,174 @@
body {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 12pt;
}
body, a, a:visited {
color: #303030;
}
#content {
padding: 30px 50px;
}
#content h1 {
font-size: 160%;
margin-bottom: 10px;
}
#footer {
margin-top: 100px;
font-size: 80%;
white-space: nowrap;
}
#footer, #footer a {
color: #a0a0a0;
}
#line-wrapping-toggle {
vertical-align: middle;
}
#label-for-line-wrapping-toggle {
vertical-align: middle;
}
ul {
margin-left: 0;
}
h1, h2, h3 {
white-space: nowrap;
}
h2 {
font-size: 120%;
}
.tab-container .tab-container {
margin-left: 8px;
}
ul.tabLinks {
padding: 0;
margin-bottom: 0;
overflow: auto;
min-width: 800px;
width: auto;
border-bottom: solid 1px #aaa;
}
ul.tabLinks li {
float: left;
height: 100%;
list-style: none;
padding: 5px 10px;
border-radius: 7px 7px 0 0;
border: solid 1px transparent;
border-bottom: none;
margin-right: 6px;
background-color: #f0f0f0;
}
ul.tabLinks li.deselected > a {
color: #6d6d6d;
}
ul.tabLinks li:hover {
background-color: #fafafa;
}
ul.tabLinks li.selected {
background-color: #c5f0f5;
border-color: #aaa;
}
ul.tabLinks a {
font-size: 120%;
display: block;
outline: none;
text-decoration: none;
margin: 0;
padding: 0;
}
ul.tabLinks li h2 {
margin: 0;
padding: 0;
}
div.tab {
}
div.selected {
display: block;
}
div.deselected {
display: none;
}
div.tab table {
min-width: 350px;
width: auto;
border-collapse: collapse;
}
div.tab th, div.tab table {
border-bottom: solid 1px #d0d0d0;
}
div.tab th {
text-align: left;
white-space: nowrap;
padding-left: 6em;
}
div.tab th:first-child {
padding-left: 0;
}
div.tab td {
white-space: nowrap;
padding-left: 6em;
padding-top: 5px;
padding-bottom: 5px;
}
div.tab td:first-child {
padding-left: 0;
}
div.tab td.numeric, div.tab th.numeric {
text-align: right;
}
span.code {
display: inline-block;
margin-top: 0;
margin-bottom: 1em;
}
span.code pre {
font-size: 11pt;
padding: 10px;
margin: 0;
background-color: #f7f7f7;
border: solid 1px #d0d0d0;
min-width: 700px;
width: auto;
}
span.wrapped pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: break-all;
}
label.hidden {
display: none;
}

View File

@@ -0,0 +1,84 @@
#summary {
margin-top: 30px;
margin-bottom: 40px;
}
#summary table {
border-collapse: collapse;
}
#summary td {
vertical-align: top;
}
.breadcrumbs, .breadcrumbs a {
color: #606060;
}
.infoBox {
width: 110px;
padding-top: 15px;
padding-bottom: 15px;
text-align: center;
}
.infoBox p {
margin: 0;
}
.counter, .percent {
font-size: 120%;
font-weight: bold;
margin-bottom: 8px;
}
#duration {
width: 125px;
}
#successRate, .summaryGroup {
border: solid 2px #d0d0d0;
-moz-border-radius: 10px;
border-radius: 10px;
}
#successRate {
width: 140px;
margin-left: 35px;
}
#successRate .percent {
font-size: 180%;
}
.success, .success a {
color: #008000;
}
div.success, #successRate.success {
background-color: #bbd9bb;
border-color: #008000;
}
.failures, .failures a {
color: #b60808;
}
.skipped, .skipped a {
color: #c09853;
}
div.failures, #successRate.failures {
background-color: #ecdada;
border-color: #b60808;
}
ul.linkList {
padding-left: 0;
}
ul.linkList li {
list-style: none;
margin-bottom: 5px;
}

View File

@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="x-ua-compatible" content="IE=edge"/>
<title>Test results - Test Summary</title>
<link href="css/base-style.css" rel="stylesheet" type="text/css"/>
<link href="css/style.css" rel="stylesheet" type="text/css"/>
<script src="js/report.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<h1>Test Summary</h1>
<div id="summary">
<table>
<tr>
<td>
<div class="summaryGroup">
<table>
<tr>
<td>
<div class="infoBox" id="tests">
<div class="counter">17</div>
<p>tests</p>
</div>
</td>
<td>
<div class="infoBox" id="failures">
<div class="counter">0</div>
<p>failures</p>
</div>
</td>
<td>
<div class="infoBox" id="ignored">
<div class="counter">0</div>
<p>ignored</p>
</div>
</td>
<td>
<div class="infoBox" id="duration">
<div class="counter">0.663s</div>
<p>duration</p>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
<div class="infoBox success" id="successRate">
<div class="percent">100%</div>
<p>successful</p>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-container">
<ul class="tabLinks">
<li>
<a href="#">Packages</a>
</li>
<li>
<a href="#">Classes</a>
</li>
</ul>
<div class="tab">
<h2>Packages</h2>
<table>
<thead>
<tr>
<th>Package</th>
<th>Tests</th>
<th>Failures</th>
<th>Ignored</th>
<th>Duration</th>
<th>Success rate</th>
</tr>
</thead>
<tbody>
<tr>
<td class="success">
<a href="packages/com.example.service.html">com.example.service</a>
</td>
<td>17</td>
<td>0</td>
<td>0</td>
<td>0.663s</td>
<td class="success">100%</td>
</tr>
</tbody>
</table>
</div>
<div class="tab">
<h2>Classes</h2>
<table>
<thead>
<tr>
<th>Class</th>
<th>Tests</th>
<th>Failures</th>
<th>Ignored</th>
<th>Duration</th>
<th>Success rate</th>
</tr>
</thead>
<tbody>
<tr>
<td class="success">
<a href="classes/com.example.service.CustomerServiceTest.html">com.example.service.CustomerServiceTest</a>
</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>0.559s</td>
<td class="success">100%</td>
</tr>
<tr>
<td class="success">
<a href="classes/com.example.service.DeliveryServiceTest.html">com.example.service.DeliveryServiceTest</a>
</td>
<td>6</td>
<td>0</td>
<td>0</td>
<td>0.051s</td>
<td class="success">100%</td>
</tr>
<tr>
<td class="success">
<a href="classes/com.example.service.OrderServiceTest.html">com.example.service.OrderServiceTest</a>
</td>
<td>9</td>
<td>0</td>
<td>0</td>
<td>0.053s</td>
<td class="success">100%</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="footer">
<p>
<div>
<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label>
</div>Generated by
<a href="https://www.gradle.org">Gradle 8.14.3</a> at 13 дек. 2025г., 19:44:16</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,218 @@
(function (window, document) {
"use strict";
function changeElementClass(element, classValue) {
if (element.getAttribute("className")) {
element.setAttribute("className", classValue);
} else {
element.setAttribute("class", classValue);
}
}
function getClassAttribute(element) {
if (element.getAttribute("className")) {
return element.getAttribute("className");
} else {
return element.getAttribute("class");
}
}
function addClass(element, classValue) {
changeElementClass(element, getClassAttribute(element) + " " + classValue);
}
function removeClass(element, classValue) {
changeElementClass(element, getClassAttribute(element).replace(classValue, ""));
}
function getCheckBox() {
return document.getElementById("line-wrapping-toggle");
}
function getLabelForCheckBox() {
return document.getElementById("label-for-line-wrapping-toggle");
}
function findCodeBlocks() {
const codeBlocks = [];
const tabContainers = getTabContainers();
for (let i = 0; i < tabContainers.length; i++) {
const spans = tabContainers[i].getElementsByTagName("span");
for (let i = 0; i < spans.length; ++i) {
if (spans[i].className.indexOf("code") >= 0) {
codeBlocks.push(spans[i]);
}
}
}
return codeBlocks;
}
function forAllCodeBlocks(operation) {
const codeBlocks = findCodeBlocks();
for (let i = 0; i < codeBlocks.length; ++i) {
operation(codeBlocks[i], "wrapped");
}
}
function toggleLineWrapping() {
const checkBox = getCheckBox();
if (checkBox.checked) {
forAllCodeBlocks(addClass);
} else {
forAllCodeBlocks(removeClass);
}
}
function initControls() {
if (findCodeBlocks().length > 0) {
const checkBox = getCheckBox();
const label = getLabelForCheckBox();
checkBox.onclick = toggleLineWrapping;
checkBox.checked = false;
removeClass(label, "hidden");
}
}
class TabManager {
baseId;
tabs;
titles;
headers;
constructor(baseId, tabs, titles, headers) {
this.baseId = baseId;
this.tabs = tabs;
this.titles = titles;
this.headers = headers;
}
select(i) {
this.deselectAll();
changeElementClass(this.tabs[i], "tab selected");
changeElementClass(this.headers[i], "selected");
while (this.headers[i].firstChild) {
this.headers[i].removeChild(this.headers[i].firstChild);
}
const a = document.createElement("a");
a.appendChild(document.createTextNode(this.titles[i]));
this.headers[i].appendChild(a);
}
deselectAll() {
for (let i = 0; i < this.tabs.length; i++) {
changeElementClass(this.tabs[i], "tab deselected");
changeElementClass(this.headers[i], "deselected");
while (this.headers[i].firstChild) {
this.headers[i].removeChild(this.headers[i].firstChild);
}
const a = document.createElement("a");
const id = this.baseId + "-tab" + i;
a.setAttribute("id", id);
a.setAttribute("href", "#tab" + i);
a.onclick = () => {
this.select(i);
return false;
};
a.appendChild(document.createTextNode(this.titles[i]));
this.headers[i].appendChild(a);
}
}
}
function getTabContainers() {
const tabContainers = Array.from(document.getElementsByClassName("tab-container"));
// Used by existing TabbedPageRenderer users, which have not adjusted to use TabsRenderer yet.
const legacyContainer = document.getElementById("tabs");
if (legacyContainer) {
tabContainers.push(legacyContainer);
}
return tabContainers;
}
function initTabs() {
let tabGroups = 0;
function createTab(num, container) {
const tabElems = findTabs(container);
const tabManager = new TabManager("tabs" + num, tabElems, findTitles(tabElems), findHeaders(container));
tabManager.select(0);
}
const tabContainers = getTabContainers();
for (let i = 0; i < tabContainers.length; i++) {
createTab(tabGroups, tabContainers[i]);
tabGroups++;
}
return true;
}
function findTabs(container) {
return findChildElements(container, "DIV", "tab");
}
function findHeaders(container) {
const owner = findChildElements(container, "UL", "tabLinks");
return findChildElements(owner[0], "LI", null);
}
function findTitles(tabs) {
const titles = [];
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
const header = findChildElements(tab, "H2", null)[0];
header.parentNode.removeChild(header);
if (header.innerText) {
titles.push(header.innerText);
} else {
titles.push(header.textContent);
}
}
return titles;
}
function findChildElements(container, name, targetClass) {
const elements = [];
const children = container.childNodes;
for (let i = 0; i < children.length; i++) {
const child = children.item(i);
if (child.nodeType === 1 && child.nodeName === name) {
if (targetClass && child.className.indexOf(targetClass) < 0) {
continue;
}
elements.push(child);
}
}
return elements;
}
// Entry point.
window.onload = function() {
initTabs();
initControls();
};
} (window, window.document));

View File

@@ -0,0 +1,123 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="x-ua-compatible" content="IE=edge"/>
<title>Test results - Package com.example.service</title>
<link href="../css/base-style.css" rel="stylesheet" type="text/css"/>
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
<script src="../js/report.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<h1>Package com.example.service</h1>
<div class="breadcrumbs">
<a href="../index.html">all</a> &gt; com.example.service</div>
<div id="summary">
<table>
<tr>
<td>
<div class="summaryGroup">
<table>
<tr>
<td>
<div class="infoBox" id="tests">
<div class="counter">17</div>
<p>tests</p>
</div>
</td>
<td>
<div class="infoBox" id="failures">
<div class="counter">0</div>
<p>failures</p>
</div>
</td>
<td>
<div class="infoBox" id="ignored">
<div class="counter">0</div>
<p>ignored</p>
</div>
</td>
<td>
<div class="infoBox" id="duration">
<div class="counter">0.663s</div>
<p>duration</p>
</div>
</td>
</tr>
</table>
</div>
</td>
<td>
<div class="infoBox success" id="successRate">
<div class="percent">100%</div>
<p>successful</p>
</div>
</td>
</tr>
</table>
</div>
<div class="tab-container">
<ul class="tabLinks">
<li>
<a href="#">Classes</a>
</li>
</ul>
<div class="tab">
<h2>Classes</h2>
<table>
<thead>
<tr>
<th>Class</th>
<th>Tests</th>
<th>Failures</th>
<th>Ignored</th>
<th>Duration</th>
<th>Success rate</th>
</tr>
</thead>
<tr>
<td class="success">
<a href="../classes/com.example.service.CustomerServiceTest.html">CustomerServiceTest</a>
</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>0.559s</td>
<td class="success">100%</td>
</tr>
<tr>
<td class="success">
<a href="../classes/com.example.service.DeliveryServiceTest.html">DeliveryServiceTest</a>
</td>
<td>6</td>
<td>0</td>
<td>0</td>
<td>0.051s</td>
<td class="success">100%</td>
</tr>
<tr>
<td class="success">
<a href="../classes/com.example.service.OrderServiceTest.html">OrderServiceTest</a>
</td>
<td>9</td>
<td>0</td>
<td>0</td>
<td>0.053s</td>
<td class="success">100%</td>
</tr>
</table>
</div>
</div>
<div id="footer">
<p>
<div>
<label class="hidden" id="label-for-line-wrapping-toggle" for="line-wrapping-toggle">Wrap lines
<input id="line-wrapping-toggle" type="checkbox" autocomplete="off"/>
</label>
</div>Generated by
<a href="https://www.gradle.org">Gradle 8.14.3</a> at 13 дек. 2025г., 19:44:16</p>
</div>
</div>
</body>
</html>

View File

@@ -1,5 +1,5 @@
build.artifact=demo
build.group=com.example
build.name=demo
build.time=2025-12-12T19\:06\:15.909391Z
build.time=2025-12-13T16\:00\:42.386508Z
build.version=0.0.1-SNAPSHOT

View File

@@ -1,13 +0,0 @@
INSERT INTO customers (id, name, email, created_at, updated_at)
VALUES
(1, 'Иван Иванов', 'ivan@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(2, 'Петр Петров', 'petr@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(3, 'Мария Сидорова', 'maria@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(4, 'Алексей Козлов', 'alex@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(5, 'Ольга Новикова', 'olga@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO deliveries (id, tracking_number, destination, status, customer_name, created_at, updated_at)
VALUES
(1, 'IVN777777', 'гоголя 34', 'В пути', 'Иван Иванов', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(2, 'IVN012021', 'Москва', 'Принято', 'Петр Петров', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/assets/react.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Delivery Management System</title>
<script type="module" crossorigin src="./assets/index-B-zXX4YT.js"></script>
<script type="module" crossorigin src="./assets/index-DZoZELOR.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BWtOf8p2.css">
</head>
<body>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="com.example.service.CustomerServiceTest" tests="2" skipped="0" failures="0" errors="0" timestamp="2025-12-13T15:44:16.086Z" hostname="MacBook-Air-Oleg.local" time="0.561">
<properties/>
<testcase name="create_WhenValidData_ShouldCreateCustomer()" classname="com.example.service.CustomerServiceTest" time="0.556"/>
<testcase name="findById_WhenCustomerExists_ShouldReturnCustomer()" classname="com.example.service.CustomerServiceTest" time="0.003"/>
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
WARNING: A Java agent has been loaded dynamically (/Users/floom/.gradle/caches/modules-2/files-2.1/net.bytebuddy/byte-buddy-agent/1.17.7/fbf3d6d649ed37fc9e9c59480a05be0a26e3c2da/byte-buddy-agent-1.17.7.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
]]></system-err>
</testsuite>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="com.example.service.DeliveryServiceTest" tests="6" skipped="0" failures="0" errors="0" timestamp="2025-12-13T15:44:16.650Z" hostname="MacBook-Air-Oleg.local" time="0.051">
<properties/>
<testcase name="findById_WhenDeliveryExists_ShouldReturnDelivery()" classname="com.example.service.DeliveryServiceTest" time="0.042"/>
<testcase name="create_WhenValidData_ShouldCreateDelivery()" classname="com.example.service.DeliveryServiceTest" time="0.002"/>
<testcase name="delete_WhenDeliveryNotExists_ShouldReturnFalse()" classname="com.example.service.DeliveryServiceTest" time="0.002"/>
<testcase name="update_WhenDeliveryExists_ShouldUpdateDelivery()" classname="com.example.service.DeliveryServiceTest" time="0.002"/>
<testcase name="delete_WhenDeliveryExists_ShouldDeleteDelivery()" classname="com.example.service.DeliveryServiceTest" time="0.001"/>
<testcase name="findAll_ShouldReturnAllDeliveries()" classname="com.example.service.DeliveryServiceTest" time="0.002"/>
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="com.example.service.OrderServiceTest" tests="9" skipped="0" failures="0" errors="0" timestamp="2025-12-13T15:44:16.702Z" hostname="MacBook-Air-Oleg.local" time="0.055">
<properties/>
<testcase name="create_WhenValidData_ShouldCreateOrder()" classname="com.example.service.OrderServiceTest" time="0.041"/>
<testcase name="findByCustomerId_ShouldReturnCustomerOrders()" classname="com.example.service.OrderServiceTest" time="0.002"/>
<testcase name="create_WhenCustomerNotFound_ShouldThrowException()" classname="com.example.service.OrderServiceTest" time="0.002"/>
<testcase name="findById_WhenOrderExists_ShouldReturnOrder()" classname="com.example.service.OrderServiceTest" time="0.001"/>
<testcase name="findAll_ShouldReturnAllOrders()" classname="com.example.service.OrderServiceTest" time="0.001"/>
<testcase name="delete_WhenOrderNotExists_ShouldReturnFalse()" classname="com.example.service.OrderServiceTest" time="0.001"/>
<testcase name="findByStatus_ShouldReturnOrdersByStatus()" classname="com.example.service.OrderServiceTest" time="0.002"/>
<testcase name="delete_WhenOrderExists_ShouldDeleteOrder()" classname="com.example.service.OrderServiceTest" time="0.001"/>
<testcase name="update_WhenOrderExists_ShouldUpdateOrder()" classname="com.example.service.OrderServiceTest" time="0.002"/>
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,4 @@
Manifest-Version: 1.0
Main-Class: com.example.DemoApplication
Start-Class: com.example.DemoApplication

Binary file not shown.

View File

@@ -65,3 +65,11 @@ Caused by: org.h2.mvstore.MVStoreException: The file is locked: /Users/floom/PIb
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
at org.h2.mvstore.MVStore.<init>(MVStore.java:286)
... 42 more
2025-12-13 03:59:21.102824+04:00 jdbc[13]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Синтаксическая ошибка в выражении SQL "SELECT * FROM ORDERS DELIVERIES [*]CUSTOMERS PRODUCTS"
Syntax error in SQL statement "SELECT * FROM ORDERS DELIVERIES [*]CUSTOMERS PRODUCTS"; SQL statement:
SELECT * FROM ORDERS DELIVERIES CUSTOMERS PRODUCTS [42000-232]
2025-12-13 03:59:33.309067+04:00 jdbc[13]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Синтаксическая ошибка в выражении SQL "SELECT * FROM ORDERS DELIVERIES [*]CUSTOMERS PRODUCTS ORDERS DELIVERIES"
Syntax error in SQL statement "SELECT * FROM ORDERS DELIVERIES [*]CUSTOMERS PRODUCTS ORDERS DELIVERIES"; SQL statement:
SELECT * FROM ORDERS DELIVERIES CUSTOMERS PRODUCTS ORDERS DELIVERIES [42000-232]

View File

@@ -1,3 +1,4 @@
// front/src/components/OrderList.jsx
import { useState, useEffect } from 'react';
import OrderItem from './OrderItem';
import OrderFilter from './OrderFilter';
@@ -12,9 +13,11 @@ function OrderList() {
const [deliveries, setDeliveries] = useState([]);
const [filteredOrders, setFilteredOrders] = useState([]);
const [editingOrder, setEditingOrder] = useState(null);
const [itemsPerPage, setItemsPerPage] = useState(5); // состояние для подсчета элементов
useEffect(() => {
loadCustomersAndDeliveries();
loadOrders(0, itemsPerPage); // itemsPerPage
}, []);
useEffect(() => {
@@ -77,8 +80,7 @@ function OrderList() {
throw new Error(errorText || `HTTP error! status: ${response.status}`);
}
// Перезагружаем данные с текущей страницы
await loadOrders(pagination.page, pagination.size);
await loadOrders(pagination.page, itemsPerPage); // itemsPerPage
setEditingOrder(null);
} catch (error) {
console.error('Ошибка создания заказа:', error);
@@ -109,7 +111,7 @@ function OrderList() {
throw new Error(errorText || `HTTP error! status: ${response.status}`);
}
await loadOrders(pagination.page, pagination.size);
await loadOrders(pagination.page, itemsPerPage); // itemsPerPage
setEditingOrder(null);
} catch (error) {
console.error('Ошибка обновления заказа:', error);
@@ -128,7 +130,7 @@ function OrderList() {
throw new Error(`HTTP error! status: ${response.status}`);
}
await loadOrders(pagination.page, pagination.size);
await loadOrders(pagination.page, itemsPerPage); // itemsPerPage
} catch (error) {
console.error('Ошибка удаления заказа:', error);
alert('Ошибка при удалении заказа: ' + error.message);
@@ -145,7 +147,14 @@ function OrderList() {
};
const handlePageChange = (newPage) => {
loadOrders(newPage, pagination.size);
loadOrders(newPage, itemsPerPage); // itemsPerPage
};
// ФУНКЦИЯ ДЛЯ ДОПКИ
const handleItemsPerPageChange = (e) => {
const newSize = parseInt(e.target.value);
setItemsPerPage(newSize);
loadOrders(0, newSize);
};
if (loading && orders.length === 0) {
@@ -153,8 +162,12 @@ function OrderList() {
}
return (
<div style={{ maxWidth: '1200px', margin: '0 auto' }}>
<h2>Управление заказами</h2>
<div style={{
maxWidth: '1200px',
margin: '0 auto',
padding: '20px'
}}>
<h2 style={{ color: '#6aa1d1' }}>Управление заказами</h2>
<OrderStats orders={orders} />
@@ -167,11 +180,52 @@ function OrderList() {
<OrderFilter onFilterChange={handleFilterChange} />
<div>
<h3>
Список заказов ({pagination.totalElements})
{pagination.totalPages > 1 && ` - Страница ${pagination.page + 1} из ${pagination.totalPages}`}
</h3>
<div style={{ marginTop: '30px' }}>
<div style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '20px',
flexWrap: 'wrap',
gap: '10px'
}}>
<h3 style={{ margin: 0, color: '#6aa1d1' }}>
Список заказов ({pagination.totalElements})
{pagination.totalPages > 1 && ` - Страница ${pagination.page + 1} из ${pagination.totalPages}`}
</h3>
{/* Список с выбором кол-ва записей */}
<div style={{
color: '#666',
fontSize: '14px',
padding: '5px 10px',
backgroundColor: '#f5f5f5',
borderRadius: '4px',
display: 'flex',
alignItems: 'center',
gap: '5px'
}}>
<span>Показывается по</span>
<select
value={itemsPerPage}
onChange={handleItemsPerPageChange}
style={{
padding: '3px 8px',
border: '1px solid #ddd',
borderRadius: '4px',
backgroundColor: 'black',
cursor: 'pointer'
}}
>
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</option>
</select>
<span>заказов на странице</span>
</div>
</div>
{/* Пагинация сверху */}
<Pagination
@@ -180,16 +234,35 @@ function OrderList() {
/>
{filteredOrders.length === 0 ? (
<p>Заказы не найдены</p>
<p style={{
textAlign: 'center',
padding: '40px',
color: '#666',
fontSize: '18px',
backgroundColor: '#f9f9f9',
borderRadius: '8px'
}}>
Заказы не найдены
</p>
) : (
filteredOrders.map(order => (
<OrderItem
key={order.id}
order={order}
onEdit={setEditingOrder}
onDelete={handleDeleteOrder}
/>
))
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(350px, 1fr))',
gap: '20px',
margin: '20px 0'
}}>
{filteredOrders.map(order => (
<div key={order.id} style={{
transition: 'transform 0.2s ease'
}}>
<OrderItem
order={order}
onEdit={setEditingOrder}
onDelete={handleDeleteOrder}
/>
</div>
))}
</div>
)}
{/* Пагинация снизу */}

View File

@@ -6,12 +6,12 @@ export const useOrders = () => {
const [loading, setLoading] = useState(true);
const [pagination, setPagination] = useState({
page: 0,
size: 10,
size: 5,
totalPages: 0,
totalElements: 0
});
const loadOrders = async (page = 0, size = 10) => {
const loadOrders = async (page = 0, size = 5) => {
setLoading(true);
try {
const response = await fetch(`http://localhost:8080/api/orders/paginated?page=${page}&size=${size}`);

View File

@@ -0,0 +1,19 @@
package com.example.controller;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.io.IOException;
@Controller
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev", matchIfMissing = false)
public class DevHomeController {
@GetMapping("/")
public void home(HttpServletResponse response) throws IOException {
// Просто перенаправляем на H2 Console
response.sendRedirect("");
}
}

View File

@@ -1,13 +1,45 @@
package com.example.controller;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerMapping;
import java.io.IOException;
@Controller
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "front", matchIfMissing = false)
public class SpaController {
@RequestMapping(value = {"/", "/orders", "/deliveries", "/customers", "/stats"})
public String redirectToIndex() {
return "forward:/index.html";
@GetMapping("/**")
public ResponseEntity<Resource> forwardToIndex(HttpServletRequest request) throws IOException {
String path = request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();
if (path.startsWith("/api") ||
path.startsWith("/h2-console") ||
path.startsWith("/swagger-ui") ||
path.startsWith("/v3") ||
path.startsWith("/actuator") ||
path.equals("/error") ||
path.contains(".")) {
return ResponseEntity.notFound().build();
}
Resource resource = new ClassPathResource("static" + path);
if (resource.exists()) {
return ResponseEntity.ok(resource);
}
Resource index = new ClassPathResource("static/index.html");
if (index.exists()) {
return ResponseEntity.ok(index);
}
return ResponseEntity.notFound().build();
}
}

View File

@@ -1,13 +0,0 @@
INSERT INTO customers (id, name, email, created_at, updated_at)
VALUES
(1, 'Иван Иванов', 'ivan@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(2, 'Петр Петров', 'petr@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(3, 'Мария Сидорова', 'maria@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(4, 'Алексей Козлов', 'alex@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(5, 'Ольга Новикова', 'olga@mail.ru', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO deliveries (id, tracking_number, destination, status, customer_name, created_at, updated_at)
VALUES
(1, 'IVN777777', 'гоголя 34', 'В пути', 'Иван Иванов', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(2, 'IVN012021', 'Москва', 'Принято', 'Петр Петров', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/assets/react.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Delivery Management System</title>
<script type="module" crossorigin src="./assets/index-B-zXX4YT.js"></script>
<script type="module" crossorigin src="./assets/index-DZoZELOR.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BWtOf8p2.css">
</head>
<body>