浏览代码

+ 대시보드 주문 업데이트

송용우 4 月之前
父节点
当前提交
1c08ea10c6
共有 3 个文件被更改,包括 405 次插入85 次删除
  1. 1 0
      backend/app/Config/Routes2.php
  2. 87 0
      backend/app/Controllers/Deli.php
  3. 317 85
      pages/view/vendor/dashboard/index.vue

+ 1 - 0
backend/app/Config/Routes2.php

@@ -123,6 +123,7 @@ $routes->post('deli/delivered', 'Deli::getDeliveredList');
 $routes->post('deli/markDelivered', 'Deli::markAsDelivered');
 $routes->post('deli/markSettled', 'Deli::markAsSettled');
 $routes->post('deli/settlement', 'Deli::getSettlementList');
+$routes->post('deli/pendingOrders', 'Deli::getPendingOrderList');
 
 // =============================================================================
 // 파트너십 전용 웹 라우팅 (향후 확장)

+ 87 - 0
backend/app/Controllers/Deli.php

@@ -489,4 +489,91 @@ class Deli extends ResourceController
 
         return $this->respond($lists, 200);
     }
+
+    // 대기중인 개별 주문 조회
+    public function getPendingOrderList()
+    {
+        $db = \Config\Database::connect();
+        
+        // POST JSON 파라미터 받기
+        $request = $this->request->getJSON(true);
+        
+        $memberType = isset($request['MEMBER_TYPE']) ? $request['MEMBER_TYPE'] : null;
+        $companyNumber = isset($request['COMPANY_NUMBER']) ? $request['COMPANY_NUMBER'] : null;
+        $infSeq = isset($request['INF_SEQ']) ? $request['INF_SEQ'] : null;
+        
+        // 디버깅 로그
+        log_message('info', 'getPendingOrderList 호출됨');
+        log_message('info', 'Request 파라미터: ' . json_encode($request));
+        log_message('info', 'MEMBER_TYPE: ' . $memberType);
+        log_message('info', 'COMPANY_NUMBER: ' . $companyNumber);
+        
+        // 먼저 ITEM_LIST에서 COMPANY_NUMBER 확인해보자
+        $itemResult = $db->table('ITEM_LIST')->where('SEQ', 1)->get()->getRowArray();
+        log_message('info', 'ITEM_SEQ=1인 제품 정보: ' . json_encode($itemResult));
+        
+        $builder = $db->table('ITEM_ORDER_LIST IOL')
+            ->select('IOL.*, IL.ITEM_NAME, IL.COMPANY_NUMBER, IM.NICK_NAME')
+            ->join('ITEM_LIST IL', 'IOL.ITEM_SEQ = IL.SEQ', 'left')
+            ->join('INF_MEMBER IM', 'IOL.INF_SEQ = IM.SEQ', 'left')
+            ->where('IOL.DEL_YN', 'N');
+        
+        // 배송정보가 등록되지 않은 주문만 (대기중)
+        $builder->where('(IOL.DELI_COMP IS NULL OR IOL.DELI_COMP = "")')
+                ->where('(IOL.DELI_NUMB IS NULL OR IOL.DELI_NUMB = "")');
+        
+        // 벤더: 자사 제품의 주문만
+        if ($memberType === 'VENDOR') {
+            if (empty($companyNumber)) {
+                log_message('error', 'VENDOR 타입인데 COMPANY_NUMBER가 없음');
+                return $this->respond([], 200);
+            }
+            $builder->where('IL.COMPANY_NUMBER', $companyNumber);
+            log_message('info', 'VENDOR 필터 적용: COMPANY_NUMBER = ' . $companyNumber);
+            
+            // 임시로 JOIN 조건 확인을 위해 COMPANY_NUMBER 조건을 제거하고 테스트
+            log_message('info', '=== 임시 테스트: COMPANY_NUMBER 조건 제거 후 조회 ===');
+            $testBuilder = $db->table('ITEM_ORDER_LIST IOL')
+                ->select('IOL.*, IL.ITEM_NAME, IL.COMPANY_NUMBER, IM.NICK_NAME')
+                ->join('ITEM_LIST IL', 'IOL.ITEM_SEQ = IL.SEQ', 'left')
+                ->join('INF_MEMBER IM', 'IOL.INF_SEQ = IM.SEQ', 'left')
+                ->where('IOL.DEL_YN', 'N')
+                ->where('(IOL.DELI_COMP IS NULL OR IOL.DELI_COMP = "")')
+                ->where('(IOL.DELI_NUMB IS NULL OR IOL.DELI_NUMB = "")');
+            
+            $testQuery = $testBuilder->getCompiledSelect(false);
+            log_message('info', '테스트 SQL 쿼리: ' . $testQuery);
+            
+            $testResult = $testBuilder->get()->getResultArray();
+            log_message('info', '테스트 조회 결과 개수: ' . count($testResult));
+            if (count($testResult) > 0) {
+                log_message('info', '테스트 첫 번째 데이터: ' . json_encode($testResult[0]));
+            }
+        }
+        
+        // 인플루언서: 본인 주문만
+        if ($memberType === 'INFLUENCER') {
+            if (empty($infSeq)) {
+                log_message('error', 'INFLUENCER 타입인데 INF_SEQ가 없음');
+                return $this->respond([], 200);
+            }
+            $builder->where('IOL.INF_SEQ', $infSeq);
+            log_message('info', 'INFLUENCER 필터 적용: INF_SEQ = ' . $infSeq);
+        }
+        
+        $builder->orderBy('IOL.REG_DATE', 'DESC');
+        
+        // 쿼리 확인
+        $compiledQuery = $builder->getCompiledSelect(false);
+        log_message('info', 'SQL 쿼리: ' . $compiledQuery);
+        
+        $lists = $builder->get()->getResultArray();
+        
+        log_message('info', '조회된 데이터 개수: ' . count($lists));
+        if (count($lists) > 0) {
+            log_message('info', '첫 번째 데이터: ' . json_encode($lists[0]));
+        }
+        
+        return $this->respond($lists, 200);
+    }
 }

