';
wholesalers.forEach(ws => {
- const data = results[ws.id];
- const isError = !data.success;
- const balance = data.balance || 0;
- const prevBalance = data.prev_balance || data.prev_month_balance || 0;
+ const balData = balanceResults[ws.id] || {};
+ const salesData = salesResults[ws.id] || {};
+ const isError = !balData.success;
+ const balance = balData.balance || 0;
+ const monthlySales = salesData.total_amount || 0;
+ const monthlyPaid = salesData.total_paid || 0;
html += `
@@ -2376,9 +2411,16 @@
});
html += `
-
-
총 미수금
-
${totalBalance.toLocaleString()}원
+
+
+
📊 ${month}월 총 주문
+
${totalSales.toLocaleString()}원
+
+
+
+
💰 총 미수금
+
${totalBalance.toLocaleString()}원
+
🕐 ${new Date().toLocaleString('ko-KR')}
`;
diff --git a/backend/test_baekje_ledger_api.py b/backend/test_baekje_ledger_api.py
new file mode 100644
index 0000000..b229c87
--- /dev/null
+++ b/backend/test_baekje_ledger_api.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+"""백제약품 주문 원장 API 분석"""
+
+import json
+import requests
+from datetime import datetime, timedelta
+import calendar
+
+# 저장된 토큰 로드
+TOKEN_FILE = r'c:\Users\청춘약국\source\pharmacy-wholesale-api\.baekje_token.json'
+with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ token_data = json.load(f)
+
+token = token_data['token']
+cust_cd = token_data['cust_cd']
+
+print(f"Token expires: {datetime.fromtimestamp(token_data['expires'])}")
+print(f"Customer code: {cust_cd}")
+
+# API 세션 설정
+session = requests.Session()
+session.headers.update({
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
+ 'Accept': 'application/json, text/plain, */*',
+ 'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
+ 'Origin': 'https://ibjp.co.kr',
+ 'Referer': 'https://ibjp.co.kr/',
+ 'Authorization': f'Bearer {token}'
+})
+
+API_URL = "https://www.ibjp.co.kr"
+
+# 1. 주문 원장 API 시도 - 다양한 엔드포인트
+endpoints = [
+ '/ordLedger/listSearch',
+ '/ordLedger/list',
+ '/ord/ledgerList',
+ '/ord/ledgerSearch',
+ '/cust/ordLedger',
+ '/custOrd/ledgerList',
+ '/ordHist/listSearch',
+ '/ordHist/list',
+]
+
+# 날짜 설정 (이번 달)
+today = datetime.now()
+year = today.year
+month = today.month
+_, last_day = calendar.monthrange(year, month)
+from_date = f"{year}{month:02d}01"
+to_date = f"{year}{month:02d}{last_day:02d}"
+
+print(f"\n조회 기간: {from_date} ~ {to_date}")
+print("\n=== API 엔드포인트 탐색 ===\n")
+
+params = {
+ 'custCd': cust_cd,
+ 'startDt': from_date,
+ 'endDt': to_date,
+ 'stDate': from_date,
+ 'edDate': to_date,
+ 'year': str(year),
+ 'month': f"{month:02d}",
+}
+
+for endpoint in endpoints:
+ try:
+ # GET 시도
+ resp = session.get(f"{API_URL}{endpoint}", params=params, timeout=10)
+ print(f"GET {endpoint}: {resp.status_code}")
+ if resp.status_code == 200:
+ try:
+ data = resp.json()
+ print(f" -> JSON Response (first 500 chars): {str(data)[:500]}")
+ except:
+ print(f" -> Text (first 200 chars): {resp.text[:200]}")
+ except Exception as e:
+ print(f"GET {endpoint}: Error - {e}")
+
+ try:
+ # POST 시도
+ resp = session.post(f"{API_URL}{endpoint}", json=params, timeout=10)
+ print(f"POST {endpoint}: {resp.status_code}")
+ if resp.status_code == 200:
+ try:
+ data = resp.json()
+ print(f" -> JSON Response (first 500 chars): {str(data)[:500]}")
+ except:
+ print(f" -> Text (first 200 chars): {resp.text[:200]}")
+ except Exception as e:
+ print(f"POST {endpoint}: Error - {e}")
+
+# 2. 이미 알려진 API로 데이터 확인
+print("\n=== 알려진 API 테스트 ===\n")
+
+# 월간 잔고 조회 (이미 있는 함수에서 사용)
+resp = session.get(f"{API_URL}/custMonth/listSearch", params={'custCd': cust_cd, 'year': str(year), 'endDt': to_date}, timeout=10)
+print(f"custMonth/listSearch: {resp.status_code}")
+if resp.status_code == 200:
+ data = resp.json()
+ print(f" -> {json.dumps(data, ensure_ascii=False, indent=2)[:1500]}")
diff --git a/backend/test_baekje_ledger_api2.py b/backend/test_baekje_ledger_api2.py
new file mode 100644
index 0000000..eae0740
--- /dev/null
+++ b/backend/test_baekje_ledger_api2.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+"""백제약품 주문 원장 API 분석 - 상세 탐색"""
+
+import json
+import requests
+from datetime import datetime
+import calendar
+
+# 저장된 토큰 로드
+TOKEN_FILE = r'c:\Users\청춘약국\source\pharmacy-wholesale-api\.baekje_token.json'
+with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ token_data = json.load(f)
+
+token = token_data['token']
+cust_cd = token_data['cust_cd']
+
+# API 세션 설정
+session = requests.Session()
+session.headers.update({
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
+ 'Accept': 'application/json, text/plain, */*',
+ 'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
+ 'Origin': 'https://ibjp.co.kr',
+ 'Referer': 'https://ibjp.co.kr/',
+ 'Authorization': f'Bearer {token}'
+})
+
+API_URL = "https://www.ibjp.co.kr"
+
+today = datetime.now()
+year = today.year
+month = today.month
+_, last_day = calendar.monthrange(year, month)
+
+print("=== 주문 원장 API 탐색 (다양한 파라미터) ===\n")
+
+# 날짜 형식 변형
+date_formats = [
+ {'startDt': f'{year}{month:02d}01', 'endDt': f'{year}{month:02d}{last_day:02d}'},
+ {'stDt': f'{year}{month:02d}01', 'edDt': f'{year}{month:02d}{last_day:02d}'},
+ {'fromDate': f'{year}-{month:02d}-01', 'toDate': f'{year}-{month:02d}-{last_day:02d}'},
+ {'strDt': f'{year}{month:02d}01', 'endDt': f'{year}{month:02d}{last_day:02d}'},
+ {'ordDt': f'{year}{month:02d}'},
+]
+
+endpoints = [
+ '/ordLedger/listSearch',
+ '/ordLedger/search',
+ '/ordLedger/ledgerList',
+ '/cust/ordLedgerList',
+ '/cust/ledger',
+ '/ord/histList',
+ '/ord/history',
+ '/ord/list',
+]
+
+for endpoint in endpoints:
+ for params in date_formats:
+ full_params = {**params, 'custCd': cust_cd}
+ try:
+ resp = session.get(f"{API_URL}{endpoint}", params=full_params, timeout=10)
+ if resp.status_code == 200:
+ print(f"✓ GET {endpoint} {params}: {resp.status_code}")
+ try:
+ data = resp.json()
+ print(f" -> {str(data)[:300]}")
+ except:
+ print(f" -> {resp.text[:200]}")
+ except Exception as e:
+ pass
+
+ try:
+ resp = session.post(f"{API_URL}{endpoint}", json=full_params, timeout=10)
+ if resp.status_code == 200:
+ print(f"✓ POST {endpoint} {params}: {resp.status_code}")
+ try:
+ data = resp.json()
+ print(f" -> {str(data)[:300]}")
+ except:
+ print(f" -> {resp.text[:200]}")
+ except Exception as e:
+ pass
+
+print("\n=== 주문 이력 관련 API ===\n")
+
+# 주문 이력 조회 시도
+order_endpoints = [
+ '/ord/ordList',
+ '/ord/orderHistory',
+ '/ordReg/list',
+ '/ordReg/history',
+ '/order/list',
+ '/order/history',
+]
+
+for endpoint in order_endpoints:
+ try:
+ params = {'custCd': cust_cd, 'startDt': f'{year}{month:02d}01', 'endDt': f'{year}{month:02d}{last_day:02d}'}
+ resp = session.get(f"{API_URL}{endpoint}", params=params, timeout=10)
+ print(f"GET {endpoint}: {resp.status_code}")
+ if resp.status_code == 200:
+ try:
+ data = resp.json()
+ print(f" -> {str(data)[:500]}")
+ except:
+ print(f" -> {resp.text[:200]}")
+ except:
+ pass
+
+print("\n=== custMonth/listSearch 상세 데이터 분석 ===\n")
+
+# 이미 작동하는 API의 데이터 상세 분석
+resp = session.get(f"{API_URL}/custMonth/listSearch", params={'custCd': cust_cd, 'year': str(year), 'endDt': f'{year}{month:02d}{last_day:02d}'}, timeout=10)
+if resp.status_code == 200:
+ data = resp.json()
+ print("월간 데이터 구조:")
+ for item in data:
+ print(f"\n월: {item.get('BALANCE_YM')}")
+ print(f" 매출액(SALE_AMT): {item.get('SALE_AMT'):,}")
+ print(f" 반품액(BACK_AMT): {item.get('BACK_AMT'):,}")
+ print(f" 순반품(PURE_BACK_AMT): {item.get('PURE_BACK_AMT'):,}")
+ print(f" 순매출(TOTAL_AMT): {item.get('TOTAL_AMT'):,}")
+ print(f" 입금액(PAY_CASH_AMT): {item.get('PAY_CASH_AMT'):,}")
+ print(f" 전월이월(PRE_TOTAL_AMT): {item.get('PRE_TOTAL_AMT'):,}")
+ print(f" 월말잔고(BALANCE_A_AMT): {item.get('BALANCE_A_AMT'):,}")
+ print(f" 회전일수(ROTATE_DAY): {item.get('ROTATE_DAY')}")
diff --git a/backend/test_baekje_monthly_sales.py b/backend/test_baekje_monthly_sales.py
new file mode 100644
index 0000000..83718e1
--- /dev/null
+++ b/backend/test_baekje_monthly_sales.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""백제약품 get_monthly_sales() 테스트"""
+
+import os
+import sys
+
+# wholesale 패키지 경로 추가
+sys.path.insert(0, r'c:\Users\청춘약국\source\pharmacy-wholesale-api')
+os.chdir(r'c:\Users\청춘약국\source\pharmacy-pos-qr-system\backend')
+
+from dotenv import load_dotenv
+load_dotenv()
+
+from wholesale import BaekjeSession
+
+def test_monthly_sales():
+ print("=" * 60)
+ print("백제약품 월간 매출 조회 테스트")
+ print("=" * 60)
+
+ session = BaekjeSession()
+
+ # 현재 월 조회
+ from datetime import datetime
+ now = datetime.now()
+ year = now.year
+ month = now.month
+
+ print(f"\n1. 현재 월 ({year}-{month:02d}) 조회:")
+ result = session.get_monthly_sales(year, month)
+ print(f" Success: {result.get('success')}")
+ if result.get('success'):
+ print(f" 월간 매출: {result.get('total_amount'):,}원")
+ print(f" 월간 반품: {result.get('total_returns'):,}원")
+ print(f" 순매출: {result.get('net_amount'):,}원")
+ print(f" 월간 입금: {result.get('total_paid'):,}원")
+ print(f" 월말 잔고: {result.get('ending_balance'):,}원")
+ print(f" 전월이월: {result.get('prev_balance'):,}원")
+ print(f" 회전일수: {result.get('rotate_days')}")
+ print(f" 조회기간: {result.get('from_date')} ~ {result.get('to_date')}")
+ else:
+ print(f" Error: {result.get('error')}")
+
+ # 전월 조회
+ prev_month = month - 1 if month > 1 else 12
+ prev_year = year if month > 1 else year - 1
+
+ print(f"\n2. 전월 ({prev_year}-{prev_month:02d}) 조회:")
+ result = session.get_monthly_sales(prev_year, prev_month)
+ print(f" Success: {result.get('success')}")
+ if result.get('success'):
+ print(f" 월간 매출: {result.get('total_amount'):,}원")
+ print(f" 월간 반품: {result.get('total_returns'):,}원")
+ print(f" 순매출: {result.get('net_amount'):,}원")
+ print(f" 월간 입금: {result.get('total_paid'):,}원")
+ print(f" 월말 잔고: {result.get('ending_balance'):,}원")
+ print(f" 전월이월: {result.get('prev_balance'):,}원")
+ print(f" 회전일수: {result.get('rotate_days')}")
+ print(f" 조회기간: {result.get('from_date')} ~ {result.get('to_date')}")
+ else:
+ print(f" Error: {result.get('error')}")
+
+ # 2달 전 조회
+ prev_month2 = prev_month - 1 if prev_month > 1 else 12
+ prev_year2 = prev_year if prev_month > 1 else prev_year - 1
+
+ print(f"\n3. 2달 전 ({prev_year2}-{prev_month2:02d}) 조회:")
+ result = session.get_monthly_sales(prev_year2, prev_month2)
+ print(f" Success: {result.get('success')}")
+ if result.get('success'):
+ print(f" 월간 매출: {result.get('total_amount'):,}원")
+ print(f" 월간 반품: {result.get('total_returns'):,}원")
+ print(f" 순매출: {result.get('net_amount'):,}원")
+ print(f" 월간 입금: {result.get('total_paid'):,}원")
+ print(f" 월말 잔고: {result.get('ending_balance'):,}원")
+ else:
+ print(f" Error: {result.get('error')}")
+
+ print("\n" + "=" * 60)
+ print("테스트 완료!")
+ print("=" * 60)
+
+if __name__ == '__main__':
+ test_monthly_sales()