영업자료 업그레이드
This commit is contained in:
25
salesmanagement/api/fix_schema.php
Normal file
25
salesmanagement/api/fix_schema.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
require_once(__DIR__ . "/../../lib/mydb.php");
|
||||
$pdo = db_connect();
|
||||
|
||||
try {
|
||||
$columns = $pdo->query("SHOW COLUMNS FROM `sales_tenant_consultations`")->fetchAll(PDO::FETCH_COLUMN);
|
||||
echo "Columns: " . implode(", ", $columns) . "\n";
|
||||
|
||||
if (!in_array('audio_file_path', $columns)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `audio_file_path` varchar(500) DEFAULT NULL AFTER `log_text` ");
|
||||
echo "Added audio_file_path\n";
|
||||
}
|
||||
if (!in_array('attachment_paths', $columns)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `attachment_paths` text DEFAULT NULL AFTER `audio_file_path` ");
|
||||
echo "Added attachment_paths\n";
|
||||
}
|
||||
if (!in_array('consultation_type', $columns)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `consultation_type` varchar(20) DEFAULT 'text' AFTER `attachment_paths` ");
|
||||
echo "Added consultation_type\n";
|
||||
}
|
||||
|
||||
echo "Schema check completed.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
@@ -50,9 +50,16 @@ try {
|
||||
$directContracts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$directSales = 0;
|
||||
foreach ($directContracts as $c) {
|
||||
$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");
|
||||
@@ -63,12 +70,16 @@ try {
|
||||
$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_subtree'];
|
||||
$totalContractCount += $childNode['contractCount_subtree'];
|
||||
$totalSales += $childNode['totalSales'];
|
||||
$totalContractCount += $childNode['contractCount'];
|
||||
$subtreeCommission += $childNode['commission']; // Aggregate commissions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +107,8 @@ try {
|
||||
'directSales' => $directSales,
|
||||
'totalSales' => $totalSales,
|
||||
'contractCount' => $totalContractCount,
|
||||
'commission' => $commission,
|
||||
'directCommission' => $commission,
|
||||
'commission' => $subtreeCommission,
|
||||
'contracts' => $directContracts,
|
||||
'children' => $children
|
||||
];
|
||||
@@ -130,9 +142,8 @@ try {
|
||||
$actualChildren = $rootNode['children'];
|
||||
$rootNode['children'] = array_merge([$directNode], $actualChildren);
|
||||
|
||||
// 중요: Root 노드 자체의 수당은 하위 '내 직접 판매'에서 합산되므로 0으로 설정하거나 isDirect를 false로 변경
|
||||
// Root node should keep its aggregated commission as its primary commission value
|
||||
$rootNode['isDirect'] = false;
|
||||
$rootNode['commission'] = 0;
|
||||
}
|
||||
|
||||
// 전체 누적 실적 계산 (전체 기간)
|
||||
|
||||
@@ -66,7 +66,7 @@ try {
|
||||
$check = $pdo->prepare("SELECT id FROM sales_member WHERE member_id = 'manager'");
|
||||
$check->execute();
|
||||
if (!$check->fetch()) {
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_member (member_id, password, name, role, parent_id) VALUES ('manager', 'manager', '일반매니저', 'manager', ?)");
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_member (member_id, password, name, role, parent_id) VALUES ('manager', 'manager', '매니저', 'manager', ?)");
|
||||
$stmt->execute([$sales_id]);
|
||||
}
|
||||
$manager_id = $pdo->lastInsertId() ?: 3;
|
||||
|
||||
@@ -94,7 +94,7 @@ try {
|
||||
return;
|
||||
}
|
||||
if ($member_id === 'manager' && $password === 'manager') {
|
||||
$pdo->prepare("INSERT IGNORE INTO sales_member (member_id, password, name, role) VALUES ('manager', 'manager', '일반매니저', 'manager')")->execute();
|
||||
$pdo->prepare("INSERT IGNORE INTO sales_member (member_id, password, name, role) VALUES ('manager', 'manager', '매니저', 'manager')")->execute();
|
||||
$stmt = $pdo->prepare("SELECT * FROM sales_member WHERE member_id = 'manager'");
|
||||
$stmt->execute();
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
@@ -15,17 +15,137 @@ if (!isset($_SESSION['sales_user'])) {
|
||||
$currentUser = $_SESSION['sales_user'];
|
||||
$pdo = db_connect();
|
||||
|
||||
// 테이블 자동 생성 (없을 경우)
|
||||
$pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS `sales_tenants` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`manager_id` int(11) NOT NULL COMMENT '영업한 영업관리자 ID',
|
||||
`sales_manager_id` int(11) DEFAULT NULL COMMENT '매칭된 매니저 ID (영업관리자 본인 또는 별도 매니저)',
|
||||
`tenant_name` varchar(200) NOT NULL,
|
||||
`representative` varchar(100) DEFAULT NULL,
|
||||
`business_no` varchar(20) DEFAULT NULL,
|
||||
`contact_phone` varchar(20) DEFAULT NULL,
|
||||
`email` varchar(100) DEFAULT NULL,
|
||||
`address` varchar(500) DEFAULT NULL,
|
||||
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sales_tenant_products` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tenant_id` int(11) NOT NULL,
|
||||
`product_name` varchar(200) NOT NULL,
|
||||
`contract_amount` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||||
`commission_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||||
`commission_amount` decimal(15,2) DEFAULT 0.00,
|
||||
`contract_date` date DEFAULT NULL,
|
||||
`operator_confirmed` tinyint(1) DEFAULT 0,
|
||||
`sub_models` text DEFAULT NULL COMMENT '선택모델인 경우 모델 ID 목록 (JSON)',
|
||||
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sales_tenant_scenarios` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tenant_id` int(11) NOT NULL,
|
||||
`scenario_type` varchar(20) NOT NULL DEFAULT 'manager' COMMENT 'sales or manager',
|
||||
`step_id` int(11) NOT NULL,
|
||||
`checkpoint_index` int(11) NOT NULL,
|
||||
`is_checked` tinyint(1) DEFAULT 0,
|
||||
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_unique_step` (`tenant_id`, `scenario_type`, `step_id`, `checkpoint_index`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sales_tenant_consultations` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tenant_id` int(11) NOT NULL,
|
||||
`manager_id` int(11) NOT NULL,
|
||||
`scenario_type` varchar(20) NOT NULL DEFAULT 'manager' COMMENT 'sales or manager',
|
||||
`step_id` int(11) DEFAULT NULL,
|
||||
`log_text` text NOT NULL,
|
||||
`audio_file_path` varchar(500) DEFAULT NULL,
|
||||
`attachment_paths` text DEFAULT NULL,
|
||||
`consultation_type` varchar(20) DEFAULT 'text' COMMENT 'text, audio, file',
|
||||
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
");
|
||||
|
||||
// --- DB Migration (기존 테이블 업데이트) ---
|
||||
try {
|
||||
// 1. sales_tenant_scenarios 테이블에 scenario_type 컬럼 추가
|
||||
$check = $pdo->query("SHOW COLUMNS FROM `sales_tenant_scenarios` LIKE 'scenario_type'")->fetch();
|
||||
if (!$check) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_scenarios` ADD COLUMN `scenario_type` varchar(20) NOT NULL DEFAULT 'manager' AFTER `tenant_id` ");
|
||||
}
|
||||
|
||||
// 2. sales_tenant_consultations 테이블에 scenario_type 컬럼 추가
|
||||
$check2 = $pdo->query("SHOW COLUMNS FROM `sales_tenant_consultations` LIKE 'scenario_type'")->fetch();
|
||||
if (!$check2) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `scenario_type` varchar(20) NOT NULL DEFAULT 'manager' AFTER `manager_id` ");
|
||||
}
|
||||
|
||||
// 3. sales_tenant_scenarios 테이블의 유니크 키 업데이트 (scenario_type 포함)
|
||||
// 인덱스 구성을 확인하여 scenario_type이 포함되어 있지 않으면 재구성
|
||||
$indices = $pdo->query("SHOW INDEX FROM `sales_tenant_scenarios` WHERE Key_name = 'idx_unique_step'")->fetchAll();
|
||||
$hasScenarioTypeInIndex = false;
|
||||
foreach ($indices as $index) {
|
||||
if ($index['Column_name'] === 'scenario_type') {
|
||||
$hasScenarioTypeInIndex = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$hasScenarioTypeInIndex) {
|
||||
try {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_scenarios` DROP INDEX `idx_unique_step` ");
|
||||
} catch (Exception $e) {}
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_scenarios` ADD UNIQUE KEY `idx_unique_step` (`tenant_id`, `scenario_type`, `step_id`, `checkpoint_index`) ");
|
||||
}
|
||||
// 4. sales_tenant_consultations 테이블에 오디오/첨부파일 컬럼 추가
|
||||
$cols = $pdo->query("SHOW COLUMNS FROM `sales_tenant_consultations`")->fetchAll(PDO::FETCH_COLUMN);
|
||||
if (!in_array('audio_file_path', $cols)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `audio_file_path` varchar(500) DEFAULT NULL AFTER `log_text` ");
|
||||
}
|
||||
if (!in_array('attachment_paths', $cols)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `attachment_paths` text DEFAULT NULL AFTER `audio_file_path` ");
|
||||
}
|
||||
if (!in_array('consultation_type', $cols)) {
|
||||
$pdo->exec("ALTER TABLE `sales_tenant_consultations` ADD COLUMN `consultation_type` varchar(20) DEFAULT 'text' AFTER `attachment_paths` ");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Migration error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($action === 'list_tenants') {
|
||||
// 운영자는 모든 테넌트, 영업관리/매니저는 본인 소속 테넌트만
|
||||
if ($currentUser['role'] === 'operator') {
|
||||
$stmt = $pdo->prepare("SELECT t.*, m.name as manager_name FROM sales_tenants t JOIN sales_member m ON t.manager_id = m.id ORDER BY t.created_at DESC");
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT t.*, m.name as register_name, m2.name as manager_name, m2.role as manager_role
|
||||
FROM sales_tenants t
|
||||
JOIN sales_member m ON t.manager_id = m.id
|
||||
LEFT JOIN sales_member m2 ON t.sales_manager_id = m2.id
|
||||
ORDER BY t.created_at DESC
|
||||
");
|
||||
$stmt->execute();
|
||||
} else {
|
||||
$stmt = $pdo->prepare("SELECT * FROM sales_tenants WHERE manager_id = ? ORDER BY created_at DESC");
|
||||
$stmt->execute([$currentUser['id']]);
|
||||
// 내가 영업했거나, 내가 매니저로 배정된 테넌트
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT t.*, m.name as register_name, m2.name as manager_name, m2.role as manager_role
|
||||
FROM sales_tenants t
|
||||
JOIN sales_member m ON t.manager_id = m.id
|
||||
LEFT JOIN sales_member m2 ON t.sales_manager_id = m2.id
|
||||
WHERE t.manager_id = ? OR t.sales_manager_id = ?
|
||||
ORDER BY t.created_at DESC
|
||||
");
|
||||
$stmt->execute([$currentUser['id'], $currentUser['id']]);
|
||||
}
|
||||
$tenants = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode(['success' => true, 'data' => $tenants]);
|
||||
@@ -54,11 +174,52 @@ try {
|
||||
$stmt->execute([$currentUser['id']]);
|
||||
$stats = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
echo json_encode(['success' => true, 'data' => $stats]);
|
||||
} elseif ($action === 'get_scenario') {
|
||||
$tenant_id = $_GET['tenant_id'] ?? null;
|
||||
$scenario_type = $_GET['scenario_type'] ?? 'manager';
|
||||
if (!$tenant_id) throw new Exception("테넌트 ID가 필요합니다.");
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM sales_tenant_scenarios WHERE tenant_id = ? AND scenario_type = ?");
|
||||
$stmt->execute([$tenant_id, $scenario_type]);
|
||||
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $results]);
|
||||
|
||||
} elseif ($action === 'get_consultations') {
|
||||
$tenant_id = $_GET['tenant_id'] ?? null;
|
||||
$scenario_type = $_GET['scenario_type'] ?? 'manager';
|
||||
$step_id = $_GET['step_id'] ?? null;
|
||||
if (!$tenant_id) throw new Exception("테넌트 ID가 필요합니다.");
|
||||
|
||||
$sql = "SELECT * FROM sales_tenant_consultations WHERE tenant_id = ? AND scenario_type = ?";
|
||||
$params = [$tenant_id, $scenario_type];
|
||||
if ($step_id) {
|
||||
$sql .= " AND step_id = ?";
|
||||
$params[] = $step_id;
|
||||
}
|
||||
$sql .= " ORDER BY created_at DESC";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode(['success' => true, 'data' => $results]);
|
||||
} elseif ($action === 'list_managers') {
|
||||
// 매니저로 매칭 가능한 사람 목록 (영업관리 또는 매니저 직급)
|
||||
$stmt = $pdo->prepare("SELECT id, name, role, member_id FROM sales_member WHERE role IN ('영업관리', '매니저') AND is_active = 1 ORDER BY name ASC");
|
||||
$stmt->execute();
|
||||
$managers = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode(['success' => true, 'data' => $managers]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
// multipart/form-data인 경우 $_POST 사용, 아니면 JSON 입력 사용
|
||||
if (empty($_POST)) {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
} else {
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
if ($action === 'create_tenant') {
|
||||
$tenant_name = $data['tenant_name'] ?? '';
|
||||
@@ -67,11 +228,12 @@ try {
|
||||
$contact_phone = $data['contact_phone'] ?? '';
|
||||
$email = $data['email'] ?? '';
|
||||
$address = $data['address'] ?? '';
|
||||
$sales_manager_id = $data['sales_manager_id'] ?? $currentUser['id']; // 지정 안하면 본인
|
||||
|
||||
if (!$tenant_name) throw new Exception("업체명은 필수입니다.");
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenants (manager_id, tenant_name, representative, business_no, contact_phone, email, address) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$currentUser['id'], $tenant_name, $representative, $business_no, $contact_phone, $email, $address]);
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenants (manager_id, sales_manager_id, tenant_name, representative, business_no, contact_phone, email, address) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$currentUser['id'], $sales_manager_id, $tenant_name, $representative, $business_no, $contact_phone, $email, $address]);
|
||||
|
||||
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId(), 'message' => '테넌트가 등록되었습니다.']);
|
||||
|
||||
@@ -81,11 +243,14 @@ try {
|
||||
$contract_amount = $data['contract_amount'] ?? 0;
|
||||
$commission_rate = $data['commission_rate'] ?? 0;
|
||||
$contract_date = $data['contract_date'] ?? date('Y-m-d');
|
||||
$sub_models = isset($data['sub_models']) ? json_encode($data['sub_models']) : null;
|
||||
|
||||
if (!$tenant_id || !$product_name) throw new Exception("필수 정보가 누락되었습니다.");
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenant_products (tenant_id, product_name, contract_amount, commission_rate, contract_date) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$tenant_id, $product_name, $contract_amount, $commission_rate, $contract_date]);
|
||||
$commission_amount = ($contract_amount * $commission_rate) / 100;
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenant_products (tenant_id, product_name, contract_amount, commission_rate, commission_amount, contract_date, sub_models) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$tenant_id, $product_name, $contract_amount, $commission_rate, $commission_amount, $contract_date, $sub_models]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => '상품 계약 정보가 등록되었습니다.']);
|
||||
|
||||
@@ -101,9 +266,174 @@ try {
|
||||
$stmt->execute([$confirmed, $product_id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => $confirmed ? '승인되었습니다.' : '승인이 취소되었습니다.']);
|
||||
} elseif ($action === 'update_checklist') {
|
||||
$tenant_id = $data['tenant_id'] ?? null;
|
||||
$scenario_type = $data['scenario_type'] ?? 'manager';
|
||||
$step_id = $data['step_id'] ?? null;
|
||||
$checkpoint_index = $data['checkpoint_index'] ?? null;
|
||||
$is_checked = $data['is_checked'] ? 1 : 0;
|
||||
|
||||
if (!$tenant_id || $step_id === null || $checkpoint_index === null) throw new Exception("필수 파라미터가 누락되었습니다.");
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO sales_tenant_scenarios (tenant_id, scenario_type, step_id, checkpoint_index, is_checked)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE is_checked = VALUES(is_checked)
|
||||
");
|
||||
$stmt->execute([$tenant_id, $scenario_type, $step_id, $checkpoint_index, $is_checked]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
|
||||
} elseif ($action === 'save_consultation') {
|
||||
$tenant_id = $data['tenant_id'] ?? null;
|
||||
$scenario_type = $data['scenario_type'] ?? 'manager';
|
||||
$step_id = $data['step_id'] ?? null;
|
||||
$log_text = $data['log_text'] ?? '';
|
||||
$consultation_type = $data['consultation_type'] ?? 'text';
|
||||
$audio_file_path = null;
|
||||
|
||||
if (!$tenant_id || !$step_id) throw new Exception("필수 정보가 누락되었습니다.");
|
||||
|
||||
// 오디오 파일 업로드 처리
|
||||
if ($consultation_type === 'audio' && isset($_FILES['audio_file'])) {
|
||||
$upload_dir = __DIR__ . "/../uploads/consultations/" . $tenant_id . "/";
|
||||
if (!file_exists($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||
|
||||
$file_ext = pathinfo($_FILES['audio_file']['name'], PATHINFO_EXTENSION) ?: 'webm';
|
||||
$file_name = "audio_" . date('Ymd_His') . "_" . uniqid() . "." . $file_ext;
|
||||
$audio_file_path = "uploads/consultations/" . $tenant_id . "/" . $file_name;
|
||||
|
||||
if (!move_uploaded_file($_FILES['audio_file']['tmp_name'], __DIR__ . "/../" . $audio_file_path)) {
|
||||
throw new Exception("오디오 파일 저장 실패");
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenant_consultations (tenant_id, manager_id, scenario_type, step_id, log_text, audio_file_path, consultation_type) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$tenant_id, $currentUser['id'], $scenario_type, $step_id, $log_text, $audio_file_path, $consultation_type]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => '기록이 저장되었습니다.']);
|
||||
} elseif ($action === 'upload_attachments') {
|
||||
$tenant_id = $data['tenant_id'] ?? null;
|
||||
$scenario_type = $data['scenario_type'] ?? 'manager';
|
||||
$step_id = $data['step_id'] ?? null;
|
||||
|
||||
if (!$tenant_id || !$step_id || !isset($_FILES['files'])) throw new Exception("필수 정보가 누락되었습니다.");
|
||||
|
||||
$upload_dir = __DIR__ . "/../uploads/attachments/" . $tenant_id . "/";
|
||||
if (!file_exists($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||
|
||||
$saved_paths = [];
|
||||
$files = $_FILES['files'];
|
||||
$count = is_array($files['name']) ? count($files['name']) : 1;
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$tmp_name = is_array($files['tmp_name']) ? $files['tmp_name'][$i] : $files['tmp_name'];
|
||||
$name = is_array($files['name']) ? $files['name'][$i] : $files['name'];
|
||||
|
||||
if (is_uploaded_file($tmp_name)) {
|
||||
$file_name = date('Ymd_His') . "_" . uniqid() . "_" . $name;
|
||||
$save_path = "uploads/attachments/" . $tenant_id . "/" . $file_name;
|
||||
if (move_uploaded_file($tmp_name, __DIR__ . "/../" . $save_path)) {
|
||||
$saved_paths[] = [
|
||||
'name' => $name,
|
||||
'path' => $save_path,
|
||||
'size' => is_array($files['size']) ? $files['size'][$i] : $files['size']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($saved_paths)) throw new Exception("저장된 파일이 없습니다.");
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO sales_tenant_consultations (tenant_id, manager_id, scenario_type, step_id, log_text, attachment_paths, consultation_type) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$tenant_id, $currentUser['id'], $scenario_type, $step_id, '첨부파일 업로드', json_encode($saved_paths, JSON_UNESCAPED_UNICODE), 'file']);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => '파일이 업로드되었습니다.']);
|
||||
} elseif ($action === 'delete_consultation') {
|
||||
$id = $data['id'] ?? null;
|
||||
if (!$id) throw new Exception("ID가 누락되었습니다.");
|
||||
|
||||
// 파일 삭제를 위해 정보 조회
|
||||
$stmt = $pdo->prepare("SELECT audio_file_path, attachment_paths FROM sales_tenant_consultations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$c = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($c) {
|
||||
if ($c['audio_file_path'] && file_exists(__DIR__ . "/../" . $c['audio_file_path'])) {
|
||||
@unlink(__DIR__ . "/../" . $c['audio_file_path']);
|
||||
}
|
||||
if ($c['attachment_paths']) {
|
||||
$paths = json_decode($c['attachment_paths'], true);
|
||||
if (is_array($paths)) {
|
||||
foreach ($paths as $p) {
|
||||
if (isset($p['path']) && file_exists(__DIR__ . "/../" . $p['path'])) {
|
||||
@unlink(__DIR__ . "/../" . $p['path']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM sales_tenant_consultations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
echo json_encode(['success' => true, 'message' => '성공적으로 삭제되었습니다.']);
|
||||
} elseif ($action === 'delete_product') {
|
||||
$product_id = $data['id'] ?? null;
|
||||
if (!$product_id) throw new Exception("ID가 누락되었습니다.");
|
||||
|
||||
// 승인되지 않은 것만 삭제 가능하도록 보안 체크 (영업관리자 관점)
|
||||
$stmt = $pdo->prepare("SELECT operator_confirmed FROM sales_tenant_products WHERE id = ?");
|
||||
$stmt->execute([$product_id]);
|
||||
$p = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$p) throw new Exception("해당 정보를 찾을 수 없습니다.");
|
||||
if ($p['operator_confirmed'] == 1) throw new Exception("이미 승인된 계약은 삭제할 수 없습니다.");
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM sales_tenant_products WHERE id = ?");
|
||||
$stmt->execute([$product_id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => '성공적으로 삭제되었습니다.']);
|
||||
} elseif ($action === 'update_tenant_manager') {
|
||||
$tenant_id = isset($data['tenant_id']) ? intval($data['tenant_id']) : null;
|
||||
$sales_manager_id = isset($data['sales_manager_id']) ? $data['sales_manager_id'] : null;
|
||||
|
||||
if (!$tenant_id) throw new Exception("테넌트 ID가 누락되었습니다.");
|
||||
|
||||
// manager_id가 0이거나 empty면 null로 처리 (지정 취소)
|
||||
$manager_val = (!empty($sales_manager_id)) ? intval($sales_manager_id) : null;
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE sales_tenants SET sales_manager_id = ? WHERE id = ?");
|
||||
$stmt->execute([$manager_val, $tenant_id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => $manager_val ? '담당 매니저가 지정되었습니다.' : '담당 매니저 지정이 취소되었습니다.']);
|
||||
} elseif ($action === 'update_product') {
|
||||
$product_id = $data['id'] ?? null;
|
||||
$product_name = $data['product_name'] ?? '';
|
||||
$contract_amount = $data['contract_amount'] ?? 0;
|
||||
$commission_rate = $data['commission_rate'] ?? 0;
|
||||
$contract_date = $data['contract_date'] ?? date('Y-m-d');
|
||||
$sub_models = isset($data['sub_models']) ? json_encode($data['sub_models']) : null;
|
||||
|
||||
if (!$product_id || !$product_name) throw new Exception("필수 정보가 누락되었습니다.");
|
||||
|
||||
// 보안 체크: 승인된 것은 수정 불가
|
||||
$stmt = $pdo->prepare("SELECT operator_confirmed FROM sales_tenant_products WHERE id = ?");
|
||||
$stmt->execute([$product_id]);
|
||||
$p = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$p) throw new Exception("해당 정보를 찾을 수 없습니다.");
|
||||
if ($p['operator_confirmed'] == 1) throw new Exception("이미 승인된 계약은 수정할 수 없습니다.");
|
||||
|
||||
$commission_amount = ($contract_amount * $commission_rate) / 100;
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE sales_tenant_products SET product_name = ?, contract_amount = ?, commission_rate = ?, commission_amount = ?, contract_date = ?, sub_models = ? WHERE id = ?");
|
||||
$stmt->execute([$product_name, $contract_amount, $commission_rate, $commission_amount, $contract_date, $sub_models, $product_id]);
|
||||
|
||||
echo json_encode(['success' => true, 'message' => '계약 정보가 수정되었습니다.']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 340 KiB |
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user