+ 317 - 85
pages/view/vendor/dashboard/index.vue

@@ -142,14 +142,52 @@
       </div>
     </div>
 
-    <!-- 상세 데이터 테이블 -->
+    <!-- 신규 주문 내역 (대기중) -->
     <div class="dashboard--table">
       <div class="table--header">
-        <h3>최근 주문 내역</h3>
+        <h3>신규 주문 내역 (대기중)</h3>
+        <v-btn 
+          color="warning" 
+          size="small"
+          @click="exportPendingData"
+        >
+          <i class="mdi mdi-download"></i>
+          엑셀 다운로드
+        </v-btn>
+      </div>
+      <div class="table--content">
+        <div class="tbl-wrapper">
+          <div class="tbl-wrap">
+            <!-- ag grid -->
+            <ag-grid-vue
+              style="width: 100%; height: calc(8 * 2.94rem)"
+              class="ag-theme-quartz"
+              :gridOptions="pendingGridOptions"
+              :rowData="pendingOrders"
+              :rowSelection="'single'"
+              :paginationPageSize="8"
+              :suppressPaginationPanel="true"
+              @grid-ready="onPendingGridReady"
+              @selection-changed="onPendingSelectionChanged"
+            >
+            </ag-grid-vue>
+            <!-- 페이징 -->
+            <div class="ag-grid-custom-pagenations">
+              <pagination @chg_page="chgPendingPage" :pageObj="pendingPageObj"></pagination>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 배송중 내역 -->
+    <div class="dashboard--table">
+      <div class="table--header">
+        <h3>배송중 내역</h3>
         <v-btn 
           color="primary" 
           size="small"
-          @click="exportData"
+          @click="exportShippingData"
         >
           <i class="mdi mdi-download"></i>
           엑셀 다운로드
@@ -160,20 +198,20 @@
           <div class="tbl-wrap">
             <!-- ag grid -->
             <ag-grid-vue
-              style="width: 100%; height: calc(10 * 2.94rem)"
+              style="width: 100%; height: calc(8 * 2.94rem)"
               class="ag-theme-quartz"
-              :gridOptions="gridOptions"
-              :rowData="recentOrders"
+              :gridOptions="shippingGridOptions"
+              :rowData="shippingOrders"
               :rowSelection="'single'"
