@@ -0,0 +1,153 @@
+package store.custom.service.editor;
+
+import static store.custom.constants.StringConstants.AFTER_PROMOTION_END;
+import static store.custom.constants.StringConstants.BEFORE_PROMOTION_START;
+import static store.custom.constants.StringConstants.RESPONSE_NO;
+import static store.custom.constants.StringConstants.RESPONSE_YES;
+
+import camp.nextstep.edu.missionutils.DateTimes;
+import java.time.LocalDate;
+import store.custom.model.PromotionResult.PromotionResult;
+import store.custom.model.order.OrderSheet;
+import store.custom.model.order.OrderedProduct;
+import store.custom.model.product.Product;
+import store.custom.model.product.Products;
+import store.custom.model.promotion.Promotion;
+import store.custom.model.promotion.Promotions;
+
+public class OrderSheetEditor {
+    // 주문서 초기 설정: 가격과 프로모션 정보 추가
+    public void addPromotionInfo(Products productCatalog, Promotions promotions, OrderSheet orderSheet) {
+        for (OrderedProduct orderProduct : orderSheet.getOrderSheet()) {
+            setProductPriceAndPromotion(orderProduct, productCatalog); // 총 가격과 프로모션 추가
+            setPromotionDetails(orderProduct, promotions); // 프로모션 관련 정보 추가
+        }
+    }
+
+    private void setProductPriceAndPromotion(OrderedProduct orderProduct, Products productCatalog) {
+        Product product = findOrderedProduct(orderProduct, productCatalog);
+        if (product != null) {
+            orderProduct.setTotalPrice(product.getPrice() * orderProduct.getQuantity());
+            setPromotionIfExist(orderProduct, product);
+        }
+    }
+
+    private Product findOrderedProduct(OrderedProduct orderProduct, Products productCatalog) {
+        for (Product product : productCatalog.getProducts()) {
+            if (product.getName().equals(orderProduct.getName())) {
+                return product;
+            }
+        }
+        return null;
+    }
+
+    private void setPromotionIfExist(OrderedProduct orderProduct, Product product) {
+        if (product.getPromotion() != null) {
+            orderProduct.setPromotion(product.getPromotion());
+        }
+    }
+
+    private void setPromotionDetails(OrderedProduct orderProduct, Promotions promotions) {
+        if (orderProduct.getPromotion() != null) {
+            LocalDate today = DateTimes.now().toLocalDate();
+            Promotion promotion = findPromotion(orderProduct.getPromotion(), promotions);
+            if (promotion != null) {
+                applyPromotionDates(orderProduct, today, promotion);
+                applyPromotionBuyAndGet(orderProduct, promotion);
+            }
+        }
+    }
+
+    private Promotion findPromotion(String promotionName, Promotions promotions) {
+        for (Promotion promotion : promotions.getPromotions()) {
+            if (promotion.getName().equals(promotionName)) {
+                return promotion;
+            }
+        }
+        return null;
+    }
+
+    private void applyPromotionDates(OrderedProduct orderProduct, LocalDate today, Promotion promotion) {
+        if (today.isBefore(LocalDate.parse(promotion.getStartDate()))) {
+            orderProduct.setPromotion(BEFORE_PROMOTION_START);
+        }
+
+        if (today.isAfter(LocalDate.parse(promotion.getEndDate()))) {
+            orderProduct.setPromotion(AFTER_PROMOTION_END);
+        }
+    }
+
+    private void applyPromotionBuyAndGet(OrderedProduct orderProduct, Promotion promotion) {
+        String orderProductPromotion = orderProduct.getPromotion();
+
+        if (orderProductPromotion != null && !orderProductPromotion.equals(BEFORE_PROMOTION_START)
+                && !orderProductPromotion.equals(AFTER_PROMOTION_END)) {
+            orderProduct.setBuy(promotion.getBuy());
+            orderProduct.setGet(promotion.getGet());
+        }
+    }
+
+    // 주문서 수정: 주문 수량에 다른 프로모션 적용 결과 반영
+    public void applyResponseForNoPromotion(String response, PromotionResult promotionResult,
+                                            OrderedProduct orderedProduct) {
+        if (response.equals(RESPONSE_YES)) {
+            processPurchaseWithNoDiscount(orderedProduct, promotionResult);
+        }
+        if (response.equals(RESPONSE_NO)) {
+            processNonPurchaseWithNoDiscount(orderedProduct, promotionResult);
+        }
+    }
+
+    private void processPurchaseWithNoDiscount(OrderedProduct orderedProduct, PromotionResult promotionResult) {
+        int promotionAppliedCount = promotionResult.getApplicablePromotionCount();
+        int nonPromotionProductCount = promotionResult.getNonPromotionProductCount();
+
+        orderedProduct.setBuy(orderedProduct.getBuy() * promotionAppliedCount + nonPromotionProductCount);
+        orderedProduct.setGet(orderedProduct.getGet() * promotionAppliedCount);
+    }
+
+    private void processNonPurchaseWithNoDiscount(OrderedProduct orderedProduct, PromotionResult promotionResult) {
+        int promotionAppliedCount = promotionResult.getApplicablePromotionCount();
+        int nonPromotionProductCount = promotionResult.getNonPromotionProductCount();
+
+        orderedProduct.setBuy(orderedProduct.getBuy() * promotionAppliedCount);
+        orderedProduct.setGet(orderedProduct.getGet() * promotionAppliedCount);
+        int productPrice = orderedProduct.getTotalPrice() / orderedProduct.getQuantity();
+        orderedProduct.setQuantity(orderedProduct.getQuantity() - nonPromotionProductCount); // 수량 감소
+        orderedProduct.setTotalPrice(productPrice * orderedProduct.getQuantity()); // 수량 감소에 따른 총 가격 변경
+    }
+
+    public void applyResponseForFreeProduct(String response, PromotionResult promotionResult,
+                                            OrderedProduct orderedProduct) {
+        if (response.equals(RESPONSE_YES)) {
+            processAdditionalPromotionApplied(orderedProduct, promotionResult);
+        }
+        if (response.equals(RESPONSE_NO)) {
+            processAdditionalPromotionNotApplied(orderedProduct, promotionResult);
+        }
+    }
+
+    private void processAdditionalPromotionApplied(OrderedProduct orderedProduct, PromotionResult promotionResult) {
+        int promotionAppliedCount = promotionResult.getApplicablePromotionCount();
+
+        orderedProduct.setBuy(orderedProduct.getBuy() * (promotionAppliedCount + 1));
+        int productPrice = orderedProduct.getTotalPrice() / orderedProduct.getQuantity();
+        orderedProduct.setQuantity(orderedProduct.getQuantity() + orderedProduct.getGet()); // 수량 증가
+        orderedProduct.setTotalPrice(productPrice * orderedProduct.getQuantity()); // 수량 증가에 따른 총 가격 변경
+        orderedProduct.setGet(orderedProduct.getGet() * (promotionAppliedCount + 1));
+    }
+
+    private void processAdditionalPromotionNotApplied(OrderedProduct orderedProduct, PromotionResult promotionResult) {
+        int promotionAppliedCount = promotionResult.getApplicablePromotionCount();
+
+        orderedProduct.setBuy(orderedProduct.getBuy() * (promotionAppliedCount + 1));
+        orderedProduct.setGet(orderedProduct.getGet() * promotionAppliedCount);
+    }
+
+    public void computeTotalWithPromotion(OrderedProduct orderedProduct, PromotionResult promotionResult) {
+        int promotionAppliedCount = promotionResult.getApplicablePromotionCount();
+
+        orderedProduct.setBuy(orderedProduct.getBuy() * promotionAppliedCount);
+        orderedProduct.setGet(orderedProduct.getGet() * promotionAppliedCount);
+    }
+}
\ No newline at end of file

리뷰: OrdersheetEditor의 역할을 이미 생성된 주문서의 변경(주문서의 초기 설정, 프로모션 내용 적용)으로 생각하고 작성하였는데, 객체가 가질 수 있는 역할의 범위를 잘 파악하지 못해 기본적인 것을 제외하고 editor에 모두 작성하였습니다. 모델 내부에서 책임을 가져갈 수 있는 부분을 고민해 보아야겠습니다. 좋은 의견 감사합니다!