« Back to History
add.php
|
20260727_165406.php
v.2
Copy Code
<?php require_once __DIR__ . '/../includes/bootstrap.php'; require_once __DIR__ . '/../includes/header.php'; require_once __DIR__ . '/../includes/sidebar.php'; $message = ''; $errMessage = ''; $default_license_type = 'Trial'; $default_trial_days = 14; $default_start_date = date('Y-m-d'); try { $tenantStmt = $pdo->query("SELECT tenant_id, tenant_name, tenant_code FROM tenant_master WHERE status = 'ACTIVE' ORDER BY tenant_name ASC"); $tenants = $tenantStmt->fetchAll(); } catch (PDOException $e) { $tenants = []; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; $tenant_id = (int)($_POST['tenant_id'] ?? 0); $company_name = trim($_POST['company_name'] ?? ''); $company_code = strtoupper(trim($_POST['company_code'] ?? '')); $company_address = trim($_POST['company_address'] ?? ''); $primary_domain = trim($_POST['primary_domain'] ?? ''); $total_machines = max(1, (int)($_POST['total_machines'] ?? 1)); $deployment_type = 'DEDICATED'; // Machine Setup Parameters $machine_type = trim($_POST['machine_type'] ?? 'Power Loom'); $group_slug = trim($_POST['group_slug'] ?? 'loom'); $prefix = trim($_POST['prefix'] ?? 'M'); $start_no = (int)($_POST['start_no'] ?? 1); $pad_width = (int)($_POST['pad_width'] ?? 3); $db_host = trim($_POST['db_host'] ?? 'localhost'); $db_port = trim($_POST['db_port'] ?? '3306'); $db_name = trim($_POST['db_name'] ?? ''); $db_user = trim($_POST['db_user'] ?? ''); $db_pass = trim($_POST['db_pass'] ?? ''); $lic_days = (int)($_POST['trial_days'] ?? 14); $lic_start_date = trim($_POST['license_start_date'] ?? date('Y-m-d')); $lic_end_date = date('Y-m-d 23:59:59', strtotime($lic_start_date . ' +' . $lic_days . ' days')); if ($action === 'test_connection') { try { if (empty($db_host) || empty($db_name) || empty($db_user)) { throw new Exception("Database connection test requires Host, Name, and Username."); } $dsn = "mysql:host={$db_host};port={$db_port};dbname={$db_name};charset=utf8mb4"; $test_pdo = new PDO($dsn, $db_user, $db_pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 5 ]); $message = "SUCCESS: Database connectivity established successfully."; } catch (Exception $e) { $errMessage = "CONNECTION FAILED: " . $e->getMessage(); } } elseif ($action === 'create_company') { if ($tenant_id > 0 && !empty($company_name) && !empty($company_code) && !empty($company_address) && !empty($primary_domain) && !empty($db_name) && !empty($db_user) && $total_machines > 0) { try { // 1. Connect to Client Target DB try { $dsn = "mysql:host={$db_host};port={$db_port};dbname={$db_name};charset=utf8mb4"; $target_pdo = new PDO($dsn, $db_user, $db_pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 5 ]); } catch (PDOException $e) { throw new Exception("Target Client Database Connection Failed: " . $e->getMessage()); } // --- BEGIN TRANSACTION ON BOTH DATABASES --- $pdo->beginTransaction(); $target_pdo->beginTransaction(); // 2. Duplicate Code Check $checkCode = $pdo->prepare("SELECT id FROM company_master WHERE UPPER(company_code) = ? LIMIT 1"); $checkCode->execute([$company_code]); if ($checkCode->fetch()) { throw new Exception("Provisioning Blocked: Company code already exists."); } // 3. Save to Central company_master (Admin DB) $stmt = $pdo->prepare("INSERT INTO company_master ( tenant_id, company_name, company_code, company_address, deployment_type, primary_domain, total_machines, db_host, db_name, db_user, db_pass, setup_status, status ) VALUES (?, ?, ?, ?, 'DEDICATED', ?, ?, ?, ?, ?, ?, 'COMPLETED', 'ACTIVE')"); $stmt->execute([ $tenant_id, $company_name, $company_code, $company_address, $primary_domain, $total_machines, $db_host, $db_name, $db_user, $db_pass ]); $new_company_id = $pdo->lastInsertId(); // 4. Save License $licStmt = $pdo->prepare("INSERT INTO trial_licenses (company_id, start_date, end_date, status) VALUES (?, ?, ?, 'ACTIVE')"); $licStmt->execute([ $new_company_id, date('Y-m-d 00:00:00', strtotime($lic_start_date)), $lic_end_date ]); // ======================================================== // CLIENT DB STRUCTURAL PROVISIONING & AUTOMATIC MACHINE SETUP // ======================================================== // A. Provision Client 'companies' Table $target_pdo->exec("CREATE TABLE IF NOT EXISTS `companies` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `short_name` varchar(100) DEFAULT NULL, `address` text DEFAULT NULL, `location` varchar(255) DEFAULT NULL, `login_code` varchar(50) DEFAULT NULL, `total_machines` int(11) DEFAULT 0, `is_active` tinyint(4) DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); $targetCompanyStmt = $target_pdo->prepare("INSERT INTO companies (id, name, short_name, address, location, login_code, total_machines, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, 1)"); $targetCompanyStmt->execute([ $new_company_id, $company_name, $company_code, $company_address, 'Surat', $company_code, $total_machines ]); // B. Provision Client 'users' Table $target_pdo->exec("CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `employee_id` int(11) DEFAULT NULL, `company_id` int(11) DEFAULT NULL, `department_id` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `username` varchar(150) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `dp_url` varchar(255) DEFAULT NULL, `password_hash` varchar(255) DEFAULT NULL, `password_plain` varchar(100) DEFAULT NULL, `role` varchar(50) DEFAULT NULL, `is_active` tinyint(4) DEFAULT 1, `created_at` datetime DEFAULT current_timestamp(), `mobile` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); $default_username = strtolower($company_code) . "_owner"; $default_plain_pass = "12345678"; $default_hash_pass = password_hash($default_plain_pass, PASSWORD_BCRYPT); $targetUserStmt = $target_pdo->prepare("INSERT INTO users (company_id, name, username, password_hash, password_plain, role, is_active, created_at) VALUES (?, ?, ?, ?, ?, 'Owner', 1, NOW())"); $targetUserStmt->execute([ $new_company_id, $company_name . " Owner", $default_username, $default_hash_pass, $default_plain_pass ]); $owner_user_id = $target_pdo->lastInsertId(); // C. Provision Client 'machines' Table & Bulk Insert Machines Automatically $target_pdo->exec("CREATE TABLE IF NOT EXISTS `machines` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(100) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `machine_type` varchar(100) DEFAULT NULL, `group_slug` varchar(100) DEFAULT 'loom', `company_id` int(11) DEFAULT NULL, `is_active` tinyint(4) DEFAULT 1, `status` varchar(50) DEFAULT 'Active', `created_by` int(11) DEFAULT NULL, `updated_by` int(11) DEFAULT NULL, `created_at` datetime DEFAULT current_timestamp(), `updated_at` datetime DEFAULT current_timestamp(), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); $now = date('Y-m-d H:i:s'); $sql_machine = "INSERT INTO machines (code, name, machine_type, group_slug, company_id, is_active, status, created_by, updated_by, created_at, updated_at) VALUES (:code, :name, :machine_type, :group_slug, :company_id, 1, 'Active', :created_by, :updated_by, :created_at, :updated_at)"; $stmt_m = $target_pdo->prepare($sql_machine); for ($i = 0; $i < $total_machines; $i++) { $num = $start_no + $i; $num_str = $pad_width > 0 ? str_pad((string)$num, $pad_width, '0', STR_PAD_LEFT) : (string)$num; $code = ($prefix !== '' ? trim($prefix) . ' ' : '') . $num_str; $name = $machine_type . ' ' . $num_str; $stmt_m->execute([ ':code' => $code, ':name' => $name, ':machine_type' => $machine_type, ':group_slug' => $group_slug, ':company_id' => $new_company_id, ':created_by' => $owner_user_id, ':updated_by' => $owner_user_id, ':created_at' => $now, ':updated_at' => $now, ]); } // --- COMMIT BOTH TRANSACTIONS --- $target_pdo->commit(); $pdo->commit(); $message = "Company & Machines Provisioned Successfully!\n" . "Company Code: {$company_code}\n" . "Total Machines Created: {$total_machines} ({$machine_type})\n" . "Default Owner Username: {$default_username}\n" . "Default Password: {$default_plain_pass}"; $_POST = []; } catch (Exception $e) { if ($target_pdo->inTransaction()) $target_pdo->rollBack(); if ($pdo->inTransaction()) $pdo->rollBack(); $errMessage = "Provisioning Failed: " . $e->getMessage(); } } else { $errMessage = "Validation Failure: Please fill all required input fields."; } } } ?> <div class="container-fluid px-4 py-3"> <div class="d-flex justify-content-between align-items-center mb-4 border-bottom pb-3"> <div> <h3 class="m-0 fw-bold text-dark">Company & Machine Provisioning Console</h3> <small class="text-muted">Mister Manager Cloud ERP Core Orchestrator Infrastructure</small> </div> <div> <a href="/admin/company/list.php" class="btn btn-sm btn-outline-secondary px-3">Company Registry List</a> </div> </div> <?php if (!empty($message)): ?> <div class="alert alert-success border-0 shadow-sm p-3 mb-4"> <strong class="d-block fw-bold text-success">PROVISIONING COMPLETE</strong> <span style="white-space: pre-line;"><?= htmlspecialchars($message) ?></span> </div> <?php endif; ?> <?php if (!empty($errMessage)): ?> <div class="alert alert-danger border-0 shadow-sm p-3 mb-4"> <strong class="d-block fw-bold text-danger">PROVISIONING ERROR</strong> <?= htmlspecialchars($errMessage) ?> </div> <?php endif; ?> <form action="add.php" method="POST" id="provisioningForm"> <input type="hidden" name="action" id="formAction" value="create_company"> <div class="row g-4"> <div class="col-xl-8 col-lg-7"> <!-- SECTION 1: Customer Linkage --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white py-3 border-0"> <span class="badge bg-secondary mb-1">SECTION 01</span> <h5 class="m-0 fw-bold text-dark">Customer / Tenant Linkage</h5> </div> <div class="card-body pt-0"> <select name="tenant_id" class="form-select form-select-sm" required> <option value="">-- Bind Active Customer Profile --</option> <?php foreach ($tenants as $t): ?> <option value="<?= $t['tenant_id'] ?>" <?= (($_POST['tenant_id'] ?? '') == $t['tenant_id']) ? 'selected' : '' ?>> <?= htmlspecialchars($t['tenant_name']) ?> [<?= htmlspecialchars($t['tenant_code']) ?>] </option> <?php endforeach; ?> </select> </div> </div> <!-- SECTION 2: Company Profile --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white py-3 border-0"> <span class="badge bg-secondary mb-1">SECTION 02</span> <h5 class="m-0 fw-bold text-dark">Company Details Matrix</h5> </div> <div class="card-body pt-0"> <div class="row g-3"> <div class="col-md-6"> <label class="form-label small fw-semibold">Company Name *</label> <input type="text" name="company_name" value="<?= htmlspecialchars($_POST['company_name'] ?? '') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-6"> <label class="form-label small fw-semibold">System Company Code *</label> <input type="text" name="company_code" placeholder="e.g. MST002" value="<?= htmlspecialchars($_POST['company_code'] ?? '') ?>" class="form-control form-control-sm text-uppercase" required> </div> <div class="col-md-12"> <label class="form-label small fw-semibold">Primary Domain *</label> <input type="text" name="primary_domain" placeholder="tenant.mistermanager.in" value="<?= htmlspecialchars($_POST['primary_domain'] ?? '') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-12"> <label class="form-label small fw-semibold">Registered Company Address *</label> <textarea name="company_address" class="form-control form-control-sm" rows="2" required><?= htmlspecialchars($_POST['company_address'] ?? '') ?></textarea> </div> </div> </div> </div> <!-- SECTION 3: Automatic Machine Bulk Provisioning Config --> <div class="card border-0 shadow-sm mb-4 border-start border-4 border-primary"> <div class="card-header bg-white py-3 border-0"> <span class="badge bg-primary mb-1">SECTION 03</span> <h5 class="m-0 fw-bold text-dark">Machine Setup & Provisioning Configuration</h5> </div> <div class="card-body pt-0"> <div class="row g-3"> <div class="col-md-4"> <label class="form-label small fw-semibold text-primary">Total Machines Count *</label> <input type="number" name="total_machines" min="1" value="<?= htmlspecialchars($_POST['total_machines'] ?? '12') ?>" class="form-control form-control-sm fw-bold border-primary" required> </div> <div class="col-md-4"> <label class="form-label small fw-semibold">Machine Type *</label> <select name="machine_type" class="form-select form-select-sm" required> <option value="Power Loom" <?= (($_POST['machine_type'] ?? '') === 'Power Loom') ? 'selected' : '' ?>>Power Loom</option> <option value="Shuttle Loom" <?= (($_POST['machine_type'] ?? '') === 'Shuttle Loom') ? 'selected' : '' ?>>Shuttle Loom</option> <option value="Rapier" <?= (($_POST['machine_type'] ?? '') === 'Rapier') ? 'selected' : '' ?>>Rapier</option> <option value="TFO" <?= (($_POST['machine_type'] ?? '') === 'TFO') ? 'selected' : '' ?>>TFO</option> <option value="Zari" <?= (($_POST['machine_type'] ?? '') === 'Zari') ? 'selected' : '' ?>>Zari</option> <option value="Other" <?= (($_POST['machine_type'] ?? '') === 'Other') ? 'selected' : '' ?>>Other</option> </select> </div> <div class="col-md-4"> <label class="form-label small fw-semibold">Group Slug *</label> <select name="group_slug" class="form-select form-select-sm" required> <option value="loom">Loom</option> <option value="zari">Zari</option> <option value="rapier">Rapier</option> <option value="tfo">TFO</option> <option value="palti">Palti</option> <option value="other">Other</option> </select> </div> <div class="col-md-4"> <label class="form-label small fw-semibold">Code Prefix</label> <input type="text" name="prefix" value="<?= htmlspecialchars($_POST['prefix'] ?? 'L') ?>" class="form-control form-control-sm" placeholder="e.g. L"> </div> <div class="col-md-4"> <label class="form-label small fw-semibold">Start Number</label> <input type="number" name="start_no" value="<?= htmlspecialchars($_POST['start_no'] ?? '1') ?>" min="0" class="form-control form-control-sm"> </div> <div class="col-md-4"> <label class="form-label small fw-semibold">Pad Width (e.g. 3 → 001)</label> <input type="number" name="pad_width" value="<?= htmlspecialchars($_POST['pad_width'] ?? '3') ?>" min="0" class="form-control form-control-sm"> </div> </div> </div> </div> <!-- SECTION 4: Database Topology --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white py-3 border-0"> <span class="badge bg-secondary mb-1">SECTION 04</span> <h5 class="m-0 fw-bold text-dark">Target Database Configuration</h5> </div> <div class="card-body pt-0"> <div class="row g-3"> <div class="col-md-9"> <label class="form-label small fw-semibold">DB Host *</label> <input type="text" name="db_host" value="<?= htmlspecialchars($_POST['db_host'] ?? 'localhost') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-3"> <label class="form-label small fw-semibold">Port *</label> <input type="number" name="db_port" value="<?= htmlspecialchars($_POST['db_port'] ?? '3306') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-12"> <label class="form-label small fw-semibold">Target DB Name *</label> <input type="text" name="db_name" value="<?= htmlspecialchars($_POST['db_name'] ?? '') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-6"> <label class="form-label small fw-semibold">DB User Access Key *</label> <input type="text" name="db_user" value="<?= htmlspecialchars($_POST['db_user'] ?? '') ?>" class="form-control form-control-sm" required> </div> <div class="col-md-6"> <label class="form-label small fw-semibold">DB Password</label> <input type="password" name="db_pass" value="<?= htmlspecialchars($_POST['db_pass'] ?? '') ?>" class="form-control form-control-sm"> </div> </div> <div class="mt-3 text-end"> <button type="button" id="btnTestConnection" class="btn btn-sm btn-dark">Test Target DB Connection</button> </div> </div> </div> <!-- SECTION 5: License Config --> <div class="card border-0 shadow-sm mb-4"> <div class="card-header bg-white py-3 border-0"> <span class="badge bg-secondary mb-1">SECTION 05</span> <h5 class="m-0 fw-bold text-dark">License Configuration</h5> </div> <div class="card-body pt-0"> <div class="row g-3"> <div class="col-md-6"> <label class="form-label small fw-semibold">Trial Duration (Days)</label> <input type="number" name="trial_days" value="<?= htmlspecialchars($_POST['trial_days'] ?? $default_trial_days) ?>" class="form-control form-control-sm" required> </div> <div class="col-md-6"> <label class="form-label small fw-semibold">Start Date</label> <input type="date" name="license_start_date" value="<?= htmlspecialchars($_POST['license_start_date'] ?? $default_start_date) ?>" class="form-control form-control-sm" required> </div> </div> </div> </div> </div> <!-- Controls Panel --> <div class="col-xl-4 col-lg-5"> <div class="card border-0 shadow-sm bg-dark text-white p-3 position-sticky" style="top: 20px;"> <h5 class="fw-bold text-white mb-3">Provisioning Action</h5> <p class="small text-white-50">Submitting will build target tables, default Owner user account, and auto-generate specified machines in client database.</p> <div class="d-grid gap-2 mt-3"> <button type="submit" id="btnExecuteProvision" class="btn btn-success fw-bold text-uppercase py-2">Create Company & Setup Machines</button> </div> </div> </div> </div> </form> </div> <script> document.addEventListener('DOMContentLoaded', function() { const form = document.getElementById('provisioningForm'); const formAction = document.getElementById('formAction'); const btnTestConnection = document.getElementById('btnTestConnection'); btnTestConnection.addEventListener('click', function() { formAction.value = 'test_connection'; form.submit(); }); }); </script> <?php require_once __DIR__ . '/../includes/footer.php'; ?>