-              :paginationPageSize="10"
+              :paginationPageSize="8"
               :suppressPaginationPanel="true"
-              @grid-ready="onGridReady"
-              @selection-changed="onSelectionChanged"
+              @grid-ready="onShippingGridReady"
+              @selection-changed="onShippingSelectionChanged"
             >
             </ag-grid-vue>
             <!-- 페이징 -->
             <div class="ag-grid-custom-pagenations">
-              <pagination @chg_page="chgPage" :pageObj="pageObj"></pagination>
+              <pagination @chg_page="chgShippingPage" :pageObj="shippingPageObj"></pagination>
             </div>
           </div>
         </div>
@@ -282,9 +320,117 @@
     avgOrderValue: 0
   });
 
-  // ag-grid 관련
-  const gridApi = ref(null);
-  const gridOptions = ref({
+  // ag-grid 관련 - 신규 주문 (대기중)
+  const pendingGridApi = ref(null);
+  const pendingGridOptions = ref({
+    columnDefs: [
+      { 
+        headerName: '주문번호', 
+        field: 'orderNo', 
+        flex: 1,
+        minWidth: 140,
+        sortable: true,
+        filter: true
+      },
+      { 
+        headerName: '인플루언서', 
+        field: 'influencer', 
+        flex: 1,
+        minWidth: 120,
+        sortable: true,
+        filter: true
+      },
+      { 
+        headerName: '제품명', 
+        field: 'productName', 
+        flex: 2,
+        minWidth: 200,
+        sortable: true,
+        filter: true
+      },
+      { 
+        headerName: '주문수량', 
+        field: 'totalQty', 
+        flex: 1,
+        minWidth: 100,
+        sortable: true,
+        filter: true,
+        valueFormatter: (params) => {
+          return `${params.value || 0}개`;
+        }
+      },
+      { 
+        headerName: '주문금액', 
+        field: 'totalAmount', 
+        flex: 1,
+        minWidth: 120,
+        sortable: true,
+        filter: true,
+        valueFormatter: (params) => {
+          return new Intl.NumberFormat('ko-KR', {
+            style: 'currency',
+            currency: 'KRW'
+          }).format(params.value || 0);
+        }
+      },
+      { 
+        headerName: '주문일', 
+        field: 'latestOrderDate', 
+        flex: 1,
+        minWidth: 120,
+        sortable: true,
+        filter: true
+      },
+      { 
+        headerName: '상태', 
+        field: 'status', 
+        flex: 0.8,
+        minWidth: 100,
+        sortable: true,
+        filter: true,
+        cellRenderer: () => {
+          return `<span class="status-chip status-warning">대기중</span>`;
+        }
+      },
+      { 
+        headerName: '액션', 
+        field: 'actions', 
+        flex: 0.6,
+        minWidth: 80,
+        sortable: false,
+        filter: false,
+        cellRenderer: () => {
+          return '<button class="action-btn">관리</button>';
+        },
+        onCellClicked: (params) => {
+          viewPendingOrder(params.data);
+        }
+      }
+    ],
+    defaultColDef: {
+      sortable: true,
+      filter: true,
+      resizable: true,
+    },
+    pagination: false,
+    animateRows: true,
+    rowHeight: 40,
+    suppressHorizontalScroll: false,
+  });
+
+  // 페이징 관련 - 신규 주문
+  const pendingPageObj = ref({
+    currentPage: 1,
+    pageSize: 8,
+    totalCnt: 0,
+    totalPage: 0
+  });
+
+  const pendingOrders = ref([]);
+
+  // ag-grid 관련 - 배송중
+  const shippingGridApi = ref(null);
+  const shippingGridOptions = ref({
     columnDefs: [
       { 
         headerName: '주문번호', 
@@ -355,11 +501,8 @@
         minWidth: 100,
         sortable: true,
         filter: true,
-        cellRenderer: (params) => {
-          const status = params.value;
-          const color = getStatusColor(status);
-          const text = getStatusText(status);
-          return `<span class="status-chip status-${color}">${text}</span>`;
+        cellRenderer: () => {
+          return `<span class="status-chip status-info">배송중</span>`;
         }
       },
       { 
@@ -373,7 +516,7 @@
           return '<button class="action-btn">보기</button>';
         },
         onCellClicked: (params) => {
-          viewOrder(params.data);
+          viewShippingOrder(params.data);
         }
       }
     ],
@@ -388,15 +531,15 @@
     suppressHorizontalScroll: false,
   });
 
-  // 페이징 관련
-  const pageObj = ref({
+  // 페이징 관련 - 배송중
+  const shippingPageObj = ref({
     currentPage: 1,
-    pageSize: 10,
+    pageSize: 8,
     totalCnt: 0,
     totalPage: 0
   });
 
-  const recentOrders = ref([]);
+  const shippingOrders = ref([]);
 
   /************************************************************************
 |    함수(METHODS)
@@ -498,40 +641,70 @@
     }
   };
 
-  // ag-grid 이벤트 핸들러
-  const onGridReady = (params) => {
-    gridApi.value = params.api;
+  // ag-grid 이벤트 핸들러 - 신규 주문 (대기중)
+  const onPendingGridReady = (params) => {
+    pendingGridApi.value = params.api;
+  };
+
+  const onPendingSelectionChanged = () => {
+    const selectedRows = pendingGridApi.value.getSelectedRows();
+    console.log('선택된 대기중 주문:', selectedRows);
+  };
+
+  // 페이지 변경 - 신규 주문
+  const chgPendingPage = (page) => {
+    pendingPageObj.value.currentPage = page;
+    const startIndex = (page - 1) * pendingPageObj.value.pageSize;
+    const endIndex = startIndex + pendingPageObj.value.pageSize;
+    const paginatedData = pendingOrders.value.slice(startIndex, endIndex);
+    
+    if (pendingGridApi.value) {
+      pendingGridApi.value.setGridOption('rowData', paginatedData);
+    }
+  };
+
+  // ag-grid 이벤트 핸들러 - 배송중
+  const onShippingGridReady = (params) => {
+    shippingGridApi.value = params.api;
   };
 
-  const onSelectionChanged = () => {
-    const selectedRows = gridApi.value.getSelectedRows();
-    console.log('선택된 행:', selectedRows);
+  const onShippingSelectionChanged = () => {
+    const selectedRows = shippingGridApi.value.getSelectedRows();
+    console.log('선택된 배송중 주문:', selectedRows);
   };
 
-  // 페이지 변경
-  const chgPage = (page) => {
-    pageObj.value.currentPage = page;
-    // 페이징 처리 로직 (현재는 클라이언트 사이드)
-    const startIndex = (page - 1) * pageObj.value.pageSize;
-    const endIndex = startIndex + pageObj.value.pageSize;
-    const paginatedData = recentOrders.value.slice(startIndex, endIndex);
+  // 페이지 변경 - 배송중
+  const chgShippingPage = (page) => {
+    shippingPageObj.value.currentPage = page;
+    const startIndex = (page - 1) * shippingPageObj.value.pageSize;
+    const endIndex = startIndex + shippingPageObj.value.pageSize;
+    const paginatedData = shippingOrders.value.slice(startIndex, endIndex);
     
-    if (gridApi.value) {
-      gridApi.value.setGridOption('rowData', paginatedData);
+    if (shippingGridApi.value) {
+      shippingGridApi.value.setGridOption('rowData', paginatedData);
     }
   };
 
   // 주문 상세 보기
-  const viewOrder = (order) => {
+  const viewPendingOrder = (order) => {
+    router.push({
+      path: `/view/common/deli/detail/${order.itemSeq}`
+    });
+  };
+
+  const viewShippingOrder = (order) => {
     router.push({
       path: `/view/order/detail/${order.orderNo}`
     });
   };
 
   // 엑셀 다운로드
-  const exportData = () => {
-    // 엑셀 다운로드 로직
-    $toast.success('데이터 다운로드를 시작합니다.');
+  const exportPendingData = () => {
+    $toast.success('신규 주문 데이터 다운로드를 시작합니다.');
+  };
+
+  const exportShippingData = () => {
+    $toast.success('배송중 데이터 다운로드를 시작합니다.');
   };
 
   // 차트 생성
@@ -782,46 +955,108 @@
     }
   };
 
-  // 최근 주문 데이터 가져오기
-  const fetchRecentOrders = async () => {
+  // 신규 주문 (대기중) 데이터 가져오기 - 새로운 API 사용
+  const fetchPendingOrders = async () => {
     try {
       const userInfo = useAuthStore().getSnsTempData?.user || JSON.parse(localStorage.getItem('authStore') || '{}')?.auth;
-      const _req = {
+      
+      console.log('사용자 정보:', userInfo);
+      console.log('COMPANY_NUMBER:', userInfo?.COMPANY_NUMBER);
+      
+      const requestData = {
         MEMBER_TYPE: 'VENDOR',
         COMPANY_NUMBER: userInfo?.COMPANY_NUMBER
       };
+      
+      console.log('API 요청 데이터:', requestData);
+      
+      const response = await useAxios().post("/deli/pendingOrders", requestData);
+      
+      const pendingData = response.data || [];
+      console.log('신규 주문 원본 데이터 개수:', pendingData.length);
+      console.log('신규 주문 원본 데이터:', pendingData);
+
+      if (pendingData.length === 0) {
+        console.warn('신규 주문 데이터가 없습니다. API 필터링 확인 필요');
+        pendingOrders.value = [];
+        pendingPageObj.value.totalCnt = 0;
+        pendingPageObj.value.totalPage = 0;
+        if (pendingGridApi.value) {
+          pendingGridApi.value.setGridOption('rowData', []);
+        }
+        return;
+      }
 
-      // 배송중 데이터
-      const shippingResponse = await useAxios().post("/deli/shipping", _req);
-      const shippingOrders = shippingResponse.data || [];
+      // 테이블 형식으로 변환
+      const formattedPendingOrders = pendingData.map((item, index) => {
+        console.log(`주문 ${index + 1} 변환:`, {
+          SEQ: item.SEQ,
+          ITEM_SEQ: item.ITEM_SEQ,
+          ITEM_NAME: item.ITEM_NAME,
+          NICK_NAME: item.NICK_NAME,
+          QTY: item.QTY,
+          TOTAL: item.TOTAL,
+          REG_DATE: item.REG_DATE
+        });
+        
+        return {
+          orderNo: `ORD-${item.SEQ || (Date.now() + index)}`,
+          itemSeq: item.ITEM_SEQ,
+          productName: item.ITEM_NAME || '상품명 없음',
+          influencer: item.NICK_NAME || '알 수 없음',
+          totalQty: item.QTY || 0,
+          totalAmount: item.TOTAL || 0,
+          latestOrderDate: $dayjs(item.REG_DATE).format('YYYY-MM-DD'),
+          status: 'pending',
+          originalData: item
+        };
+      });
 
-      // 배송완료 데이터
-      const deliveredResponse = await useAxios().post("/deli/delivered", _req);
-      const deliveredOrders = deliveredResponse.data || [];
+      console.log('변환된 신규 주문 데이터:', formattedPendingOrders);
 
-      // 정산완료 데이터
-      const settlementResponse = await useAxios().post("/deli/settlement", {
-        ..._req,
-        SETTLEMENT_STATUS: 'COMPLETED'
-      });
-      const settlementOrders = settlementResponse.data || [];
-
-      // 모든 주문 데이터 통합 및 정렬
-      const allOrders = [
-        ...shippingOrders.map(order => ({ ...order, status: 'shipping' })),
-        ...deliveredOrders.map(order => ({ ...order, status: 'delivered' })),
-        ...settlementOrders.map(order => ({ ...order, status: 'completed' }))
-      ];
-
-      // 날짜순 정렬 (최신순)
-      allOrders.sort((a, b) => {
-        const dateA = new Date(a.DELIVERED_DATE || a.SHIPPING_DATE || a.REG_DATE || a.ORDER_DATE);
-        const dateB = new Date(b.DELIVERED_DATE || b.SHIPPING_DATE || b.REG_DATE || b.ORDER_DATE);
-        return dateB - dateA;
+      pendingOrders.value = formattedPendingOrders;
+      
+      // 페이징 정보 업데이트
+      pendingPageObj.value.totalCnt = formattedPendingOrders.length;
+      pendingPageObj.value.totalPage = Math.ceil(formattedPendingOrders.length / pendingPageObj.value.pageSize);
+      
+      console.log('페이징 정보:', {
+        totalCnt: pendingPageObj.value.totalCnt,
+        totalPage: pendingPageObj.value.totalPage,
+        pageSize: pendingPageObj.value.pageSize
       });
+      
+      // ag-grid 데이터 갱신 (첫 페이지만)
+      const firstPageData = formattedPendingOrders.slice(0, pendingPageObj.value.pageSize);
+      console.log('그리드에 설정할 첫 페이지 데이터:', firstPageData);
+      
+      if (pendingGridApi.value) {
+        pendingGridApi.value.setGridOption('rowData', firstPageData);
+        console.log('그리드 데이터 설정 완료');
+      } else {
+        console.warn('pendingGridApi가 없습니다');
+      }
+
+    } catch (error) {
+      console.error('신규 주문 데이터 조회 실패:', error);
+      $toast.error('신규 주문 데이터를 불러오는데 실패했습니다.');
+    }
+  };
+
+  // 배송중 데이터 가져오기
+  const fetchShippingOrders = async () => {
+    try {
+      const userInfo = useAuthStore().getSnsTempData?.user || JSON.parse(localStorage.getItem('authStore') || '{}')?.auth;
+      const _req = {
+        MEMBER_TYPE: 'VENDOR',
+        COMPANY_NUMBER: userInfo?.COMPANY_NUMBER
+      };
+
+      const response = await useAxios().post("/deli/shipping", _req);
+      const shippingData = response.data || [];
 
       // 테이블 형식으로 변환
-      const formattedOrders = allOrders.map((order, index) => ({
+      const formattedShippingOrders = shippingData.map((order, index) => ({
         orderNo: `ORD-${order.SEQ || (Date.now() + index)}`,
         influencer: order.NICK_NAME || '알 수 없음',
         productName: order.ITEM_NAME || '상품명 없음',
@@ -829,29 +1064,25 @@
         deliveryCompany: order.DELI_COMP || '-',
         trackingNumber: order.DELI_NUMB || '-',
         orderDate: $dayjs(order.ORDER_DATE || order.REG_DATE).format('YYYY-MM-DD'),
-        status: order.status,
-        deliveryInfo: {
-          company: order.DELI_COMP,
-          number: order.DELI_NUMB
-        },
+        status: 'shipping',
         originalData: order
       }));
 
-      recentOrders.value = formattedOrders;
+      shippingOrders.value = formattedShippingOrders;
       
       // 페이징 정보 업데이트
-      pageObj.value.totalCnt = formattedOrders.length;
-      pageObj.value.totalPage = Math.ceil(formattedOrders.length / pageObj.value.pageSize);
+      shippingPageObj.value.totalCnt = formattedShippingOrders.length;
+      shippingPageObj.value.totalPage = Math.ceil(formattedShippingOrders.length / shippingPageObj.value.pageSize);
       
       // ag-grid 데이터 갱신 (첫 페이지만)
-      const firstPageData = formattedOrders.slice(0, pageObj.value.pageSize);
-      if (gridApi.value) {
-        gridApi.value.setGridOption('rowData', firstPageData);
+      const firstPageData = formattedShippingOrders.slice(0, shippingPageObj.value.pageSize);
+      if (shippingGridApi.value) {
+        shippingGridApi.value.setGridOption('rowData', firstPageData);
       }
 
     } catch (error) {
-      console.error('최근 주문 데이터 조회 실패:', error);
-      $toast.error('최근 주문 데이터를 불러오는데 실패했습니다.');
+      console.error('배송중 데이터 조회 실패:', error);
+      $toast.error('배송중 데이터를 불러오는데 실패했습니다.');
     }
   };
 
@@ -862,7 +1093,8 @@
     try {
       await Promise.all([
         fetchSettlementData(),
-        fetchRecentOrders()
+        fetchPendingOrders(),
+        fetchShippingOrders()
       ]);
       
       // 데이터 로드 후 애니메이션과 차트 생성