Compare commits
No commits in common. "1cd2aa60d457bdc05a1c446e902c06285009c996" and "c6cebf145dd9d92c8ad2fdf1991187bcf9af9c5d" have entirely different histories.
1cd2aa60d4
...
c6cebf145d
@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Exports;
|
|
||||||
|
|
||||||
use Maatwebsite\Excel\Concerns\FromArray;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
||||||
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
|
||||||
|
|
||||||
class RingkasanExport implements FromArray, WithHeadings, ShouldAutoSize
|
|
||||||
{
|
|
||||||
protected $data;
|
|
||||||
|
|
||||||
public function __construct(iterable $data)
|
|
||||||
{
|
|
||||||
$this->data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function array(): array
|
|
||||||
{
|
|
||||||
$rows = [];
|
|
||||||
|
|
||||||
// Iterasi setiap hari/bulan
|
|
||||||
foreach ($this->data as $item) {
|
|
||||||
// Baris pertama untuk entri sales pertama
|
|
||||||
if (count($item['sales']) > 0) {
|
|
||||||
foreach ($item['sales'] as $index => $sales) {
|
|
||||||
$rows[] = [
|
|
||||||
'Tanggal' => $item['tanggal'],
|
|
||||||
'Nama Sales' => $sales['nama'],
|
|
||||||
'Item Terjual' => $sales['item_terjual'],
|
|
||||||
'Berat Terjual' => $sales['berat_terjual'],
|
|
||||||
'Pendapatan' => $sales['pendapatan'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Baris jika tidak ada sales hari itu
|
|
||||||
$rows[] = [
|
|
||||||
'Tanggal' => $item['tanggal'],
|
|
||||||
'Nama Sales' => 'N/A',
|
|
||||||
'Item Terjual' => 0,
|
|
||||||
'Berat Terjual' => 0,
|
|
||||||
'Pendapatan' => 0,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Baris Total Harian/Bulanan
|
|
||||||
$rows[] = [
|
|
||||||
'Tanggal' => $item['tanggal'],
|
|
||||||
'Nama Sales' => '** TOTAL **', // Tandai sebagai baris total
|
|
||||||
'Item Terjual' => $item['total_item_terjual'],
|
|
||||||
'Berat Terjual' => $item['total_berat'],
|
|
||||||
'Pendapatan' => $item['total_pendapatan'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function headings(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'Periode',
|
|
||||||
'Nama Sales/Keterangan',
|
|
||||||
'Item Terjual',
|
|
||||||
'Total Berat Terjual',
|
|
||||||
'Total Pendapatan',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,90 +13,44 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
|
||||||
use App\Exports\RingkasanExport;
|
|
||||||
|
|
||||||
class LaporanController extends Controller
|
class LaporanController extends Controller
|
||||||
{
|
{
|
||||||
private const CURRENCY_SYMBOL = 'Rp ';
|
private const CURRENCY_SYMBOL = 'Rp ';
|
||||||
private const WEIGHT_UNIT = ' g';
|
private const WEIGHT_UNIT = ' g';
|
||||||
private const DEFAULT_DISPLAY = '-';
|
private const DEFAULT_DISPLAY = '-';
|
||||||
private const CACHE_TTL = 300; // 5 menit
|
|
||||||
private const DEFAULT_PER_PAGE = 15;
|
|
||||||
private const MAX_PER_PAGE = 100;
|
|
||||||
private const DAILY_PER_PAGE = 7;
|
|
||||||
private const MONTHLY_PER_PAGE = 12;
|
|
||||||
private const PAGINATION_DAYS_LIMIT = 365;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Endpoint untuk ringkasan laporan dengan caching
|
|
||||||
*/
|
|
||||||
public function ringkasan(Request $request)
|
public function ringkasan(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
$filter = $request->query('filter', 'bulan');
|
$filter = $request->query('filter', 'bulan');
|
||||||
$page = (int) $request->query('page', 1);
|
$page = $request->query('page', 1);
|
||||||
|
|
||||||
// Validasi filter
|
$allSalesNames = Transaksi::select('nama_sales')->distinct()->pluck('nama_sales');
|
||||||
if (!in_array($filter, ['hari', 'bulan'])) {
|
|
||||||
return response()->json(['error' => 'Filter harus "hari" atau "bulan"'], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache key berdasarkan filter dan page
|
|
||||||
$cacheKey = "laporan_ringkasan_{$filter}_page_{$page}";
|
|
||||||
|
|
||||||
$data = Cache::remember($cacheKey, self::CACHE_TTL, function () use ($filter, $page) {
|
|
||||||
$allSalesNames = $this->getAllSalesNames();
|
|
||||||
|
|
||||||
if ($filter === 'hari') {
|
if ($filter === 'hari') {
|
||||||
return $this->processLaporanHarian($allSalesNames, $page, true);
|
return $this->laporanHarian($page, $allSalesNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->processLaporanBulanan($allSalesNames, $page, true);
|
return $this->laporanBulanan($page, $allSalesNames);
|
||||||
});
|
|
||||||
|
|
||||||
return response()->json($data);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::error('Error in ringkasan method: ' . $e->getMessage());
|
|
||||||
return response()->json(['error' => 'Terjadi kesalahan saat mengambil data'], 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detail laporan per produk dengan validasi dan error handling yang lebih baik
|
|
||||||
*/
|
|
||||||
public function detailPerProduk(Request $request)
|
public function detailPerProduk(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
$request->validate([
|
||||||
$validatedData = $request->validate([
|
'tanggal' => 'required|date_format:Y-m-d',
|
||||||
'tanggal' => 'required|date_format:Y-m-d|before_or_equal:today',
|
|
||||||
'sales_id' => 'nullable|integer|exists:sales,id',
|
|
||||||
'nampan_id' => 'nullable|integer',
|
|
||||||
'nama_pembeli' => 'nullable|string|max:255',
|
|
||||||
'page' => 'nullable|integer|min:1',
|
'page' => 'nullable|integer|min:1',
|
||||||
'per_page' => 'nullable|integer|min:1|max:' . self::MAX_PER_PAGE,
|
'per_page' => 'nullable|integer|min:1|max:100',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tanggal = $validatedData['tanggal'];
|
$tanggal = $request->query('tanggal');
|
||||||
$salesId = $request->query('sales_id');
|
$salesId = $request->query('sales_id');
|
||||||
$nampanId = $request->query('nampan_id');
|
$nampanId = $request->query('nampan_id');
|
||||||
$namaPembeli = $request->query('nama_pembeli');
|
$namaPembeli = $request->query('nama_pembeli');
|
||||||
$page = (int) $request->query('page', 1);
|
$page = $request->query('page', 1);
|
||||||
$perPage = (int) $request->query('per_page', self::DEFAULT_PER_PAGE);
|
$perPage = $request->query('per_page', 15);
|
||||||
|
|
||||||
$carbonDate = Carbon::parse($tanggal);
|
$carbonDate = Carbon::parse($tanggal);
|
||||||
|
|
||||||
// Validasi nampan_id jika ada
|
|
||||||
if ($nampanId && $nampanId != 0) {
|
|
||||||
if (!Nampan::where('id', $nampanId)->exists()) {
|
|
||||||
return response()->json(['error' => 'Nampan tidak ditemukan'], 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$produkTerjualQuery = $this->buildBaseItemQuery($carbonDate);
|
$produkTerjualQuery = $this->buildBaseItemQuery($carbonDate);
|
||||||
$this->applyFilters($produkTerjualQuery, $salesId, $nampanId, $namaPembeli);
|
$this->applyFilters($produkTerjualQuery, $salesId, $nampanId, $namaPembeli);
|
||||||
|
|
||||||
@ -105,18 +59,15 @@ class LaporanController extends Controller
|
|||||||
'produks.id as id_produk',
|
'produks.id as id_produk',
|
||||||
'produks.nama as nama_produk',
|
'produks.nama as nama_produk',
|
||||||
DB::raw('COUNT(item_transaksis.id) as jumlah_item_terjual'),
|
DB::raw('COUNT(item_transaksis.id) as jumlah_item_terjual'),
|
||||||
DB::raw('COALESCE(SUM(produks.berat), 0) as berat_terjual'),
|
DB::raw('SUM(produks.berat) as berat_terjual'),
|
||||||
DB::raw('COALESCE(SUM(item_transaksis.harga_deal), 0) as pendapatan')
|
DB::raw('SUM(item_transaksis.harga_deal) as pendapatan')
|
||||||
)
|
)
|
||||||
->groupBy('produks.id', 'produks.nama')
|
->groupBy('produks.id', 'produks.nama')
|
||||||
->get()
|
->get()
|
||||||
->keyBy('id_produk');
|
->keyBy('id_produk');
|
||||||
|
|
||||||
$totals = $this->calculateTotals($produkTerjual);
|
$totals = $this->calculateTotals($produkTerjual);
|
||||||
$semuaProdukPaginated = Produk::select('id', 'nama')
|
$semuaProdukPaginated = Produk::select('id', 'nama')->orderBy('nama')->paginate($perPage, ['*'], 'page', $page);
|
||||||
->orderBy('nama')
|
|
||||||
->paginate($perPage, ['*'], 'page', $page);
|
|
||||||
|
|
||||||
$detailItem = $this->mapProductsWithSalesData($semuaProdukPaginated, $produkTerjual);
|
$detailItem = $this->mapProductsWithSalesData($semuaProdukPaginated, $produkTerjual);
|
||||||
$filterInfo = $this->buildFilterInfo($carbonDate, $salesId, $nampanId, $namaPembeli);
|
$filterInfo = $this->buildFilterInfo($carbonDate, $salesId, $nampanId, $namaPembeli);
|
||||||
|
|
||||||
@ -126,55 +77,65 @@ class LaporanController extends Controller
|
|||||||
'produk' => $detailItem->values(),
|
'produk' => $detailItem->values(),
|
||||||
'pagination' => $this->buildPaginationInfo($semuaProdukPaginated),
|
'pagination' => $this->buildPaginationInfo($semuaProdukPaginated),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::error('Error in detailPerProduk method: ' . $e->getMessage());
|
|
||||||
return response()->json(['error' => 'Terjadi kesalahan saat mengambil data produk'], 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detail laporan per nampan dengan perbaikan validasi dan error handling
|
|
||||||
*/
|
|
||||||
public function detailPerNampan(Request $request)
|
public function detailPerNampan(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
$request->validate([
|
||||||
$validatedData = $request->validate([
|
'tanggal' => 'required|date_format:Y-m-d',
|
||||||
'tanggal' => 'required|date_format:Y-m-d|before_or_equal:today',
|
|
||||||
'sales_id' => 'nullable|integer|exists:sales,id',
|
|
||||||
'produk_id' => 'nullable|integer|exists:produks,id',
|
|
||||||
'nama_pembeli' => 'nullable|string|max:255',
|
|
||||||
'page' => 'nullable|integer|min:1',
|
'page' => 'nullable|integer|min:1',
|
||||||
'per_page' => 'nullable|integer|min:1|max:' . self::MAX_PER_PAGE,
|
'per_page' => 'nullable|integer|min:1|max:100',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tanggal = $validatedData['tanggal'];
|
$tanggal = $request->query('tanggal');
|
||||||
$salesId = $request->query('sales_id');
|
$salesId = $request->query('sales_id');
|
||||||
$produkId = $request->query('produk_id');
|
$produkId = $request->query('produk_id');
|
||||||
$namaPembeli = $request->query('nama_pembeli');
|
$namaPembeli = $request->query('nama_pembeli');
|
||||||
$page = (int) $request->query('page', 1);
|
$page = $request->query('page', 1);
|
||||||
$perPage = (int) $request->query('per_page', self::DEFAULT_PER_PAGE);
|
$perPage = $request->query('per_page', 15);
|
||||||
|
|
||||||
$carbonDate = Carbon::parse($tanggal);
|
$carbonDate = Carbon::parse($tanggal);
|
||||||
|
|
||||||
|
// Query untuk mendapatkan data penjualan per nampan
|
||||||
$nampanTerjualQuery = $this->buildBaseItemQuery($carbonDate);
|
$nampanTerjualQuery = $this->buildBaseItemQuery($carbonDate);
|
||||||
$this->applyNampanFilters($nampanTerjualQuery, $salesId, $produkId, $namaPembeli);
|
$this->applyNampanFilters($nampanTerjualQuery, $salesId, $produkId, $namaPembeli);
|
||||||
|
|
||||||
|
// Menggunakan COALESCE untuk menggabungkan nampan dan brankas
|
||||||
$nampanTerjual = $nampanTerjualQuery
|
$nampanTerjual = $nampanTerjualQuery
|
||||||
->leftJoin('nampans', 'items.id_nampan', '=', 'nampans.id')
|
->leftJoin('nampans', 'items.id_nampan', '=', 'nampans.id')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('COALESCE(items.id_nampan, 0) as id_nampan'),
|
DB::raw('COALESCE(items.id_nampan, 0) as id_nampan'),
|
||||||
DB::raw('COALESCE(nampans.nama, "Brankas") as nama_nampan'),
|
DB::raw('COALESCE(nampans.nama, "Brankas") as nama_nampan'),
|
||||||
DB::raw('COUNT(item_transaksis.id) as jumlah_item_terjual'),
|
DB::raw('COUNT(item_transaksis.id) as jumlah_item_terjual'),
|
||||||
DB::raw('COALESCE(SUM(produks.berat), 0) as berat_terjual'),
|
DB::raw('SUM(produks.berat) as berat_terjual'),
|
||||||
DB::raw('COALESCE(SUM(item_transaksis.harga_deal), 0) as pendapatan')
|
DB::raw('SUM(item_transaksis.harga_deal) as pendapatan')
|
||||||
)
|
)
|
||||||
->groupBy('id_nampan', 'nama_nampan')
|
->groupBy('id_nampan', 'nama_nampan')
|
||||||
->get()
|
->get()
|
||||||
->keyBy('id_nampan');
|
->keyBy('id_nampan');
|
||||||
|
|
||||||
$totals = $this->calculateTotals($nampanTerjual);
|
$totals = $this->calculateTotals($nampanTerjual);
|
||||||
$semuaNampanPaginated = $this->getAllNampanWithPagination($page, $perPage);
|
|
||||||
|
// Mendapatkan semua nampan + entry untuk brankas
|
||||||
|
$semuaNampan = Nampan::select('id', 'nama')->orderBy('nama')->get();
|
||||||
|
|
||||||
|
// Tambahkan entry brankas (id = 0)
|
||||||
|
$brankasEntry = (object) ['id' => 0, 'nama' => 'Brankas'];
|
||||||
|
$semuaNampanCollection = $semuaNampan->prepend($brankasEntry);
|
||||||
|
|
||||||
|
// Pagination manual
|
||||||
|
$currentPage = $page;
|
||||||
|
$offset = ($currentPage - 1) * $perPage;
|
||||||
|
$itemsForCurrentPage = $semuaNampanCollection->slice($offset, $perPage);
|
||||||
|
|
||||||
|
$semuaNampanPaginated = new LengthAwarePaginator(
|
||||||
|
$itemsForCurrentPage,
|
||||||
|
$semuaNampanCollection->count(),
|
||||||
|
$perPage,
|
||||||
|
$currentPage,
|
||||||
|
['path' => request()->url(), 'query' => request()->query()]
|
||||||
|
);
|
||||||
|
|
||||||
$detailItem = $this->mapNampanWithSalesData($semuaNampanPaginated, $nampanTerjual);
|
$detailItem = $this->mapNampanWithSalesData($semuaNampanPaginated, $nampanTerjual);
|
||||||
$filterInfo = $this->buildNampanFilterInfo($carbonDate, $salesId, $produkId, $namaPembeli);
|
$filterInfo = $this->buildNampanFilterInfo($carbonDate, $salesId, $produkId, $namaPembeli);
|
||||||
|
|
||||||
@ -184,104 +145,15 @@ class LaporanController extends Controller
|
|||||||
'nampan' => $detailItem->values(),
|
'nampan' => $detailItem->values(),
|
||||||
'pagination' => $this->buildPaginationInfo($semuaNampanPaginated),
|
'pagination' => $this->buildPaginationInfo($semuaNampanPaginated),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::error('Error in detailPerNampan method: ' . $e->getMessage());
|
|
||||||
return response()->json(['error' => 'Terjadi kesalahan saat mengambil data nampan'], 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function laporanHarian(int $page, Collection $allSalesNames)
|
||||||
* Export laporan ringkasan dengan validasi format
|
|
||||||
*/
|
|
||||||
public function exportRingkasan(Request $request)
|
|
||||||
{
|
{
|
||||||
try {
|
$perPage = 7;
|
||||||
$validatedData = $request->validate([
|
|
||||||
'filter' => 'required|in:hari,bulan',
|
|
||||||
'format' => 'required|in:pdf,xlsx,csv',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$filter = $validatedData['filter'];
|
|
||||||
$format = $validatedData['format'];
|
|
||||||
|
|
||||||
$allSalesNames = $this->getAllSalesNames();
|
|
||||||
|
|
||||||
if ($filter === 'hari') {
|
|
||||||
$data = $this->processLaporanHarian($allSalesNames, 1, false);
|
|
||||||
} else {
|
|
||||||
$data = $this->processLaporanBulanan($allSalesNames, 1, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileName = "laporan_ringkasan_{$filter}_" . Carbon::now()->format('Ymd') . ".{$format}";
|
|
||||||
|
|
||||||
if ($format === 'pdf') {
|
|
||||||
$pdf = PDF::loadView('exports.ringkasan_pdf', [
|
|
||||||
'data' => $data,
|
|
||||||
'filter' => $filter
|
|
||||||
]);
|
|
||||||
$pdf->setPaper('a4', 'landscape');
|
|
||||||
return $pdf->download($fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format XLSX atau CSV
|
|
||||||
return Excel::download(new RingkasanExport($data), $fileName);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Log::error('Error in exportRingkasan method: ' . $e->getMessage());
|
|
||||||
return response()->json(['error' => 'Terjadi kesalahan saat export data'], 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method untuk mendapatkan semua nama sales dengan caching
|
|
||||||
*/
|
|
||||||
private function getAllSalesNames(): Collection
|
|
||||||
{
|
|
||||||
return Cache::remember('all_sales_names', self::CACHE_TTL, function () {
|
|
||||||
return Transaksi::select('nama_sales')->distinct()->pluck('nama_sales');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method untuk mendapatkan semua nampan dengan pagination
|
|
||||||
*/
|
|
||||||
private function getAllNampanWithPagination(int $page, int $perPage): LengthAwarePaginator
|
|
||||||
{
|
|
||||||
$semuaNampan = Nampan::select('id', 'nama')->orderBy('nama')->get();
|
|
||||||
$brankasEntry = (object) ['id' => 0, 'nama' => 'Brankas'];
|
|
||||||
$semuaNampanCollection = $semuaNampan->prepend($brankasEntry);
|
|
||||||
|
|
||||||
$offset = ($page - 1) * $perPage;
|
|
||||||
$itemsForCurrentPage = $semuaNampanCollection->slice($offset, $perPage);
|
|
||||||
|
|
||||||
return new LengthAwarePaginator(
|
|
||||||
$itemsForCurrentPage,
|
|
||||||
$semuaNampanCollection->count(),
|
|
||||||
$perPage,
|
|
||||||
$page,
|
|
||||||
['path' => request()->url(), 'query' => request()->query()]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logika inti untuk menghasilkan data laporan harian yang sudah dioptimasi
|
|
||||||
*/
|
|
||||||
private function processLaporanHarian(Collection $allSalesNames, int $page = 1, bool $limitPagination = true)
|
|
||||||
{
|
|
||||||
$perPage = self::DAILY_PER_PAGE;
|
|
||||||
|
|
||||||
if ($limitPagination) {
|
|
||||||
$endDate = Carbon::today()->subDays(($page - 1) * $perPage);
|
$endDate = Carbon::today()->subDays(($page - 1) * $perPage);
|
||||||
$startDate = $endDate->copy()->subDays($perPage - 1);
|
$startDate = $endDate->copy()->subDays($perPage - 1);
|
||||||
$totalHariUntukPaginasi = self::PAGINATION_DAYS_LIMIT;
|
|
||||||
} else {
|
|
||||||
$endDate = Carbon::today();
|
|
||||||
$startDate = $endDate->copy()->subYear()->addDay();
|
|
||||||
$totalHariUntukPaginasi = $endDate->diffInDays($startDate) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaksis = Transaksi::with(['itemTransaksi.item.produk'])
|
$transaksis = Transaksi::with('itemTransaksi.item.produk')
|
||||||
->whereBetween('created_at', [$startDate->startOfDay(), $endDate->endOfDay()])
|
->whereBetween('created_at', [$startDate->startOfDay(), $endDate->endOfDay()])
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->get();
|
->get();
|
||||||
@ -328,27 +200,23 @@ class LaporanController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($limitPagination) {
|
$totalHariUntukPaginasi = 365;
|
||||||
return new LengthAwarePaginator(
|
$paginatedData = new LengthAwarePaginator(
|
||||||
array_reverse(array_values($laporan)),
|
array_reverse(array_values($laporan)),
|
||||||
$totalHariUntukPaginasi,
|
$totalHariUntukPaginasi,
|
||||||
$perPage,
|
$perPage,
|
||||||
$page,
|
$page,
|
||||||
['path' => request()->url(), 'query' => request()->query()]
|
['path' => request()->url(), 'query' => request()->query()]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return response()->json($paginatedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return collect(array_reverse(array_values($laporan)));
|
private function laporanBulanan(int $page, Collection $allSalesNames)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logika inti untuk menghasilkan data laporan bulanan yang sudah dioptimasi
|
|
||||||
*/
|
|
||||||
private function processLaporanBulanan(Collection $allSalesNames, int $page = 1, bool $limitPagination = true)
|
|
||||||
{
|
{
|
||||||
$perPage = self::MONTHLY_PER_PAGE;
|
$perPage = 12;
|
||||||
|
|
||||||
$transaksis = Transaksi::with(['itemTransaksi.item.produk'])
|
$transaksis = Transaksi::with('itemTransaksi.item.produk')
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
@ -376,22 +244,17 @@ class LaporanController extends Controller
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($limitPagination) {
|
$paginatedData = new LengthAwarePaginator(
|
||||||
return new LengthAwarePaginator(
|
|
||||||
$laporan->forPage($page, $perPage)->values(),
|
$laporan->forPage($page, $perPage)->values(),
|
||||||
$laporan->count(),
|
$laporan->count(),
|
||||||
$perPage,
|
$perPage,
|
||||||
$page,
|
$page,
|
||||||
['path' => request()->url(), 'query' => request()->query()]
|
['path' => request()->url(), 'query' => request()->query()]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return response()->json($paginatedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $laporan->values();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Membangun query dasar untuk item transaksi
|
|
||||||
*/
|
|
||||||
private function buildBaseItemQuery(Carbon $carbonDate)
|
private function buildBaseItemQuery(Carbon $carbonDate)
|
||||||
{
|
{
|
||||||
return ItemTransaksi::query()
|
return ItemTransaksi::query()
|
||||||
@ -401,20 +264,19 @@ class LaporanController extends Controller
|
|||||||
->whereDate('transaksis.created_at', $carbonDate);
|
->whereDate('transaksis.created_at', $carbonDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function applyFilters($query, $salesId, $nampanId, $namaPembeli)
|
||||||
* Menerapkan filter untuk query produk
|
|
||||||
*/
|
|
||||||
private function applyFilters($query, $salesId, $nampanId, $namaPembeli): void
|
|
||||||
{
|
{
|
||||||
if ($salesId) {
|
if ($salesId) {
|
||||||
$query->join('sales', 'transaksis.id_sales', '=', 'sales.id')
|
$query->join('sales', 'transaksis.id_sales', '=', 'sales.id')
|
||||||
->where('sales.id', $salesId);
|
->where('sales.id', $salesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($nampanId !== null) {
|
if ($nampanId) {
|
||||||
if ($nampanId == 0) {
|
if ($nampanId == 0) {
|
||||||
|
// Filter untuk brankas (id_nampan = null)
|
||||||
$query->whereNull('items.id_nampan');
|
$query->whereNull('items.id_nampan');
|
||||||
} else {
|
} else {
|
||||||
|
// Filter untuk nampan tertentu
|
||||||
$query->where('items.id_nampan', $nampanId);
|
$query->where('items.id_nampan', $nampanId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,10 +286,7 @@ class LaporanController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function applyNampanFilters($query, $salesId, $produkId, $namaPembeli)
|
||||||
* Menerapkan filter untuk query nampan
|
|
||||||
*/
|
|
||||||
private function applyNampanFilters($query, $salesId, $produkId, $namaPembeli): void
|
|
||||||
{
|
{
|
||||||
if ($salesId) {
|
if ($salesId) {
|
||||||
$query->join('sales', 'transaksis.id_sales', '=', 'sales.id')
|
$query->join('sales', 'transaksis.id_sales', '=', 'sales.id')
|
||||||
@ -443,9 +302,6 @@ class LaporanController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menghitung total dari data penjualan
|
|
||||||
*/
|
|
||||||
private function calculateTotals(Collection $data): array
|
private function calculateTotals(Collection $data): array
|
||||||
{
|
{
|
||||||
$totalPendapatan = $data->sum('pendapatan');
|
$totalPendapatan = $data->sum('pendapatan');
|
||||||
@ -459,9 +315,6 @@ class LaporanController extends Controller
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Memetakan produk dengan data penjualan
|
|
||||||
*/
|
|
||||||
private function mapProductsWithSalesData($paginatedData, Collection $salesData): Collection
|
private function mapProductsWithSalesData($paginatedData, Collection $salesData): Collection
|
||||||
{
|
{
|
||||||
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
|
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
|
||||||
@ -484,9 +337,6 @@ class LaporanController extends Controller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Memetakan nampan dengan data penjualan
|
|
||||||
*/
|
|
||||||
private function mapNampanWithSalesData($paginatedData, Collection $salesData): Collection
|
private function mapNampanWithSalesData($paginatedData, Collection $salesData): Collection
|
||||||
{
|
{
|
||||||
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
|
return $paginatedData->getCollection()->map(function ($item) use ($salesData) {
|
||||||
@ -509,9 +359,6 @@ class LaporanController extends Controller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Membangun informasi filter untuk produk
|
|
||||||
*/
|
|
||||||
private function buildFilterInfo(Carbon $carbonDate, $salesId, $nampanId, $namaPembeli): array
|
private function buildFilterInfo(Carbon $carbonDate, $salesId, $nampanId, $namaPembeli): array
|
||||||
{
|
{
|
||||||
$filterInfo = [
|
$filterInfo = [
|
||||||
@ -526,7 +373,7 @@ class LaporanController extends Controller
|
|||||||
$filterInfo['nama_sales'] = $sales?->nama;
|
$filterInfo['nama_sales'] = $sales?->nama;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($nampanId !== null) {
|
if ($nampanId) {
|
||||||
if ($nampanId == 0) {
|
if ($nampanId == 0) {
|
||||||
$filterInfo['nampan'] = 'Brankas';
|
$filterInfo['nampan'] = 'Brankas';
|
||||||
} else {
|
} else {
|
||||||
@ -538,9 +385,6 @@ class LaporanController extends Controller
|
|||||||
return $filterInfo;
|
return $filterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Membangun informasi filter untuk nampan
|
|
||||||
*/
|
|
||||||
private function buildNampanFilterInfo(Carbon $carbonDate, $salesId, $produkId, $namaPembeli): array
|
private function buildNampanFilterInfo(Carbon $carbonDate, $salesId, $produkId, $namaPembeli): array
|
||||||
{
|
{
|
||||||
$filterInfo = [
|
$filterInfo = [
|
||||||
@ -563,9 +407,6 @@ class LaporanController extends Controller
|
|||||||
return $filterInfo;
|
return $filterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Membangun informasi pagination
|
|
||||||
*/
|
|
||||||
private function buildPaginationInfo($paginatedData): array
|
private function buildPaginationInfo($paginatedData): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@ -578,9 +419,6 @@ class LaporanController extends Controller
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menghitung data sales dari transaksi
|
|
||||||
*/
|
|
||||||
private function hitungDataSales(Collection $transaksisPerSales): array
|
private function hitungDataSales(Collection $transaksisPerSales): array
|
||||||
{
|
{
|
||||||
$itemTerjual = $transaksisPerSales->sum(fn($t) => $t->itemTransaksi->count());
|
$itemTerjual = $transaksisPerSales->sum(fn($t) => $t->itemTransaksi->count());
|
||||||
@ -597,9 +435,6 @@ class LaporanController extends Controller
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Default data untuk sales yang tidak ada transaksi
|
|
||||||
*/
|
|
||||||
private function defaultSalesData(string $namaSales): array
|
private function defaultSalesData(string $namaSales): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@ -610,34 +445,23 @@ class LaporanController extends Controller
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format nilai data sales untuk tampilan
|
|
||||||
*/
|
|
||||||
private function formatSalesDataValues(Collection $salesData): Collection
|
private function formatSalesDataValues(Collection $salesData): Collection
|
||||||
{
|
{
|
||||||
return $salesData->map(function ($sale) {
|
return $salesData->map(function ($sale) {
|
||||||
$sale['item_terjual'] = $sale['item_terjual'] > 0 ? $sale['item_terjual'] : self::DEFAULT_DISPLAY;
|
$sale['item_terjual'] = $sale['item_terjual'] > 0 ? $sale['item_terjual'] : self::DEFAULT_DISPLAY;
|
||||||
$sale['berat_terjual'] = $sale['berat_terjual_raw'] > 0 ?
|
$sale['berat_terjual'] = $sale['berat_terjual_raw'] > 0 ? $this->formatWeight($sale['berat_terjual_raw']) : self::DEFAULT_DISPLAY;
|
||||||
$this->formatWeight($sale['berat_terjual_raw']) : self::DEFAULT_DISPLAY;
|
$sale['pendapatan'] = $sale['pendapatan_raw'] > 0 ? $this->formatCurrency($sale['pendapatan_raw']) : self::DEFAULT_DISPLAY;
|
||||||
$sale['pendapatan'] = $sale['pendapatan_raw'] > 0 ?
|
|
||||||
$this->formatCurrency($sale['pendapatan_raw']) : self::DEFAULT_DISPLAY;
|
|
||||||
|
|
||||||
unset($sale['berat_terjual_raw'], $sale['pendapatan_raw']);
|
unset($sale['berat_terjual_raw'], $sale['pendapatan_raw']);
|
||||||
return $sale;
|
return $sale;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format mata uang
|
|
||||||
*/
|
|
||||||
private function formatCurrency(float $amount): string
|
private function formatCurrency(float $amount): string
|
||||||
{
|
{
|
||||||
return self::CURRENCY_SYMBOL . number_format($amount, 2, ',', '.');
|
return self::CURRENCY_SYMBOL . number_format($amount, 2, ',', '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Format berat
|
|
||||||
*/
|
|
||||||
private function formatWeight(float $weight): string
|
private function formatWeight(float $weight): string
|
||||||
{
|
{
|
||||||
return number_format($weight, 2, ',', '.') . self::WEIGHT_UNIT;
|
return number_format($weight, 2, ',', '.') . self::WEIGHT_UNIT;
|
||||||
|
@ -7,11 +7,9 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"barryvdh/laravel-dompdf": "^3.1",
|
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/sanctum": "^4.2",
|
"laravel/sanctum": "^4.2",
|
||||||
"laravel/tinker": "^2.10.1",
|
"laravel/tinker": "^2.10.1"
|
||||||
"maatwebsite/excel": "^3.1"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
956
composer.lock
generated
956
composer.lock
generated
@ -4,85 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9c49b3a92b2742e4eb3dcf6c597b178a",
|
"content-hash": "6c1db6bb080cbc76da51ad3d02a29077",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
|
||||||
"name": "barryvdh/laravel-dompdf",
|
|
||||||
"version": "v3.1.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/barryvdh/laravel-dompdf.git",
|
|
||||||
"reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d",
|
|
||||||
"reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"dompdf/dompdf": "^3.0",
|
|
||||||
"illuminate/support": "^9|^10|^11|^12",
|
|
||||||
"php": "^8.1"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"larastan/larastan": "^2.7|^3.0",
|
|
||||||
"orchestra/testbench": "^7|^8|^9|^10",
|
|
||||||
"phpro/grumphp": "^2.5",
|
|
||||||
"squizlabs/php_codesniffer": "^3.5"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"aliases": {
|
|
||||||
"PDF": "Barryvdh\\DomPDF\\Facade\\Pdf",
|
|
||||||
"Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf"
|
|
||||||
},
|
|
||||||
"providers": [
|
|
||||||
"Barryvdh\\DomPDF\\ServiceProvider"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.0-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Barryvdh\\DomPDF\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Barry vd. Heuvel",
|
|
||||||
"email": "barryvdh@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A DOMPDF Wrapper for Laravel",
|
|
||||||
"keywords": [
|
|
||||||
"dompdf",
|
|
||||||
"laravel",
|
|
||||||
"pdf"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
|
|
||||||
"source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://fruitcake.nl",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/barryvdh",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-02-13T15:07:54+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.13.1",
|
"version": "0.13.1",
|
||||||
@ -212,162 +135,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-09T16:56:22+00:00"
|
"time": "2024-02-09T16:56:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "composer/pcre",
|
|
||||||
"version": "3.3.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/composer/pcre.git",
|
|
||||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
|
||||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.4 || ^8.0"
|
|
||||||
},
|
|
||||||
"conflict": {
|
|
||||||
"phpstan/phpstan": "<1.11.10"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpstan/phpstan": "^1.12 || ^2",
|
|
||||||
"phpstan/phpstan-strict-rules": "^1 || ^2",
|
|
||||||
"phpunit/phpunit": "^8 || ^9"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"phpstan": {
|
|
||||||
"includes": [
|
|
||||||
"extension.neon"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "3.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Composer\\Pcre\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Jordi Boggiano",
|
|
||||||
"email": "j.boggiano@seld.be",
|
|
||||||
"homepage": "http://seld.be"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
|
|
||||||
"keywords": [
|
|
||||||
"PCRE",
|
|
||||||
"preg",
|
|
||||||
"regex",
|
|
||||||
"regular expression"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/composer/pcre/issues",
|
|
||||||
"source": "https://github.com/composer/pcre/tree/3.3.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://packagist.com",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/composer",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2024-11-12T16:29:46+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "composer/semver",
|
|
||||||
"version": "3.4.4",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/composer/semver.git",
|
|
||||||
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
|
|
||||||
"reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpstan/phpstan": "^1.11",
|
|
||||||
"symfony/phpunit-bridge": "^3 || ^7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "3.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Composer\\Semver\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Nils Adermann",
|
|
||||||
"email": "naderman@naderman.de",
|
|
||||||
"homepage": "http://www.naderman.de"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jordi Boggiano",
|
|
||||||
"email": "j.boggiano@seld.be",
|
|
||||||
"homepage": "http://seld.be"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Rob Bast",
|
|
||||||
"email": "rob.bast@gmail.com",
|
|
||||||
"homepage": "http://robbast.nl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Semver library that offers utilities, version constraint parsing and validation.",
|
|
||||||
"keywords": [
|
|
||||||
"semantic",
|
|
||||||
"semver",
|
|
||||||
"validation",
|
|
||||||
"versioning"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"irc": "ircs://irc.libera.chat:6697/composer",
|
|
||||||
"issues": "https://github.com/composer/semver/issues",
|
|
||||||
"source": "https://github.com/composer/semver/tree/3.4.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://packagist.com",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/composer",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-08-20T19:15:30+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
"version": "v3.0.3",
|
"version": "v3.0.3",
|
||||||
@ -610,161 +377,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-05T11:56:58+00:00"
|
"time": "2024-02-05T11:56:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "dompdf/dompdf",
|
|
||||||
"version": "v3.1.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/dompdf/dompdf.git",
|
|
||||||
"reference": "a51bd7a063a65499446919286fb18b518177155a"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a",
|
|
||||||
"reference": "a51bd7a063a65499446919286fb18b518177155a",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"dompdf/php-font-lib": "^1.0.0",
|
|
||||||
"dompdf/php-svg-lib": "^1.0.0",
|
|
||||||
"ext-dom": "*",
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"masterminds/html5": "^2.0",
|
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-gd": "*",
|
|
||||||
"ext-json": "*",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"mockery/mockery": "^1.3",
|
|
||||||
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11",
|
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
|
||||||
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-gd": "Needed to process images",
|
|
||||||
"ext-gmagick": "Improves image processing performance",
|
|
||||||
"ext-imagick": "Improves image processing performance",
|
|
||||||
"ext-zlib": "Needed for pdf stream compression"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Dompdf\\": "src/"
|
|
||||||
},
|
|
||||||
"classmap": [
|
|
||||||
"lib/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-2.1"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "The Dompdf Community",
|
|
||||||
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
|
||||||
"homepage": "https://github.com/dompdf/dompdf",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/dompdf/issues",
|
|
||||||
"source": "https://github.com/dompdf/dompdf/tree/v3.1.0"
|
|
||||||
},
|
|
||||||
"time": "2025-01-15T14:09:04+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dompdf/php-font-lib",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/dompdf/php-font-lib.git",
|
|
||||||
"reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d",
|
|
||||||
"reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"FontLib\\": "src/FontLib"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-2.1-or-later"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "The FontLib Community",
|
|
||||||
"homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
|
||||||
"homepage": "https://github.com/dompdf/php-font-lib",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
|
||||||
"source": "https://github.com/dompdf/php-font-lib/tree/1.0.1"
|
|
||||||
},
|
|
||||||
"time": "2024-12-02T14:37:59+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dompdf/php-svg-lib",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/dompdf/php-svg-lib.git",
|
|
||||||
"reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af",
|
|
||||||
"reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"php": "^7.1 || ^8.0",
|
|
||||||
"sabberworm/php-css-parser": "^8.4"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Svg\\": "src/Svg"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-3.0-or-later"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "The SvgLib Community",
|
|
||||||
"homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A library to read, parse and export to PDF SVG files.",
|
|
||||||
"homepage": "https://github.com/dompdf/php-svg-lib",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
|
||||||
"source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0"
|
|
||||||
},
|
|
||||||
"time": "2024-04-29T13:26:35+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "dragonmantank/cron-expression",
|
"name": "dragonmantank/cron-expression",
|
||||||
"version": "v3.4.0",
|
"version": "v3.4.0",
|
||||||
@ -897,67 +509,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-03-06T22:45:56+00:00"
|
"time": "2025-03-06T22:45:56+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ezyang/htmlpurifier",
|
|
||||||
"version": "v4.18.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
|
||||||
"reference": "cb56001e54359df7ae76dc522d08845dc741621b"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
|
|
||||||
"reference": "cb56001e54359df7ae76dc522d08845dc741621b",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"cerdic/css-tidy": "^1.7 || ^2.0",
|
|
||||||
"simpletest/simpletest": "dev-master"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
|
|
||||||
"ext-bcmath": "Used for unit conversion and imagecrash protection",
|
|
||||||
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
|
|
||||||
"ext-tidy": "Used for pretty-printing HTML"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"library/HTMLPurifier.composer.php"
|
|
||||||
],
|
|
||||||
"psr-0": {
|
|
||||||
"HTMLPurifier": "library/"
|
|
||||||
},
|
|
||||||
"exclude-from-classmap": [
|
|
||||||
"/library/HTMLPurifier/Language/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-2.1-or-later"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Edward Z. Yang",
|
|
||||||
"email": "admin@htmlpurifier.org",
|
|
||||||
"homepage": "http://ezyang.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Standards compliant HTML filter written in PHP",
|
|
||||||
"homepage": "http://htmlpurifier.org/",
|
|
||||||
"keywords": [
|
|
||||||
"html"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
|
||||||
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
|
|
||||||
},
|
|
||||||
"time": "2024-11-01T03:51:45+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "fruitcake/php-cors",
|
"name": "fruitcake/php-cors",
|
||||||
"version": "v1.3.0",
|
"version": "v1.3.0",
|
||||||
@ -2520,339 +2071,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-12-08T08:18:47+00:00"
|
"time": "2024-12-08T08:18:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "maatwebsite/excel",
|
|
||||||
"version": "3.1.67",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/SpartnerNL/Laravel-Excel.git",
|
|
||||||
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d",
|
|
||||||
"reference": "e508e34a502a3acc3329b464dad257378a7edb4d",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"composer/semver": "^3.3",
|
|
||||||
"ext-json": "*",
|
|
||||||
"illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0",
|
|
||||||
"php": "^7.0||^8.0",
|
|
||||||
"phpoffice/phpspreadsheet": "^1.30.0",
|
|
||||||
"psr/simple-cache": "^1.0||^2.0||^3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"laravel/scout": "^7.0||^8.0||^9.0||^10.0",
|
|
||||||
"orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0",
|
|
||||||
"predis/predis": "^1.1"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"aliases": {
|
|
||||||
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
|
|
||||||
},
|
|
||||||
"providers": [
|
|
||||||
"Maatwebsite\\Excel\\ExcelServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Maatwebsite\\Excel\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Patrick Brouwers",
|
|
||||||
"email": "patrick@spartner.nl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Supercharged Excel exports and imports in Laravel",
|
|
||||||
"keywords": [
|
|
||||||
"PHPExcel",
|
|
||||||
"batch",
|
|
||||||
"csv",
|
|
||||||
"excel",
|
|
||||||
"export",
|
|
||||||
"import",
|
|
||||||
"laravel",
|
|
||||||
"php",
|
|
||||||
"phpspreadsheet"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
|
|
||||||
"source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://laravel-excel.com/commercial-support",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/patrickbrouwers",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-08-26T09:13:16+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "maennchen/zipstream-php",
|
|
||||||
"version": "3.1.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
|
||||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
|
||||||
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"ext-zlib": "*",
|
|
||||||
"php-64bit": "^8.2"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"brianium/paratest": "^7.7",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"friendsofphp/php-cs-fixer": "^3.16",
|
|
||||||
"guzzlehttp/guzzle": "^7.5",
|
|
||||||
"mikey179/vfsstream": "^1.6",
|
|
||||||
"php-coveralls/php-coveralls": "^2.5",
|
|
||||||
"phpunit/phpunit": "^11.0",
|
|
||||||
"vimeo/psalm": "^6.0"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"guzzlehttp/psr7": "^2.4",
|
|
||||||
"psr/http-message": "^2.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"ZipStream\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Paul Duncan",
|
|
||||||
"email": "pabs@pablotron.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jonatan Männchen",
|
|
||||||
"email": "jonatan@maennchen.ch"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jesse Donat",
|
|
||||||
"email": "donatj@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "András Kolesár",
|
|
||||||
"email": "kolesar@kolesar.hu"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
|
||||||
"keywords": [
|
|
||||||
"stream",
|
|
||||||
"zip"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
|
||||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/maennchen",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-01-27T12:07:53+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "markbaker/complex",
|
|
||||||
"version": "3.0.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/MarkBaker/PHPComplex.git",
|
|
||||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
|
||||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.2 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Complex\\": "classes/src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"email": "mark@lange.demon.co.uk"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP Class for working with complex numbers",
|
|
||||||
"homepage": "https://github.com/MarkBaker/PHPComplex",
|
|
||||||
"keywords": [
|
|
||||||
"complex",
|
|
||||||
"mathematics"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
|
|
||||||
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
|
|
||||||
},
|
|
||||||
"time": "2022-12-06T16:21:08+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "markbaker/matrix",
|
|
||||||
"version": "3.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/MarkBaker/PHPMatrix.git",
|
|
||||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
|
|
||||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpdocumentor/phpdocumentor": "2.*",
|
|
||||||
"phploc/phploc": "^4.0",
|
|
||||||
"phpmd/phpmd": "2.*",
|
|
||||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
|
||||||
"sebastian/phpcpd": "^4.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Matrix\\": "classes/src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"email": "mark@demon-angel.eu"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP Class for working with matrices",
|
|
||||||
"homepage": "https://github.com/MarkBaker/PHPMatrix",
|
|
||||||
"keywords": [
|
|
||||||
"mathematics",
|
|
||||||
"matrix",
|
|
||||||
"vector"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
|
|
||||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
|
|
||||||
},
|
|
||||||
"time": "2022-12-02T22:17:43+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "masterminds/html5",
|
|
||||||
"version": "2.10.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/Masterminds/html5-php.git",
|
|
||||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
|
||||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-dom": "*",
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "2.7-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Masterminds\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Matt Butcher",
|
|
||||||
"email": "technosophos@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Matt Farina",
|
|
||||||
"email": "matt@mattfarina.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Asmir Mustafic",
|
|
||||||
"email": "goetas@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "An HTML5 parser and serializer.",
|
|
||||||
"homepage": "http://masterminds.github.io/html5-php",
|
|
||||||
"keywords": [
|
|
||||||
"HTML5",
|
|
||||||
"dom",
|
|
||||||
"html",
|
|
||||||
"parser",
|
|
||||||
"querypath",
|
|
||||||
"serializer",
|
|
||||||
"xml"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
|
||||||
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
|
||||||
},
|
|
||||||
"time": "2025-07-25T09:04:22+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
"version": "3.9.0",
|
"version": "3.9.0",
|
||||||
@ -3357,112 +2575,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-05-08T08:14:37+00:00"
|
"time": "2025-05-08T08:14:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "phpoffice/phpspreadsheet",
|
|
||||||
"version": "1.30.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
|
|
||||||
"reference": "2f39286e0136673778b7a142b3f0d141e43d1714"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/2f39286e0136673778b7a142b3f0d141e43d1714",
|
|
||||||
"reference": "2f39286e0136673778b7a142b3f0d141e43d1714",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"composer/pcre": "^1||^2||^3",
|
|
||||||
"ext-ctype": "*",
|
|
||||||
"ext-dom": "*",
|
|
||||||
"ext-fileinfo": "*",
|
|
||||||
"ext-gd": "*",
|
|
||||||
"ext-iconv": "*",
|
|
||||||
"ext-libxml": "*",
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"ext-simplexml": "*",
|
|
||||||
"ext-xml": "*",
|
|
||||||
"ext-xmlreader": "*",
|
|
||||||
"ext-xmlwriter": "*",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"ext-zlib": "*",
|
|
||||||
"ezyang/htmlpurifier": "^4.15",
|
|
||||||
"maennchen/zipstream-php": "^2.1 || ^3.0",
|
|
||||||
"markbaker/complex": "^3.0",
|
|
||||||
"markbaker/matrix": "^3.0",
|
|
||||||
"php": "^7.4 || ^8.0",
|
|
||||||
"psr/http-client": "^1.0",
|
|
||||||
"psr/http-factory": "^1.0",
|
|
||||||
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-main",
|
|
||||||
"dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
|
|
||||||
"friendsofphp/php-cs-fixer": "^3.2",
|
|
||||||
"mitoteam/jpgraph": "^10.3",
|
|
||||||
"mpdf/mpdf": "^8.1.1",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpstan/phpstan": "^1.1",
|
|
||||||
"phpstan/phpstan-phpunit": "^1.0",
|
|
||||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7",
|
|
||||||
"tecnickcom/tcpdf": "^6.5"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
|
|
||||||
"ext-intl": "PHP Internationalization Functions",
|
|
||||||
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
|
|
||||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
|
||||||
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Maarten Balliauw",
|
|
||||||
"homepage": "https://blog.maartenballiauw.be"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"homepage": "https://markbakeruk.net"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Franck Lefevre",
|
|
||||||
"homepage": "https://rootslabs.net"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Erik Tilt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Adrien Crivelli"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
|
||||||
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
|
|
||||||
"keywords": [
|
|
||||||
"OpenXML",
|
|
||||||
"excel",
|
|
||||||
"gnumeric",
|
|
||||||
"ods",
|
|
||||||
"php",
|
|
||||||
"spreadsheet",
|
|
||||||
"xls",
|
|
||||||
"xlsx"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
|
|
||||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.0"
|
|
||||||
},
|
|
||||||
"time": "2025-08-10T06:28:02+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "phpoption/phpoption",
|
"name": "phpoption/phpoption",
|
||||||
"version": "1.9.4",
|
"version": "1.9.4",
|
||||||
@ -4226,72 +3338,6 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-06-25T14:20:11+00:00"
|
"time": "2025-06-25T14:20:11+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "sabberworm/php-css-parser",
|
|
||||||
"version": "v8.9.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
|
||||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
|
||||||
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-iconv": "*",
|
|
||||||
"php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
|
|
||||||
"rawr/cross-data-providers": "^2.0.0"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"ext-mbstring": "for parsing UTF-8 CSS"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "9.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Sabberworm\\CSS\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Raphael Schweikert"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Oliver Klee",
|
|
||||||
"email": "github@oliverklee.de"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jake Hotson",
|
|
||||||
"email": "jake.github@qzdesign.co.uk"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Parser for CSS Files written in PHP",
|
|
||||||
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
|
||||||
"keywords": [
|
|
||||||
"css",
|
|
||||||
"parser",
|
|
||||||
"stylesheet"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
|
||||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0"
|
|
||||||
},
|
|
||||||
"time": "2025-07-11T13:20:48+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
"version": "v7.3.0",
|
"version": "v7.3.0",
|
||||||
|
@ -140,7 +140,6 @@ const exportOptions = ref([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const filterRingkasan = ref("bulan");
|
const filterRingkasan = ref("bulan");
|
||||||
const loadingExport = ref(false);
|
|
||||||
const exportFormat = ref(null);
|
const exportFormat = ref(null);
|
||||||
const ringkasanLaporan = ref([]);
|
const ringkasanLaporan = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -218,43 +217,9 @@ const selectFilter = (option) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const selectExport = (option) => {
|
const selectExport = (option) => {
|
||||||
|
exportFormat.value = option.value;
|
||||||
isExportOpen.value = false;
|
isExportOpen.value = false;
|
||||||
triggerDownload(option.value);
|
alert(`Fitur Belum dikerjakan. Laporan akan diekspor dalam format ${option.label}`);
|
||||||
};
|
|
||||||
|
|
||||||
const triggerDownload = async (format) => {
|
|
||||||
loadingExport.value = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.get('/api/laporan/ringkasan/export', {
|
|
||||||
params: {
|
|
||||||
filter: filterRingkasan.value,
|
|
||||||
format: format
|
|
||||||
},
|
|
||||||
responseType: 'blob',
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
const fileName = `laporan_${filterRingkasan.value}_${new Date().toISOString().split('T')[0]}.${format}`;
|
|
||||||
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', fileName);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
|
|
||||||
link.remove();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Gagal mengunduh laporan:", error);
|
|
||||||
alert("Terjadi kesalahan saat membuat laporan.");
|
|
||||||
} finally {
|
|
||||||
loadingExport.value = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeDropdownsOnClickOutside = (event) => {
|
const closeDropdownsOnClickOutside = (event) => {
|
||||||
@ -266,6 +231,7 @@ const closeDropdownsOnClickOutside = (event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --- Lifecycle Hooks ---
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchRingkasan(pagination.value.current_page);
|
fetchRingkasan(pagination.value.current_page);
|
||||||
document.addEventListener('click', closeDropdownsOnClickOutside);
|
document.addEventListener('click', closeDropdownsOnClickOutside);
|
||||||
|
@ -202,12 +202,11 @@ const loadKategori = async () => {
|
|||||||
|
|
||||||
const loadProduk = async () => {
|
const loadProduk = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`/api/produk`, {
|
await axios.delete(`/api/produk/${detail.value.id}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.data && Array.isArray(response.data)) {
|
if (response.data && Array.isArray(response.data)) {
|
||||||
products.value = response.data;
|
products.value = response.data;
|
||||||
}
|
}
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Laporan Ringkasan</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: sans-serif; font-size: 10px; }
|
|
||||||
table { width: 100%; border-collapse: collapse; margin-bottom: 15px; }
|
|
||||||
th, td { border: 1px solid #ccc; padding: 4px; text-align: left; }
|
|
||||||
th { background-color: #f0f0f0; }
|
|
||||||
.text-right { text-align: right; }
|
|
||||||
.text-center { text-align: center; }
|
|
||||||
tr.total-row td { background-color: #f9f9f9; font-weight: bold; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2 style="text-align: center;">Laporan Ringkasan {{ ucfirst($filter) }}</h2>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Tanggal</th>
|
|
||||||
<th>Nama Sales</th>
|
|
||||||
<th>Item Terjual</th>
|
|
||||||
<th>Berat Terjual</th>
|
|
||||||
<th>Pendapatan</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach($data as $item)
|
|
||||||
@php $rowCount = count($item['sales']) > 0 ? count($item['sales']) : 1; @endphp
|
|
||||||
|
|
||||||
@if(count($item['sales']) > 0)
|
|
||||||
@foreach($item['sales'] as $index => $sales)
|
|
||||||
<tr>
|
|
||||||
@if($index == 0)
|
|
||||||
<td rowspan="{{ $rowCount }}">{{ $item['tanggal'] }}</td>
|
|
||||||
@endif
|
|
||||||
<td>{{ $sales['nama'] }}</td>
|
|
||||||
<td class="text-center">{{ $sales['item_terjual'] }}</td>
|
|
||||||
<td class="text-right">{{ $sales['berat_terjual'] }}</td>
|
|
||||||
<td class="text-right">{{ $sales['pendapatan'] }}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
@else
|
|
||||||
<tr>
|
|
||||||
<td>{{ $item['tanggal'] }}</td>
|
|
||||||
<td colspan="4" class="text-center" style="font-style: italic;">Tidak ada data transaksi</td>
|
|
||||||
</tr>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
{{-- Baris Total --}}
|
|
||||||
<tr class="total-row">
|
|
||||||
<td colspan="2" class="text-right"><strong>Total Periode Ini</strong></td>
|
|
||||||
<td class="text-center"><strong>{{ $item['total_item_terjual'] }}</strong></td>
|
|
||||||
<td class="text-right"><strong>{{ $item['total_berat'] }}</strong></td>
|
|
||||||
<td class="text-right"><strong>{{ $item['total_pendapatan'] }}</strong></td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -42,8 +42,6 @@ Route::prefix('api')->group(function () {
|
|||||||
Route::get('laporan', [LaporanController::class, 'ringkasan']);
|
Route::get('laporan', [LaporanController::class, 'ringkasan']);
|
||||||
Route::get('detail-per-produk', [LaporanController::class, 'detailPerProduk']);
|
Route::get('detail-per-produk', [LaporanController::class, 'detailPerProduk']);
|
||||||
Route::get('detail-per-nampan', [LaporanController::class, 'detailPerNampan']);
|
Route::get('detail-per-nampan', [LaporanController::class, 'detailPerNampan']);
|
||||||
|
|
||||||
Route::get('/laporan/ringkasan/export', [LaporanController::class, 'exportRingkasan']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware(['auth:sanctum', 'role:owner,kasir'])->group(function () {
|
Route::middleware(['auth:sanctum', 'role:owner,kasir'])->group(function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user