From dc403877870dbacd7ee1abe2376a52d0828a29ab Mon Sep 17 00:00:00 2001
From: mrfoxygmfr <mrfoxygmfr@sch9.ru>
Date: Mon, 28 Apr 2025 00:46:14 +0300
Subject: feat: operations controller + pages

---
 .../http/controllers/OperationsController.java     |  78 ++++++++++++++++
 src/main/resources/templates/operationEdit.html    |  10 +++
 src/main/resources/templates/operations.html       | 100 +++++++++++++++++++++
 3 files changed, 188 insertions(+)
 create mode 100644 src/main/java/ru/mrfoxygmfr/warehouse_accounting/http/controllers/OperationsController.java
 create mode 100644 src/main/resources/templates/operationEdit.html
 create mode 100644 src/main/resources/templates/operations.html

diff --git a/src/main/java/ru/mrfoxygmfr/warehouse_accounting/http/controllers/OperationsController.java b/src/main/java/ru/mrfoxygmfr/warehouse_accounting/http/controllers/OperationsController.java
new file mode 100644
index 0000000..f4acdd1
--- /dev/null
+++ b/src/main/java/ru/mrfoxygmfr/warehouse_accounting/http/controllers/OperationsController.java
@@ -0,0 +1,78 @@
+package ru.mrfoxygmfr.warehouse_accounting.http.controllers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import ru.mrfoxygmfr.warehouse_accounting.db.dao.*;
+import ru.mrfoxygmfr.warehouse_accounting.db.dao.specs.OperationSpecs;
+import ru.mrfoxygmfr.warehouse_accounting.db.models.*;
+
+import java.util.List;
+
+@Controller
+public class OperationsController {
+    @Autowired
+    private OperationDAO operationDAO;
+
+    @GetMapping(value = { "/", "/index", "/operations"})
+    public String operations(@RequestParam(name = "operationType", required = false) OperationType type,
+                             @RequestParam(name = "operationStatus", required = false) OperationStatus status,
+                             @RequestParam(name = "operationProductName", required = false) String productName,
+                             @RequestParam(name = "operationPartnerName", required = false) String partnerName,
+                             Model model) {
+        Specification<Operation> spec = Specification.where(null);
+        if (type != null) {
+            spec = spec.and(OperationSpecs.operationTypeEqual(type));
+            model.addAttribute("operationTypeFilter", type.toString());
+        }
+        if (status != null) {
+            spec = spec.and(OperationSpecs.operationStatusEqual(status));
+            model.addAttribute("operationStatusFilter", status.toString());
+        }
+        if (productName != null) {
+            spec = spec.and(OperationSpecs.operationProductsContainsLike(productName));
+            model.addAttribute("operationProductNameFilter", productName);
+        }
+        if (partnerName != null) {
+            spec = spec.and(OperationSpecs.operationPartnerNameLike(partnerName));
+            model.addAttribute("operationPartnerNameFilter", partnerName);
+        }
+        List<Operation> operations = operationDAO.findAll(spec);
+        model.addAttribute("operations", operations);
+        return "operations";
+    }
+
+    @GetMapping("operation")
+    public String operation(@RequestParam(name = "id") Integer id, Model model) {
+        Operation operation = operationDAO.findById(id).orElseThrow();
+        model.addAttribute("operation", operation);
+        return "operationEdit";
+    }
+
+    @PostMapping("operation")
+    public String operation(
+            @RequestParam(name = "id") Integer id,
+            @RequestParam(name = "type") String type,
+            @RequestParam(name = "status") String status,
+            @RequestParam(name = "partner_id") Integer partnerId,
+            @RequestParam(name = "responsible_id") Integer responsibleId,
+            Model model) {
+        Operation operation;
+        if (id != null) {
+            operation = operationDAO.findById(id).orElseThrow();
+        } else {
+            operation = new Operation();
+        }
+
+        return String.format("redirect:/operation?id=%d", operation.getId());
+    }
+
+    @GetMapping("newOperation")
+    public String newOperation(Model model) {
+        return "operationEdit";
+    }
+}
diff --git a/src/main/resources/templates/operationEdit.html b/src/main/resources/templates/operationEdit.html
new file mode 100644
index 0000000..566549b
--- /dev/null
+++ b/src/main/resources/templates/operationEdit.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/operations.html b/src/main/resources/templates/operations.html
new file mode 100644
index 0000000..e310992
--- /dev/null
+++ b/src/main/resources/templates/operations.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" lang="en">
+<div th:replace="~{common :: head}"></div>
+
+<body>
+<div th:replace="~{common :: page-header}"></div>
+
+<div class="indent">
+    <form method="get" action="/newOperation">
+        <button id="newOperationBtn" type="submit" class="btn btn-primary">Создать новую операцию</button>
+    </form>
+    <br>
+
+    <form method="get" action="/operations">
+        <table class="table">
+            <thead class="theme-dark">
+            <tr>
+                <th colspan="6">Фильтры</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td>Тип</td>
+                <td>
+                    <select id="operationTypeFilter" name="operationType">
+                        <option value="">Любой</option>
+                        <option th:value="'SUPPLY'" th:text="SUPPLY" th:selected="${operationTypeFilter == 'SUPPLY'}"></option>
+                        <option th:value="'ISSUE'" th:text="ISSUE" th:selected="${operationTypeFilter == 'ISSUE'}"></option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <td>Статус</td>
+                <td>
+                    <select id="operationStatusFilter" name="operationStatus">
+                        <option value="">Любой</option>
+                        <option th:value="'CHECKOUT'" th:text="CHECKOUT" th:selected="${operationStatusFilter == 'CHECKOUT'}"></option>
+                        <option th:value="'APPROVAL'" th:text="APPROVAL" th:selected="${operationStatusFilter == 'APPROVAL'}"></option>
+                        <option th:value="'READY'" th:text="READY" th:selected="${operationStatusFilter == 'READY'}"></option>
+                        <option th:value="'EXECUTED'" th:text="EXECUTED" th:selected="${operationStatusFilter == 'EXECUTED'}"></option>
+                        <option th:value="'CANCELLED'" th:text="CANCELLED" th:selected="${operationStatusFilter == 'CANCELLED'}"></option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <td>Включает товар с названием</td>
+                <td>
+                    <input type="text" id="operationProductNameFilter" name="operationProductName" th:value="${operationProductNameFilter}">
+                </td>
+            </tr>
+            <tr>
+                <td>Партнер (название)</td>
+                <td>
+                    <input type="text" id="operationPartnerNameFilter" name="operationPartnerName" th:value="${operationPartnerNameFilter}">
+                </td>
+            </tr>
+            <tr>
+                <td colspan="6"><input id="saveBtn" type="submit" value="Применить" class="btn btn-primary"></td>
+            </tr>
+            </tbody>
+        </table>
+    </form>
+
+    <table class="table table-bordered table-warning">
+        <thead class="thead-dark">
+        <tr>
+            <th scope="col">№</th>
+            <th scope="col">Тип</th>
+            <th scope="col">Партнер</th>
+            <th scope="col">Статус</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr th:if="${operations.isEmpty()}">
+            <td colspan="6">Данному фильтру не удовлетворяет ни одной операции.</td>
+        </tr>
+        <tr th:each="operation : ${operations}">
+            <td>
+                <a th:href="'/operation?id=' + ${operation.getId()}">
+                    <span th:text="${operation.getId()}"></span>
+                </a>
+            </td>
+            <td>
+                <span th:text="${operation.getType()}"></span>
+            </td>
+            <td>
+                <span th:text="${operation.getPartner().getName()}"></span>
+            </td>
+            <td>
+                <span th:text="${operation.getStatus()}"></span>
+            </td>
+        </tr>
+        </tbody>
+    </table>
+</div>
+
+<div th:replace="~{common :: site-footer}"></div>
+<div th:replace="~{common :: site-script}"></div>
+</body>
+</html>
\ No newline at end of file
-- 
cgit mrf-deployment