diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..0666ffa --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,18 @@ + +body { + font-family: 'Inter', sans-serif; + background-color: #F8F9FA; +} + +.navbar-brand { + font-weight: 600; +} + +.header-gradient { + background: linear-gradient(90deg, #0d6efd 0%, #0d6efd 100%); + color: white; +} + +.card-header { + font-weight: 500; +} diff --git a/db/config.php b/db/config.php index 2162f3c..6a7203f 100644 --- a/db/config.php +++ b/db/config.php @@ -1,7 +1,7 @@ + + + + + + diff --git a/header.php b/header.php new file mode 100644 index 0000000..8239755 --- /dev/null +++ b/header.php @@ -0,0 +1,45 @@ + + + + + + + vipanalisa + + + + + + + + + + + + + + + + + + diff --git a/import.php b/import.php new file mode 100644 index 0000000..aa8ffa8 --- /dev/null +++ b/import.php @@ -0,0 +1,124 @@ + +beginTransaction(); + + $success_count = 0; + $error_count = 0; + $errors = []; + + try { + $handle = fopen($file, "r"); + $header = fgetcsv($handle, 1000, ","); // Read header row + + // Prepare statement for checking duplicates + $check_stmt = $pdo->prepare("SELECT COUNT(*) FROM tabelmaster WHERE NO_FAKTUR = ? AND NAMA_SALES = ? AND TANGGAL = ?"); + + // Prepare statement for insertion + $insert_stmt = $pdo->prepare("INSERT INTO tabelmaster (NAMA_SALES, TANGGAL, NO_FAKTUR, MERK, OUTLET, PRODUK, QTY, HARGA, BULAN, TAHUN, PERIODE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + + $row_number = 1; + while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { + $row_number++; + if (count($data) !== 11) { + $errors[] = "Row {$row_number}: Invalid column count."; + $error_count++; + continue; + } + + // Assign variables from CSV data + list($nama_sales, $tanggal, $no_faktur, $merk, $outlet, $produk, $qty, $harga, $bulan, $tahun, $periode) = $data; + + // Basic Validation + $check_stmt->execute([$no_faktur, $nama_sales, $tanggal]); + if ($check_stmt->fetchColumn() > 0) { + $errors[] = "Row {$row_number}: Duplicate record found for NO_FAKTUR {$no_faktur}, NAMA_SALES {$nama_sales}, TANGGAL {$tanggal}."; + $error_count++; + continue; + } + + // Data Normalization + $harga_numeric = str_replace(['Rp', '.', ','], '', $harga); + + // Insert data + $insert_stmt->execute([ + $nama_sales, $tanggal, $no_faktur, $merk, $outlet, $produk, + (int)$qty, $harga_numeric, (int)$bulan, (int)$tahun, $periode + ]); + + $success_count++; + } + fclose($handle); + + $pdo->commit(); + $import_summary = ['success' => $success_count, 'errors' => $error_count, 'error_details' => $errors]; + + } catch (Exception $e) { + $pdo->rollBack(); + $error_message = "An error occurred during import: " . $e->getMessage(); + } + } else { + $error_message = "File upload failed. Please try again."; + } +} + +require_once 'header.php'; +?> + +
+ + + + + +
+
Import Summary
+
+

Successfully imported records.

+

Failed to import records.

+ +
+
Error Details:
+
    + +
  • -
  • + +
+ +
+
+ + +
+
+ Import Data from CSV +
+
+
+
+ + +
+
+ CSV Format: The file must have 11 columns in the following order:
+ NAMA_SALES, TANGGAL, NO_FAKTUR, MERK, OUTLET, PRODUK, QTY, HARGA, BULAN, TAHUN, PERIODE +
The first row should be the header and will be skipped. +
+ +
+
+
+
+ + diff --git a/index.php b/index.php index 7205f3d..6003891 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,291 @@ query('SELECT DISTINCT NAMA_SALES FROM tabelmaster WHERE NAMA_SALES IS NOT NULL AND NAMA_SALES != "" ORDER BY NAMA_SALES'); + $sales_options = $sales_options_stmt->fetchAll(PDO::FETCH_COLUMN); + + $periode_options_stmt = $pdo->query('SELECT DISTINCT PERIODE FROM tabelmaster WHERE PERIODE IS NOT NULL AND PERIODE != "" ORDER BY PERIODE DESC'); + $periode_options = $periode_options_stmt->fetchAll(PDO::FETCH_COLUMN); + + // Handle form submission for analysis + $analysis_results = []; + $chart_labels_json = '[]'; + $chart_data_json = '[]'; + $selected_sales = $_POST['nama_sales'] ?? 'all'; + $selected_periode = $_POST['periode'] ?? 'all'; + + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['run_analysis'])) { + $sql = " + SELECT + MERK, + SUM(QTY) as total_qty, + SUM(QTY * CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as total_omzet, + AVG(CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as avg_price, + COUNT(DISTINCT NO_FAKTUR) as transactions_count + FROM + tabelmaster + WHERE 1=1"; + + $params = []; + if ($selected_sales !== 'all') { + $sql .= ' AND NAMA_SALES = :nama_sales'; + $params[':nama_sales'] = $selected_sales; + } + if ($selected_periode !== 'all') { + $sql .= ' AND PERIODE = :periode'; + $params[':periode'] = $selected_periode; + } + + $sql .= ' GROUP BY MERK HAVING SUM(QTY) > 0 ORDER BY total_omzet DESC'; + + $analysis_stmt = $pdo->prepare($sql); + $analysis_stmt->execute($params); + $analysis_results = $analysis_stmt->fetchAll(); + + if (!empty($analysis_results)) { + $chart_labels = []; + $chart_data = []; + foreach ($analysis_results as $row) { + $chart_labels[] = $row['MERK']; + $chart_data[] = $row['total_omzet']; + } + $chart_labels_json = json_encode($chart_labels); + $chart_data_json = json_encode($chart_data); + } + } + + + // Get total records for raw data pagination + $total_stmt = $pdo->query('SELECT COUNT(*) FROM tabelmaster'); + $total_records = $total_stmt->fetchColumn(); + $total_pages = ceil($total_records / $limit); + + // Fetch records for the current page of raw data + $stmt = $pdo->prepare('SELECT * FROM tabelmaster ORDER BY TANGGAL DESC, NO_FAKTUR DESC LIMIT :limit OFFSET :offset'); + $stmt->bindParam(':limit', $limit, PDO::PARAM_INT); + $stmt->bindParam(':offset', $offset, PDO::PARAM_INT); + $stmt->execute(); + $records = $stmt->fetchAll(); + +} catch (PDOException $e) { + $error_message = "Database error: " . $e->getMessage(); +} + +require_once 'header.php'; ?> - - - - - - New Style - - - - - - - - - - - - - - - - - - - - - -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

-
-
- - - + +
+ + + + + +
+
+ Analisa Penjualan per Merk +
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ + + +
+
+ Hasil Analisa +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
MerkTotal KuantitasTotal OmzetHarga Rata-rataJumlah Transaksi
Rp Rp
+
+
+ +
+
+
+ +
+
+ Hasil Analisa +
+
+
Tidak ada data yang cocok dengan filter yang dipilih.
+
+
+ + + + +
+
+ Data Master +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nama SalesTanggalNo FakturMerkOutletProdukQtyHargaBulanTahunPeriode
+
+ + + + +
+
+ + + + \ No newline at end of file diff --git a/public.php b/public.php new file mode 100644 index 0000000..56db496 --- /dev/null +++ b/public.php @@ -0,0 +1,188 @@ +query(' + SELECT + MERK, + SUM(QTY * CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as total_omzet + FROM + tabelmaster + GROUP BY + MERK + ORDER BY + total_omzet DESC + LIMIT 5 + '); + $top_brands = $top_brands_stmt->fetchAll(); + + // Query 2: Sales per Period for Trend Chart + $sales_by_period_stmt = $pdo->query(' + SELECT + PERIODE, + SUM(QTY * CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as total_omzet + FROM + tabelmaster + WHERE PERIODE IS NOT NULL AND PERIODE != "" + GROUP BY + PERIODE + ORDER BY + PERIODE ASC + '); + $sales_by_period = $sales_by_period_stmt->fetchAll(); + + if (!empty($sales_by_period)) { + $chart_labels = []; + $chart_data = []; + foreach ($sales_by_period as $row) { + $chart_labels[] = $row['PERIODE']; + $chart_data[] = $row['total_omzet']; + } + $chart_labels_json = json_encode($chart_labels); + $chart_data_json = json_encode($chart_data); + } + +} catch (PDOException $e) { + $error_message = "Database error: " . $e->getMessage(); +} +?> + + + + + + Ringkasan Penjualan - vipanalisa + + + + + + + + + + + + + + + + + +
+
+

Ringkasan Penjualan Publik

+
+
+ +
+ + + +
+ +
+
+
+ Top 5 Merk Terlaris +
+
+ +

Data tidak tersedia.

+ +
    + +
  • + + Rp +
  • + +
+ +
+
+
+ + +
+
+
+ Tren Penjualan per Periode +
+
+ +

Data tren tidak tersedia.

+ + + +
+
+
+
+ +
+ + + + + + + diff --git a/sales_analysis.php b/sales_analysis.php new file mode 100644 index 0000000..ce4ba6b --- /dev/null +++ b/sales_analysis.php @@ -0,0 +1,181 @@ +query('SELECT DISTINCT PERIODE FROM tabelmaster WHERE PERIODE IS NOT NULL AND PERIODE != \'\' ORDER BY PERIODE DESC'); + $periode_options = $periode_options_stmt->fetchAll(PDO::FETCH_COLUMN); + + // Handle form submission for analysis + $analysis_results = []; + $chart_labels_json = '[]'; + $chart_data_json = '[]'; + $selected_periode = $_POST['periode'] ?? 'all'; + + if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['run_analysis'])) { + $sql = "\n SELECT\n NAMA_SALES,\n SUM(QTY) as total_qty,\n SUM(QTY * CAST(REPLACE(HARGA, ',', '') AS DECIMAL(15,2))) as total_omzet,\n AVG(CAST(REPLACE(HARGA, ',', '') AS DECIMAL(15,2))) as avg_price,\n COUNT(DISTINCT NO_FAKTUR) as transactions_count\n FROM\n tabelmaster\n WHERE 1=1"; + + $params = []; + if ($selected_periode !== 'all') { + $sql .= ' AND PERIODE = :periode'; + $params[':periode'] = $selected_periode; + } + + $sql .= ' GROUP BY NAMA_SALES HAVING SUM(QTY) > 0 ORDER BY total_omzet DESC'; + + $analysis_stmt = $pdo->prepare($sql); + $analysis_stmt->execute($params); + $analysis_results = $analysis_stmt->fetchAll(); + + if (!empty($analysis_results)) { + $chart_labels = []; + $chart_data = []; + foreach ($analysis_results as $row) { + $chart_labels[] = $row['NAMA_SALES']; + $chart_data[] = $row['total_omzet']; + } + $chart_labels_json = json_encode($chart_labels); + $chart_data_json = json_encode($chart_data); + } + } + +} catch (PDOException $e) { + $error_message = "Database error: " . $e->getMessage(); +} + +require_once 'header.php'; +?> + +
+ + + + + +
+
+ Analisa Penjualan per Sales +
+
+
+
+
+ + +
+
+ +
+
+
+
+
+ + + +
+
+ Hasil Analisa +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
Nama SalesTotal KuantitasTotal OmzetHarga Rata-rataJumlah Transaksi
Rp Rp
+
+
+ +
+
+
+ +
+
+ Hasil Analisa +
+
+
Tidak ada data yang cocok dengan filter yang dipilih.
+
+
+ + + + + \ No newline at end of file