From ad83789b077bbac744c82281f9564ff0813460f8 Mon Sep 17 00:00:00 2001 From: freehyeon Date: Thu, 12 Dec 2024 17:08:44 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8C=88=EB=BD=95=ED=95=9C=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 한수씨가 원함 --- .../stockm8/controller/OrderController.java | 125 +-- .../com/stockm8/domain/vo/OrderItemVO.java | 9 +- .../java/com/stockm8/domain/vo/OrderVO.java | 14 +- .../java/com/stockm8/domain/vo/StockVO.java | 62 +- .../java/com/stockm8/domain/vo/StockVO2.java | 58 ++ .../com/stockm8/persistence/OrderDAO.java | 14 +- .../com/stockm8/persistence/OrderDAOImpl.java | 43 +- .../com/stockm8/service/OrderService.java | 12 +- .../com/stockm8/service/OrderServiceImpl.java | 22 +- .../main/resources/mappers/OrderMapper.xml | 102 ++- .../webapp/WEB-INF/views/order/register.jsp | 676 ++++++++++++----- .../webapp/WEB-INF/views/order/register2.jsp | 399 ++++++++++ .../webapp/WEB-INF/views/order/register3.jsp | 713 ++++++++++++++++++ .../webapp/WEB-INF/views/product/register.jsp | 3 + stockMate/src/main/webapp/css/OrderStyle.css | 425 +++++++---- 15 files changed, 2169 insertions(+), 508 deletions(-) create mode 100644 stockMate/src/main/java/com/stockm8/domain/vo/StockVO2.java create mode 100644 stockMate/src/main/webapp/WEB-INF/views/order/register2.jsp create mode 100644 stockMate/src/main/webapp/WEB-INF/views/order/register3.jsp diff --git a/stockMate/src/main/java/com/stockm8/controller/OrderController.java b/stockMate/src/main/java/com/stockm8/controller/OrderController.java index 01f642a..bdcefe6 100644 --- a/stockMate/src/main/java/com/stockm8/controller/OrderController.java +++ b/stockMate/src/main/java/com/stockm8/controller/OrderController.java @@ -1,20 +1,28 @@ package com.stockm8.controller; +import java.util.HashMap; import java.util.List; - +import java.util.Map; import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.OrderItemVO; +import com.stockm8.domain.vo.OrderVO; +import com.stockm8.domain.vo.StockVO; +import com.stockm8.domain.vo.UserVO; import com.stockm8.service.OrderService; +import com.stockm8.service.UserService; @Controller @RequestMapping(value = "/order") @@ -24,72 +32,95 @@ public class OrderController { @Inject private OrderService orderService; + @Inject + private UserService userService; /** - * 주문 등록 페이지 표시 + * 주문 등록 페이지 표시(GET) * http://localhost:8088/order/register + * @param model Spring MVC 모델 객체 + * @return 주문 등록 페이지의 뷰 이름 + * */ @RequestMapping(value = "/register", method = RequestMethod.GET) - public String orderRegisterGET(Model model) throws Exception { + public String orderRegisterGET(Model model, HttpServletRequest request) throws Exception { logger.info("orderRegisterGET() 호출"); - return "order/register"; // WEB-INF/views/Order/OrderRegister.jsp를 찾음 + +// // 세션에서 userId 가져오기 +// HttpSession session = request.getSession(false); +// Long userId = (session != null) ? (Long)session.getAttribute("userId") : null; +// +// // userId로 사용자 정보 조회 +// UserVO user = userService.getUserById(userId); +// int businessId = user.getBusinessId(); + + return "order/register"; } -// /** -// * 주문 등록 처리 -// */ -// @RequestMapping(value = "/register", method = RequestMethod.POST) -// @ResponseBody -// public String OrderRegisterPOST(@RequestBody OrderVO vo) throws Exception { -// logger.info("OrderRegisterPOST() 호출"); -// logger.info("주문 정보: {}", vo); -// -// try { -// // 현재 시간 설정 -// Timestamp currentTime = new Timestamp(System.currentTimeMillis()); -// vo.setCreatedAt(currentTime); -// vo.setUpdatedAt(currentTime); -// vo.setStatus("pending"); -// -// // 주문항목들의 시간 설정 -// if (vo.getOrderItems() != null) { -// for (OrderItemVO item : vo.getOrderItems()) { -// item.setCreatedAt(currentTime); -// item.setUpdatedAt(currentTime); -// } -// } -// -// // 주문 등록 -// oSer.insertOrder(vo); -// -// logger.info("주문등록 성공! 주문번호: {}", vo.getOrderNumber()); -// return "success"; -// -// } catch (Exception e) { -// logger.error("주문등록 실패: {}", e.getMessage()); -// throw e; -// } -// } + /** + * 주문 등록 처리(POST) + * http://localhost:8088/order/register + * @param order 클라이언트에서 전송된 주문 정보 + * @return 처리 결과를 담은 Map 객체 + * @throws Exception 주문 처리 중 발생하는 예외 + * + */ + @RequestMapping(value = "/register", + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Map orderRegisterPOST(@RequestBody OrderVO order) throws Exception { + logger.info("orderRegisterPOST() 호출"); + logger.info("주문 정보: " + order); + + // 주문에 orderItems가 있는지 확인(유효성 검사) + if (order.getOrderItems() == null || order.getOrderItems().isEmpty()) { + throw new IllegalArgumentException("주문 항목이 누락되었습니다."); + } + + + // 주문번호 생성 및 설정 + String orderNumber = orderService.generateOrderNumber(); + order.setOrderNumber(orderNumber); + + // 첫 번째 주문 항목 가져오기 + OrderItemVO orderItem = order.getOrderItems().get(0); + + // 주문 처리 + orderService.insertOrder(order); + + // 응답 생성 + Map response = new HashMap<>(); + response.put("status", "success"); + response.put("message", "주문이 성공적으로 등록되었습니다."); + response.put("orderNumber", orderNumber); + + return response; + } /** - * 전체 제품 목록 조회 + * 가용 재고 목록 조회 + * http://localhost:8088/order/findAvailableStocks */ - @RequestMapping(value = "/findAllProducts", + @RequestMapping(value = "/findAvailableStocks", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public List findAllProducts() throws Exception { - logger.info("findAllProducts() 호출"); - return orderService.findAllProducts(); + public List findAvailableStocks() throws Exception { + logger.info("findAvailableStocks() 호출"); + return orderService.findAvailableStocks(); } /** * 주문번호 생성 + * http://localhost:8088/order/generateOrderNumber */ - @RequestMapping(value = "/generateOrderNumber", method = RequestMethod.GET) + @RequestMapping(value = "/generateOrderNumber", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public String generateOrderNumber() throws Exception { logger.info("generateOrderNumber() 호출"); return orderService.generateOrderNumber(); } -} +} //OrderController \ No newline at end of file diff --git a/stockMate/src/main/java/com/stockm8/domain/vo/OrderItemVO.java b/stockMate/src/main/java/com/stockm8/domain/vo/OrderItemVO.java index a5c431c..1f07a2b 100644 --- a/stockMate/src/main/java/com/stockm8/domain/vo/OrderItemVO.java +++ b/stockMate/src/main/java/com/stockm8/domain/vo/OrderItemVO.java @@ -9,10 +9,11 @@ public class OrderItemVO { private int orderItemId; // 주문 상세 항목 고유 ID private int orderId; // 주문 ID private int productId; // 주문 상품 ID + private int warehouseId; // 창고 ID private int quantity; // 주문 수량 private double unitPrice; // 제품 단가 - private double subtotalPrice; // 해당 상품의 총 금액 (quantity * unitPrice) - private Timestamp createdAt; // 주문 생성 날짜 - private Timestamp updatedAt; // 주문 수정 날짜 private String remarks; // 특정 상품에 대한 비고 사항 -} + private double stotalPrice; // 주문 1건의 전체 총 금액 + private Timestamp createdAt; // 생성 시간 + private Timestamp updatedAt; // 수정 시간 +} //OrderItemVO diff --git a/stockMate/src/main/java/com/stockm8/domain/vo/OrderVO.java b/stockMate/src/main/java/com/stockm8/domain/vo/OrderVO.java index 4db7bb4..4bc49b7 100644 --- a/stockMate/src/main/java/com/stockm8/domain/vo/OrderVO.java +++ b/stockMate/src/main/java/com/stockm8/domain/vo/OrderVO.java @@ -1,20 +1,24 @@ package com.stockm8.domain.vo; import java.sql.Timestamp; +import java.util.List; + import lombok.Data; @Data public class OrderVO { - private int orderId; // 주문 고유 ID - private String orderNumber; // 주문 번호 - private int warehouseId; // 주문 대상 창고 + private int orderId; // 주문 고유 ID + private String orderNumber; // 주문 번호 (예: ORD-YYYYMMDD-001) private double totalPrice; // 주문 전체 총 금액 private int createdBy; // 주문을 생성한 사용자 ID private Timestamp createdAt; // 주문 생성 날짜 private Timestamp updatedAt; // 주문 수정 날짜 private String status; // 주문 상태 (pending, confirmed, cancelled) - - + + private List orderItems; // 주문 항목 리스트 + + + }// OrderVO diff --git a/stockMate/src/main/java/com/stockm8/domain/vo/StockVO.java b/stockMate/src/main/java/com/stockm8/domain/vo/StockVO.java index 53ae9c1..c89d2dc 100644 --- a/stockMate/src/main/java/com/stockm8/domain/vo/StockVO.java +++ b/stockMate/src/main/java/com/stockm8/domain/vo/StockVO.java @@ -6,53 +6,19 @@ @Data public class StockVO { - private int stockId; // 고유 재고 ID - private int productId; // 상품 ID - private int warehouseId; // 창고 ID - private int businessId; // 사업자 ID - - private int totalQuantity; // 창고 내 총 재고 수량 - private int reservedQuantity; // 예약된 수량 - - // availableStock은 totalQuantity - reservedQuantity로 계산 - private int availableStock; // 사용 가능한 재고 (totalQuantity - reservedQuantity) - - // totalQuantity에 대한 getter - public int getTotalQuantity() { - return totalQuantity; - } - - public void setTotalQuantity(int totalQuantity) { - this.totalQuantity = totalQuantity; - updateAvailableStock(); // 값이 변경되면 availableStock을 자동으로 업데이트 - } - - // reservedQuantity에 대한 getter - public int getReservedQuantity() { - return reservedQuantity; - } - - public void setReservedQuantity(int reservedQuantity) { - this.reservedQuantity = reservedQuantity; - updateAvailableStock(); // 값이 변경되면 availableStock을 자동으로 업데이트 - } - - // availableStock을 계산하는 getter - public int getAvailableStock() { - return availableStock; - } - - // availableStock 계산 - private void updateAvailableStock() { - this.availableStock = this.totalQuantity - this.reservedQuantity; - } - - private Timestamp createdAt; // 재고 등록 시간 - private Timestamp updatedAt; // 최근 수정 시간 - - private String description; // 재고 설명 - - private String dscription; // 재고 설명 - private Boolean isDeleted; // 논리 삭제 여부 (true: 삭제됨, false: 활성) + private int stockId; // 고유 재고 ID + private int productId; // 상품 ID + private int warehouseId; // 창고 ID + private int businessId; // 사업자 ID + private int totalQuantity; // 창고 내 총 재고 수량 + private int reservedQuantity; // 예약된 수량 + private int availableStock; // 사용 가능한 재고 + private Timestamp updatedAt; // 최근 수정 시간 + private Timestamp createdAt; // 재고 등록 일자 + private String description; // 재고 설명 + private boolean isDeleted; // 논리 삭제 여부 + + private ProductVO product; // 상품 정보 (JOIN 용) + private String warehouseName; // 창고명 (JOIN 용) } diff --git a/stockMate/src/main/java/com/stockm8/domain/vo/StockVO2.java b/stockMate/src/main/java/com/stockm8/domain/vo/StockVO2.java new file mode 100644 index 0000000..f4a5821 --- /dev/null +++ b/stockMate/src/main/java/com/stockm8/domain/vo/StockVO2.java @@ -0,0 +1,58 @@ +package com.stockm8.domain.vo; + +import java.sql.Timestamp; + +import lombok.Data; + +@Data +public class StockVO2 { + private int stockId; // 고유 재고 ID + private int productId; // 상품 ID + private int warehouseId; // 창고 ID + private int businessId; // 사업자 ID + + private int totalQuantity; // 창고 내 총 재고 수량 + private int reservedQuantity; // 예약된 수량 + + // availableStock은 totalQuantity - reservedQuantity로 계산 + private int availableStock; // 사용 가능한 재고 (totalQuantity - reservedQuantity) + + // totalQuantity에 대한 getter + public int getTotalQuantity() { + return totalQuantity; + } + + public void setTotalQuantity(int totalQuantity) { + this.totalQuantity = totalQuantity; + updateAvailableStock(); // 값이 변경되면 availableStock을 자동으로 업데이트 + } + + // reservedQuantity에 대한 getter + public int getReservedQuantity() { + return reservedQuantity; + } + + public void setReservedQuantity(int reservedQuantity) { + this.reservedQuantity = reservedQuantity; + updateAvailableStock(); // 값이 변경되면 availableStock을 자동으로 업데이트 + } + + // availableStock을 계산하는 getter + public int getAvailableStock() { + return availableStock; + } + + // availableStock 계산 + private void updateAvailableStock() { + this.availableStock = this.totalQuantity - this.reservedQuantity; + } + + private Timestamp createdAt; // 재고 등록 시간 + private Timestamp updatedAt; // 최근 수정 시간 + + private String description; // 재고 설명 + + private String dscription; // 재고 설명 + private Boolean isDeleted; // 논리 삭제 여부 (true: 삭제됨, false: 활성) + +} diff --git a/stockMate/src/main/java/com/stockm8/persistence/OrderDAO.java b/stockMate/src/main/java/com/stockm8/persistence/OrderDAO.java index 4ba1fa2..8d4d4dd 100644 --- a/stockMate/src/main/java/com/stockm8/persistence/OrderDAO.java +++ b/stockMate/src/main/java/com/stockm8/persistence/OrderDAO.java @@ -5,6 +5,7 @@ import com.stockm8.domain.vo.OrderItemVO; import com.stockm8.domain.vo.OrderVO; import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.StockVO; public interface OrderDAO { @@ -14,9 +15,16 @@ public interface OrderDAO { // 주문 항목 등록 public void insertOrderItem(OrderItemVO orderItem) throws Exception; - // 모든 제품 목록 조회 - public List findAllProducts() throws Exception; + // 주문과 주문항목을 한번에 처리 + public void insertOrderWithItems(OrderVO order) throws Exception; + + // 모든 재고 목록 조회 + public List findAvailableStocks() throws Exception; //주문번호 생성 public String generateOrderNumber() throws Exception; -} + + + // 재고의 예약 수량을 업데이트.. 이거는 뭐지..>> + public void updateStockReservedQuantity(int stockId, int quantity) throws Exception; +} // OrderDAO diff --git a/stockMate/src/main/java/com/stockm8/persistence/OrderDAOImpl.java b/stockMate/src/main/java/com/stockm8/persistence/OrderDAOImpl.java index 1b8ea52..4431d58 100644 --- a/stockMate/src/main/java/com/stockm8/persistence/OrderDAOImpl.java +++ b/stockMate/src/main/java/com/stockm8/persistence/OrderDAOImpl.java @@ -14,6 +14,7 @@ import com.stockm8.domain.vo.OrderItemVO; import com.stockm8.domain.vo.OrderVO; import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.StockVO; @Repository public class OrderDAOImpl implements OrderDAO { @@ -27,6 +28,7 @@ public class OrderDAOImpl implements OrderDAO { @Override public void insertOrder(OrderVO order) throws Exception { + sqlSession.insert(NAMESPACE + "insertOrder", order); } @@ -36,25 +38,56 @@ public void insertOrderItem(OrderItemVO orderItem) throws Exception { } @Override - public List findAllProducts() throws Exception { - return sqlSession.selectList(NAMESPACE + "findAllProducts"); + public List findAvailableStocks() throws Exception { + return sqlSession.selectList(NAMESPACE + "findAvailableStocks"); } @Override - public String generateOrderNumber() throws Exception { + public void updateStockReservedQuantity(int stockId, int quantity) throws Exception { + sqlSession.update(NAMESPACE + "updateStockReservedQuantity", + new java.util.HashMap() {{ + put("stockId", stockId); + put("quantity", quantity); + }} + ); + } + + /** + * 새로운 주문번호 생성 + * 동시성 제어를 위해 synchronized 키워드 사용 + * 형식: ORD-YYYYMMDD-### + */ + + @Override + public synchronized String generateOrderNumber() throws Exception { + // 현재 날짜 형식 지정 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String date = sdf.format(new Date()); // 해당 날짜의 마지막 주문번호 조회 String lastOrderNumber = sqlSession.selectOne(NAMESPACE + "getLastOrderNumberForDate", date); + // 시퀀스 번호 생성 int sequence = 1; if (lastOrderNumber != null && !lastOrderNumber.isEmpty()) { - // 마지막 주문번호에서 시퀀스 추출 (ORD-20241210-001에서 001 부분) String sequenceStr = lastOrderNumber.substring(lastOrderNumber.lastIndexOf("-") + 1); sequence = Integer.parseInt(sequenceStr) + 1; } + // 주문번호 생성 및 반환 return String.format("ORD-%s-%03d", date, sequence); } -} \ No newline at end of file + + @Override + public void insertOrderWithItems(OrderVO order) throws Exception { + // 주문 마스터 등록(Order 와 Orderitem 을 한번에 처리) + sqlSession.insert(NAMESPACE + "insertOrder", order); + + // 생성된 주문 ID로 각 주문 항목 등록 + for (OrderItemVO item : order.getOrderItems()) { + item.setOrderId(order.getOrderId()); + sqlSession.insert(NAMESPACE + "insertOrderItem", item); + } + + } +} // OrderImpl \ No newline at end of file diff --git a/stockMate/src/main/java/com/stockm8/service/OrderService.java b/stockMate/src/main/java/com/stockm8/service/OrderService.java index 73b140c..da1c567 100644 --- a/stockMate/src/main/java/com/stockm8/service/OrderService.java +++ b/stockMate/src/main/java/com/stockm8/service/OrderService.java @@ -4,15 +4,17 @@ import com.stockm8.domain.vo.OrderItemVO; import com.stockm8.domain.vo.OrderVO; -import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.StockVO; public interface OrderService { // 주문 등록 (주문항목 포함) - public void insertOrder(OrderVO order, OrderItemVO orderItem) throws Exception; + public void insertOrder(OrderVO order) throws Exception; - // 모든 제품 목록 조회 - public List findAllProducts() throws Exception; + // 재고 목록 조회 + public List findAvailableStocks() throws Exception; // 주문번호 생성 public String generateOrderNumber() throws Exception; -} \ No newline at end of file + +} //OrderService diff --git a/stockMate/src/main/java/com/stockm8/service/OrderServiceImpl.java b/stockMate/src/main/java/com/stockm8/service/OrderServiceImpl.java index c0260df..6d8acbb 100644 --- a/stockMate/src/main/java/com/stockm8/service/OrderServiceImpl.java +++ b/stockMate/src/main/java/com/stockm8/service/OrderServiceImpl.java @@ -10,6 +10,7 @@ import com.stockm8.domain.vo.OrderItemVO; import com.stockm8.domain.vo.OrderVO; // OrderItemVO import 제거 import com.stockm8.domain.vo.ProductVO; +import com.stockm8.domain.vo.StockVO; import com.stockm8.persistence.OrderDAO; @Service @@ -22,15 +23,12 @@ public class OrderServiceImpl implements OrderService { @Override @Transactional - public void insertOrder(OrderVO order, OrderItemVO orderItem) throws Exception { - // 주문 등록 - odao.insertOrder(order); - - // 생성된 주문 ID를 주문항목에 설정 - orderItem.setOrderId(order.getOrderId()); - - // 주문항목 등록 - odao.insertOrderItem(orderItem); + public void insertOrder(OrderVO order) throws Exception { + odao.insertOrderWithItems(order); + } + @Override + public List findAvailableStocks() throws Exception { + return odao.findAvailableStocks(); } @Override @@ -38,8 +36,4 @@ public String generateOrderNumber() throws Exception { return odao.generateOrderNumber(); } - @Override - public List findAllProducts() throws Exception { - return odao.findAllProducts(); - } -} \ No newline at end of file +} //OrderServiceImpl \ No newline at end of file diff --git a/stockMate/src/main/resources/mappers/OrderMapper.xml b/stockMate/src/main/resources/mappers/OrderMapper.xml index 8136a88..91cff9c 100644 --- a/stockMate/src/main/resources/mappers/OrderMapper.xml +++ b/stockMate/src/main/resources/mappers/OrderMapper.xml @@ -4,18 +4,69 @@ "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO test_orders ( order_number, - warehouse_id, total_price, created_by, created_at, status ) VALUES ( #{orderNumber}, - #{warehouseId}, #{totalPrice}, #{createdBy}, NOW(), @@ -28,47 +79,34 @@ - INSERT INTO order_items ( + INSERT INTO test_order_items ( order_id, product_id, + warehouse_id, quantity, unit_price, - subtotal_price, - created_at, - remarks + remarks, + created_at + ) VALUES ( #{orderId}, #{productId}, + #{warehouseId}, #{quantity}, #{unitPrice}, - #{subtotalPrice}, - NOW(), - #{remarks} + #{remarks}, + NOW() + ) - - - + + + UPDATE test_stocks + SET reserved_quantity = reserved_quantity + #{quantity} + WHERE stock_id = #{stockId} + + -
+
-
-
- - -
-
-
-
제품 정보
+ +
+
+ + +
+ +
+ + +
+
+
+ 재고 정보 + +
+
-
- - -
+ + +
- - + +
+
+ + +
+
+
+ +
+
- + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
@@ -69,29 +108,28 @@
- - + +
- - + +
- - 단가 +
- - + +
@@ -99,47 +137,65 @@
- - + +
- - + +
+
총계 정보
+
+
+
+
+ + +
+
+
+
+
+ -
+ +
- +
- +
+ + + + +
+ + +
+ +
+ + + + + + + + \ No newline at end of file diff --git a/stockMate/src/main/webapp/WEB-INF/views/order/register3.jsp b/stockMate/src/main/webapp/WEB-INF/views/order/register3.jsp new file mode 100644 index 0000000..120e67d --- /dev/null +++ b/stockMate/src/main/webapp/WEB-INF/views/order/register3.jsp @@ -0,0 +1,713 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + 주문 발주 페이지 + + + + + +
+

주문 발주

+ +
+ +
+
주문 정보
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ + +
+ + +
+ +
+ + +
+
총계 정보
+
+
+
+
+ + +
+
+
+
+
+ + + + + +
+ + +
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/stockMate/src/main/webapp/WEB-INF/views/product/register.jsp b/stockMate/src/main/webapp/WEB-INF/views/product/register.jsp index ad3a0e6..6bf1818 100644 --- a/stockMate/src/main/webapp/WEB-INF/views/product/register.jsp +++ b/stockMate/src/main/webapp/WEB-INF/views/product/register.jsp @@ -42,6 +42,9 @@ + diff --git a/stockMate/src/main/webapp/css/OrderStyle.css b/stockMate/src/main/webapp/css/OrderStyle.css index c2d6ed2..969278b 100644 --- a/stockMate/src/main/webapp/css/OrderStyle.css +++ b/stockMate/src/main/webapp/css/OrderStyle.css @@ -1,159 +1,268 @@ @charset "UTF-8"; - \ No newline at end of file +/* Reset & Base Styles */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: Arial, sans-serif; + line-height: 1.6; + padding: 20px; +} + +/* Layout */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +/* Card Styles */ +.card { + border: 1px solid #ddd; + border-radius: 4px; + margin-bottom: 20px; + background: white; /* 추가: 배경색 명시 */ + box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* 추가: 그림자 효과 */ +} + +.card-header { + background: #f8f9fa; + padding: 10px 15px; + border-bottom: 1px solid #ddd; + font-weight: bold; /* 추가: 헤더 텍스트 강조 */ +} + +.card-body { + padding: 15px; +} + +/* Grid System */ +.row { + display: flex; + flex-wrap: wrap; + margin: -10px; +} + +.col-md-3, .col-md-4, .col-md-6, .col-12 { + padding: 10px; +} + +.col-md-3 { width: 25%; } +.col-md-4 { width: 33.333%; } +.col-md-6 { width: 50%; } +.col-12 { width: 100%; } + +/* Form Elements */ +.form-group { + margin-bottom: 15px; +} + +.form-label { + display: block; + margin-bottom: 5px; + font-weight: bold; + color: #333; /* 추가: 라벨 색상 */ +} + +.required-label::after { + content: " *"; + color: red; +} + +.form-control { + width: 100%; + padding: 8px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 14px; + transition: border-color 0.3s; /* 추가: 부드러운 전환 효과 */ +} + +.form-control:focus { + border-color: #0d6efd; + outline: none; + box-shadow: 0 0 0 2px rgba(13,110,253,0.25); +} + +/* Buttons */ +.btn { + display: inline-block; + padding: 8px 16px; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + transition: all 0.3s; /* 추가: 버튼 호버 효과 */ +} + +.btn:hover { + opacity: 0.9; + transform: translateY(-1px); +} + +.btn-primary { + background: #0d6efd; + color: white; +} + +.btn-success { + background: #198754; + color: white; +} + +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:disabled { + background: #e9acb3; + cursor: not-allowed; + opacity: 0.7; +} + +/* Utility Classes */ +.text-center { + text-align: center; +} + +/* Modal Styles */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1050; + opacity: 0; + transition: opacity 0.3s; /* 추가: 모달 페이드 효과 */ +} + +.modal.show { + display: block !important; + opacity: 1; +} + +.modal-dialog { + position: relative; + width: 100%; + max-width: 2000px; + margin: 50px auto; + top: 50%; + transform: translateY(-50%); + display: block; +} + +.modal-content { + background: white; + border-radius: 4px; + box-shadow: 0 4px 6px rgba(0,0,0,0.1); /* 추가: 모달 그림자 */ +} + +.modal-header { + padding: 15px; + border-bottom: 1px solid #ddd; + display: flex; + justify-content: space-between; + align-items: center; + background: #f8f9fa; /* 추가: 헤더 배경색 */ +} + +.modal-body { + padding: 15px; + max-height: 70vh; + overflow-y: auto; +} + +.btn-close { + background: none; + border: none; + font-size: 20px; + cursor: pointer; + padding: 5px; + transition: transform 0.2s; /* 추가: 닫기 버튼 호버 효과 */ +} + +.btn-close:hover { + transform: scale(1.1); +} + +/* Table Styles */ +table { + width: 100%; + border-collapse: collapse; +} + +th, td { + padding: 8px; + border: 1px solid #ddd; + text-align: left; +} + +th { + background: #f8f9fa; /* 추가: 테이블 헤더 배경색 */ + font-weight: bold; +} + +.stock-table { + margin-top: 10px; + width: 100%; + overflow-x: auto; + white-space: nowrap; +} + +.stock-table tr:hover { + background-color: #f5f5f5; /* 추가: 행 호버 효과 */ +} + +.product-table { + font-size: 0.9rem; +} + +/* Custom Components */ +.stock-info-card { + margin-bottom: 20px; + position: relative; /* 추가: 상대 위치 지정 */ +} + + (max-width: 768px) { + .col-md-3, .col-md-4, .col-md-6 { + width: 100%; + } + + + .btn { + width: 100%; + margin-bottom: 10px; + } +} + +/* 추가: 로딩 인디케이터 스타일 */ +.loading { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.8); + display: flex; + justify-content: center; + align-items: center; + z-index: 2000; +} + +.loading::after { + content: "로딩중..."; + font-size: 1.2rem; + color: #0d6efd; +} \ No newline at end of file