prepare("SELECT * FROM sales_member WHERE member_id = 'sales' LIMIT 1"); $stmt->execute(); $testUser = $stmt->fetch(PDO::FETCH_ASSOC); if ($testUser) { $currentUser = $testUser; $userId = $currentUser['id']; $userRole = $currentUser['role']; } else { echo json_encode(['success' => false, 'error' => '로그인이 필요합니다.']); exit; } } catch (Exception $e) { echo json_encode(['success' => false, 'error' => '로그인이 필요합니다.']); exit; } } else { $currentUser = $_SESSION['sales_user']; $userId = $currentUser['id']; $userRole = $currentUser['role']; } // 기간 필터링 (기본값: 당월) $startDate = $_GET['startDate'] ?? date('Y-m-01'); $endDate = $_GET['endDate'] ?? date('Y-m-t'); try { $pdo = db_connect(); // 1. 조직도 트리 생성 함수 (재귀) function buildOrgTree($pdo, $parentId, $depth, $startDate, $endDate, $targetUserId) { // 이 멤버의 정보 가져오기 $stmt = $pdo->prepare("SELECT id, name, role FROM sales_member WHERE id = ? AND is_active = 1"); $stmt->execute([$parentId]); $member = $stmt->fetch(PDO::FETCH_ASSOC); if (!$member) return null; // 이 멤버의 직접 실적 가져오기 (기존 sales_record + 신규 sales_tenant_products) $sql = " SELECT id, customer_name as customer, contract_date as contractDate, amount FROM sales_record WHERE member_id = ? AND status = 'completed' AND contract_date BETWEEN ? AND ? UNION ALL SELECT p.id, t.tenant_name as customer, p.contract_date as contractDate, p.contract_amount as amount FROM sales_tenant_products p JOIN sales_tenants t ON p.tenant_id = t.id WHERE (t.sales_manager_id = ? OR (t.sales_manager_id IS NULL AND t.manager_id = ?)) AND p.contract_date BETWEEN ? AND ? "; $stmt = $pdo->prepare($sql); $stmt->execute([$parentId, $startDate, $endDate, $parentId, $parentId, $startDate, $endDate]); $directContracts = $stmt->fetchAll(PDO::FETCH_ASSOC); $directSales = 0; $rate = 0; if ($parentId == $targetUserId) $rate = 0.20; else if ($depth == 1) $rate = 0.05; else if ($depth == 2) $rate = 0.03; foreach ($directContracts as &$c) { $c['commission'] = $c['amount'] * $rate; $directSales += $c['amount']; } unset($c); // 하위 멤버들 가져오기 $stmt = $pdo->prepare("SELECT id FROM sales_member WHERE parent_id = ? AND is_active = 1"); $stmt->execute([$parentId]); $childrenIds = $stmt->fetchAll(PDO::FETCH_COLUMN); $children = []; $totalSales = $directSales; $totalContractCount = count($directContracts); $commission = $directSales * $rate; $subtreeCommission = $commission; foreach ($childrenIds as $childId) { $childNode = buildOrgTree($pdo, $childId, $depth + 1, $startDate, $endDate, $targetUserId); if ($childNode) { $children[] = $childNode; $totalSales += $childNode['totalSales']; $totalContractCount += $childNode['contractCount']; $subtreeCommission += $childNode['commission']; // Aggregate commissions } } // 수당 계산 (targetUserId 기준) // targetUserId == parentId 이면 본인의 직접 판매 (20%) // targetUserId 가 parentId의 부모이면 (depth=1) 관리자 수당 (5%) // targetUserId 가 parentId의 조부모이면 (depth=2) 교육자 수당 (3%) $commission = 0; if ($parentId == $targetUserId) { $commission = $directSales * 0.20; } else if ($depth == 1) { $commission = $directSales * 0.05; } else if ($depth == 2) { $commission = $directSales * 0.03; } return [ 'id' => 'node_' . $member['id'], 'real_id' => $member['id'], 'name' => $member['name'], 'role' => $member['role'], 'depth' => $depth, 'isDirect' => ($parentId == $targetUserId), 'directSales' => $directSales, 'totalSales' => $totalSales, 'contractCount' => $totalContractCount, 'directCommission' => $commission, 'commission' => $subtreeCommission, 'contracts' => $directContracts, 'children' => $children ]; } // 대상 사용자 결정 $rootUserId = $userId; if ($userRole === 'operator' && isset($_GET['target_id'])) { $rootUserId = $_GET['target_id']; } // 트리 구축 (본인 노드) $rootNode = buildOrgTree($pdo, $rootUserId, 0, $startDate, $endDate, $rootUserId); // 프론트엔드 형식에 맞게 내 직접 판매 노드를 children의 첫번째로 삽입 if ($rootNode) { $directNode = [ 'id' => 'root-direct', 'name' => '내 직접 판매', 'depth' => 0, 'role' => '판매자', 'isDirect' => true, 'totalSales' => $rootNode['directSales'], 'contractCount' => count($rootNode['contracts']), 'commission' => $rootNode['directSales'] * 0.20, 'contracts' => $rootNode['contracts'], 'children' => [] ]; // Root node's children should include this direct node + actual children $actualChildren = $rootNode['children']; $rootNode['children'] = array_merge([$directNode], $actualChildren); // Root node should keep its aggregated commission as its primary commission value $rootNode['isDirect'] = false; } // 전체 누적 실적 계산 (전체 기간) function calculateTotalStats($pdo, $parentId, $targetUserId, $depth) { $sql = " SELECT amount FROM sales_record WHERE member_id = ? AND status = 'completed' UNION ALL SELECT p.contract_amount as amount FROM sales_tenant_products p JOIN sales_tenants t ON p.tenant_id = t.id WHERE (t.sales_manager_id = ? OR (t.sales_manager_id IS NULL AND t.manager_id = ?)) "; $stmt = $pdo->prepare($sql); $stmt->execute([$parentId, $parentId, $parentId]); $amounts = $stmt->fetchAll(PDO::FETCH_COLUMN); $directSales = array_sum($amounts); $count = count($amounts); $commission = 0; if ($parentId == $targetUserId) $commission = $directSales * 0.20; else if ($depth == 1) $commission = $directSales * 0.05; else if ($depth == 2) $commission = $directSales * 0.03; $stats = [ 'totalSales' => $directSales, 'totalCommission' => $commission, 'totalCount' => $count ]; $stmt = $pdo->prepare("SELECT id FROM sales_member WHERE parent_id = ? AND is_active = 1"); $stmt->execute([$parentId]); $children = $stmt->fetchAll(PDO::FETCH_COLUMN); foreach ($children as $childId) { if ($depth < 2) { // 수당은 2단계 하위까지만 $childStats = calculateTotalStats($pdo, $childId, $targetUserId, $depth + 1); $stats['totalSales'] += $childStats['totalSales']; $stats['totalCommission'] += $childStats['totalCommission']; $stats['totalCount'] += $childStats['totalCount']; } else { // 실적만 합산 $childStats = calculateTotalStats($pdo, $childId, $targetUserId, $depth + 1); $stats['totalSales'] += $childStats['totalSales']; $stats['totalCount'] += $childStats['totalCount']; } } return $stats; } $totalStats = calculateTotalStats($pdo, $rootUserId, $rootUserId, 0); // 역할별 수당 합계 계산 (현재 기간 트리 기반) function summarizeCommissions($node, &$summary) { if ($node['isDirect']) { $summary['direct'] += $node['commission']; } else if ($node['depth'] == 1) { $summary['manager'] += $node['commission']; } else if ($node['depth'] == 2) { $summary['educator'] += $node['commission']; } foreach ($node['children'] as $child) { summarizeCommissions($child, $summary); } } $commissionSummary = ['direct' => 0, 'manager' => 0, 'educator' => 0]; if ($rootNode) { summarizeCommissions($rootNode, $commissionSummary); } echo json_encode([ 'success' => true, 'total_stats' => $totalStats, 'period_stats' => [ 'startDate' => $startDate, 'endDate' => $endDate, 'commission_summary' => $commissionSummary, 'total_period_commission' => array_sum($commissionSummary) ], 'org_tree' => $rootNode ], JSON_UNESCAPED_UNICODE); } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); }