@@ -1 +1,206 @@
-# java-convenience-store-precourse
+
+노션 링크를 통해 더 편하게 볼 수 있습니다.
+
+https://tangy-napkin-64d.notion.site/4-_-_-14e5dc39aa55800480aecff3d88bce24?pvs=4
+
+## 👉 로직
+
+✅ **요구사항 해석한 내용** (주관적일 수 있다고 생각하여 적어봤습니다 🙌)
+
+- **프로모션 할인**
+    - **오늘 날짜가 프로모션 기간 내에 포함된 경우에만 할인을 적용한다.**
+    - **프로모션 혜택은 프로모션 재고 내에서만 적용할 수 있다.**
+        - 프로모션 적용이 가능한 상품에 대해, 고객이 해당 수량보다 적게 가져와 추가하는 경우,
+          추가하는 상품 1개는 프로모션 재고가 감소된다. 이때 프로모셔 재고가 추가적으로 1개가 더 있는지 확인해야 한다고 생각함.
+    - **프로모션 기간 중이라면 프로모션 재고를 우선적으로 차감하며, 프로모션 재고가 부족할 경우에는 일반 재고를 사용한다.**
+        - **프로모션 기간이 아니라면, 이 경우에도 프로모션 재고를 우선적으로 차감할 것인가?**
+
+          1번) 프로모션 기간 유무에 상관없이 무조건 프로모션 재고를 우선적으로 차감한다.
+
+          2번) 프로모션 기간이 아니라면 우선 일반 재고를 우선적으로 차감한다.
+
+          3번) 프로모션 기간이 아니라면 일반 재고만 차감 가능하다.
+
+          4번) 프로모션 기간이 아니라면 구매 불가이다.
+
+          → **2번**으로 해석함. 이유는 나중에 미래에 프로모션 기간이 되었을 때를 생각하면 우선 일반재고를 차감해야 한다고 생각함.
+
+- **멤버십 할인**
+    - **멤버십 회원은 프로모션 미적용 금액의 30%를 할인받는다.**
+        - **프로모션 미적용이란?**
+
+          1번) 프로모션 기간이 아닌 프로모션 상품은 프로모션 미적용 상품에 포함된다.
+
+          2번) (1번과 반대)프로모션 기간이 아니더라도 프로모션 혜택이 가능했던 상품이기 때문에 프로모션 미적용 상품이 아니다.
+
+          3번) 프로모션 상품이 줄어들어 0이 된 상황이면(일반 재고만으로 결제해야 하는 상황) 이 상품은 프로모션 미적용 상품이다.
+
+          → **1번&3번으로 해석함. (표로 정리한 내용은 노션 참고)**
+  
+    - **프로모션 적용 후 남은 금액에 대해 멤버십 할인을 적용한다.**
+    - **멤버십 할인의 최대 한도는 8,000원이다.**
+        - **최대 한도 8000원은 플레이를 할 때마다 초기화 되는가?**
+
+          1번) 멤버십 할인은 누적된다. 즉 한번 플레이할 때 멤버십 할인의 최대한도인 8000원이 전부 적용되면, 다음 플레이에서는 멤버십할인이 되지 않는다.
+
+          2번) 멤버십 할인은 누적되지 않는다. 즉 한 번 플레이할 때 멤버십 할인이 8000원이 되더라도 다음 플레이에서 최대 8000원의 멤버십 할인을 받을 수 있다.
+
+          → **2번**으로 해석함.
+
+
+✅ **전제**
+
+- **사용자가 입력한 상품 종류 1개에 대한 구매 수량 = n**
+- **영수중에 출력되는 상품 수량은 “결제한다”고 표현했습니다.**
+    - **따라서 결재하는 상품의 수량과 n은 다를 수 있습니다.**
+- 프로모션 혜택이 가능한 상품, 프로모션 적용이 가능한 상품은 다릅니다. (위 표 참고)
+
+✅ **로직**
+
+1. **프로모션 기간 아님(**3️⃣,4️⃣) ****→ 일반 재고 우선 감소 + 나머지는 프로모션 재고 감소,
+
+- 프로모션 기간이 아닌 경우란?
+    - 프로모션 혜택이 가능한 상품이지만 기간이 아니라 ‘프로모션 미적용’ 상품인 경우 또는
+      프로모션 혜택이 애초에 없어 ‘프로모션 미적용’ 상품인 경우(처음부터 일반재고만 있는 경우)
+- 일반재고 ≥ n, 일반재고 < n 나눠서 일반재고/프로모션 재고 “결제”함
+- 멤버십 할인 있음
+
+2. **프로모션 기간(**1️⃣,2️⃣) → 프로모션 재고 우선 감소
+
+- **case1) 프로모션 재고 > n**
+    - 프로모션 재고만으로 제품을 충분히 구매할 수 있는 경우
+        - 이때 “결제”하는 프로모션 재고의 수는 n개
+    - 고객이 해당 수량보다 적게 가져온 경우 추가 여부를 입력받음
+        - 추가 가능할 정도로 프로모션 재고가 충분한지 검사 후, 추가 여부 묻기
+            - 추가함 → “결제”하는 프로모션 재고의 수/증정품 수/결제한 상품의 수량을 **1개** 늘림, 멤버십 할인 받지 않음
+            - 추가하지 않음 → 멤버십 할인 받지 않음(프로모션 상품이기 때문에, ‘실행 결과 예시’ 참고하기)
+
+- **case2) 프로모션 재고 == n**
+    - “결제”해야 하는 프로모션 재고의 수는 n개
+    - 프로모션 적용이 가능한 상품에 대해,
+        - 프로모션 혜택 없이 결제해야 하는 상품의 개수라면
+        - 일부 수량(k개)에 대해 정가로 결제할지 여부를 입력받음
+            - 정가 결제하지 않음 →  “결제” 해야하는 프로모션 재고의 수 == n-k, 일반재고  “결제” 아무것도 안함, **결제할 상품의 수량을 k개 줄임**, 멤버십 할인 받지 않음
+            - 정가로 결제함 →프로모션 재고 모두 “결제”, 멤버십 할인 받지 않음
+
+- **case3) 프로모션 재고 < n**
+    - 프로모션 재고가 부족한 경우
+    - 프로모션 적용이 가능한 상품에 대해,
+        - 프로모션 혜택 없이 결제해야 하는 상품의 개수만큼 남았다면
+        - 일부 수량(k개)에 대해 정가로 결제할지 여부를 입력받음
+            - 정가 결제하지 않음 → “결제” 해야하는 프로모션 재고의 수 == n-k, 일반재고  “결제” 아무것도 안함, **결제할 상품의 수량을 k개 줄임**, 멤버십 할인 받지 않음
+            - 정가로 결제함  → 프로모션 재고 모두  “결제”, 나머지는 일반재고에서 “결제”, 멤버십 할인 받지 않음
+                - **단 k==n인 경우(프로모션 재고가 0개여서 구매 수량을 전부 일반재고에서 “결제”해야 하는 경우)는 멤버십 할인을 받음**
+
+- **case4) 추가적으로 물어볼거 없을 때**
+    - 정가로 결제할 상품의 수량, 추가할 수량이 없을 때
+    - “결제” 해야하는 프로모션 재고의 수 == n
+    - 멤버십 할인 받지 않음
+
+## 👉 입력
+
+- 입력값 전체 공통 예외처리
+    - [x]  빈값 또는 null값 입력시
+
+- **구매할 상품과 수량**
+    - 상품명,수량은 하이픈(-)으로
+    - 개별 상품은 대괄호([])로 묶어 쉼표(,)로 구분
+    - `구매하실 상품명과 수량을 입력해 주세요. (예: [사이다-2],[감자칩-1])`
+    - 예외처리
+        - `,`으로 split한 후 각각에 대해서…
+            - [x]  []이 ‘양쪽 끝에’ 각각 없으면
+            - [x]  -이 없으면
+
+          → 빈문자열인지도 함께 확인이 가능
+
+        - -으로 split한 후 각각에 대해서…
+            - [x]  (스스로 판단한 내용) 상품 이름 중복 입력시
+            - [x]  판매 상품이 아니면
+            - [x]  재고 수량을 초과했으면
+                - 프로모션 재고가 부족할 경우에는 일반 재고를 사용함
+            - [x]  수량을 숫자 아닌 자료형으로 입력하면
+            - [x]  수량을 0이하 입력하면
+
+- Y/N 공통 예외처리
+    - [x]  `Y` 또는 `N` 이 아닌 값을 입력했을 때
+- **증정 받을 수 있는 상품 추가 여부**
+    - 프로모션이 적용이 가능한 상품에 대해 고객이 해당 수량보다 적게 가져온 경우,
+    - 그 수량만큼 추가 여부를 입력받기
+    - `현재 {상품명}은(는) 1개를 무료로 더 받을 수 있습니다. 추가하시겠습니까? (Y/N)`
+- **정가로 결제할지에 대한 여부**
+    - 프로모션 재고가 부족하여 일부 수량을 프로모션 혜택 없이 결제해야 하는 경우,
+    - 일부 수량에 대해 정가로 결제할지 여부를 입력받기
+    - `현재 {상품명} {수량}개는 프로모션 할인이 적용되지 않습니다. 그래도 구매하시겠습니까? (Y/N)`
+    - 스스로 판단한 내용
+        - `N`를 입력시 : 구매를 아예 하지 않음
+- **멤버십 할인 적용 여부**
+    - `멤버십 할인을 받으시겠습니까? (Y/N)`
+    - 멤버십 회원은 프로모션 미적용 금액의 30%를 할인받는다.
+    - 프로모션 적용 후 남은 금액에 대해 멤버십 할인을 적용한다.
+    - 멤버십 할인의 최대 한도는 8,000원이다.
+- **추가 구매 여부**
+    - `감사합니다. 구매하고 싶은 다른 상품이 있나요? (Y/N)`
+
+## 👉 출력
+
+- 환영 인사와 함께 상품명, 가격, 프로모션 이름, 재고를 안내한다. 만약 재고가 0개라면 `재고 없음`을 출력
+    - **천단위 쉼표 찍기**
+
+    ```java
+    안녕하세요. W편의점입니다.
+    현재 보유하고 있는 상품입니다.
+    
+    - 콜라 1,000원 10개 탄산2+1
+    - 콜라 1,000원 10개
+    - 사이다 1,000원 8개 탄산2+1
+    - 사이다 1,000원 7개
+    - 오렌지주스 1,800원 9개 MD추천상품
+    - 오렌지주스 1,800원 재고 없음
+    - 탄산수 1,200원 5개 탄산2+1
+    - 탄산수 1,200원 재고 없음
+    - 물 500원 10개
+    - 비타민워터 1,500원 6개
+    - 감자칩 1,500원 5개 반짝할인
+    - 감자칩 1,500원 5개
+    - 초코바 1,200원 5개 MD추천상품
+    - 초코바 1,200원 5개
+    - 에너지바 2,000원 5개
+    - 정식도시락 6,400원 8개
+    - 컵라면 1,700원 1개 MD추천상품
+    - 컵라면 1,700원 10개
+    ```
+
+
+- 구매 상품 내역, 증정 상품 내역, 금액 정보를 출력
+    - **천단위 쉼표 찍기**
+
+    ```java
+    ==============W 편의점================
+    상품명		수량	금액
+    콜라		    3 	3,000
+    에너지바 		5 	10,000
+    =============증	정===============
+    콜라		1
+    ====================================
+    총구매액		   8	13,000
+    행사할인			-1,000
+    멤버십할인			-3,000
+    내실돈			 9,000
+    ```
+
+
+- 에러 메시지
+    - 사용자가 잘못된 값을 입력했을 때, **"[ERROR]"로 시작**하는 오류 메시지와 함께 상황에 맞는 안내를 출력한다.
+        - 구매할 상품과 수량 형식이 올바르지 않은 경우: `[ERROR] 올바르지 않은 형식으로 입력했습니다. 다시 입력해 주세요.`
+        - 존재하지 않는 상품을 입력한 경우: `[ERROR] 존재하지 않는 상품입니다. 다시 입력해 주세요.`
+        - 구매 수량이 재고 수량을 초과한 경우: `[ERROR] 재고 수량을 초과하여 구매할 수 없습니다. 다시 입력해 주세요.`
+        - 기타 잘못된 입력의 경우: `[ERROR] 잘못된 입력입니다. 다시 입력해 주세요.`
+
+- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
+    - `Exception`이 아닌 `IllegalArgumentException`, `IllegalStateException` 등과 같은 명확한 유형을 처리한다.
+
+## 👉 추가 라이브러리
+
+- `camp.nextstep.edu.missionutils`에서 제공하는 `DateTimes` 및 `Console` API를 사용하여 구현해야 한다.
+    - 현재 날짜와 시간을 가져오려면 `camp.nextstep.edu.missionutils.DateTimes`의 `now()`를 활용한다.
+    - 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.

리뷰: 프로모션 재고가 없는 경우 어차피 추가가 불가능하기 때문에 추가하는 경우에 들어가기 전에 확인 해야한다고 생각합니다.