' . @$p2->title.'';
if (count($child3) > 0) {
$html .= '';
$html .= '';
diff --git a/app/Http/Controllers/Activity/FormAdaptasiController.php b/app/Http/Controllers/Activity/FormAdaptasiController.php
new file mode 100644
index 0000000..27b70fd
--- /dev/null
+++ b/app/Http/Controllers/Activity/FormAdaptasiController.php
@@ -0,0 +1,388 @@
+ $user ? $user->name : 'Guest',
+ 'waktu' => $km->created_at->translatedFormat('l, d F Y, H:i'),
+ 'nama' => $km->nama_kegiatan,
+ 'tahun' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'subsektor' => $km->sub_sektor,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'penurunan' => $km->emission_factor,
+ ];
+
+ return view('form.index-adaptasi-thankyou', compact('data', 'km'));
+ }
+
+ public function downloadPDF(string $id)
+ {
+ $user = Auth::user();
+ $km = KegiatanAdaptasi::findOrFail($id);
+
+ $data = [
+ 'oleh' => $user ? $user->name : 'Guest',
+ 'waktu' => $km->created_at->translatedFormat('l, d F Y, H:i'),
+ 'nama' => $km->nama_kegiatan,
+ 'tahun' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'subsektor' => $km->sub_sektor,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'penurunan' => $km->emission_factor,
+ ];
+
+ $pdf = PDF::loadView('form.index-adaptasi.pdf', compact('data'))
+ ->setPaper('a4', 'portrait');
+
+ return $pdf->download('bukti-submission-'.$km->nama_kegiatan.'.pdf');
+ }
+
+ public function view(string $id)
+ {
+ $ka = KegiatanAdaptasi::findOrFail($id);
+ $sessionData = [
+ 'adaptation_id' => $ka->adaptation_id,
+ 'nama_kegiatan' => $ka->nama_kegiatan,
+ 'tahun_kegiatan' => $ka->tahun_kegiatan,
+ 'sektor' => $ka->sektor,
+ 'sub_sektor' => $ka->sub_sektor,
+ 'kategori_aksi' => $ka->kategori_aksi,
+ // 'jenis_aksi' => $ka->jenis_aksi,
+ // 'aksi' => $ka->aksi,
+ 'pelaksana_kegiatan' => $ka->pelaksana_kegiatan,
+ 'lokasi_kegiatan' => $ka->lokasi_kegiatan,
+ 'waktu_kegiatan' => $ka->waktu_kegiatan,
+ 'dokumen' => $ka->dokumen,
+ 'alokasi_apbn' => $ka->alokasi_apbn,
+ 'alokasi_apbd' => $ka->alokasi_apbd,
+ 'alokasi_swasta' => $ka->alokasi_swasta,
+ 'alokasi_sumber_dana_lain' => $ka->alokasi_sumber_dana_lain,
+ 'realisasi_apbn' => $ka->realisasi_apbn,
+ 'realisasi_apbd' => $ka->realisasi_apbd,
+ 'realisasi_swasta' => $ka->realisasi_swasta,
+ 'realisasi_sumber_dana_lain' => $ka->realisasi_sumber_dana_lain,
+ 'detail_kegiatan' => $ka->detail_kegiatan,
+ ];
+
+ return view('form.index-adaptasi-view', [
+ 'sessionData' => $sessionData,
+ 'id' => $id,
+ ]);
+ }
+
+ public function edit(string $id, Request $request)
+ {
+ $ka = KegiatanAdaptasi::findOrFail($id);
+ $sessionData = [
+ 'adaptation_id' => $ka->adaptation_id,
+ 'nama_kegiatan' => $ka->nama_kegiatan,
+ 'tahun_kegiatan' => $ka->tahun_kegiatan,
+ 'sektor' => $ka->sektor,
+ 'sub_sektor' => $ka->sub_sektor,
+ 'kategori_aksi' => $ka->kategori_aksi,
+ // 'jenis_aksi' => $ka->jenis_aksi,
+ // 'aksi' => $ka->aksi,
+ 'pelaksana_kegiatan' => $ka->pelaksana_kegiatan,
+ 'lokasi_kegiatan' => $ka->lokasi_kegiatan,
+ 'waktu_kegiatan' => $ka->waktu_kegiatan,
+ 'dokumen' => $ka->dokumen,
+ 'alokasi_apbn' => $ka->alokasi_apbn,
+ 'alokasi_apbd' => $ka->alokasi_apbd,
+ 'alokasi_swasta' => $ka->alokasi_swasta,
+ 'alokasi_sumber_dana_lain' => $ka->alokasi_sumber_dana_lain,
+ 'realisasi_apbn' => $ka->realisasi_apbn,
+ 'realisasi_apbd' => $ka->realisasi_apbd,
+ 'realisasi_swasta' => $ka->realisasi_swasta,
+ 'realisasi_sumber_dana_lain' => $ka->realisasi_sumber_dana_lain,
+ 'detail_kegiatan' => $ka->detail_kegiatan,
+ ];
+
+ $request->session()->put('kegiatan_adaptasi', $sessionData);
+
+ $startYear = 200;
+ $currentYear = now()->year;
+ $years = range($startYear, $currentYear);
+ rsort($years);
+
+ $sectors = KegiatanAdaptasi::distinct()->pluck('sektor')->toArray();
+
+ return view('form.index-adaptasi-edit', [
+ 'sessionData' => $sessionData,
+ 'years' => $years,
+ 'currentYear' => $currentYear,
+ 'sectors' => $sectors,
+ 'adaptation' => $ka,
+ 'readonly' => false
+ ]);
+ }
+
+ public function create(Request $request)
+ {
+ if ($request->has('reset')) {
+ $request->session()->forget('kegiatan_adaptasi');
+ }
+ $sessionData = $request->session()->get('kegiatan_adaptasi', []);
+
+ $startYear = 2000;
+ $currentYear = date('Y');
+ $years = range($startYear, $currentYear);
+ rsort($years);
+
+ return view('form.index-adaptasi', compact('sessionData', 'years', 'currentYear'));
+ }
+
+ public function update(Request $request, $id)
+ {
+ $kegiatanAdaptasi = KegiatanAdaptasi::findOrFail($id);
+
+ $sessionData = $request->session()->get('kegiatan_adaptasi');
+ if (empty($sessionData)) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Data tidak lengkap, silakan lengkapi semua bagian.'
+ ]);
+ }
+
+ try {
+ DB::transaction(function() use ($sessionData, $request, $kegiatanAdaptasi) {
+ $kegiatanAdaptasi->update([
+ 'adaptation_id' => $sessionData['adaptation_id'] ?? null,
+ 'nama_kegiatan' => $sessionData['nama_kegiatan'] ?? null,
+ 'tahun_kegiatan' => $sessionData['tahun_kegiatan'] ?? null,
+ 'sektor' => $sessionData['sektor'] ?? null,
+ 'sub_sektor' => $sessionData['sub_sektor'] ?? null,
+ 'kategori_aksi' => $sessionData['kategori_aksi'] ?? null,
+ // 'jenis_aksi' => $sessionData['jenis_aksi'] ?? null,
+ // 'aksi' => $sessionData['aksi'] ?? null,
+ 'pelaksana_kegiatan' => $sessionData['pelaksana_kegiatan'] ?? null,
+ 'lokasi_kegiatan' => $sessionData['lokasi_kegiatan'] ?? null,
+ 'waktu_kegiatan' => $sessionData['waktu_kegiatan'] ?? null,
+ 'dokumen' => $sessionData['dokumen'] ?? null,
+ 'alokasi_apbn' => $sessionData['alokasi_apbn'] ?? null,
+ 'alokasi_apbd' => $sessionData['alokasi_apbd'] ?? null,
+ 'alokasi_swasta' => $sessionData['alokasi_swasta'] ?? null,
+ 'alokasi_sumber_dana_lain' => $sessionData['alokasi_sumber_dana_lain'] ?? null,
+ 'realisasi_apbn' => $sessionData['realisasi_apbn'] ?? null,
+ 'realisasi_apbd' => $sessionData['realisasi_apbd'] ?? null,
+ 'realisasi_swasta' => $sessionData['realisasi_swasta'] ?? null,
+ 'realisasi_sumber_dana_lain' => $sessionData['realisasi_sumber_dana_lain'] ?? null,
+ 'detail_kegiatan' => $request['detail_kegiatan'] ?? $sessionData['detail_kegiatan'],
+ 'updated_by' => auth()->check() ? auth()->user()->name : null,
+ ]);
+
+ $request->session()->forget('kegiatan_adaptasi');
+ });
+
+ return response()->json([
+ 'success' => true,
+ 'redirect' => route('formAdaptasi.thankYou', $id),
+ ]);
+ } catch(\Exception $e) {
+ Log::error('Error updating data: ' . $e->getMessage());
+ return back()->with('error', 'Gagal mengupdate data. Silakan coba lagi.');
+ }
+ }
+
+ public function storePart1(Request $request)
+ {
+ $validated = $request->validate([
+ 'nama_kegiatan' => 'required|string',
+ 'tahun_kegiatan' => 'required|integer|min:2000|max:' . date('Y'),
+ 'sektor' => 'required|string',
+ 'sub_sektor' => 'required|string',
+ 'kategori_aksi' => 'required|string',
+ // 'jenis_aksi' => 'required|string',
+ // 'aksi' => 'required|string',
+ 'pelaksana_kegiatan' => 'nullable|string',
+ 'lokasi_kegiatan' => 'nullable|string',
+ 'waktu_kegiatan' => 'nullable|string',
+ 'dokumen' => 'nullable|string',
+ 'adaptation_id' => 'required|string'
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_adaptasi');
+ $sessionArray = is_object($sessionData) ? $sessionData->toArray() : (array) $sessionData;
+ $mergedData = array_merge($sessionArray, $validated);
+
+ $request->session()->put('kegiatan_adaptasi', $mergedData);
+
+ return response()->json(['success' => true]);
+ }
+
+ public function storePart2(Request $request)
+ {
+ $validated = $request->validate([
+ 'alokasi_apbn' => 'nullable|string',
+ 'alokasi_apbd' => 'nullable|string',
+ 'alokasi_swasta' => 'nullable|string',
+ 'alokasi_sumber_dana_lain' => 'nullable|string',
+ 'realisasi_apbn' => 'nullable|string',
+ 'realisasi_apbd' => 'nullable|string',
+ 'realisasi_swasta' => 'nullable|string',
+ 'realisasi_sumber_dana_lain' => 'nullable|string'
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_adaptasi');
+
+ if(!$sessionData) {
+ return response()->json(['success' => false, 'message' => 'Silakan lengkapi bagian Informasi Umum terlebih dahulu']);
+ }
+
+ $updatedData = array_merge($sessionData, $validated);
+
+ $request->session()->put('kegiatan_adaptasi', $updatedData);
+ return response()->json(['success' => true]);
+ }
+
+ public function storeFinal(Request $request)
+ {
+ $sessionData = $request->session()->get('kegiatan_adaptasi');
+
+ if (empty($sessionData)) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Silakan lengkapi semua bagian terlebih dahulu'
+ ]);
+ }
+
+ try {
+ $adaptasiId = Str::uuid()->toString();
+
+ DB::transaction(function() use ($sessionData, $request, $adaptasiId) {
+ // 1️⃣ Create master record
+ KegiatanAdaptasi::create([
+ 'id' => $adaptasiId,
+ 'adaptation_id' => $sessionData['adaptation_id'] ?? null,
+ 'nama_kegiatan' => $sessionData['nama_kegiatan'] ?? null,
+ 'tahun_kegiatan' => $sessionData['tahun_kegiatan'] ?? null,
+ 'sektor' => $sessionData['sektor'] ?? null,
+ 'sub_sektor' => $sessionData['sub_sektor'] ?? null,
+ 'kategori_aksi' => $sessionData['kategori_aksi'] ?? null,
+ // 'jenis_aksi' => $sessionData['jenis_aksi'] ?? null,
+ // 'aksi' => $sessionData['aksi'] ?? null,
+ 'pelaksana_kegiatan' => $sessionData['pelaksana_kegiatan'] ?? null,
+ 'lokasi_kegiatan' => $sessionData['lokasi_kegiatan'] ?? null,
+ 'waktu_kegiatan' => $sessionData['waktu_kegiatan'] ?? null,
+ 'dokumen' => $sessionData['dokumen'] ?? null,
+ 'alokasi_apbn' => $sessionData['alokasi_apbn'] ?? null,
+ 'alokasi_apbd' => $sessionData['alokasi_apbd'] ?? null,
+ 'alokasi_swasta' => $sessionData['alokasi_swasta'] ?? null,
+ 'alokasi_sumber_dana_lain' => $sessionData['alokasi_sumber_dana_lain'] ?? null,
+ 'realisasi_apbn' => $sessionData['realisasi_apbn'] ?? null,
+ 'realisasi_apbd' => $sessionData['realisasi_apbd'] ?? null,
+ 'realisasi_swasta' => $sessionData['realisasi_swasta'] ?? null,
+ 'realisasi_sumber_dana_lain' => $sessionData['realisasi_sumber_dana_lain'] ?? null,
+ 'detail_kegiatan' => $sessionData['detail_kegiatan'] ?? $request->input('detail_kegiatan'),
+ 'created_by' => auth()->check() ? auth()->user()->name : null,
+ ]);
+
+ // bersihkan session setelah sukses
+ $request->session()->forget('kegiatan_adaptasi');
+ });
+
+ return response()->json([
+ 'success' => true,
+ 'redirect' => route('formAdaptasi.thankYou', $adaptasiId),
+ ]);
+ } catch (\Exception $e) {
+ Log::error('Error storing final data: ' . $e->getMessage());
+ return back()->with('error', 'Gagal menyimpan data. Silakan coba lagi.');
+ }
+ }
+
+
+ public function getSectors()
+ {
+ $query = Adaptation::select('sector')
+ ->where('is_active', true)
+ ->distinct();
+ $result = $query->pluck('sector');
+
+ return response()->json($result);
+ }
+
+ public function getSubSectors(Request $request)
+ {
+ $param = $request->input('sector');
+
+ $query = Adaptation::select('sub_sector')
+ ->where('sector', $param)
+ ->where('is_active', true)
+ ->distinct();
+ $result = $query->pluck('sub_sector');
+
+ return response()->json($result);
+ }
+
+ public function getKategoriAksi(Request $request)
+ {
+ $param = $request->input('sub_sector');
+ $param2 = $request->input('sector');
+
+ $query = Adaptation::select('id','kategori_aksi')
+ ->where('sub_sector', $param)
+ ->where('sector', $param2)
+ ->where('is_active', true)
+ ->distinct()
+ ->get();
+
+ // kirim langsung object, jangan pluck
+ return response()->json($query);
+ }
+
+
+ public function getJenisAksi(Request $request)
+ {
+ $param = $request->input('sub_sector');
+ $param2 = $request->input('sector');
+ $param3 = $request->input('kategori');
+
+ $query = Adaptation::select('jenis_aksi')
+ ->where('sub_sector', $param)
+ ->where('sector', $param2)
+ ->where('kategori_aksi', $param3)
+ ->where('is_active', true)
+ ->distinct()->get();
+ $result = $query->pluck('jenis_aksi');
+
+ return response()->json($result);
+ }
+
+ public function getAksi(Request $request)
+ {
+ $param = $request->input('sub_sector');
+ $param2 = $request->input('sector');
+ $param3 = $request->input('kategori');
+ $param4 = $request->input('jenis');
+
+ $query = Adaptation::select('id', 'aksi')
+ ->where('sub_sector', $param)
+ ->where('sector', $param2)
+ ->where('kategori_aksi', $param3)
+ ->where('jenis_aksi', $param4)
+ ->where('is_active', true)
+ ->distinct('aksi')->get();
+
+ return response()->json($query);
+ }
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/Activity/FormController.php b/app/Http/Controllers/Activity/FormController.php
new file mode 100644
index 0000000..fbdf059
--- /dev/null
+++ b/app/Http/Controllers/Activity/FormController.php
@@ -0,0 +1,311 @@
+formService = $formService;
+ }
+
+ public static function middleware(): array
+ {
+ $sector = request()->route('sector');
+ $code = request()->route('code');
+
+ return [
+ // //new Middleware('permission:/' . $sector . '/' . $code, except: ['getUserActivities']),
+ ];
+ }
+
+ public function data($sector, $code, $inventoryYear, $instansi = null)
+ {
+ // Fetch the form from the database based on sector and code
+ $form = SettingForm::rowActive()->where('sector', $sector)->where('code', $code)->first();
+
+ if (!$form) {
+ abort(404, 'Page not found');
+ }
+
+ // Fetch form details
+ $formDetails = SettingFormDetail::rowActive()->where('form_code', $code)->orderByRowNum()->get();
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ }
+
+ // get Agencies for produsen data mapping
+ $user = Auth::user();
+ $scope = $user->getScope();
+
+ if ($scope === LingkupAksesData::INTERNAL->value) {
+ $instansi = $user->agency_id;
+ }
+
+ $agencies = Agency::whereHas('agencyActivity', function ($query) use ($sector, $code, $scope, $user) {
+ $query->where('form_sector', $sector)
+ ->where('form_code', $code);
+
+ if ($scope === LingkupAksesData::INTERNAL->value) {
+ $query->where('agency_id', $user->agency_id);
+ }
+ })->get();
+
+ // Fetch activity form and activity form details using service
+ $activityForm = $this->formService->getActivityForm($sector, $code, $inventoryYear, $instansi);
+ if ($instansi == 'all') {
+ $activityFormId = $activityForm->pluck('id')->toArray();
+ } else {
+ $activityFormId = $activityForm->id ?? null;
+ }
+
+ $activityFormDetails = $this->formService->getActivityFormDetails($activityFormId, $instansi);
+
+ // Fetch all units & set the mappings
+ $allUnits = ReferenceUnit::rowActive()->get();
+ $unitsMap = $allUnits->keyBy('code');
+ $unitsByCategory = $allUnits->groupBy('category');
+
+ // For Copy data feature
+ // $availableYears = ActivityForm::select('inventory_year')->distinct()
+ // ->where('sector', $sector)->where('form_code', $code)->rowActive()
+ // ->orderBy('inventory_year', 'desc')->get()->pluck('inventory_year')->toArray();
+
+ $isLocked = ActivityLock::isLocked($inventoryYear);
+ $isApprove = false;
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $isApprove = ActivityApprovalKonsolidasi::isApprove($activityFormId, $sector, $code, $inventoryYear, $instansi);
+ }
+
+ $internal = $instansi;
+
+ return compact(
+ 'form',
+ 'formDetails',
+ 'activityForm',
+ 'activityFormDetails',
+ 'unitsMap',
+ 'unitsByCategory',
+ 'inventoryYear',
+ 'isLocked',
+ 'agencies',
+ 'internal',
+ 'isApprove'
+ );
+ }
+
+ public function show($sector, $code)
+ {
+ // Filter by Year
+ $inventoryYear = request('inventoryYear') ?? date('Y');
+ $instansi = request('instansi') ?? null;
+
+ // Retrieve data
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+
+ return view('form.index', $data);
+ }
+
+ public function save(Request $request, $sector, $code)
+ {
+ $request->validate([
+ 'data' => 'required|array',
+ ]);
+
+ // Filter by Year
+ $inventoryYear = $request->input('inventoryYear') ?? date('Y');
+ $instansi = request('instansi') ?? null;
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ } else {
+ $instansi = null;
+ }
+
+ $data = $request->input('data');
+ $unitCodes = $request->input('unit_code');
+
+ try {
+ $this->formService->save($sector, $code, $inventoryYear, $data, $unitCodes, $instansi);
+ return redirect()->back()->with('success', 'Data berhasil disimpan.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data gagal disimpan. Mohon dicoba kembali.' . $e->getMessage()]);
+ }
+ }
+
+ public function convertUnit(Request $request)
+ {
+ $fromUnit = $request->get('from');
+ $toUnit = $request->get('to');
+ $value = $request->get('value');
+
+ $convertedValue = $this->formService->convertUnit($fromUnit, $toUnit, $value);
+
+ if ($convertedValue !== null) {
+ $output = getFormattedValue($convertedValue);
+ return response()->json([
+ 'success' => true,
+ 'convertedValue' => $output,
+ ]);
+ }
+
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Konversi tidak ditemukan',
+ ]);
+ }
+
+ public function import(Request $request, $sector, $code, $inventoryYear, $instansi = null)
+ {
+ $request->validate([
+ 'import_file' => 'required|file|mimes:xlsx,xls|max:2048', // Adjust max file size as needed
+ ]);
+
+ try {
+ $formDetails = SettingFormDetail::where('form_code', $code)->rowActive()->orderByRowNum()->get();
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ } else {
+ $instansi = null;
+ }
+
+ Excel::import(new FormImport($this->formService, $sector, $code, $inventoryYear, $formDetails, $instansi), $request->file('import_file'));
+
+ return redirect()->back()->with('success', 'Data berhasil diimpor.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data gagal diimpor. Mohon dicoba kembali.' . $e->getMessage()]);
+ }
+ }
+
+ public function export($sector, $code, $inventoryYear, $instansi = null)
+ {
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+ $data['inventoryYear'] = $inventoryYear;
+ $data['instansi'] = $instansi;
+
+ $isTemplate = request('isTemplate') ?? false;
+ $data['isTemplate'] = $isTemplate;
+
+ $instansiTitle = ($instansi && $instansi != 'all' && $instansi != 'none') ? ' (' . $instansi . ')' : '';
+ $titleExcel = $data['form']->name . ' ' . $inventoryYear . $instansiTitle;
+
+ if ($isTemplate) {
+ $titleExcel = 'Template ' . $titleExcel;
+ } else {
+ $titleExcel = 'Data Aktivitas ' . $titleExcel;
+ }
+
+ $data['titleExcel'] = $titleExcel;
+ $fileName = $titleExcel . '.xlsx';
+
+ return Excel::download(new FormExport($data), $fileName);
+ }
+
+ public function getUserActivities(Request $request)
+ {
+ if ($request->ajax()) {
+ $data = [];
+ $formId = $request->query('form_id');
+
+ if ($formId !== null && $formId !== '0') {
+ // $data = LogUserActivity::with('user')->where('form_id', $formId)
+ // ->orderBy('created_at', 'desc');
+ $data = LogUserActivity::rowActive()->orderByRowNum()->where('form_id', $formId);
+ }
+
+ $result = datatables()->of($data)
+ ->addIndexColumn()
+ ->addColumn('user_name', function ($row) {
+ return $row->user->name;
+ })
+ ->editColumn('activity_type', function ($row) {
+ return ActivityType::from($row->activity_type)->label();
+ })
+ ->editColumn('created_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s');
+ })
+ ->make(true);
+
+ return $result;
+ }
+ }
+
+ public function lock($sector, $code, $id)
+ {
+ try {
+ $this->formService->lockForm($id);
+ return redirect()->back()->with('success', 'Data Aktivitas berhasil dikunci.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data Aktivitas gagal dikunci. Mohon dicoba kembali.']);
+ }
+ }
+
+ public function unlock($sector, $code, $id)
+ {
+ try {
+ $this->formService->unlockForm($id);
+ return redirect()->back()->with('success', 'Data Aktivitas berhasil dibuka.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data Aktivitas gagal dibuka. Mohon dicoba kembali.']);
+ }
+ }
+
+ public function copyData(Request $request, $sector, $code)
+ {
+ try {
+ $fromYear = $request->input('from_year');
+ $toYear = $request->input('to_year');
+
+ $this->formService->copyData($sector, $code, $fromYear, $toYear);
+
+ return redirect()->back()->with('success', 'Data Aktivitas berhasil disalin.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data Aktivitas gagal disalin. Mohon dicoba kembali.']);
+ }
+ }
+
+ public function approvalKonsolidasi($sector, $code, $inventoryYear, $instansi = null)
+ {
+ try {
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ }
+
+ $form = $data['activityForm'];
+ $this->formService->approvalKonsolidasi($form, $sector, $code, $inventoryYear, $instansi);
+
+ return redirect()->back()->with('success', 'Persetujuan Data Produsen berhasil diproses.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Persetujuan Data Produsen gagal diproses. Mohon dicoba kembali.' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Activity/FormKehutananController.php b/app/Http/Controllers/Activity/FormKehutananController.php
new file mode 100644
index 0000000..147e27d
--- /dev/null
+++ b/app/Http/Controllers/Activity/FormKehutananController.php
@@ -0,0 +1,216 @@
+formService = $formService;
+ }
+
+ public static function middleware(): array
+ {
+ $sector = 'folu';
+ $code = 'lahan_mineral';
+
+ return [
+ //new Middleware('permission:/' . $sector . '/' . $code),
+ ];
+ }
+
+ public function data($sector, $code, $inventoryYear, $instansi = null)
+ {
+ // Fetch the form from the database based on sector and code
+ $form = SettingForm::rowActive()->where('sector', $sector)->where('code', $code)->first();
+
+ if (!$form) {
+ abort(404, 'Page not found');
+ }
+
+ // Fetch form details
+ $lands = $this->lands;
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ }
+
+ // get Agencies for produsen data mapping
+ $user = Auth::user();
+ $scope = $user->getScope();
+
+ if ($scope === LingkupAksesData::INTERNAL->value) {
+ $instansi = $user->agency_id;
+ }
+
+ $agencies = Agency::whereHas('agencyActivity', function ($query) use ($sector, $code, $scope, $user) {
+ $query->where('form_sector', $sector)
+ ->where('form_code', $code);
+
+ if ($scope === LingkupAksesData::INTERNAL->value) {
+ $query->where('agency_id', $user->agency_id);
+ }
+ })->get();
+
+ // Fetch activity form and activity form details using service
+ $activityForm = $this->formService->getActivityForm($sector, $code, $inventoryYear, $instansi);
+ if ($instansi == 'all') {
+ $activityFormId = $activityForm->pluck('id')->toArray();
+ } else {
+ $activityFormId = $activityForm->id ?? null;
+ }
+
+ $activityFormDetails = $this->formService->getActivityFormDetails($activityFormId, $instansi);
+
+ $isLocked = ActivityLock::isLocked($inventoryYear);
+ $isApprove = false;
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $isApprove = ActivityApprovalKonsolidasi::isApprove($activityFormId, $sector, $code, $inventoryYear, $instansi);
+ }
+
+ $internal = $instansi;
+
+ return compact(
+ 'form',
+ 'lands',
+ 'activityForm',
+ 'activityFormDetails',
+ 'inventoryYear',
+ 'isLocked',
+ 'agencies',
+ 'internal',
+ 'isApprove'
+ );
+ }
+
+ public function show()
+ {
+ $sector = $this->sector;
+ $code = $this->code;
+ $inventoryYear = request('inventoryYear') ?? date('Y');
+ $instansi = request('instansi') ?? null;
+
+ // Retrieve data
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+
+ return view('form.index-kehutanan', $data);
+ }
+
+ public function import(Request $request, $inventoryYear, $instansi = null)
+ {
+ $request->validate([
+ 'import_file' => 'required|file|mimes:xlsx,xls|max:2048', // Adjust max file size as needed
+ ]);
+
+ $sector = $this->sector;
+ $code = $this->code;
+ $importService = $this->formService;
+
+ try {
+ $lands = $this->lands;
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ } else {
+ $instansi = null;
+ }
+
+ Excel::import(new FormKehutananImport($importService, $sector, $code, $inventoryYear, $lands, $instansi), $request->file('import_file'));
+
+ return redirect()->back()->with('success', 'Data berhasil diimpor.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Data gagal diimpor. Mohon dicoba kembali.' . $e->getMessage()]);
+ }
+ }
+
+ public function export($inventoryYear, $instansi = null)
+ {
+ $sector = $this->sector;
+ $code = $this->code;
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+ $data['inventoryYear'] = $inventoryYear;
+
+ $isTemplate = request('isTemplate') ?? false;
+ $data['isTemplate'] = $isTemplate;
+ $instansiTitle = ($instansi && $instansi != 'all' && $instansi != 'none') ? ' (' . $instansi . ')' : '';
+ $titleExcel = $data['form']->name . ' ' . $inventoryYear . $instansiTitle;
+
+ if ($isTemplate) {
+ $titleExcel = 'Template ' . $titleExcel;
+ } else {
+ $titleExcel = 'Data Aktivitas ' . $titleExcel;
+ }
+
+ $data['titleExcel'] = $titleExcel;
+ $fileName = $titleExcel . '.xlsx';
+
+ return Excel::download(new FormKehutananExport($data), $fileName);
+ }
+
+ public function approvalKonsolidasi($inventoryYear, $instansi = null)
+ {
+ $sector = $this->sector;
+ $code = $this->code;
+ try {
+ $data = $this->data($sector, $code, $inventoryYear, $instansi);
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $agency = Agency::where('name', $instansi)->rowActive()->first();
+ $instansi = $agency ? $agency->id : null;
+ }
+
+ $form = $data['activityForm'];
+ $this->formService->approvalKonsolidasi($form, $sector, $code, $inventoryYear, $instansi);
+
+ return redirect()->back()->with('success', 'Persetujuan Data Produsen berhasil diproses.');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Persetujuan Data Produsen gagal diproses. Mohon dicoba kembali.' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Activity/FormMetadataController.php b/app/Http/Controllers/Activity/FormMetadataController.php
new file mode 100644
index 0000000..d6875f0
--- /dev/null
+++ b/app/Http/Controllers/Activity/FormMetadataController.php
@@ -0,0 +1,59 @@
+metaService = $metaService;
+ }
+
+ public function index(Request $request)
+ {
+ $formId = $request->query('form_id');
+ $metadataList = ActivityFormMetadata::rowActive()->where('form_id', $formId)->orderBy('updated_at', 'DESC')->get();
+ $form = ActivityForm::rowActive()->where('id', $formId)->first();
+ if ($form) {
+ $form['storagePath'] = 'forms/' . $form->sector . '/' . $form->form_code . '/' . $form->inventory_year . '/metadata';
+ }
+
+ return view('form.metadata.list', compact('metadataList', 'form'));
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'name' => 'required|string|max:255',
+ 'publisher' => 'required|string|max:255',
+ 'published_year' => 'required|integer',
+ 'contact_name' => 'required|string|max:255',
+ 'contact_phone' => 'required|string|max:255',
+ 'contact_email' => 'required|email|max:255',
+ 'file_document' => 'required|file|max:2048|mimes:pdf,doc,docx,xlsx,xls',
+ ], [
+ 'file_document.max' => 'Ukuran file tidak boleh melebihi 2MB.',
+ ]);
+
+ $metadata = $this->metaService->store($request->all());
+
+ return response()->json(['success' => 'Metadata berhasil disimpan.']);
+ }
+
+ public function destroy(Request $request, ActivityFormMetadata $metadata)
+ {
+ $storagePath = $request->input('storage_path');
+
+ $this->metaService->destroy($metadata, $storagePath);
+
+ return response()->json(['success' => 'Metadata berhasil dihapus.']);
+ }
+}
diff --git a/app/Http/Controllers/Activity/FormMitigasiController.php b/app/Http/Controllers/Activity/FormMitigasiController.php
new file mode 100644
index 0000000..4a71293
--- /dev/null
+++ b/app/Http/Controllers/Activity/FormMitigasiController.php
@@ -0,0 +1,777 @@
+formMitigasiService = $formMitigasiService;
+ }
+
+ public function thankYou(string $id)
+ {
+ $user = Auth::user();
+ $km = KegiatanMitigasi::findOrFail($id);
+
+ $data = [
+ 'oleh' => $user ? $user->name : 'Guest',
+ 'waktu' => $km->created_at->translatedFormat('l, d F Y, H:i'),
+ 'nama' => $km->nama_kegiatan,
+ 'tahun' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'subsektor' => $km->sub_sektor,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'penurunan' => $km->emission_factor,
+ ];
+
+ return view('form.index-mitigasi-thankyou', compact('data', 'km'));
+ }
+
+ public function downloadPDF(string $id)
+ {
+ $user = Auth::user();
+ $km = KegiatanMitigasi::findOrFail($id);
+
+ $data = [
+ 'oleh' => $user ? $user->name : 'Guest',
+ 'waktu' => $km->created_at->translatedFormat('l, d F Y, H:i'),
+ 'nama' => $km->nama_kegiatan,
+ 'tahun' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'subsektor' => $km->sub_sektor,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'penurunan' => $km->emission_factor,
+ ];
+
+ $pdf = PDF::loadView('form.index-mitigasi-pdf', compact('data'))
+ ->setPaper('a4', 'portrait');
+
+ return $pdf->download('bukti-submission-'.$km->nama_kegiatan.'.pdf');
+ }
+
+ public function view(string $id)
+ {
+ $km = KegiatanMitigasi::with('sumberData')->findOrFail($id);
+ $forms = ActivityDataMitigationForm::where('kegiatan_mitigasi_id', $id)->get();
+
+ $sessionData = [
+ 'tipe_kegiatan' => $km->tipe_kegiatan,
+ 'tahun_kegiatan' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'sub_sektor' => $km->sub_sektor,
+ 'kategori_perhitungan' => $km->kategori_perhitungan,
+ 'kategori_sub_aktivitas' => $km->kategori_sub_aktivitas,
+ 'mitigation_id' => $km->mitigation_id,
+ 'tipe_laporan' => $km->tipe_laporan,
+ 'nama_kegiatan' => $km->nama_kegiatan,
+ 'informasi_lokasi_kegiatan' => $km->informasi_lokasi_kegiatan,
+ 'jenis_kegiatan' => $km->jenis_kegiatan,
+ 'pelaksana_kegiatan' => $km->pelaksana_kegiatan,
+ 'pelaksana_kegiatan_rad' => $km->pelaksana_kegiatan_rad,
+ 'nomenklatur_kemendagri' => $km->nomenklatur_kemendagri,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'realisasi' => $km->realisasi,
+ 'sdg' => is_array($km->sdg) ? $km->sdg : (json_decode($km->sdg, true) ?? []),
+ 'catatan' => $km->catatan,
+ 'alokasi_apbn' => $km->alokasi_apbn,
+ 'alokasi_apbd' => $km->alokasi_apbd,
+ 'alokasi_swasta' => $km->alokasi_swasta,
+ 'alokasi_sumber_dana_lain' => $km->alokasi_sumber_dana_lain,
+ 'realisasi_apbn' => $km->realisasi_apbn,
+ 'realisasi_apbd' => $km->realisasi_apbd,
+ 'realisasi_swasta' => $km->realisasi_swasta,
+ 'realisasi_sumber_dana_lain' => $km->realisasi_sumber_dana_lain,
+ 'kabupaten_kota_location' => $km->kabupaten_kota_location,
+ 'kecamatan_location' => $km->kecamatan_location,
+ 'kelurahan_location' => $km->kelurahan_location,
+ 'lat_location' => $km->lat_location,
+ 'long_location' => $km->long_location,
+ 'sumber_data' => $km->sumberData->map(fn($s) => [
+ 'title' => $s->judul_sumber_reference,
+ 'year' => $s->tahun_sumber_reference,
+ 'link' => $s->link_sumber_reference,
+ ])->toArray(),
+ 'activity_forms' => $forms->mapWithKeys(function($f) {
+ $raw = $f->values_array;
+ if (is_string($raw)) {
+ $values = json_decode($raw, true) ?: [];
+ } elseif (is_array($raw)) {
+ $values = $raw;
+ } else {
+ $values = [$f->value];
+ }
+ $values = array_map('strval', $values);
+ return [
+ "activity_data_{$f->sequence}" => $values,
+ "unit_{$f->sequence}" => $f->unit,
+ ];
+ })->toArray(),
+ ];
+
+ return view('form.index-mitigasi-view', [
+ 'sessionData' => $sessionData,
+ 'id' => $id,
+ ]);
+ }
+
+ public function edit(string $id, Request $request)
+ {
+ $km = KegiatanMitigasi::with('sumberData')->findOrFail($id);
+ $forms = ActivityDataMitigationForm::where('kegiatan_mitigasi_id', $id)->get();
+
+ $sessionData = [
+ 'mitigation_id' => $km->mitigation_id,
+ 'tipe_laporan' => $km->tipe_laporan,
+ 'tipe_kegiatan' => $km->tipe_kegiatan,
+ 'tahun_kegiatan' => $km->tahun_kegiatan,
+ 'sektor' => $km->sektor,
+ 'sub_sektor' => $km->sub_sektor,
+ 'kategori_perhitungan' => $km->kategori_perhitungan,
+ 'kategori_sub_aktivitas' => $km->kategori_sub_aktivitas,
+ 'nama_kegiatan' => $km->nama_kegiatan,
+ 'informasi_lokasi_kegiatan' => $km->informasi_lokasi_kegiatan,
+ 'jenis_kegiatan' => $km->jenis_kegiatan,
+ 'pelaksana_kegiatan' => $km->pelaksana_kegiatan,
+ 'pelaksana_kegiatan_rad' => $km->pelaksana_kegiatan_rad,
+ 'nomenklatur_kemendagri' => $km->nomenklatur_kemendagri,
+ 'target' => $km->target,
+ 'satuan' => $km->satuan,
+ 'realisasi' => $km->realisasi,
+ 'sdg' => json_decode($km->sdg, true) ?? [],
+ 'catatan' => $km->catatan,
+ 'alokasi_apbn' => $km->alokasi_apbn,
+ 'alokasi_apbd' => $km->alokasi_apbd,
+ 'alokasi_swasta' => $km->alokasi_swasta,
+ 'alokasi_sumber_dana_lain' => $km->alokasi_sumber_dana_lain,
+ 'realisasi_apbn' => $km->realisasi_apbn,
+ 'realisasi_apbd' => $km->realisasi_apbd,
+ 'realisasi_swasta' => $km->realisasi_swasta,
+ 'realisasi_sumber_dana_lain' => $km->realisasi_sumber_dana_lain,
+ 'kabupaten_kota_location' => $km->kabupaten_kota_location,
+ 'kecamatan_location' => $km->kecamatan_location,
+ 'kelurahan_location' => $km->kelurahan_location,
+ 'lat_location' => $km->lat_location,
+ 'long_location' => $km->long_location,
+ 'sumber_data' => $km->sumberData->map(fn($s) => [
+ 'title' => $s->judul_sumber_reference,
+ 'year' => $s->tahun_sumber_reference,
+ 'link' => $s->link_sumber_reference,
+ ])->toArray(),
+ 'activity_forms' => $forms->mapWithKeys(function($f) {
+ $raw = $f->values_array;
+ if (is_string($raw)) {
+ $values = json_decode($raw, true) ?: [];
+ } elseif (is_array($raw)) {
+ $values = $raw;
+ } else {
+ $values = [$f->value];
+ }
+ $values = array_map('strval', $values);
+ return [
+ "activity_data_{$f->sequence}" => $values,
+ "unit_{$f->sequence}" => $f->unit,
+ ];
+ })->toArray(),
+ ];
+
+ $request->session()->put('kegiatan_mitigasi', $sessionData);
+
+ $startYear = 2000;
+ $currentYear = now()->year;
+ $years = range($startYear, $currentYear);
+ rsort($years);
+
+ $sectors = KegiatanMitigasi::distinct()->pluck('sektor')->toArray();
+
+ return view('form.index-mitigasi-edit', [
+ 'sessionData' => $sessionData,
+ 'years' => $years,
+ 'currentYear' => $currentYear,
+ 'sectors' => $sectors,
+ 'mitigation' => $km,
+ 'readonly' => false
+ ]);
+ }
+
+ protected function persistActivityForms(array $inputs, string $mitigationId, string $kegiatanMitigasiId)
+ {
+ $isMultipleMap = ActivityDataMitigation::where('mitigation_id', $mitigationId)
+ ->pluck('is_multiple', 'sequence')
+ ->toArray();
+ $typeMap = ActivityDataMitigation::where('mitigation_id', $mitigationId)
+ ->pluck('type_emission_reduction', 'sequence')
+ ->toArray();
+
+ foreach ($isMultipleMap as $sequence => $isMultiple) {
+ $unit = $inputs['unit_' . $sequence] ?? null;
+ $value = $inputs['activity_data_' . $sequence] ?? null;
+ $typeEmis = $typeMap[$sequence] ?? null;
+
+ if ($isMultiple) {
+ $clean = is_array($value) ? array_filter($value, fn($v) => $v !== null && $v !== '') : [];
+ if (!empty($clean)) {
+ ActivityDataMitigationForm::create([
+ 'kegiatan_mitigasi_id' => $kegiatanMitigasiId,
+ 'sequence' => $sequence,
+ 'value' => null,
+ 'values_array' => array_values($clean),
+ 'unit' => $unit,
+ 'mitigation_id' => $mitigationId,
+ 'type_emission_reduction' => $typeEmis,
+ ]);
+ }
+ } else {
+ $single = is_array($value) ? ($value[0] ?? null) : $value;
+ if ($single !== null && $single !== '') {
+ ActivityDataMitigationForm::create([
+ 'kegiatan_mitigasi_id' => $kegiatanMitigasiId,
+ 'sequence' => $sequence,
+ 'value' => $single,
+ 'values_array' => null,
+ 'unit' => $unit,
+ 'mitigation_id' => $mitigationId,
+ 'type_emission_reduction' => $typeEmis,
+ ]);
+ }
+ }
+ }
+ }
+
+ public function create(Request $request)
+ {
+ if ($request->has('reset')) {
+ $request->session()->forget('kegiatan_mitigasi');
+ }
+ $sessionData = $request->session()->get('kegiatan_mitigasi', []);
+
+ $startYear = 2000;
+ $currentYear = date('Y');
+ $years = range($startYear, $currentYear);
+ rsort($years);
+
+ return view('form.index-mitigasi', compact('sessionData', 'years', 'currentYear'));
+ }
+
+ public function update(Request $request, $id)
+ {
+ $kegiatanMitigasi = KegiatanMitigasi::with('sumberData')->findOrFail($id);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+ if (empty($sessionData)) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Data tidak lengkap, silakan lengkapi semua bagian.'
+ ]);
+ }
+
+ try {
+ DB::transaction(function() use ($sessionData, $request, $kegiatanMitigasi) {
+ $kegiatanMitigasi->revisi = ($kegiatanMitigasi->revisi ?? 0) + 1;
+ $kegiatanMitigasi->update([
+ 'tipe_kegiatan' => $sessionData['tipe_kegiatan'] ?? null,
+ 'tahun_kegiatan' => $this->sanitizeInteger($sessionData['tahun_kegiatan'] ?? null),
+ 'sektor' => $sessionData['sektor'] ?? null,
+ 'sub_sektor' => $sessionData['sub_sektor'] ?? null,
+ 'kategori_perhitungan' => $sessionData['kategori_perhitungan'] ?? null,
+ 'kategori_sub_aktivitas' => $sessionData['kategori_sub_aktivitas'] ?? null,
+ 'mitigation_id' => $sessionData['mitigation_id'] ?? null,
+ 'tipe_laporan' => $sessionData['tipe_laporan'] ?? 'laporan',
+ 'nama_kegiatan' => $sessionData['nama_kegiatan'] ?? null,
+ 'informasi_lokasi_kegiatan' => $sessionData['informasi_lokasi_kegiatan'] ?? null,
+ 'jenis_kegiatan' => $sessionData['jenis_kegiatan'] ?? null,
+ 'pelaksana_kegiatan' => $sessionData['pelaksana_kegiatan'] ?? null,
+ 'pelaksana_kegiatan_rad' => $sessionData['pelaksana_kegiatan_rad'] ?? null,
+ 'nomenklatur_kemendagri' => $sessionData['nomenklatur_kemendagri'] ?? null,
+ 'target' => $sessionData['target'] ?? null,
+ 'satuan' => $sessionData['satuan'] ?? null,
+ 'realisasi' => $sessionData['realisasi'] ?? null,
+ 'sdg' => json_encode($sessionData['sdg'] ?? []),
+ 'catatan' => $sessionData['catatan'] ?? null,
+ 'alokasi_apbn' => $sessionData['alokasi_apbn'] ?? null,
+ 'alokasi_apbd' => $sessionData['alokasi_apbd'] ?? null,
+ 'alokasi_swasta' => $sessionData['alokasi_swasta'] ?? null,
+ 'alokasi_sumber_dana_lain' => $sessionData['alokasi_sumber_dana_lain'] ?? null,
+ 'realisasi_apbn' => $sessionData['realisasi_apbn'] ?? null,
+ 'realisasi_apbd' => $sessionData['realisasi_apbd'] ?? null,
+ 'realisasi_swasta' => $sessionData['realisasi_swasta'] ?? null,
+ 'realisasi_sumber_dana_lain'=> $sessionData['realisasi_sumber_dana_lain'] ?? null,
+ 'kabupaten_kota_location' => $sessionData['kabupaten_kota_location'] ?? null,
+ 'kecamatan_location' => $sessionData['kecamatan_location'] ?? null,
+ 'kelurahan_location' => $sessionData['kelurahan_location'] ?? null,
+ 'lat_location' => $sessionData['lat_location'] ?? null,
+ 'long_location' => $sessionData['long_location'] ?? null,
+ 'updated_by' => auth()->check() ? auth()->user()->name : null,
+ ]);
+
+ // Update sumber data (delete all, re-insert sanitized)
+ $kegiatanMitigasi->sumberData()->delete();
+ foreach($sessionData['sumber_data'] ?? [] as $s) {
+ $kegiatanMitigasi->sumberData()->create([
+ 'id' => Str::uuid(),
+ 'judul_sumber_reference' => trim($s['title'] ?? '') ?: null,
+ 'tahun_sumber_reference' => $this->sanitizeInteger($s['year'] ?? null),
+ 'link_sumber_reference' => trim($s['link'] ?? '') ?: null,
+ ]);
+ }
+
+ ActivityDataMitigationForm::where('kegiatan_mitigasi_id', $kegiatanMitigasi->id)->delete();
+ $this->persistActivityForms($request->all(), $sessionData['mitigation_id'], $kegiatanMitigasi->id);
+
+ $this->formMitigasiService->calculateAndPersist($sessionData['mitigation_id'], $kegiatanMitigasi);
+
+ $request->session()->forget('kegiatan_mitigasi');
+ });
+
+ return response()->json([
+ 'success' => true,
+ 'redirect' => route('formMitigasi.thankYou', $id),
+ ]);
+ } catch (\Exception $e) {
+ Log::error('Error updating data: ' . $e->getMessage());
+ return back()->with('error', 'Gagal mengupdate data. Silakan coba lagi.');
+ }
+ }
+
+ public function loadQuestion(Request $request)
+ {
+ $mitigation_id = $request->input('mitigation_id');
+
+ if (!Str::isUuid($mitigation_id)) {
+ return response()->json(['message' => 'Invalid mitigation ID'], 400);
+ }
+
+ $questions = ActivityDataMitigation::select(
+ 'activity_data_mitigation.id',
+ 'activity_data_mitigation.activity_data',
+ 'activity_data_mitigation.unit',
+ 'activity_data_mitigation.sequence',
+ 'activity_data_mitigation.type',
+ 'activity_data_mitigation.list_data',
+ 'activity_data_mitigation.is_multiple',
+ 'activity_data_mitigation.question_plus',
+ 'activity_data_mitigation.ad_sequence',
+ 'activity_data_mitigation.type_emission_reduction',
+ 'activity_data_mitigation.is_required',
+ 'activity_data_mitigation.title_group',
+ 'activity_data_mitigation.keterangan',
+ 'am.activity_desc as activity_desc',
+ 'am.activity_type as title'
+ )
+ ->join('activity.mitigation as am', 'activity_data_mitigation.mitigation_id', '=', 'am.id')
+ ->where('activity_data_mitigation.mitigation_id', $mitigation_id)
+ ->orderBy('activity_data_mitigation.sequence')
+ ->get()
+ ->map(function ($item) {
+ $dataMitigation = ActivityDataMitigation::with('units')
+ ->find($item->id);
+
+ $units = $dataMitigation && $dataMitigation->units->isNotEmpty()
+ ? $dataMitigation->units->pluck('unit')
+ : collect([$item->unit])->filter();
+
+ $category = $dataMitigation && $dataMitigation->units->isNotEmpty()
+ ? $dataMitigation->units->pluck('category')
+ : collect([$item->unit])->filter();
+
+ return [
+ 'id' => $item->id,
+ 'sequence' => $item->sequence,
+ 'activity_data' => $item->activity_data,
+ 'units' => $units->values(),
+ 'category' => $category->values(),
+ 'type' => $item->type,
+ 'choices' => $this->parseListData($item->list_data),
+ 'is_multiple' => (bool)$item->is_multiple,
+ 'is_required' => (bool)$item->is_required,
+ 'question_plus' => $item->question_plus,
+ 'ad_sequence' => $item->ad_sequence,
+ 'type_emission_reduction' => $item->type_emission_reduction,
+ 'activity_desc' => $item->activity_desc,
+ 'title' => $item->title,
+ 'title_group' => $item->title_group,
+ 'keterangan' => $item->keterangan,
+ ];
+ });
+
+ return response()->json($questions);
+ }
+
+ public function storePart1(Request $request)
+ {
+ $validated = $request->validate([
+ 'tipe_kegiatan' => 'required|in:inti,pendukung,prasyarat',
+ 'tahun_kegiatan' => 'required|integer|min:2000|max:' . date('Y'),
+ 'sektor' => 'required|string',
+ 'sub_sektor' => 'required|string',
+ 'kategori_perhitungan' => 'required|string',
+ 'kategori_sub_aktivitas' => 'sometimes|nullable|string',
+ 'mitigation_id' => 'required|string'
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+ $sessionArray = is_object($sessionData) ? $sessionData->toArray() : (array) $sessionData;
+ $mergedData = array_merge($sessionArray, $validated);
+
+ if ($request->filled('laporan')) {
+ $mergedData['tipe_laporan'] = $request->laporan;
+ } else {
+ $mergedData['tipe_laporan'] = $sessionArray['tipe_laporan'] ?? 'laporan';
+ }
+
+ $request->session()->put('kegiatan_mitigasi', $mergedData);
+
+ return response()->json(['success' => true]);
+ }
+
+ public function storePart2(Request $request)
+ {
+ $validated = $request->validate([
+ 'nama_kegiatan' => 'required|string',
+ 'informasi_lokasi_kegiatan' => 'required|string',
+ 'jenis_kegiatan' => 'required|string|in:lokal,berkelanjutan',
+ 'pelaksana_kegiatan' => 'nullable|string',
+ 'pelaksana_kegiatan_rad' => 'nullable|string',
+ 'nomenklatur_kemendagri' => 'nullable|string',
+ 'target' => 'required|string',
+ 'satuan' => 'required|string',
+ 'realisasi' => 'nullable|string',
+ 'sdg' => 'nullable|array',
+ 'catatan' => 'nullable|string',
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+
+ if (!$sessionData) {
+ return response()->json(['success' => false, 'message' => 'Silakan lengkapi bagian Informasi Umum terlebih dahulu']);
+ }
+
+ $updatedData = array_merge($sessionData, $validated);
+
+ $request->session()->put('kegiatan_mitigasi', $updatedData);
+ return response()->json(['success' => true]);
+ }
+
+ public function storePart3(Request $request)
+ {
+ $validated = $request->validate([
+ 'alokasi_apbn' => 'nullable|string',
+ 'alokasi_apbd' => 'nullable|string',
+ 'alokasi_swasta' => 'nullable|string',
+ 'alokasi_sumber_dana_lain' => 'nullable|string',
+ 'realisasi_apbn' => 'nullable|string',
+ 'realisasi_apbd' => 'nullable|string',
+ 'realisasi_swasta' => 'nullable|string',
+ 'realisasi_sumber_dana_lain' => 'nullable|string'
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+
+ if (!$sessionData) {
+ return response()->json(['success' => false, 'message' => 'Silakan lengkapi bagian Informasi Umum terlebih dahulu']);
+ }
+
+ $updatedData = array_merge($sessionData, $validated);
+
+ $request->session()->put('kegiatan_mitigasi', $updatedData);
+ return response()->json(['success' => true]);
+ }
+
+ public function storePart4(Request $request)
+ {
+ try {
+ $validated = $request->validate([
+ 'titleSourceReference' => 'nullable|array',
+ 'titleSourceReference.*' => 'nullable|string|max:255',
+ 'yearSourceReference' => 'nullable|array',
+ 'yearSourceReference.*' => 'nullable|string|max:4',
+ 'linkSourceReference' => 'nullable|array',
+ 'linkSourceReference.*' => 'nullable|string|max:500',
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi', []);
+
+ if (empty($sessionData)) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Silakan lengkapi bagian Informasi Umum terlebih dahulu.'
+ ]);
+ }
+
+ $titles = $validated['titleSourceReference'] ?? [];
+ $years = $validated['yearSourceReference'] ?? [];
+ $links = $validated['linkSourceReference'] ?? [];
+
+ $max = max(count($titles), count($years), count($links));
+
+ $sumberDataList = [];
+ for ($i = 0; $i < $max; $i++) {
+ $sumberDataList[] = [
+ 'title' => trim($titles[$i] ?? ''),
+ 'year' => trim($years[$i] ?? ''),
+ 'link' => trim($links[$i] ?? ''),
+ ];
+ }
+
+ $updatedData = array_merge($sessionData, ['sumber_data' => $sumberDataList]);
+ $request->session()->put('kegiatan_mitigasi', $updatedData);
+
+ return response()->json(['success' => true]);
+ } catch (\Exception $e) {
+ Log::error('Error storePart4: '.$e->getMessage());
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Terjadi error server: '.$e->getMessage()
+ ]);
+ }
+ }
+
+ public function storePart5(Request $request)
+ {
+ $validated = $request->validate([
+ 'kabupaten_kota_location' => 'nullable|string',
+ 'kecamatan_location' => 'nullable|string',
+ 'kelurahan_location' => 'nullable|string',
+ 'lat_location' => 'nullable|string',
+ 'long_location' => 'nullable|string'
+ ]);
+
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+
+ if (!$sessionData) {
+ return response()->json(['success' => false, 'message' => 'Silakan lengkapi bagian Informasi Umum terlebih dahulu']);
+ }
+
+ $updatedData = array_merge($sessionData, $validated);
+
+ $request->session()->put('kegiatan_mitigasi', $updatedData);
+ return response()->json(['success' => true]);
+ }
+
+ public function storeFinal(Request $request)
+ {
+ $sessionData = $request->session()->get('kegiatan_mitigasi');
+ if (empty($sessionData)) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Silakan lengkapi semua bagian terlebih dahulu'
+ ]);
+ }
+
+ try {
+ $mitigasiId = Str::uuid()->toString();
+
+ DB::transaction(function() use ($sessionData, $request, $mitigasiId) {
+ $kegiatanMitigasi = KegiatanMitigasi::create([
+ 'id' => $mitigasiId,
+ 'tipe_kegiatan' => $sessionData['tipe_kegiatan'] ?? null,
+ 'tahun_kegiatan' => $this->sanitizeInteger($sessionData['tahun_kegiatan'] ?? null),
+ 'sektor' => $sessionData['sektor'] ?? null,
+ 'sub_sektor' => $sessionData['sub_sektor'] ?? null,
+ 'kategori_perhitungan' => $sessionData['kategori_perhitungan'] ?? null,
+ 'kategori_sub_aktivitas' => $sessionData['kategori_sub_aktivitas'] ?? null,
+ 'mitigation_id' => $sessionData['mitigation_id'] ?? null,
+ 'tipe_laporan' => $sessionData['tipe_laporan'] ?? 'laporan',
+ 'nama_kegiatan' => $sessionData['nama_kegiatan'] ?? null,
+ 'informasi_lokasi_kegiatan' => $sessionData['informasi_lokasi_kegiatan'] ?? null,
+ 'jenis_kegiatan' => $sessionData['jenis_kegiatan'] ?? null,
+ 'pelaksana_kegiatan' => $sessionData['pelaksana_kegiatan'] ?? null,
+ 'pelaksana_kegiatan_rad' => $sessionData['pelaksana_kegiatan_rad'] ?? null,
+ 'nomenklatur_kemendagri' => $sessionData['nomenklatur_kemendagri'] ?? null,
+ 'target' => $sessionData['target'] ?? null,
+ 'satuan' => $sessionData['satuan'] ?? null,
+ 'realisasi' => $sessionData['realisasi'] ?? null,
+ 'sdg' => json_encode($sessionData['sdg'] ?? []),
+ 'catatan' => $sessionData['catatan'] ?? null,
+ 'alokasi_apbn' => $sessionData['alokasi_apbn'] ?? null,
+ 'alokasi_apbd' => $sessionData['alokasi_apbd'] ?? null,
+ 'alokasi_swasta' => $sessionData['alokasi_swasta'] ?? null,
+ 'alokasi_sumber_dana_lain' => $sessionData['alokasi_sumber_dana_lain'] ?? null,
+ 'realisasi_apbn' => $sessionData['realisasi_apbn'] ?? null,
+ 'realisasi_apbd' => $sessionData['realisasi_apbd'] ?? null,
+ 'realisasi_swasta' => $sessionData['realisasi_swasta'] ?? null,
+ 'realisasi_sumber_dana_lain' => $sessionData['realisasi_sumber_dana_lain'] ?? null,
+ 'kabupaten_kota_location'=> $sessionData['kabupaten_kota_location'] ?? null,
+ 'kecamatan_location' => $sessionData['kecamatan_location'] ?? null,
+ 'kelurahan_location' => $sessionData['kelurahan_location'] ?? null,
+ 'lat_location' => $sessionData['lat_location'] ?? null,
+ 'long_location' => $sessionData['long_location'] ?? null,
+ 'created_by' => auth()->check() ? auth()->user()->name : null,
+ ]);
+
+ collect($sessionData['sumber_data'] ?? [])
+ ->filter(function($s) {
+ return
+ trim($s['title'] ?? '') !== '' ||
+ trim($s['year'] ?? '') !== '' ||
+ trim($s['link'] ?? '') !== '';
+ })
+ ->each(function($s) use ($kegiatanMitigasi) {
+ $kegiatanMitigasi->sumberData()->create([
+ 'id' => Str::uuid()->toString(),
+ 'judul_sumber_reference' => trim($s['title'] ?? '') ?: null,
+ 'tahun_sumber_reference' => $this->sanitizeInteger($s['year'] ?? null),
+ 'link_sumber_reference' => trim($s['link'] ?? '') ?: null,
+ ]);
+ });
+
+ $this->persistActivityForms($request->all(), $sessionData['mitigation_id'], $mitigasiId);
+
+ $this->formMitigasiService->calculateAndPersist($sessionData['mitigation_id'], $kegiatanMitigasi, $mitigasiId);
+
+ $request->session()->forget('kegiatan_mitigasi');
+ });
+
+ return response()->json([
+ 'success' => true,
+ 'redirect' => route('formMitigasi.thankYou', $mitigasiId),
+ ]);
+ } catch (\Exception $e) {
+ Log::error('Error storing final data: ' . $e->getMessage());
+ return back()->with('error', 'Gagal menyimpan data. Silakan coba lagi.');
+ }
+ }
+
+
+ // ... fungsi getSectors, getSubSectors, getKategoriPerhitungan, getSubActivity, getAksiRAD, getKabkot, getKecamatan, getKelurahan tidak perlu diubah ...
+ public function getSectors()
+ {
+ $query = Mitigation::select('sector')
+ ->where('is_active', true)
+ ->distinct();
+ $result = $query->pluck('sector');
+
+ return response()->json($result);
+ }
+
+ public function getSubSectors(Request $request)
+ {
+ $param = $request->input('sector');
+
+ $query = Mitigation::select('sub_sector')
+ ->where('sector', $param)
+ ->where('is_active', true)
+ ->distinct();
+ $result = $query->pluck('sub_sector');
+
+ return response()->json($result);
+ }
+
+ public function getKategoriPerhitungan(Request $request)
+ {
+ $param = $request->input('sub_sector');
+ $param2 = $request->input('sector');
+
+ $query = Mitigation::select('id', 'activity_type')
+ ->where('sub_sector', $param)
+ ->where('sector', $param2)
+ ->where('is_active', true)
+ ->distinct('activity_type')->get();
+
+ return response()->json($query);
+ }
+
+ public function getSubActivity(Request $request)
+ {
+ $param = $request->input('sub_sector');
+ $param2 = $request->input('sector');
+ $param3 = $request->input('activity');
+
+ $query = Mitigation::select('id', 'sub_activity', 'sub_activity_desc')
+ ->where('sub_sector', $param)
+ ->where('sector', $param2)
+ ->where('activity_type', $param3)
+ ->where('is_active', true)
+ ->distinct('sub_activity')->get();
+
+ return response()->json($query);
+ }
+
+ public function getAksiRAD(Request $request)
+ {
+ $param = $request->input('sub_sector');
+
+ $data = MitigationRendahKarbonDaerah::select('sector', 'sub_sector', 'name')
+ ->where('sub_sector', $param)
+ ->distinct('name')->get();
+
+ $result = $data->map(function ($item) {
+ return "[" . $item->sector . " - " . $item->sub_sector . "] " . $item->name;
+ });
+
+ return response()->json($result);
+ }
+
+ public function getKabkot()
+ {
+ $query = Kabupaten::select('kabkot_id', 'kabkot_name')
+ ->get();
+
+ return response()->json($query);
+ }
+
+ public function getKecamatan(Request $request)
+ {
+ $param = $request->input('kabkot_id');
+
+ $query = Kecamatan::select('kec_id', 'kec_name')
+ ->where('kabkot_id', $param)
+ ->get();
+
+ return response()->json($query);
+ }
+
+ public function getKelurahan(Request $request)
+ {
+ $kabkot_id = $request->input('kabkot_id');
+ $kec_id = $request->input('kec_id');
+
+ $query = Kelurahan::select('kel_id', 'kel_name')
+ ->where('kabkot_id', $kabkot_id)
+ ->where('kec_id', $kec_id)
+ ->get();
+
+ return response()->json($query);
+ }
+}
diff --git a/app/Http/Controllers/Activity/LivestockManureController.php b/app/Http/Controllers/Activity/LivestockManureController.php
new file mode 100644
index 0000000..a8369a2
--- /dev/null
+++ b/app/Http/Controllers/Activity/LivestockManureController.php
@@ -0,0 +1,184 @@
+service = $service;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/agriculture/kotoran_ternak'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+ $data = $this->service->getAll();
+
+ $result = datatables()::of($data)
+ ->addColumn('no_baris', function ($lm) {
+ return $lm->row_num;
+ })
+ ->addColumn('status', function ($lm) {
+ if ($lm->active_status == 1) {
+ return 'Aktif';
+ } else {
+ return 'Tidak Aktif';
+ }
+ })
+ ->editColumn('ef_direct_n2o_n', function ($lm) {
+ if ($lm->ef_direct_n2o_n === 0) {
+ return 0; // Show 0 as is
+ }
+
+ $output = getFormattedValue($lm->ef_direct_n2o_n, 2);
+ return $output;
+ })
+ ->editColumn('ef_evaporation_n', function ($lm) {
+ if ($lm->ef_evaporation_n === 0) {
+ return 0; // Show 0 as is
+ }
+
+ $output = getFormattedValue($lm->ef_evaporation_n);
+ return $output;
+ })
+ ->addColumn('action', function ($lm) {
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ if ($lm->active_status == 0) {
+ $btn .= ' ';
+ }
+
+ return $btn;
+ })
+ ->rawColumns(['no_baris', 'status', 'action'])
+ ->make(true);
+
+ return $result;
+ }
+
+ return view('form.livestock-manure.index');
+ }
+
+ public function create()
+ {
+ return view('form.livestock-manure.create');
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'name' => 'required|string|max:255',
+ 'ef_direct_n2o_n' => 'nullable',
+ 'ef_evaporation_n' => 'nullable'
+ ]);
+
+ try {
+ $nextRowNum = LivestockManure::max('row_num') + 1;
+ $formattedEf1 = getOriginalValue($request->input('ef_direct_n2o_n'));
+ $formattedEf2 = getOriginalValue($request->input('ef_evaporation_n'));
+ $data = array_merge($request->all(), [
+ 'row_num' => $nextRowNum,
+ 'active_status' => 0,
+ 'ef_direct_n2o_n' => $formattedEf1,
+ 'ef_evaporation_n' => $formattedEf2,
+ ]);
+ $this->service->create($data);
+
+ return redirect()->route('livestockManure.index')->with('success', 'Jenis Pengelolaan Kotoran Ternak berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Jenis Pengelolaan Kotoran Ternak gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $lm = $this->service->find($id);
+ return view('form.livestock-manure.edit', compact('lm'));
+ }
+
+ public function update(Request $request, LivestockManure $kotoran_ternak)
+ {
+ $request->validate([
+ // 'code' => [
+ // 'required',
+ // 'string',
+ // 'max:255',
+ // new UniqueInSchema('activity', 'livestock_manure', 'code', $lm->id),
+ // ],
+ 'name' => 'required|string|max:255',
+ 'ef_direct_n2o_n' => 'nullable',
+ 'ef_evaporation_n' => 'nullable',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+
+ $formattedEf1 = getOriginalValue($request->input('ef_direct_n2o_n'));
+ $formattedEf2 = getOriginalValue($request->input('ef_evaporation_n'));
+ $data = array_merge($request->all(), [
+ 'ef_direct_n2o_n' => $formattedEf1,
+ 'ef_evaporation_n' => $formattedEf2,
+ ]);
+
+ $this->service->update($kotoran_ternak, $data);
+
+ return redirect()->route('livestockManure.index')->with('success', 'Jenis Pengelolaan Kotoran Ternak berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Jenis Pengelolaan Kotoran Ternak gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy(LivestockManure $kotoran_ternak)
+ {
+ try {
+ $this->service->delete($kotoran_ternak);
+
+ $records = LivestockManure::orderBy('row_num')->get();
+ foreach ($records as $index => $record) {
+ $record->row_num = $index + 1;
+ $record->save();
+ }
+
+ return redirect()->route('livestockManure.index')->with('success', 'Jenis Pengelolaan Kotoran Ternak berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Jenis Pengelolaan Kotoran Ternak gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function setAktif($id)
+ {
+ try {
+ $this->service->setAktif($id);
+ return redirect()->route('livestockManure.index')->with('success', 'Jenis Pengelolaan Kotoran Ternak berhasil diaktifkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Gagal mengaktifkan Jenis Pengelolaan Kotoran Ternak. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Dashboard/DashboardInventoryController.php b/app/Http/Controllers/Dashboard/DashboardInventoryController.php
index 9a1e49e..b0510a9 100644
--- a/app/Http/Controllers/Dashboard/DashboardInventoryController.php
+++ b/app/Http/Controllers/Dashboard/DashboardInventoryController.php
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Dashboard;
use App\Http\Controllers\Controller;
+use App\Services\DashboardService;
use Illuminate\Http\Request;
class DashboardInventoryController extends Controller
@@ -11,13 +12,27 @@ class DashboardInventoryController extends Controller
protected $template = 'modules.dashboard.inventory';
protected $route = 'modules.dashboard.inventory';
- /**
- * Display a listing of the resource.
- */
- public function index()
+ protected $emissionService;
+
+ public function __construct(DashboardService $emissionService)
{
- $data['title'] = $this->title;
- return view($this->template.'.index',$data);
+ $this->emissionService = $emissionService;
+ }
+
+ public function index(Request $request)
+ {
+ try {
+ $inventoryYear = $request->input('year', date('Y'));
+
+ $dashboardData = $this->emissionService->getDashboardData($inventoryYear);
+
+ return view($this->template.'.index', $dashboardData);
+ } catch (\Exception $e) {
+ Log::error('Error loading dashboard data', [
+ 'message' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ ]);
+ }
}
/**
diff --git a/app/Http/Controllers/Emisi/Agriculture3A2bController.php b/app/Http/Controllers/Emisi/Agriculture3A2bController.php
new file mode 100644
index 0000000..723b11c
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3A2bController.php
@@ -0,0 +1,30 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // manure_mgmt_direct_n2o
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3AController.php b/app/Http/Controllers/Emisi/Agriculture3AController.php
new file mode 100644
index 0000000..0c02e46
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3AController.php
@@ -0,0 +1,31 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // enteric_fermentation
+ // manure_mgmt
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3C1Controller.php b/app/Http/Controllers/Emisi/Agriculture3C1Controller.php
new file mode 100644
index 0000000..adf5697
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3C1Controller.php
@@ -0,0 +1,31 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // padi_sawah
+ // padi_ladang
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3C3Controller.php b/app/Http/Controllers/Emisi/Agriculture3C3Controller.php
new file mode 100644
index 0000000..393f40b
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3C3Controller.php
@@ -0,0 +1,30 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // urea_fertilization
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3C4Controller.php b/app/Http/Controllers/Emisi/Agriculture3C4Controller.php
new file mode 100644
index 0000000..9f5c048
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3C4Controller.php
@@ -0,0 +1,28 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // managed_soils_direct_n2o
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3C5Controller.php b/app/Http/Controllers/Emisi/Agriculture3C5Controller.php
new file mode 100644
index 0000000..15dda28
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3C5Controller.php
@@ -0,0 +1,28 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // managed_soils_indirect_n2o
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Agriculture3C6Controller.php b/app/Http/Controllers/Emisi/Agriculture3C6Controller.php
new file mode 100644
index 0000000..bfb1e9d
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Agriculture3C6Controller.php
@@ -0,0 +1,30 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // manure_mgmt_indirect_n2o
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Energy1AController.php b/app/Http/Controllers/Emisi/Energy1AController.php
new file mode 100644
index 0000000..ef58082
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Energy1AController.php
@@ -0,0 +1,28 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/EnergyGPCController.php b/app/Http/Controllers/Emisi/EnergyGPCController.php
new file mode 100644
index 0000000..2fd8f3c
--- /dev/null
+++ b/app/Http/Controllers/Emisi/EnergyGPCController.php
@@ -0,0 +1,26 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Folu3BController.php b/app/Http/Controllers/Emisi/Folu3BController.php
new file mode 100644
index 0000000..6efda51
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Folu3BController.php
@@ -0,0 +1,48 @@
+service = $service;
+ }
+
+ public function data($sector, $code, $inventoryYear)
+ {
+ // Fetch the form from the database based on sector and code
+ $form = SettingForm::rowActive()->where('sector', $sector)->where('code', $code)->first();
+
+ if (!$form) {
+ abort(404, 'Page not found');
+ }
+
+ // Fetch form details
+ $formDetails = SettingFormDetail::rowActive()->where('form_code', $code)->orderByRowNum()->get();
+
+ // Fetch activity form and activity form details using service
+ $activityForm = $this->service->getActivityForm($sector, $code, $inventoryYear);
+ $activityFormId = $activityForm->id ?? null;
+ $activityFormDetails = $this->service->getActivityFormDetails($activityFormId);
+
+ return compact('form', 'formDetails', 'activityForm', 'activityFormDetails');
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/GpcMappingController.php b/app/Http/Controllers/Emisi/GpcMappingController.php
new file mode 100644
index 0000000..ea2d604
--- /dev/null
+++ b/app/Http/Controllers/Emisi/GpcMappingController.php
@@ -0,0 +1,26 @@
+service = $service;
+ }
+
+ public function save(Request $request, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4AController.php b/app/Http/Controllers/Emisi/Waste4AController.php
new file mode 100644
index 0000000..c4b5299
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4AController.php
@@ -0,0 +1,26 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4AMethaneController.php b/app/Http/Controllers/Emisi/Waste4AMethaneController.php
new file mode 100644
index 0000000..44e5a33
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4AMethaneController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4APreController.php b/app/Http/Controllers/Emisi/Waste4APreController.php
new file mode 100644
index 0000000..be9b411
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4APreController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4B1Controller.php b/app/Http/Controllers/Emisi/Waste4B1Controller.php
new file mode 100644
index 0000000..a3b632e
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4B1Controller.php
@@ -0,0 +1,30 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // ch4
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4B2Controller.php b/app/Http/Controllers/Emisi/Waste4B2Controller.php
new file mode 100644
index 0000000..4ce711d
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4B2Controller.php
@@ -0,0 +1,30 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // n2o
+
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4C1Controller.php b/app/Http/Controllers/Emisi/Waste4C1Controller.php
new file mode 100644
index 0000000..78d20c2
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4C1Controller.php
@@ -0,0 +1,26 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4C2aController.php b/app/Http/Controllers/Emisi/Waste4C2aController.php
new file mode 100644
index 0000000..4c34ee8
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4C2aController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ //4c2_co2
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4C2bController.php b/app/Http/Controllers/Emisi/Waste4C2bController.php
new file mode 100644
index 0000000..a89e4c2
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4C2bController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ //4c2_ch4
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4C2cController.php b/app/Http/Controllers/Emisi/Waste4C2cController.php
new file mode 100644
index 0000000..aa45568
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4C2cController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ //4c2_n2o
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4D1aController.php b/app/Http/Controllers/Emisi/Waste4D1aController.php
new file mode 100644
index 0000000..196ffad
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4D1aController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // 4D1_TOW
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4D1cController.php b/app/Http/Controllers/Emisi/Waste4D1cController.php
new file mode 100644
index 0000000..7533979
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4D1cController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // 4D1_CH4
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4D1dController.php b/app/Http/Controllers/Emisi/Waste4D1dController.php
new file mode 100644
index 0000000..3f446d7
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4D1dController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // 4D1_N
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Emisi/Waste4D1eController.php b/app/Http/Controllers/Emisi/Waste4D1eController.php
new file mode 100644
index 0000000..070db0a
--- /dev/null
+++ b/app/Http/Controllers/Emisi/Waste4D1eController.php
@@ -0,0 +1,27 @@
+service = $service;
+ }
+
+ public function save(Request $request, $code, $inventoryYear)
+ {
+ // 4D1_Indirect_N2O
+ if ($code) {
+ $result = $this->service->save($code, $inventoryYear);
+
+ return $result;
+ }
+ }
+}
diff --git a/app/Http/Controllers/Energi/BahanBakarListrikController.php b/app/Http/Controllers/Energi/BahanBakarListrikController.php
deleted file mode 100644
index 1f3a4b6..0000000
--- a/app/Http/Controllers/Energi/BahanBakarListrikController.php
+++ /dev/null
@@ -1,65 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'CRF','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/GCOMController.php b/app/Http/Controllers/Kalkulasi/GCOMController.php
deleted file mode 100644
index 298e26b..0000000
--- a/app/Http/Controllers/Kalkulasi/GCOMController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'GCOM','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/GPCController.php b/app/Http/Controllers/Kalkulasi/GPCController.php
deleted file mode 100644
index 7f5c058..0000000
--- a/app/Http/Controllers/Kalkulasi/GPCController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'GPC','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/HitungProdusenController.php b/app/Http/Controllers/Kalkulasi/HitungProdusenController.php
deleted file mode 100644
index 08ee99b..0000000
--- a/app/Http/Controllers/Kalkulasi/HitungProdusenController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Hitung Produsen','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/KalkulasiEmisiController.php b/app/Http/Controllers/Kalkulasi/KalkulasiEmisiController.php
deleted file mode 100644
index 48bfd4c..0000000
--- a/app/Http/Controllers/Kalkulasi/KalkulasiEmisiController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Kalkulasi Emisi','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/KunciAktifitasController.php b/app/Http/Controllers/Kalkulasi/KunciAktifitasController.php
deleted file mode 100644
index 2bef4ad..0000000
--- a/app/Http/Controllers/Kalkulasi/KunciAktifitasController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Kunci Aktivitas','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/SalinAktifitasController.php b/app/Http/Controllers/Kalkulasi/SalinAktifitasController.php
deleted file mode 100644
index 9c0d8e8..0000000
--- a/app/Http/Controllers/Kalkulasi/SalinAktifitasController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Salin Aktivitas','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Kalkulasi/WorksheetController.php b/app/Http/Controllers/Kalkulasi/WorksheetController.php
deleted file mode 100644
index 29dcbb7..0000000
--- a/app/Http/Controllers/Kalkulasi/WorksheetController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Worksheet','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Kalkulasi'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Limbah/DistribusiSampahDomestikController.php b/app/Http/Controllers/Limbah/DistribusiSampahDomestikController.php
deleted file mode 100644
index a5690ae..0000000
--- a/app/Http/Controllers/Limbah/DistribusiSampahDomestikController.php
+++ /dev/null
@@ -1,65 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'AR','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = AR::orderBy('nomor_baris','ASC')->get();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->ArId),
- 'kode' => @$row->kode,
- 'nama' => @$row->nama,
- 'deskripsi' => @$row->deskripsi,
- 'nomor_baris' => @$row->nomor_baris,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'kode' => 'required|string|max:255|unique:p_ar,kode',
- 'nama' => 'required|string|max:255',
- 'deskripsi' => 'required|string',
- 'nomor_baris' => 'required|numeric',
- ],[
- 'kode.unique' => 'Kode Tidak Boleh Sama',
- 'nomor_baris.numeric' => 'Nomor Baris Harus Berupa Angka',
-
- 'kode.required' => 'Tidak Boleh Kosong',
- 'nama.required' => 'Tidak Boleh Kosong',
- 'deskripsi.required' => 'Tidak Boleh Kosong',
- 'nomor_baris.required' => 'Tidak Boleh Kosong',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = AR::find($keyId);
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new AR;
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'AR','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = AR::where('ArId',$keyId)->first();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = AR::where('ArId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/EFController.php b/app/Http/Controllers/Pengaturan/EFController.php
deleted file mode 100644
index 074e3d7..0000000
--- a/app/Http/Controllers/Pengaturan/EFController.php
+++ /dev/null
@@ -1,202 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'EF','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['activity'] = Activity::all();
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
- if(request()->activity){
- $data = EF::with(['activity','sumberdata'])->where('ms_activity_id',decode_id(request()->activity))->orderBy('nomor_baris','ASC')->get();
- }else{
- $data = EF::with(['activity','sumberdata'])->orderBy('nomor_baris','ASC')->get();
- }
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->EFId),
- 'activity' => @$row->activity->nama,
- 'sumberdata' => @$row->sumberdata->nama,
- 'kategori' => @$row->category,
- 'kode' => @$row->kode,
- 'nilai' => @$row->value,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'ms_activity_id' => 'required',
- 'sumberdata_ef_id' => 'required',
- 'value' => 'required',
- 'category' => 'required|string|max:255',
- 'tag_1' => 'nullable|string|max:255',
- 'tag_2' => 'nullable|string|max:255',
- 'tag_3' => 'nullable|string|max:255',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = EF::find($keyId);
- $data->ms_activity_id = decode_id($request->ms_activity_id);
- $data->tag_1 = $request->tag_1;
- $data->tag_2 = $request->tag_2;
- $data->tag_3 = $request->tag_3;
- $data->category = $request->category;
- $data->sumberdata_ef_id = decode_id($request->sumberdata_ef_id);
- $data->value = $request->value;
- $data->deskripsi = $request->deskripsi;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new EF;
- $data->ms_activity_id = decode_id($request->ms_activity_id);
- $data->tag_1 = $request->tag_1;
- $data->tag_2 = $request->tag_2;
- $data->tag_3 = $request->tag_3;
- $data->category = $request->category;
- $data->sumberdata_ef_id = decode_id($request->sumberdata_ef_id);
- $data->value = $request->value;
- $data->deskripsi = $request->deskripsi;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'AR','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = EF::where('EFId',$keyId)->first();
- $data['activity'] = Activity::all();
- $data['sumberdata'] = SumberDataEF::all();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = EF::where('EFId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/GHGController.php b/app/Http/Controllers/Pengaturan/GHGController.php
deleted file mode 100644
index 1b7418c..0000000
--- a/app/Http/Controllers/Pengaturan/GHGController.php
+++ /dev/null
@@ -1,187 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'GHG','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = GHG::orderBy('nomor_baris','ASC')->get();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->GhgId),
- 'kode' => @$row->kode,
- 'nama' => @$row->nama,
- 'deskripsi' => @$row->deskripsi,
- 'nomor_baris' => @$row->nomor_baris,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'kode' => 'required|string|max:255|unique:p_ar,kode',
- 'nama' => 'required|string|max:255',
- 'deskripsi' => 'required|string',
- 'nomor_baris' => 'required|numeric',
- ],[
- 'kode.unique' => 'Kode Tidak Boleh Sama',
- 'nomor_baris.numeric' => 'Nomor Baris Harus Berupa Angka',
-
- 'kode.required' => 'Tidak Boleh Kosong',
- 'nama.required' => 'Tidak Boleh Kosong',
- 'deskripsi.required' => 'Tidak Boleh Kosong',
- 'nomor_baris.required' => 'Tidak Boleh Kosong',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = GHG::find($keyId);
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new GHG;
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'GHG','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = GHG::where('GhgId',$keyId)->first();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = GHG::where('GhgId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/GWPController.php b/app/Http/Controllers/Pengaturan/GWPController.php
deleted file mode 100644
index d50a33b..0000000
--- a/app/Http/Controllers/Pengaturan/GWPController.php
+++ /dev/null
@@ -1,211 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'GWP','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['ar'] = AR::where('status',1)->orderBy('nomor_baris','ASC')->get();
- return view($this->template.'.form',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = GHG::orderBy('nomor_baris','ASC')->get();
- $ar = AR::where('status',1)->orderBy('nomor_baris','ASC')->get();
- $_data = [];
-
-
-
- foreach ($data as $key => $row) {
-
- $_ardata = [];
- foreach ($ar as $keyAr => $rowAr) {
-
- $_ardata['ar_'.$rowAr->ArId.'_'.strtolower($rowAr->kode)] = '';
- }
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
-
-
- $_data[] = array_merge([
- 'no' => $key+1,
- 'id' => encode_id($row->GhgId),
- 'kode' => ''.@$row->kode,
- 'nama' => @$row->deskripsi,
- 'status' => @$status,
- 'action' => @$action,
- ],$_ardata);
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $post = request()->all();
-
- $ghg_list = $post['ghg'] ?? [];
- $ghg_count = count($ghg_list);
- $ar_inputs = [];
- try {
- foreach ($post as $k => $v) {
- if (\Str::startsWith($k, 'ar_')) {
- // ekstrak ArId dari nama, format di code sebelumnya: ar_{ArId}_{kode}
- if (preg_match('/^ar_(\d+)_/', $k, $m)) {
- $arId = (int) $m[1];
- } else {
- // fallback: jika tidak ada angka, gunakan seluruh key (atau handle sesuai kebutuhan)
- // skip jika tidak bisa ambil ArId
- continue;
- }
- $ar_inputs[$arId] = array_values((array) $v); // cast ke array & reindex
- }
- }
-
- foreach ($ar_inputs as $arId => $vals) {
- $len = count($vals);
- if ($len < $ghg_count) {
- $ar_inputs[$arId] = array_pad($vals, $ghg_count, null);
- } elseif ($len > $ghg_count) {
- $ar_inputs[$arId] = array_slice($vals, 0, $ghg_count);
- }
- }
-
- $inserts = [];
- $now = now();
-
- for ($i = 0; $i < $ghg_count; $i++) {
- // decode ghg id (sesuaikan fungsi decode_id)
- $ghgEncoded = $ghg_list[$i];
- $ghgId = decode_id($ghgEncoded);
-
- foreach ($ar_inputs as $arId => $vals) {
- $rawValue = $vals[$i];
- $value = is_string($rawValue) ? trim($rawValue) : $rawValue;
- if ($value === '') $value = null;
-
- $inserts[] = [
- 'ghg_id' => $ghgId,
- 'ar_id' => $arId,
- 'value' => $value,
- 'created_at'=> $now,
- 'updated_at'=> $now,
- ];
- }
- }
-
- \DB::transaction(function () use ($inserts) {
- $chunkSize = 500;
- foreach (array_chunk($inserts, $chunkSize) as $chunk) {
- foreach ($chunk as $row) {
- GWP::updateOrCreate(
- [
- 'ghg_id' => $row['ghg_id'],
- 'ar_id' => $row['ar_id'],
- ],[
- 'value' => @$row['value'] ? @$row['value'] : 0
- ]
- );
- }
- }
- });
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
-
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- //
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/KategoriController.php b/app/Http/Controllers/Pengaturan/KategoriController.php
deleted file mode 100644
index 18e145d..0000000
--- a/app/Http/Controllers/Pengaturan/KategoriController.php
+++ /dev/null
@@ -1,170 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Kategori','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = Kategori::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->KategoriId),
- 'alias' => @$row->alias,
- 'nama' => @$row->nama,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'nama' => 'required|string|max:255',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = Kategori::find($keyId);
- $data->alias = str_replace(' ','_',strtolower($request->nama));
- $data->nama = $request->nama;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new Kategori;
- $data->alias = str_replace(' ','_',strtolower($request->nama));
- $data->nama = $request->nama;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Kategori','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = Kategori::where('KategoriId',$keyId)->first();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = Kategori::where('KategoriId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/PengumumanController.php b/app/Http/Controllers/Pengaturan/PengumumanController.php
deleted file mode 100644
index 30c4c24..0000000
--- a/app/Http/Controllers/Pengaturan/PengumumanController.php
+++ /dev/null
@@ -1,209 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Pengumuman/Peraturan','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FilePengumuman::all();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FilePengumumanId),
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/pengumuman');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'pengumuman/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FilePengumuman::find($keyId);
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FilePengumuman;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FilePengumuman::where('FilePengumumanId',$keyId)->first();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FilePengumuman::where('FilePengumumanId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/SumberDataEFController.php b/app/Http/Controllers/Pengaturan/SumberDataEFController.php
deleted file mode 100644
index 060d913..0000000
--- a/app/Http/Controllers/Pengaturan/SumberDataEFController.php
+++ /dev/null
@@ -1,187 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Sumber Data EF','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = SumberDataEF::orderBy('nomor_baris','ASC')->get();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->SumberDataId),
- 'kode' => @$row->kode,
- 'nama' => @$row->nama,
- 'deskripsi' => @$row->deskripsi,
- 'nomor_baris' => @$row->nomor_baris,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'kode' => 'required|string|max:255|unique:p_sumberdata_ef,kode',
- 'nama' => 'required|string|max:255',
- 'deskripsi' => 'required|string',
- 'nomor_baris' => 'required|numeric',
- ],[
- 'kode.unique' => 'Kode Tidak Boleh Sama',
- 'nomor_baris.numeric' => 'Nomor Baris Harus Berupa Angka',
-
- 'kode.required' => 'Tidak Boleh Kosong',
- 'nama.required' => 'Tidak Boleh Kosong',
- 'deskripsi.required' => 'Tidak Boleh Kosong',
- 'nomor_baris.required' => 'Tidak Boleh Kosong',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = SumberDataEF::find($keyId);
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new SumberDataEF;
- $data->kode = $request->kode;
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'AR','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = SumberDataEF::where('SumberDataId',$keyId)->first();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = SumberDataEF::where('SumberDataId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/UnitController.php b/app/Http/Controllers/Pengaturan/UnitController.php
deleted file mode 100644
index d1dd303..0000000
--- a/app/Http/Controllers/Pengaturan/UnitController.php
+++ /dev/null
@@ -1,180 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Unit','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = Unit::orderBy('UnitId','ASC')->get();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->UnitId),
- 'kode' => @$row->kode,
- 'kategori' => @$row->kategori->nama,
- 'nama' => @$row->nama,
- 'nomor_baris' => @$row->nomor_baris,
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $request->validate([
- 'nama' => 'required|string|max:255',
- ]);
-
- try {
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = Unit::find($keyId);
- $data->kategori_id = decode_id($request->kategori_id);
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->kode = $request->kode;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }else{
- $data = new Unit;
- $data->kategori_id = decode_id($request->kategori_id);
- $data->nama = $request->nama;
- $data->deskripsi = $request->deskripsi;
- $data->kode = $request->kode;
- $data->nomor_baris = $request->nomor_baris;
- $data->status = $request->status;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Unit','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = Unit::where('UnitId',$keyId)->first();
- $data['kategori'] = Kategori::all();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = Unit::where('UnitId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/UnitKonversiController.php b/app/Http/Controllers/Pengaturan/UnitKonversiController.php
deleted file mode 100644
index e5829bf..0000000
--- a/app/Http/Controllers/Pengaturan/UnitKonversiController.php
+++ /dev/null
@@ -1,198 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Unit Konversi','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['kategori'] = Kategori::all();
- $data['unit'] = Unit::where('kategori_id',decode_id(@request()->kategori_id))->get();
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
- if(@$request->kategori_id){
- $data = Unit::where('kategori_id',decode_id($request->kategori_id))->orderBy('UnitId','ASC')->get();
- }else{
- $data = [];
- }
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
- //unit to
- foreach ($data as $keyAr => $rowAr) {
- $_ardata['input_'.$rowAr->UnitId.'_'.strtolower($rowAr->kode)] = '';
- }
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $unit = Unit::where('kode',$row->kode)->first();
-
- // $input = '';
- // $input = '';
- // $input .= '';
-
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- // $action .= '
';
- if(session('group_id') == 1){
- // $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = array_merge([
- 'no' => $key+1,
- 'id' => encode_id($row->UnitId),
- 'kategori' => @$row->kategori->nama,
- 'nama' => @$row->nama,
- 'kategoriID' => @$row->kategori->KategoriId,
- 'UnitId' => $unit->UnitId,
- 'status' => @$status,
- 'input' => @$input,
- 'action' => @$action,
- ],$_ardata);
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- $kategoriId = decode_id($request->kategori_id);
-
- foreach ($request->all() as $key => $value) {
- // pastikan key diawali "val_"
- if (!str_starts_with($key, 'val_')) {
- continue;
- }
-
- // pecah: "val_6_17" -> ["val", "6", "17"]
- $parts = explode('_', $key);
-
- // jaga-jaga kalau format gak sesuai
- if (count($parts) !== 3) {
- continue;
- }
-
- $fromId = (int) $parts[1];
- $toId = (int) $parts[2];
-
- // skip kalau value kosong (opsional)
- if ($value === null || $value === '') {
- continue;
- }
-
- UnitKonversi::updateOrCreate(
- ['kategori_id' => $kategoriId, 'from_id' => $fromId, 'to_id' => $toId],
- ['value' => $value, 'updated_at' => now()]
- );
- }
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
-
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Unit Konversi','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = UnitKonversi::where('UnitKonversiId',$keyId)->first();
- $data['kategori'] = Kategori::all();
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = UnitKonversi::where('UnitKonversiId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pengaturan/UploadAktifitasController.php b/app/Http/Controllers/Pengaturan/UploadAktifitasController.php
deleted file mode 100644
index 86a53d4..0000000
--- a/app/Http/Controllers/Pengaturan/UploadAktifitasController.php
+++ /dev/null
@@ -1,219 +0,0 @@
-route, 'module',true);
-
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Data Aktifitas','active' => true],
- ];
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['sektor'] = Sektor::all();
-
- return view($this->template.'.index',$data);
- }
-
- public function grid(Request $request)
- {
-
- $data = FileDataAktivitas::with(['sektor'])->get();
- $_data = [];
-
-
- foreach ($data as $key => $row) {
-
-
- $action = '';
- $status = '';
- if($row->status == 0){
- $status = ' Tidak Aktif ';
- }else{
- $status = ' Aktif ';
- }
- $file = '';
- $action .= '';
- if((permission('is_create', $this->route.'.*','module',false)) || (permission('is_update', $this->route.'.*','module',false))){
- $action .= '
';
- if(session('group_id') == 1){
- $action .= '
';
- }
- }
- $action .= '
';
-
- $_data[] = [
- 'no' => $key+1,
- 'id' => encode_id($row->FileDataAktivitasId),
- 'sektor' => @$row->sektor->nama,
- 'tahun' => @$row->tahun,
- 'nama' => @$row->nama,
- 'file' => @$file,
- 'created_at' => date('d-m-Y H:i:s',strtotime(@$row->created_at)),
- 'status' => @$status,
- 'action' => @$action,
- ];
-
- }
-
- // return response()->json($_data); // Return the data as a JSON response
- return response()->json($_data);
-
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
- /**
- * Store a newly created resource in storage.
- */
- public function store(Request $request)
- {
- // dd(request()->all());
- $request->validate([
- 'sektor' => 'required',
- 'tahun' => 'required',
- 'nama' => 'required',
- 'file' => 'required|file|mimes:xls,xlsx,pdf,png,jpg,jpeg,docx|max:2000',
- ]);
-
- try {
-
- if (@$request->file) {
- $file = $request->file;
- $destinationPath = public_path('uploads/data_aktifitas');
- $current = Carbon::now()->format('Y/m/d');
- $path = $destinationPath . '/' . $current;
- $fileName = $file->getClientOriginalName();
- $fileMime = $file->getClientMimeType();
- $fileExtension = $file->getClientOriginalExtension();
- $fileSize = $file->getSize();
- if(($fileExtension != 'xls') && ($fileExtension != 'xlsx') && ($fileExtension != 'pdf') && ($fileExtension != 'docx') && ($fileExtension != 'png') && ($fileExtension != 'jpg') && ($fileExtension != 'jpeg') ){
- return redirect()->back()->with([
- 'message' => 'Maaf File Harus Berupa xls,xlsx,pdf,png,jpg,jpeg,docx!',
- 'type' => "error"
- ]);
- }
- $newFilename = session('id').'_'.uniqid('file_') . '.' . $fileExtension;
-
- if (!File::exists($path)) {
- File::isDirectory($path) or File::makeDirectory($path, 0777, true, true);
- }
-
- $filePath = 'data_aktifitas/' . $current . '/' . $newFilename;
- $uploaded = $file->move($path, $newFilename);
- }
-
-
- if(@request()->secure_id){
- $keyId = decode_id(@request()->secure_id);
- $data = FileDataAktivitas::find($keyId);
- $data->ms_sektor_id = decode_id($request->sektor);
- $data->ms_subsektor_id = @$request->subsektor ? decode_id($request->subsektor) : NULL;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }else{
- $data = new FileDataAktivitas;
- $data->ms_sektor_id = decode_id($request->sektor);
- $data->ms_subsektor_id = @$request->subsektor ? decode_id($request->subsektor) : NULL;
- $data->tahun = $request->tahun;
- $data->nama = $request->nama;
- $data->file = $filePath;
- $data->deskripsi = $request->deskripsi;
- $data->save();
- }
-
-
- return redirect()->back()->with([
- 'message' => 'Berhasil update data',
- 'type' => 'success',
- ]);
- } catch (\Exception $e) {
- return redirect()->back()->with([
- 'message' => 'Gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage(),
- 'type' => 'error',
- ]);
- }
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update($id = null)
- {
- $data['breadcrumbs'] = [
- ['name' => 'Dashboard'],
- ['name' => 'Pengaturan'],
- ['name' => 'Data Aktivitas','active' => true],
- ];
- $keyId = decode_id($id);
- $data['title'] = $this->title;
- $data['route'] = $this->route;
- $data['keyId'] = $id;
- $data['item'] = FileDataAktivitas::where('FileDataAktivitasId',$keyId)->first();
- $data['sektor'] = Sektor::all();
-
- return view($this->template.'.form',$data);
- }
-
- public function delete($id)
- {
- $keyId = decode_id($id);
-
- $data = FileDataAktivitas::where('FileDataAktivitasId',$keyId)->delete();
-
- return response()->json(['success' => true,'message' => 'Berhasil update data','type' => 'success']);
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
- }
-}
diff --git a/app/Http/Controllers/Pertanian/HortikulturaController.php b/app/Http/Controllers/Pertanian/HortikulturaController.php
deleted file mode 100644
index 7870f26..0000000
--- a/app/Http/Controllers/Pertanian/HortikulturaController.php
+++ /dev/null
@@ -1,65 +0,0 @@
-service = $service;
+ }
+
+ public function show($inventoryYear = null, $activityYear = null, $sectorCode = null)
+ {
+ $categories = ReferenceSector::rowActive()->orderByRowNum()->get();
+ $worksheets = ReferenceWs::with('children')->rowActive()->where('sector', $sectorCode)->isMain()->orderByRowNum()->get();
+
+ $crfData = ActivityCrf::rowActive()
+ ->where('sector', $sectorCode)
+ ->where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->get();
+
+ return view('reports.crf.index', [
+ 'inventoryYear' => $inventoryYear ?? date('Y'),
+ 'activityYear' => $activityYear ?? date('Y') - 1,
+ 'sectorCode' => $sectorCode,
+
+ 'categories' => $categories,
+ 'worksheets' => $worksheets,
+ 'crfData' => $crfData,
+ ]);
+ }
+
+ public function export(Request $request)
+ {
+ // Validate and sanitize inputs
+ $validator = Validator::make($request->all(), [
+ 'inventoryYear' => 'required|integer',
+ 'activityYear' => 'required|integer',
+ 'sectorCode' => 'required|string',
+ ]);
+
+ if ($validator->fails()) {
+ return redirect()->back()->withErrors($validator)->withInput();
+ }
+
+ $inventoryYear = $request->input('inventoryYear');
+ $activityYear = $request->input('activityYear');
+ $sectorCode = $request->input('sectorCode');
+
+ // Fetch the necessary data
+ $sector = ReferenceSector::rowActive()->where('code', $sectorCode)->first();
+ $worksheets = ReferenceWs::with('children')->rowActive()->where('sector', $sectorCode)->isMain()->orderByRowNum()->get();
+ $crfData = ActivityCrf::rowActive()
+ ->where('sector', $sectorCode)
+ ->where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->get();
+
+ $titleExcel = 'CRF_' . strtoupper($sector->name) . '_' . $inventoryYear . '_' . $activityYear;
+ $sector->inventoryYear = $inventoryYear;
+ $sector->activityYear = $activityYear;
+
+ return Excel::download(new CrfExport($sector, $crfData, $worksheets), $titleExcel . '.xlsx');
+ }
+}
diff --git a/app/Http/Controllers/Reports/GcomCrfController.php b/app/Http/Controllers/Reports/GcomCrfController.php
new file mode 100644
index 0000000..15492e7
--- /dev/null
+++ b/app/Http/Controllers/Reports/GcomCrfController.php
@@ -0,0 +1,78 @@
+service = $service;
+ }
+
+ public function show($inventoryYear = null, $activityYear = null, $sectorCode = null)
+ {
+ $gpcOutput = ActivityGpcOutput::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)->rowActive()
+ ->first();
+
+ $gpc = [];
+ if ($gpcOutput) {
+ $gpc = $gpcOutput->getAllColumnsWithReference();
+ }
+
+ $gpcData = GcomCrfData::getAllData();
+
+ return view('reports.gcom-crf.index', [
+ 'inventoryYear' => $inventoryYear ?? date('Y'),
+ 'activityYear' => $activityYear ?? date('Y') - 1,
+
+ 'gpcData' => $gpcData,
+
+ 'gpcOutput' => $gpcOutput,
+ 'gpc' => $gpc,
+ ]);
+ }
+
+ public function export(Request $request)
+ {
+ // Validate and sanitize inputs
+ $validator = Validator::make($request->all(), [
+ 'inventoryYear' => 'required|integer',
+ 'activityYear' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return redirect()->back()->withErrors($validator)->withInput();
+ }
+
+ $inventoryYear = $request->input('inventoryYear');
+ $activityYear = $request->input('activityYear');
+
+ // Fetch the necessary data
+ $gpcOutput = ActivityGpcOutput::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)->rowActive()
+ ->first();
+
+ $gpc = [];
+ if ($gpcOutput) {
+ $gpc = $gpcOutput->getAllColumnsWithReference();
+ }
+
+ $gpcData = GcomCrfData::getAllData();
+
+ $titleExcel = 'GCOM-CRF_' . $inventoryYear . '_' . $activityYear;
+
+ return Excel::download(new GcomCrfExport($inventoryYear, $activityYear, $gpcData, $gpc), $titleExcel . '.xlsx');
+ }
+}
diff --git a/app/Http/Controllers/Reports/GpcOutputController.php b/app/Http/Controllers/Reports/GpcOutputController.php
new file mode 100644
index 0000000..ad3d002
--- /dev/null
+++ b/app/Http/Controllers/Reports/GpcOutputController.php
@@ -0,0 +1,69 @@
+service = $service;
+ }
+
+ public function show($inventoryYear = null)
+ {
+ $inventoryYear = $inventoryYear ?? date('Y');
+ $years = activityYearRange($inventoryYear, false);
+
+ $gpcOutputs = ActivityGpcOutput::where('inventory_year', $inventoryYear)
+ ->rowActive()->orderBy('activity_year', 'desc')
+ ->whereBetween('activity_year', [$years[0], end($years)])
+ ->get();
+
+ $gpcOutputRList = [];
+ foreach ($gpcOutputs as $gpcOutput) {
+ $gpcOutputRList[] = $gpcOutput->getAllColumnsWithReference();
+ }
+
+ return view('reports.gpc-output.index', [
+ 'inventoryYear' => $inventoryYear,
+ 'gpcOutputs' => $gpcOutputs,
+ 'gpcOutputRList' => $gpcOutputRList,
+ ]);
+ }
+
+ public function export(Request $request)
+ {
+ $validator = Validator::make($request->all(), [
+ 'inventoryYear' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return redirect()->back()->withErrors($validator)->withInput();
+ }
+
+ $inventoryYear = $request->input('inventoryYear');
+
+ // Fetch the necessary data
+ $gpcOutputs = ActivityGpcOutput::where('inventory_year', $inventoryYear)
+ ->rowActive()->orderBy('activity_year', 'desc')->get();
+
+ $gpcOutputRList = [];
+ foreach ($gpcOutputs as $gpcOutput) {
+ $gpcOutputRList[] = $gpcOutput->getAllColumnsWithReference();
+ }
+
+ $titleExcel = 'GPC-OUTPUT_' . $inventoryYear;
+
+ return Excel::download(new GpcOutputExport($inventoryYear, $gpcOutputs, $gpcOutputRList), $titleExcel . '.xlsx');
+ }
+}
diff --git a/app/Http/Controllers/Reports/WorksheetController.php b/app/Http/Controllers/Reports/WorksheetController.php
new file mode 100644
index 0000000..18f6d7f
--- /dev/null
+++ b/app/Http/Controllers/Reports/WorksheetController.php
@@ -0,0 +1,93 @@
+service = $service;
+ }
+
+ public function show($inventoryYear = null, $activityYear = null, $sectorCode = null, $wsCode = null)
+ {
+ $categories = ReferenceSector::rowActive()->orderByRowNum()->get();
+ $worksheets = $sectorCode ? $this->service->getWorksheets($sectorCode) : [];
+
+ // Fetch worksheet data
+ $wsData = $this->service->getWorksheet($sectorCode, $wsCode);
+
+ // Check if wsData and model are valid
+ if ($wsData && class_exists($wsData->model)) {
+ $modelClass = $wsData->model;
+ $emisiData = $this->service->getEmissionsData($modelClass, $inventoryYear, $activityYear, $wsCode);
+ } else {
+ $emisiData = [];
+ }
+
+ return view('reports.worksheet.index', [
+ 'inventoryYear' => $inventoryYear ?? date('Y'),
+ 'activityYear' => $activityYear,
+ 'sectorCode' => $sectorCode,
+ 'wsCode' => $wsCode,
+
+ 'categories' => $categories,
+ 'worksheets' => $worksheets,
+
+ 'wsData' => $wsData,
+ 'emisiData' => $emisiData
+ ]);
+ }
+
+ public function getWorksheetsBySector(Request $request)
+ {
+ $code = $request->input('sector');
+ $worksheets = $this->service->getWorksheets($code);
+
+ return response()->json($worksheets);
+ }
+
+ public function export(Request $request)
+ {
+ // Validate and sanitize inputs
+ $validator = Validator::make($request->all(), [
+ 'inventoryYear' => 'required|integer',
+ 'activityYear' => 'required|integer',
+ 'sectorCode' => 'required|string',
+ 'wsCode' => 'required|string',
+ ]);
+
+ if ($validator->fails()) {
+ return redirect()->back()->withErrors($validator)->withInput();
+ }
+
+ $inventoryYear = (int) $request->input('inventoryYear');
+ $activityYear = $request->input('activityYear') ? (int) $request->input('activityYear') : null;
+ $sectorCode = $request->input('sectorCode');
+ $wsCode = $request->input('wsCode');
+
+ $wsData = $this->service->getWorksheet($sectorCode, $wsCode);
+
+ if ($wsData && class_exists($wsData->model)) {
+ $modelClass = $wsData->model;
+ $emisiData = $this->service->getEmissionsData($modelClass, $inventoryYear, $activityYear, $wsCode);
+ } else {
+ $emisiData = [];
+ }
+
+ $titleExcel = 'WORKSHEET ' . strtoupper($sectorCode) . '-' . $wsCode . '-' . $activityYear . '-' . $inventoryYear;
+ $wsData['titleExcel'] = $titleExcel;
+
+ return Excel::download(new WorksheetExport($wsData, $emisiData), $titleExcel . '.xlsx');
+ }
+}
diff --git a/app/Http/Controllers/Setting/ArController.php b/app/Http/Controllers/Setting/ArController.php
new file mode 100644
index 0000000..61894a6
--- /dev/null
+++ b/app/Http/Controllers/Setting/ArController.php
@@ -0,0 +1,170 @@
+arService = $arService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/ar'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.index',$data);
+ }
+
+ // public function show(){
+ // dd('a');
+ // }
+ public function create()
+ {
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.create',$data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'code' => [
+ 'required',
+ 'string',
+ 'max:255',
+ new UniqueInSchema('reference', 'ar', 'code'),
+ ],
+ 'name' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $data = array_merge($request->all(), ['active_status' => 0]);
+ $this->arService->create($data);
+
+ return redirect()->route($this->route.'.index')->with('success', 'AR berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'AR gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $data['ar'] = $this->arService->find($id);
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.edit', $data);
+ }
+
+ public function update(Request $request, ReferenceAr $ar)
+ {
+ $request->validate([
+ 'code' => [
+ 'required',
+ 'string',
+ 'max:255',
+ new UniqueInSchema('reference', 'ar', 'code', $ar->id),
+ ],
+ 'name' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $this->arService->update($ar, $request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'AR berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'AR gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy(ReferenceAr $ar)
+ {
+ try {
+ $this->arService->delete($ar);
+
+ return redirect()->route($this->route.'.index')->with('success', 'AR berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'AR gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function setAktif($id)
+ {
+ try {
+ $this->arService->setAktif($id);
+ return redirect()->route($this->route.'.index')->with('success', 'AR berhasil diaktifkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Gagal mengaktifkan AR. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function grid()
+ {
+ $data = $this->arService->getAll();
+ $_data = [];
+
+ foreach ($data as $key => $row) {
+
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ if ($row->active_status == 0) {
+ $btn .= ' ';
+ }
+
+ if ($row->active_status == 1) {
+ $status = 'Aktif';
+ } else {
+ $status = 'Tidak Aktif';
+ }
+
+ $_data[] = [
+ 'no' => $key+1,
+ 'no_baris' => @$row->row_num,
+ 'code' => $row->code,
+ 'name' => $row->name,
+ 'description' => $row->description,
+ 'no_baris' => $row->row_num,
+ 'status' => $status,
+ 'action' => @$btn,
+ ];
+
+ }
+
+ return response()->json($_data);
+ }
+}
diff --git a/app/Http/Controllers/Setting/DataAktivitasController.php b/app/Http/Controllers/Setting/DataAktivitasController.php
new file mode 100644
index 0000000..21d3be2
--- /dev/null
+++ b/app/Http/Controllers/Setting/DataAktivitasController.php
@@ -0,0 +1,208 @@
+fileService = $fileService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/data_aktivitas'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ $data['sectors'] = $this->fileService->getSectors();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.index', $data);
+ }
+
+ public function create()
+ {
+ $data['sectors'] = $this->fileService->getSectors();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.create', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'sector' => 'required|string|max:255',
+ 'sub_sector' => 'nullable|string|max:255',
+ 'inventory_year' => 'required|integer',
+ 'name' => 'required|string|max:255',
+ 'file_document' => 'required|file|max:2048|mimes:pdf,doc,docx,xlsx,xls',
+ ], [
+ 'file_document.max' => 'Ukuran file tidak boleh melebihi 2MB.',
+ ]);
+
+ try {
+ $this->fileService->save($request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'File Data Aktivitas berhasil diupload.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Data Aktivitas gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $data = $this->fileService->find($id);
+ if ($data) {
+ $data['storagePath'] = 'data_aktivitas/' . $data->sector . '/' . $data->inventory_year;
+ }
+
+ $data['sectors'] = $this->fileService->getSectors();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.edit', $data);
+ }
+
+ public function update(Request $request, $id)
+ {
+ $request->validate([
+ 'sector' => 'required|string|max:255',
+ 'sub_sector' => 'nullable|string|max:255',
+ 'inventory_year' => 'required|integer',
+ 'name' => 'required|string|max:255',
+ 'file_document' => 'nullable|file|max:2048|mimes:pdf,doc,docx,xlsx,xls',
+ ], [
+ 'file_document.max' => 'Ukuran file tidak boleh melebihi 2MB.',
+ ]);
+
+ try {
+ $data = $request->all();
+ $data['id'] = $id; // Set the ID of the record to update
+
+ $this->fileService->save($data);
+
+ return redirect()->route($this->route.'.index')->with('success', 'File Data Aktivitas berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Data Aktivitas gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy($id)
+ {
+ try {
+ $data = $this->fileService->find($id);
+ if ($data) {
+ $storagePath = 'data_aktivitas/' . $data->sector . '/' . $data->inventory_year;
+ }
+
+ $this->fileService->destroy($cms, $storagePath);
+
+ return redirect()->route($this->route.'.index')->with('success', 'File Data Aktivitas berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Data Aktivitas gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function fetchSubSectors(Request $request)
+ {
+ $request->validate([
+ 'sector_code' => 'required|string'
+ ]);
+
+ $subSectors = ReferenceSubSector::rowActive()->where('sector_code', $request->sector_code)->get();
+
+ return response()->json($subSectors);
+ }
+
+ public function grid(Request $request)
+ {
+
+ $_data = [];
+ $user = Auth::user();
+ $scope = $user->getScope();
+ $data = CmsFileDataAktivitas::rowActive();
+
+ if ($scope === LingkupAksesData::INTERNAL->value) {
+ $data->whereHas('creator', function ($q) use ($user) {
+ $q->where('agency_id', $user->agency_id);
+ });
+ } else if ($scope === '') {
+ $data->where('created_by', null);
+ }
+
+ // Apply category filter if a category is selected
+ if ($request->has('sectorFilter') && $request->sectorFilter != '' && $request->sectorFilter != 'SEMUA SEKTOR') {
+ $data = $data->where('sector', $request->sectorFilter);
+ }
+
+ if ($request->has('subSectorFilter') && $request->subSectorFilter != '' && $request->subSectorFilter != 'SEMUA SUB SEKTOR') {
+ $data = $data->where('sub_sector', $request->subSectorFilter);
+ }
+
+ // Apply inventory year filter if a year is selected
+ if ($request->has('inventoryYearFilter') && $request->inventoryYearFilter != '') {
+ $data = $data->where('inventory_year', $request->inventoryYearFilter);
+ }
+
+ foreach ($data->get() as $key => $row) {
+
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ $sector = $row->sectorData->name;
+ if ($row->sub_sector) {
+ $sector = $sector . ': ' . $row->subSector->name;
+ }
+
+ if ($row->file_upload) {
+ $storagePath = 'data_aktivitas/' . $row->sector . '/' . $row->inventory_year;
+ $file = '
+
+ ';
+ } else {
+ $file = 'No File';
+ }
+
+
+ $_data[] = [
+ 'no' => $key+1,
+ 'sector' => $sector,
+ 'file' => $file,
+ 'inventory_year' => $row->inventory_year,
+ 'name' => $row->name,
+ 'agency' => $row->agency,
+ 'created_at' => $row->created_at->format('d-m-Y H:i:s'),
+ 'action' => @$btn,
+ ];
+
+ }
+
+ return response()->json($_data);
+ }
+}
diff --git a/app/Http/Controllers/Setting/EfController.php b/app/Http/Controllers/Setting/EfController.php
new file mode 100644
index 0000000..cfc9897
--- /dev/null
+++ b/app/Http/Controllers/Setting/EfController.php
@@ -0,0 +1,226 @@
+efService = $efService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/ef'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+
+ }
+
+ $data['activities'] = $this->efService->getActivities();
+ $data['categories'] = $this->efService->getCategories();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.index', $data);
+ }
+
+
+ public function getCategoriesByActivity(Request $request)
+ {
+ $activityCode = $request->input('activity_code');
+ $categories = $this->efService->getCategories($activityCode);
+
+ return response()->json($categories);
+ }
+
+ public function create()
+ {
+ $data['activities'] = $this->efService->getActivities();
+ $data['efSources'] = $this->efService->getEfSources();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.create', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'activity_code' => 'required',
+ 'category' => 'required',
+ 'ef_source_code' => [
+ 'required',
+ new ExistInSchema('reference', 'ef_source', 'code')
+ ],
+ 'description' => 'nullable',
+ 'tag_1' => 'nullable|string',
+ 'tag_2' => 'nullable|string',
+ 'tag_3' => 'nullable|string',
+ ]);
+
+ try {
+ $request['value'] = getOriginalValue($request['value']);
+ $this->efService->create($request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'EF berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'EF gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $data['ef'] = $this->efService->find($id);
+ $data['activities'] = $this->efService->getActivities();
+ $data['efSources'] = $this->efService->getEfSources();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.edit', $data);
+ }
+
+ public function update(Request $request, ReferenceEf $ef)
+ {
+ $request->validate([
+ 'activity_code' => 'required',
+ 'category' => 'required',
+ 'ef_source_code' => [
+ 'required',
+ new ExistInSchema('reference', 'ef_source', 'code')
+ ],
+ 'value' => 'required',
+ 'description' => 'nullable',
+ 'tag_1' => 'nullable|string',
+ 'tag_2' => 'nullable|string',
+ 'tag_3' => 'nullable|string',
+ ]);
+
+ try {
+ $request['value'] = getOriginalValue($request['value']);
+ $this->efService->update($ef, $request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'EF berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'EF gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+
+ public function destroy(ReferenceEf $ef)
+ {
+ try {
+ $this->efService->delete($ef);
+
+ return redirect()->route($this->route.'.index')->with('success', 'Unit berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Unit gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function storeEfSource(Request $request)
+ {
+ $request->validate([
+ 'code' => [
+ 'required',
+ 'string',
+ 'max:255',
+ new UniqueInSchema('reference', 'ef_source', 'code'),
+ ],
+ 'name' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $efSource = [
+ 'code' => $request->input('code'),
+ 'name' => $request->input('name'),
+ 'description' => $request->input('description'),
+ 'row_num' => $request->input('row_num'),
+ ];
+
+ $this->efService->create($efSource, ReferenceEfSource::class);
+
+ return response()->json($efSource, 201);
+ } catch (\Exception $e) {
+ return response()->json(['error' => 'Sumber Data EF gagal dibuat.'], 500);
+ }
+ }
+
+ public function grid(Request $request)
+ {
+
+ $_data = [];
+ $data = $this->efService->getAll();
+
+ $activityCodeFilter = $request->activityCodeFilter ?? null;
+ $categoryFilter = $request->categoryFilter ?? null;
+
+ if (!is_null($activityCodeFilter) && $activityCodeFilter != 'SEMUA AKTIVITAS') {
+ $data = $data->where('activity_code', $activityCodeFilter);
+ }
+
+ if (!is_null($categoryFilter) && $categoryFilter != 'SEMUA KATEGORI') {
+ $data = $data->where('category', $categoryFilter);
+ }
+
+ foreach ($data as $key => $row) {
+
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ if ($row->active_status == 1) {
+ $status = 'Aktif';
+ } else {
+ $status = 'Tidak Aktif';
+ }
+
+ $tags = array();
+ for ($i = 1; $i <= 3; $i++) {
+ $col = $row->{'tag_' . $i}; // Correctly access the dynamic property
+ if ($col && $col != '') {
+ array_push($tags, '' . $col . '');
+ }
+ }
+
+ $_data[] = [
+ 'no' => $key+1,
+ 'value' => $row->value ? getFormattedValue($row->value) : 0,
+ 'activity' => $row->activity ? $row->activity->name : 'N/A',
+ 'ef_resource' => $row->efSource ? $row->efSource->name : 'N/A',
+ 'category' => $row->category,
+ 'description' => $row->description,
+ 'status' => $status,
+ 'tags' => $tags,
+ 'action' => @$btn,
+ ];
+
+ }
+
+ return response()->json($_data);
+ }
+}
diff --git a/app/Http/Controllers/Setting/EfSourceController.php b/app/Http/Controllers/Setting/EfSourceController.php
new file mode 100644
index 0000000..f3e2dbb
--- /dev/null
+++ b/app/Http/Controllers/Setting/EfSourceController.php
@@ -0,0 +1,139 @@
+efSourceService = $efSourceService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/ef_source'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.index',$data);
+ }
+
+ public function create()
+ {
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.create',$data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'code' => [
+ 'required',
+ 'string',
+ 'max:255',
+ new UniqueInSchema('reference', 'ef_source', 'code'),
+ ],
+ 'name' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $this->efSourceService->create($request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'Sumber Data EF berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Sumber Data EF gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $data['efSource'] = $this->efSourceService->find($id);
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+ return view($this->template.'.edit', $data);
+ }
+
+ public function update(Request $request, ReferenceEfSource $efSource)
+ {
+ $request->validate([
+ 'code' => [
+ 'required',
+ 'string',
+ 'max:255',
+ new UniqueInSchema('reference', 'ef_source', 'code', $efSource->id),
+ ],
+ 'name' => 'required|string|max:255',
+ 'description' => 'nullable|string',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $this->efSourceService->update($efSource, $request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'Sumber Data EF berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Sumber Data EF gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy(ReferenceEfSource $efSource)
+ {
+ try {
+ $this->efSourceService->delete($efSource);
+
+ return redirect()->route($this->route.'.index')->with('success', 'Sumber Data EF berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Sumber Data EF gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function grid(Request $request)
+ {
+ $data = $this->efSourceService->getAll();
+ $_data = [];
+
+ foreach ($data as $key => $row) {
+
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ $_data[] = [
+ 'no' => $key+1,
+ 'no_baris' => @$row->row_num,
+ 'code' => $row->code,
+ 'name' => $row->name,
+ 'description' => $row->description,
+ 'no_baris' => $row->row_num,
+ 'action' => @$btn,
+ ];
+
+ }
+
+ return response()->json($_data);
+ }
+}
diff --git a/app/Http/Controllers/Setting/GwpController.php b/app/Http/Controllers/Setting/GwpController.php
new file mode 100644
index 0000000..2f848db
--- /dev/null
+++ b/app/Http/Controllers/Setting/GwpController.php
@@ -0,0 +1,57 @@
+gwpService = $gwpService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/gwp'),
+ ];
+ }
+
+ public function index()
+ {
+ $data['ghgs'] = ReferenceGhg::rowActive()->orderByRowNum()->get();
+ $data['ars'] = ReferenceAr::rowActive()->orderByRowNum()->get();
+ $data['gwpMatrix'] = $this->gwpService->getMatrix();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.index',$data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'gwp' => 'required|array',
+ ]);
+
+ try {
+ $this->gwpService->save($request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'GWP berhasil disimpan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'GWP gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Setting/PeraturanController.php b/app/Http/Controllers/Setting/PeraturanController.php
new file mode 100644
index 0000000..88b5ab6
--- /dev/null
+++ b/app/Http/Controllers/Setting/PeraturanController.php
@@ -0,0 +1,134 @@
+fileService = $fileService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/peraturan'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+ $query = $this->fileService->getAll();
+
+ $result = datatables()->of($query)
+ ->addColumn('file_upload', function ($row) {
+ if ($row->file_upload) {
+ $storagePath = 'peraturan';
+ return '
+
+ ';
+ } else {
+ return 'No File';
+ }
+ })
+ ->addColumn('action', function ($data) {
+ $actionBtn = 'Edit';
+ $actionBtn .= ' ';
+ return $actionBtn;
+ })
+ ->rawColumns(['file_upload', 'action'])
+ ->make(true);
+
+ return $result;
+ }
+
+ return view('setting.file-peraturan.index');
+ }
+
+
+ public function create()
+ {
+ return view('setting.file-peraturan.create');
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'name' => 'required|string|max:255',
+ 'file_document' => 'required|file|max:2048|mimes:pdf,doc,docx,xlsx,xls',
+ ], [
+ 'file_document.max' => 'Ukuran file tidak boleh melebihi 2MB.',
+ ]);
+
+ try {
+ $this->fileService->save($request->all());
+
+ return redirect()->route('peraturan.index')->with('success', 'File Pengumuman / File Peraturan-Peraturan berhasil diupload.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Pengumuman / File Peraturan-Peraturan gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $data = $this->fileService->find($id);
+ if ($data) {
+ $data['storagePath'] = 'peraturan';
+ }
+
+ return view('setting.file-peraturan.edit', compact('data'));
+ }
+
+ public function update(Request $request, $id)
+ {
+ $request->validate([
+ 'name' => 'required|string|max:255',
+ 'file_document' => 'nullable|file|max:2048|mimes:pdf,doc,docx,xlsx,xls',
+ ], [
+ 'file_document.max' => 'Ukuran file tidak boleh melebihi 2MB.',
+ ]);
+
+ try {
+ $data = $request->all();
+ $data['id'] = $id;
+
+ $this->fileService->save($data);
+
+ return redirect()->route('peraturan.index')->with('success', 'File Pengumuman / File Peraturan-Peraturan berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Pengumuman / File Peraturan-Peraturan gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy($id)
+ {
+ try {
+ $data = $this->fileService->find($id);
+ if ($data) {
+ $storagePath = 'peraturan';
+ }
+
+ $this->fileService->destroy($cms, $storagePath);
+
+ return redirect()->route('unit.index')->with('success', 'File Pengumuman / File Peraturan-Peraturan berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'File Pengumuman / File Peraturan-Peraturan gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Setting/UnitController.php b/app/Http/Controllers/Setting/UnitController.php
new file mode 100644
index 0000000..aa6cc2d
--- /dev/null
+++ b/app/Http/Controllers/Setting/UnitController.php
@@ -0,0 +1,149 @@
+unitService = $unitService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/unit'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+
+ // Pass the list of categories to the view
+ $data['categories'] = $this->unitService->getCategories();
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.index',$data);
+ }
+
+
+ public function create()
+ {
+ $categories = $this->unitService->getCategories();
+ return view($this->template.'.create', compact('categories'));
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'category' => 'required',
+ 'code' => [
+ 'required',
+ new UniqueInSchema('reference', 'unit', 'code')
+ ],
+ 'name' => 'required',
+ 'description' => 'nullable',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $this->unitService->create($request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'Unit berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Unit gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function edit($id)
+ {
+ $unit = $this->unitService->find($id);
+ $categories = $this->unitService->getCategories();
+ return view($this->template.'.edit', compact('unit', 'categories'));
+ }
+
+ public function update(Request $request, ReferenceUnit $unit)
+ {
+ $request->validate([
+ 'category' => 'required',
+ 'code' => [
+ 'required',
+ new UniqueInSchema('reference', 'unit', 'code', $unit->id)
+ ],
+ 'name' => 'required',
+ 'description' => 'nullable',
+ 'row_num' => 'required|numeric',
+ ]);
+
+ try {
+ $this->unitService->update($unit, $request->all());
+
+ return redirect()->route($this->route.'.index')->with('success', 'Unit berhasil diperbarui.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Unit gagal diperbarui. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function destroy(ReferenceUnit $unit)
+ {
+ try {
+ $this->unitService->delete($unit);
+
+ return redirect()->route($this->route.'.index')->with('success', 'Unit berhasil dihapus.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Unit gagal dihapus. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function grid(Request $request)
+ {
+ $units = $this->unitService->getAll();
+
+ // Apply category filter if a category is selected
+ if ($request->has('category') && $request->category != '' && $request->category != 'SEMUA KATEGORI') {
+ $units = $units->where('category', $request->category);
+ }
+
+ $data = $units;
+ $_data = [];
+
+ foreach ($data as $key => $row) {
+
+ $btn = 'Edit';
+ $btn .= ' ';
+
+ $_data[] = [
+ 'no' => $key+1,
+ 'no_baris' => @$row->row_num,
+ 'code' => $row->code,
+ 'name' => $row->name,
+ 'description' => $row->description,
+ 'no_baris' => $row->row_num,
+ 'category' => $row->category,
+ 'action' => @$btn,
+ ];
+
+ }
+
+ return response()->json($_data);
+ }
+}
diff --git a/app/Http/Controllers/Setting/UnitConversionController.php b/app/Http/Controllers/Setting/UnitConversionController.php
new file mode 100644
index 0000000..3e0ab58
--- /dev/null
+++ b/app/Http/Controllers/Setting/UnitConversionController.php
@@ -0,0 +1,60 @@
+unitConversionService = $unitConversionService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/setting/unit_conversion'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ // For combobox category
+ $data['categories'] = $this->unitConversionService->getCategories();
+ $data['selectedCategory'] = $request->get('category', $data['categories']->first());
+
+ // For unit conversion matrix
+ $data['units'] = $this->unitConversionService->getUnitsByCategory($data['selectedCategory']);
+ $data['conversions'] = $this->unitConversionService->getConversionsByCategory($data['selectedCategory']);
+ $data['route'] = $this->route;
+ $data['title'] = $this->title;
+
+ return view($this->template.'.index', $data);
+ }
+
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'category' => 'required',
+ 'conversions' => 'required|array',
+ ]);
+
+ try {
+ $this->unitConversionService->save($request->category, $request->get('conversions', []));
+
+ return redirect()->route($this->route.'.index', ['category' => $request->category])->with('success', 'Unit Conversion berhasil disimpan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Unit Conversion gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Tool/CalculationController.php b/app/Http/Controllers/Tool/CalculationController.php
new file mode 100644
index 0000000..4f624bd
--- /dev/null
+++ b/app/Http/Controllers/Tool/CalculationController.php
@@ -0,0 +1,150 @@
+service = $service;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/tool/calculation'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+ $query = $this->service->getRawAll();
+
+ // Apply category filter if a category is selected
+ if ($request->has('sectorFilter') && $request->sectorFilter != '' && $request->sectorFilter != 'SEMUA SEKTOR') {
+ $query = $query->where($request->sectorFilter, true);
+ }
+
+ if ($request->has('inventoryYearFilter') && $request->inventoryYearFilter != '' && $request->inventoryYearFilter != 'SEMUA TAHUN') {
+ $query = $query->where('inventory_year', $request->inventoryYearFilter);
+ }
+
+ $result = datatables()->of($query)
+ ->addColumn('sector', function ($row) {
+ return $row->sector;
+ })
+ ->addColumn('duration', function ($row) {
+ if ($row->finished_time === null || $row->executed_time === null) {
+ return '';
+ }
+
+ // Parse the date-time strings into Carbon instances
+ $start = Carbon::parse($row->executed_time);
+ $end = Carbon::parse($row->finished_time);
+
+ // Calculate the difference in seconds
+ $diffInSeconds = $start->diffInSeconds($end);
+
+ // Format the duration as HH:MM:SS
+ $hours = floor($diffInSeconds / 3600);
+ $minutes = floor(($diffInSeconds % 3600) / 60);
+ $seconds = $diffInSeconds % 60;
+
+ return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+ })
+ ->editColumn('created_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s')
+ ?? '';
+ })
+ ->editColumn('executed_time', function ($row) {
+ if ($row->executed_time === null) {
+ return '';
+ }
+
+ return $row->executed_time->format('d-m-Y H:i:s');
+ })
+ ->editColumn('finished_time', function ($row) {
+ if ($row->finished_time === null) {
+ return '';
+ }
+
+ return $row->finished_time->format('d-m-Y H:i:s');
+ })
+ ->addColumn('status', function ($row) {
+ $status = SigdStatus::from($row->calculation_status);
+ return $status->badge() ?? '';
+ })
+ ->rawColumns(['status', 'sector', 'duration'])
+ ->make(true);
+
+ return $result;
+ }
+
+ $sectors = $this->service->getSectors();
+ return view('tool.calculation.index', compact('sectors'));
+ }
+
+
+ public function create()
+ {
+ return view('tool.calculation.create');
+ }
+
+ public function store(Request $request)
+ {
+ // Validate the form data
+ $request->validate([
+ 'inventory_year' => 'required|integer|min:2000|max:' . date('Y'),
+ 'energy' => 'boolean',
+ 'agriculture' => 'boolean',
+ 'folu' => 'boolean',
+ 'waste' => 'boolean',
+ 'ippu' => 'boolean',
+ ]);
+
+ $isLocked = ActivityLock::isLocked($request->inventory_year);
+
+ if ($isLocked) {
+ return back()->withErrors(['error' => 'Kalkulasi Emisi gagal disimpan. Tahun Inventory dikunci.']);
+ }
+
+ try {
+ $data = $request->all();
+ $data['energy'] = $request->has('energy') ? 1 : 0;
+ $data['agriculture'] = $request->has('agriculture') ? 1 : 0;
+ $data['folu'] = $request->has('folu') ? 1 : 0;
+ $data['waste'] = $request->has('waste') ? 1 : 0;
+ $data['ippu'] = $request->has('ippu') ? 1 : 0;
+
+ $this->service->create($data);
+ logUserActivity(ActivityType::CALCULATION_EMISI);
+
+ return redirect()->route('calculation.index')->with('success', 'Kalkulasi Emisi berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Kalkulasi Emisi gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function getActivityYearRange(Request $request)
+ {
+ $inventoryYear = (int) $request->query('inventoryYear');
+ $years = activityYearRange($inventoryYear);
+
+ return response()->json([
+ 'years' => $years
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/Tool/CalculationController.php.bak b/app/Http/Controllers/Tool/CalculationController.php.bak
new file mode 100644
index 0000000..53d1433
--- /dev/null
+++ b/app/Http/Controllers/Tool/CalculationController.php.bak
@@ -0,0 +1,148 @@
+service = $service;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/tool/calculation'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+ $query = $this->service->getRawAll();
+
+ // Apply category filter if a category is selected
+ if ($request->has('sectorFilter') && $request->sectorFilter != '' && $request->sectorFilter != 'SEMUA SEKTOR') {
+ $query = $query->where($request->sectorFilter, true);
+ }
+
+ if ($request->has('inventoryYearFilter') && $request->inventoryYearFilter != '' && $request->inventoryYearFilter != 'SEMUA TAHUN') {
+ $query = $query->where('inventory_year', $request->inventoryYearFilter);
+ }
+
+ $result = datatables()->of($query)
+ ->addColumn('sector', function ($row) {
+ return $row->sector;
+ })
+ ->addColumn('duration', function ($row) {
+ if ($row->finished_time === null || $row->executed_time === null) {
+ return '';
+ }
+
+ // Parse the date-time strings into Carbon instances
+ $start = Carbon::parse($row->executed_time);
+ $end = Carbon::parse($row->finished_time);
+
+ // Calculate the difference in seconds
+ $diffInSeconds = $start->diffInSeconds($end);
+
+ // Format the duration as HH:MM:SS
+ $hours = floor($diffInSeconds / 3600);
+ $minutes = floor(($diffInSeconds % 3600) / 60);
+ $seconds = $diffInSeconds % 60;
+
+ return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+ })
+ ->editColumn('created_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s')
+ ?? '';
+ })
+ ->editColumn('executed_time', function ($row) {
+ if ($row->executed_time === null) {
+ return '';
+ }
+
+ return $row->executed_time->format('d-m-Y H:i:s');
+ })
+ ->editColumn('finished_time', function ($row) {
+ if ($row->finished_time === null) {
+ return '';
+ }
+
+ return $row->finished_time->format('d-m-Y H:i:s');
+ })
+ ->addColumn('status', function ($row) {
+ $status = SigdStatus::from($row->calculation_status);
+ return $status->badge() ?? '';
+ })
+ ->rawColumns(['status', 'sector', 'duration'])
+ ->make(true);
+
+ return $result;
+ }
+
+ $sectors = $this->service->getSectors();
+ return view('tool.calculation.index', compact('sectors'));
+ }
+
+
+ public function create()
+ {
+ return view('tool.calculation.create');
+ }
+
+ public function store(Request $request)
+ {
+ // Validate the form data
+ $request->validate([
+ 'inventory_year' => 'required|integer|min:2000|max:' . date('Y'),
+ 'energy' => 'boolean',
+ 'agriculture' => 'boolean',
+ 'folu' => 'boolean',
+ 'waste' => 'boolean',
+ ]);
+
+ $isLocked = ActivityLock::isLocked($request->inventory_year);
+
+ if ($isLocked) {
+ return back()->withErrors(['error' => 'Kalkulasi Emisi gagal disimpan. Tahun Inventory dikunci.']);
+ }
+
+ try {
+ $data = $request->all();
+ $data['energy'] = $request->has('energy') ? 1 : 0;
+ $data['agriculture'] = $request->has('agriculture') ? 1 : 0;
+ $data['folu'] = $request->has('folu') ? 1 : 0;
+ $data['waste'] = $request->has('waste') ? 1 : 0;
+
+ $this->service->create($data);
+ logUserActivity(ActivityType::CALCULATION_EMISI);
+
+ return redirect()->route('calculation.index')->with('success', 'Kalkulasi Emisi berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Kalkulasi Emisi gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+
+ public function getActivityYearRange(Request $request)
+ {
+ $inventoryYear = (int) $request->query('inventoryYear');
+ $years = activityYearRange($inventoryYear);
+
+ return response()->json([
+ 'years' => $years
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/Tool/CopyActivityController.php b/app/Http/Controllers/Tool/CopyActivityController.php
new file mode 100644
index 0000000..eb1d6f4
--- /dev/null
+++ b/app/Http/Controllers/Tool/CopyActivityController.php
@@ -0,0 +1,117 @@
+service = $service;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/tool/copy_activity'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ $availableYears = ActivityForm::select('inventory_year')->whereNull('agency_id')
+ ->distinct()->rowActive()->orderBy('inventory_year', 'desc')
+ ->get()->pluck('inventory_year')->toArray();
+
+ if ($request->ajax()) {
+ $query = $this->service->getRawAll();
+
+ $result = datatables()->of($query)
+ ->addColumn('duration', function ($row) {
+ if ($row->finished_time === null || $row->executed_time === null) {
+ return '';
+ }
+
+ $start = Carbon::parse($row->executed_time);
+ $end = Carbon::parse($row->finished_time);
+
+ // Calculate the difference in seconds
+ $diffInSeconds = $start->diffInSeconds($end);
+
+ // Format the duration as HH:MM:SS
+ $hours = floor($diffInSeconds / 3600);
+ $minutes = floor(($diffInSeconds % 3600) / 60);
+ $seconds = $diffInSeconds % 60;
+
+ return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+ })
+ ->editColumn('created_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s')
+ ?? '';
+ })
+ ->editColumn('executed_time', function ($row) {
+ if ($row->executed_time === null) {
+ return '';
+ }
+
+ return $row->executed_time->format('d-m-Y H:i:s');
+ })
+ ->editColumn('finished_time', function ($row) {
+ if ($row->finished_time === null) {
+ return '';
+ }
+
+ return $row->finished_time->format('d-m-Y H:i:s');
+ })
+ ->addColumn('status', function ($row) {
+ $status = SigdStatus::from($row->status);
+ return $status->badge() ?? '';
+ })
+ ->rawColumns(['status', 'duration'])
+ ->make(true);
+
+ return $result;
+ }
+
+ return view('tool.copy.index', [
+ 'availableYears' => $availableYears
+ ]);
+ }
+
+ public function store(Request $request)
+ {
+ // Validate the form data
+ $request->validate([
+ 'from_year' => 'required|integer|min:2000|max:' . date('Y'),
+ 'to_year' => 'required|integer|min:2000|max:' . date('Y') . '|different:from_year',
+ ]);
+
+ $isLocked = ActivityLock::isLocked($request->to_year);
+
+ if ($isLocked) {
+ return back()->withErrors(['error' => 'Salin Aktivitas gagal disimpan. Tahun Inventory tujuan dikunci.']);
+ }
+
+ try {
+ $data = $request->all();
+
+ $this->service->create($data);
+
+ return redirect()->route('copy.index')->with('success', 'Salin Aktivitas berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Salin Aktivitas gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Tool/LockActivityController.php b/app/Http/Controllers/Tool/LockActivityController.php
new file mode 100644
index 0000000..0554931
--- /dev/null
+++ b/app/Http/Controllers/Tool/LockActivityController.php
@@ -0,0 +1,105 @@
+lockService = $lockService;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/tool/lock_activity'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ if ($request->ajax()) {
+ $locks = $this->lockService->getAll();
+
+ $result = datatables()->of($locks)
+ ->editColumn('updated_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s')
+ ?? '';
+ })
+ ->addColumn('status', function ($row) {
+ if ($row->lock_status == 'locked') {
+ return 'LOCKED';
+ } else {
+ return 'OPEN';
+ }
+ })
+ ->addColumn('action', function ($row) {
+ $buttonStyle = 'style="min-width: 120px;"'; // Adjust min-width as needed
+
+ $action = $row->lock_status == 'locked'
+ ? ''
+ : '';
+
+ return $action;
+ })
+ ->rawColumns(['status', 'action'])
+ ->make(true);
+
+ return $result;
+ }
+
+ return view('tool.lock.index');
+ }
+
+ public function lock(Request $request)
+ {
+ // Validate the input data
+ $request->validate([
+ 'year' => 'required|integer|min:2000|max:' . date('Y'),
+ 'copy_activity' => 'nullable|in:yes,no'
+ ]);
+
+ try {
+ if ($request->copy_activity === 'yes') {
+ $this->lockService->copyActivityToNextYear($request->year);
+ }
+
+ $this->lockService->lock($request->year);
+
+ return redirect()->back()->with('success', 'Tahun Inventory ' . $request->year . ' berhasil dikunci' . ($request->copy_activity === 'ya' ? ' dan data aktivitas berhasil disalin ke tahun berikutnya' : ''));
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Tahun Inventory ' . $request->year . ' gagal dikunci. Mohon dicoba kembali.']);
+ }
+ }
+
+
+ public function unlock(Request $request)
+ {
+ $request->validate([
+ 'year' => 'required|integer|min:2000|max:' . date('Y'),
+ ]);
+
+ try {
+ $this->lockService->unlock($request->year);
+ return redirect()->back()->with('success', 'Tahun Inventory ' . $request->year . ' berhasil dibuka');
+ } catch (\Exception $e) {
+ return redirect()->back()->withErrors(['error' => 'Tahun Inventory ' . $request->year . 'gagal dibuka. Mohon dicoba kembali.']);
+ }
+ }
+}
diff --git a/app/Http/Controllers/Tool/ProdusenCalculateController.php b/app/Http/Controllers/Tool/ProdusenCalculateController.php
new file mode 100644
index 0000000..de5e0bf
--- /dev/null
+++ b/app/Http/Controllers/Tool/ProdusenCalculateController.php
@@ -0,0 +1,116 @@
+service = $service;
+ }
+
+ public static function middleware(): array
+ {
+ return [
+ //new Middleware('permission:/tool/produsen_calculate'),
+ ];
+ }
+
+ public function index(Request $request)
+ {
+ $availableYears = ActivityForm::select('inventory_year')->whereNotNull('agency_id')
+ ->distinct()->rowActive()->orderBy('inventory_year', 'desc')
+ ->get()->pluck('inventory_year')->toArray();
+
+ if ($request->ajax()) {
+ $query = $this->service->getRawAll();
+
+ $result = datatables()->of($query)
+ ->addColumn('duration', function ($row) {
+ if ($row->finished_time === null || $row->executed_time === null) {
+ return '';
+ }
+
+ $start = Carbon::parse($row->executed_time);
+ $end = Carbon::parse($row->finished_time);
+
+ // Calculate the difference in seconds
+ $diffInSeconds = $start->diffInSeconds($end);
+
+ // Format the duration as HH:MM:SS
+ $hours = floor($diffInSeconds / 3600);
+ $minutes = floor(($diffInSeconds % 3600) / 60);
+ $seconds = $diffInSeconds % 60;
+
+ return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+ })
+ ->editColumn('created_at', function ($row) {
+ return $row->created_at->format('d-m-Y H:i:s')
+ ?? '';
+ })
+ ->editColumn('executed_time', function ($row) {
+ if ($row->executed_time === null) {
+ return '';
+ }
+
+ return $row->executed_time->format('d-m-Y H:i:s');
+ })
+ ->editColumn('finished_time', function ($row) {
+ if ($row->finished_time === null) {
+ return '';
+ }
+
+ return $row->finished_time->format('d-m-Y H:i:s');
+ })
+ ->addColumn('status', function ($row) {
+ $status = SigdStatus::from($row->status);
+ return $status->badge() ?? '';
+ })
+ ->rawColumns(['status', 'duration'])
+ ->make(true);
+
+ return $result;
+ }
+
+ return view('tool.produsen-calculate.index', [
+ 'availableYears' => $availableYears
+ ]);
+ }
+
+ public function store(Request $request)
+ {
+ // Validate the form data
+ $request->validate([
+ 'inventory_year' => 'required|integer|min:2000|max:' . date('Y'),
+ ]);
+
+ $isLocked = ActivityLock::isLocked($request->inventory_year);
+
+ if ($isLocked) {
+ return back()->withErrors(['error' => 'Hitung Data dari Produsen gagal disimpan. Tahun Inventory tujuan dikunci.']);
+ }
+
+ try {
+ $data = $request->all();
+
+ $this->service->create($data);
+
+ return redirect()->route('produsenCalculate.index')->with('success', 'Proses Hitung Data dari Produsen berhasil ditambahkan.');
+ } catch (\Exception $e) {
+ return back()->withErrors(['error' => 'Proses Hitung Data dari Produsen Aktivitas gagal disimpan. Silakan coba lagi. Error: ' . $e->getMessage()]);
+ }
+ }
+}
diff --git a/app/Http/Middleware/CheckEmailStatus.php b/app/Http/Middleware/CheckEmailStatus.php
new file mode 100644
index 0000000..32f0240
--- /dev/null
+++ b/app/Http/Middleware/CheckEmailStatus.php
@@ -0,0 +1,22 @@
+check() && auth()->user()->email_verified_at === null) {
+ return redirect()->route('email.updateNotice');
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/CheckPermissions.php b/app/Http/Middleware/CheckPermissions.php
new file mode 100644
index 0000000..fc58066
--- /dev/null
+++ b/app/Http/Middleware/CheckPermissions.php
@@ -0,0 +1,23 @@
+value('id');
+
+ if ($user && $user->userGroup->permissions->contains('menu_id', $menuId)) {
+ return $next($request);
+ }
+
+ throw new NotFoundHttpException();
+ }
+}
diff --git a/app/Imports/FormImport.php b/app/Imports/FormImport.php
new file mode 100644
index 0000000..35e983c
--- /dev/null
+++ b/app/Imports/FormImport.php
@@ -0,0 +1,54 @@
+formService = $formService;
+ $this->sector = $sector;
+ $this->code = $code;
+ $this->inventoryYear = $inventoryYear ?? date('Y');
+ $this->formDetails = $formDetails;
+
+ $this->instansi = $instansi;
+ }
+
+ public function collection(Collection $rows)
+ {
+ $data = []; // Initialize data array to hold all years' data
+
+ foreach ($rows as $row) {
+ $year = $row['tahun'];
+ $yearData = [];
+
+ $items = $row->toArray();
+ $items = array_values($items);
+ for ($i = 0; $i < count($items); $i++) {
+ if ($i !== 0) {
+ $activityCode = $this->formDetails[$i - 1]->activity_code;
+ $unitCode = $this->formDetails[$i - 1]->unit_code;
+ $yearData["{$activityCode}-{$unitCode}"] = getFormattedValue($items[$i]);
+ }
+ }
+
+ if (!isset($data[$year])) {
+ $data[$year] = [];
+ }
+ $data[$year] = $yearData;
+ }
+
+ $this->formService->save($this->sector, $this->code, $this->inventoryYear, $data, null, $this->instansi);
+ }
+}
diff --git a/app/Imports/FormKehutananImport.php b/app/Imports/FormKehutananImport.php
new file mode 100644
index 0000000..8d864a2
--- /dev/null
+++ b/app/Imports/FormKehutananImport.php
@@ -0,0 +1,46 @@
+formService = $formService;
+ $this->sector = $sector;
+ $this->code = $code;
+ $this->inventoryYear = $inventoryYear ?? date('Y');
+ $this->lands = $lands;
+
+ $this->instansi = $instansi;
+ }
+
+ public function collection(Collection $rows)
+ {
+ $data = [];
+
+ for ($i = 0; $i < count($rows); $i++) {
+ $land1 = strtolower($this->lands[$i]);
+ $items = $rows[$i]->toArray();
+ $items = array_values($items);
+ for ($j = 0; $j < count($items); $j++) {
+ if ($j !== 0) {
+ $land2 = strtolower($this->lands[$j - 1]);
+ $data["{$land1}_{$land2}"] = getFormattedValue($items[$j]);
+ }
+ }
+ }
+
+ $this->formService->save($this->sector, $this->code, $this->inventoryYear, $data, $this->instansi);
+ }
+}
diff --git a/app/Models/ActivityApprovalKonsolidasi.php b/app/Models/ActivityApprovalKonsolidasi.php
new file mode 100644
index 0000000..f75be63
--- /dev/null
+++ b/app/Models/ActivityApprovalKonsolidasi.php
@@ -0,0 +1,32 @@
+ $formId,
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'agency_id' => $agencyId,
+ 'status' => 1
+ ])->rowActive()->exists();
+ }
+}
diff --git a/app/Models/ActivityCopy.php b/app/Models/ActivityCopy.php
new file mode 100644
index 0000000..e975e8a
--- /dev/null
+++ b/app/Models/ActivityCopy.php
@@ -0,0 +1,18 @@
+ 'datetime',
+ 'finished_time' => 'datetime',
+ ];
+}
diff --git a/app/Models/ActivityCrf.php b/app/Models/ActivityCrf.php
new file mode 100644
index 0000000..9da67d2
--- /dev/null
+++ b/app/Models/ActivityCrf.php
@@ -0,0 +1,25 @@
+belongsTo(ReferenceWs::class, 'ws_code', 'ws_code');
+ }
+
+ public function sektor()
+ {
+ return $this->belongsTo(ReferenceSector::class, 'sector', 'code');
+ }
+}
diff --git a/app/Models/ActivityDataMitigation.php b/app/Models/ActivityDataMitigation.php
new file mode 100644
index 0000000..4cfa8fc
--- /dev/null
+++ b/app/Models/ActivityDataMitigation.php
@@ -0,0 +1,46 @@
+belongsTo(KegiatanMitigasi::class, 'mitigation_id', 'id');
+ }
+
+ public function units()
+ {
+ return $this->hasMany(ActivityDataMitigationUnit::class, 'activity_data_mitigation_id', 'id');
+ }
+
+}
diff --git a/app/Models/ActivityDataMitigationForm.php b/app/Models/ActivityDataMitigationForm.php
new file mode 100644
index 0000000..5a740b1
--- /dev/null
+++ b/app/Models/ActivityDataMitigationForm.php
@@ -0,0 +1,34 @@
+ 'array',
+ ];
+
+ public function kegiatanMitigasi()
+ {
+ return $this->belongsTo(KegiatanMitigasi::class, 'kegiatan_mitigasi_id', 'id');
+ }
+}
\ No newline at end of file
diff --git a/app/Models/ActivityDataMitigationUnit.php b/app/Models/ActivityDataMitigationUnit.php
new file mode 100644
index 0000000..c1cfccc
--- /dev/null
+++ b/app/Models/ActivityDataMitigationUnit.php
@@ -0,0 +1,20 @@
+belongsTo(SettingForm::class, 'form_code', 'code');
+ }
+
+ public function agency()
+ {
+ return $this->belongsTo(Agency::class, 'agency_id', 'id');
+ }
+}
diff --git a/app/Models/ActivityFormDetail.php b/app/Models/ActivityFormDetail.php
new file mode 100644
index 0000000..d05a5c4
--- /dev/null
+++ b/app/Models/ActivityFormDetail.php
@@ -0,0 +1,47 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+
+ public function form()
+ {
+ return $this->belongsTo(ActivityForm::class, 'form_id', 'id');
+ }
+
+ public function unit()
+ {
+ return $this->belongsTo(Unit::class, 'activity_unit_code', 'code');
+ }
+
+ public function scopeGetValue($query, $inventoryYear, $activityYear, $sector, $code, $activityCode)
+ {
+ $form = ActivityForm::where('inventory_year', $inventoryYear)
+ ->where('sector', $sector)->where('form_code', $code)->whereNull('agency_id')
+ ->rowActive()->orderBy('inventory_year', 'desc')
+ ->first();
+
+ if ($form) {
+ $result = $query->where('form_id', $form->id)->where('activity_year', $activityYear)
+ ->where('activity_code', $activityCode)->rowActive()
+ ->first();
+
+ return $result ? $result->activity_value : 0;
+ }
+
+ return 0;
+ }
+}
diff --git a/app/Models/ActivityFormMetadata.php b/app/Models/ActivityFormMetadata.php
new file mode 100644
index 0000000..ea20771
--- /dev/null
+++ b/app/Models/ActivityFormMetadata.php
@@ -0,0 +1,17 @@
+belongsTo(ActivityForm::class, 'form_id', 'id');
+ }
+}
diff --git a/app/Models/ActivityGpc.php b/app/Models/ActivityGpc.php
new file mode 100644
index 0000000..84de6fd
--- /dev/null
+++ b/app/Models/ActivityGpc.php
@@ -0,0 +1,13 @@
+$columnName;
+
+ if ($columnName == 'created_by' || $columnName == 'updated_by') {
+ return $value;
+ }
+
+ if (is_null($value)) {
+ $gpcCode = str_replace('_', '.', strtoupper($columnName));
+ $reference = ReferenceGpc::where('gpc_code', $gpcCode)->first();
+
+ if ($reference) {
+ return $reference->notation_key;
+ }
+ }
+
+ if ($value == 0) {
+ return 'NE';
+ }
+
+ return $value;
+ }
+
+ public function getAllColumnsWithReference()
+ {
+ $columns = array_intersect($this->getFillable(), $this->columnRefs);
+ // $columns = $this->getFillable();
+ $data = [];
+
+ foreach ($columns as $column) {
+ $data[$column] = $this->getColumnValueOrReference($column);
+ }
+
+ return $data;
+ }
+}
diff --git a/app/Models/ActivityLock.php b/app/Models/ActivityLock.php
new file mode 100644
index 0000000..5dedcdf
--- /dev/null
+++ b/app/Models/ActivityLock.php
@@ -0,0 +1,23 @@
+where('lock_status', 'locked')->rowActive()
+ ->exists();
+ }
+}
diff --git a/app/Models/ActivityProdusenCalculate.php b/app/Models/ActivityProdusenCalculate.php
new file mode 100644
index 0000000..f43d843
--- /dev/null
+++ b/app/Models/ActivityProdusenCalculate.php
@@ -0,0 +1,18 @@
+ 'datetime',
+ 'finished_time' => 'datetime',
+ ];
+}
diff --git a/app/Models/Adaptation.php b/app/Models/Adaptation.php
new file mode 100644
index 0000000..267b639
--- /dev/null
+++ b/app/Models/Adaptation.php
@@ -0,0 +1,33 @@
+ 'string',
+ 'is_active' => 'bool'
+ ];
+
+ protected $fillable = [
+ 'id',
+ 'sector',
+ 'sub_sector',
+ 'kategori_aksi',
+ 'jenis_aksi',
+ 'aksi',
+ 'is_active',
+ 'created_by',
+ 'updated_by'
+ ];
+}
\ No newline at end of file
diff --git a/app/Models/Agency.php b/app/Models/Agency.php
new file mode 100644
index 0000000..636ccc3
--- /dev/null
+++ b/app/Models/Agency.php
@@ -0,0 +1,27 @@
+hasMany(User::class);
+ }
+
+ public function userGroup()
+ {
+ return $this->belongsTo(UserGroup::class, 'user_group_id', 'id');
+ }
+
+ public function agencyActivity()
+ {
+ return $this->hasMany(AgencyActivity::class);
+ }
+}
diff --git a/app/Models/AgencyActivity.php b/app/Models/AgencyActivity.php
new file mode 100644
index 0000000..6a57042
--- /dev/null
+++ b/app/Models/AgencyActivity.php
@@ -0,0 +1,35 @@
+belongsTo(SettingForm::class, 'form_code', 'code')
+ ->where('form_sector', $this->form_sector);
+ }
+
+ public function agency()
+ {
+ return $this->belongsTo(Agency::class, 'agency_id', 'id');
+ }
+
+ public function getKeyName()
+ {
+ return $this->primaryKey;
+ }
+}
diff --git a/app/Models/Agriculture3A.php b/app/Models/Agriculture3A.php
new file mode 100644
index 0000000..2c0a5a8
--- /dev/null
+++ b/app/Models/Agriculture3A.php
@@ -0,0 +1,21 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Agriculture3A2b.php b/app/Models/Agriculture3A2b.php
new file mode 100644
index 0000000..fad9de2
--- /dev/null
+++ b/app/Models/Agriculture3A2b.php
@@ -0,0 +1,22 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Agriculture3C1.php b/app/Models/Agriculture3C1.php
new file mode 100644
index 0000000..edbaa07
--- /dev/null
+++ b/app/Models/Agriculture3C1.php
@@ -0,0 +1,20 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Agriculture3C3.php b/app/Models/Agriculture3C3.php
new file mode 100644
index 0000000..9ab4672
--- /dev/null
+++ b/app/Models/Agriculture3C3.php
@@ -0,0 +1,18 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Agriculture3C4.php b/app/Models/Agriculture3C4.php
new file mode 100644
index 0000000..e648fa7
--- /dev/null
+++ b/app/Models/Agriculture3C4.php
@@ -0,0 +1,19 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/BaselineDataMitigation.php b/app/Models/BaselineDataMitigation.php
new file mode 100644
index 0000000..1493a88
--- /dev/null
+++ b/app/Models/BaselineDataMitigation.php
@@ -0,0 +1,36 @@
+belongsTo(Mitigation::class, 'mitigation_id');
+ }
+}
\ No newline at end of file
diff --git a/app/Models/Calculation.php b/app/Models/Calculation.php
new file mode 100644
index 0000000..7d840ad
--- /dev/null
+++ b/app/Models/Calculation.php
@@ -0,0 +1,54 @@
+ 'datetime',
+ 'finished_time' => 'datetime',
+ ];
+
+ public function getSectorAttribute()
+ {
+ $tags = [];
+
+ // $badgeStyle = 'font-size: 10px; padding: 8px;';
+ $badgeStyle = '';
+
+ if ($this->energy) {
+ $tags[] = 'ENERGI';
+ }
+ if ($this->agriculture) {
+ $tags[] = 'PERTANIAN';
+ }
+ if ($this->folu) {
+ $tags[] = 'LAHAN';
+ }
+ if ($this->waste) {
+ $tags[] = 'LIMBAH';
+ }
+ if ($this->ippu) {
+ $tags[] = 'IPPU';
+ }
+
+ return implode(' ', $tags);
+ }
+}
diff --git a/app/Models/CmsFileDataAktivitas.php b/app/Models/CmsFileDataAktivitas.php
new file mode 100644
index 0000000..456bda9
--- /dev/null
+++ b/app/Models/CmsFileDataAktivitas.php
@@ -0,0 +1,35 @@
+belongsTo(ReferenceSector::class, 'sector', 'code');
+ }
+
+ public function subSector()
+ {
+ return $this->belongsTo(ReferenceSubSector::class, 'sub_sector', 'code');
+ }
+
+ public function creator()
+ {
+ return $this->belongsTo(User::class, 'created_by', 'name');
+ }
+}
diff --git a/app/Models/CmsFilePeraturan.php b/app/Models/CmsFilePeraturan.php
new file mode 100644
index 0000000..5765926
--- /dev/null
+++ b/app/Models/CmsFilePeraturan.php
@@ -0,0 +1,11 @@
+belongsTo(Mitigation::class, 'mitigation_id');
+ }
+}
\ No newline at end of file
diff --git a/app/Models/EmissionFactorMitigation.php b/app/Models/EmissionFactorMitigation.php
new file mode 100644
index 0000000..908f692
--- /dev/null
+++ b/app/Models/EmissionFactorMitigation.php
@@ -0,0 +1,37 @@
+belongsTo(Mitigation::class, 'mitigation_id');
+ }
+}
\ No newline at end of file
diff --git a/app/Models/EmissionFactorReference.php b/app/Models/EmissionFactorReference.php
new file mode 100644
index 0000000..a845b07
--- /dev/null
+++ b/app/Models/EmissionFactorReference.php
@@ -0,0 +1,31 @@
+ 'float'
+ ];
+
+ protected $keyType = 'string';
+ public $incrementing = false;
+
+ public $timestamps = true;
+ const CREATED_AT = 'created_at';
+ const UPDATED_AT = 'updated_at';
+}
\ No newline at end of file
diff --git a/app/Models/EmissionReductionMitigation.php b/app/Models/EmissionReductionMitigation.php
new file mode 100644
index 0000000..460a2af
--- /dev/null
+++ b/app/Models/EmissionReductionMitigation.php
@@ -0,0 +1,35 @@
+belongsTo(Mitigation::class, 'mitigation_id');
+ }
+}
\ No newline at end of file
diff --git a/app/Models/Energy1A.php b/app/Models/Energy1A.php
new file mode 100644
index 0000000..cfd6432
--- /dev/null
+++ b/app/Models/Energy1A.php
@@ -0,0 +1,22 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/EnergyGpcI13.php b/app/Models/EnergyGpcI13.php
new file mode 100644
index 0000000..20f7a11
--- /dev/null
+++ b/app/Models/EnergyGpcI13.php
@@ -0,0 +1,19 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/EnergyGpcI41.php b/app/Models/EnergyGpcI41.php
new file mode 100644
index 0000000..3671138
--- /dev/null
+++ b/app/Models/EnergyGpcI41.php
@@ -0,0 +1,20 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/EnergyGpcI42.php b/app/Models/EnergyGpcI42.php
new file mode 100644
index 0000000..33c199f
--- /dev/null
+++ b/app/Models/EnergyGpcI42.php
@@ -0,0 +1,19 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/EnergyGpcI51.php b/app/Models/EnergyGpcI51.php
new file mode 100644
index 0000000..edbbdd6
--- /dev/null
+++ b/app/Models/EnergyGpcI51.php
@@ -0,0 +1,20 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/EnergyPLN.php b/app/Models/EnergyPLN.php
new file mode 100644
index 0000000..441ed93
--- /dev/null
+++ b/app/Models/EnergyPLN.php
@@ -0,0 +1,19 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Folu3B.php b/app/Models/Folu3B.php
new file mode 100644
index 0000000..1a1af8c
--- /dev/null
+++ b/app/Models/Folu3B.php
@@ -0,0 +1,19 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Ippu1A.php b/app/Models/Ippu1A.php
new file mode 100644
index 0000000..9a6df4d
--- /dev/null
+++ b/app/Models/Ippu1A.php
@@ -0,0 +1,34 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Kabupaten.php b/app/Models/Kabupaten.php
new file mode 100644
index 0000000..7a73be9
--- /dev/null
+++ b/app/Models/Kabupaten.php
@@ -0,0 +1,20 @@
+ 'array',
+ 'emission_factor' => 'float'
+ ];
+
+ public function sumberData()
+ {
+ return $this->hasMany(SumberDataMitigasi::class, 'kegiatan_mitigasi_id', 'id');
+ }
+
+ public function activityDataMitigasi()
+ {
+ return $this->hasMany(ActivityDataMitigationForm::class, 'kegiatan_mitigasi_id', 'id');
+ }
+}
diff --git a/app/Models/Kelurahan.php b/app/Models/Kelurahan.php
new file mode 100644
index 0000000..3cc362a
--- /dev/null
+++ b/app/Models/Kelurahan.php
@@ -0,0 +1,22 @@
+belongsTo(ActivityForm::class, 'form_id', 'id');
+ // }
+
+ // public function unit()
+ // {
+ // return $this->belongsTo(Unit::class, 'activity_unit_code', 'code');
+ // }
+}
diff --git a/app/Models/LogUserActivity.php b/app/Models/LogUserActivity.php
new file mode 100644
index 0000000..0495eac
--- /dev/null
+++ b/app/Models/LogUserActivity.php
@@ -0,0 +1,22 @@
+belongsTo(User::class, 'user_id');
+ }
+
+ public function form()
+ {
+ return $this->belongsTo(ActivityForm::class, 'form_id', 'id');
+ }
+}
diff --git a/app/Models/Mitigation.php b/app/Models/Mitigation.php
new file mode 100644
index 0000000..5ec2248
--- /dev/null
+++ b/app/Models/Mitigation.php
@@ -0,0 +1,34 @@
+ 'string',
+ 'is_active' => 'bool'
+ ];
+
+ protected $fillable = [
+ 'id',
+ 'sector',
+ 'sub_sector',
+ 'activity_type',
+ 'activity_desc',
+ 'sub_activity',
+ 'sub_activity_desc',
+ 'is_active',
+ 'created_by',
+ 'updated_by'
+ ];
+}
diff --git a/app/Models/MitigationRendahKarbonDaerah.php b/app/Models/MitigationRendahKarbonDaerah.php
new file mode 100644
index 0000000..1b76415
--- /dev/null
+++ b/app/Models/MitigationRendahKarbonDaerah.php
@@ -0,0 +1,21 @@
+belongsTo(UserGroup::class);
+ }
+
+ public function menu()
+ {
+ return $this->belongsTo(Menu::class);
+ }
+}
diff --git a/app/Models/ReferenceActivity.php b/app/Models/ReferenceActivity.php
new file mode 100644
index 0000000..2fadab3
--- /dev/null
+++ b/app/Models/ReferenceActivity.php
@@ -0,0 +1,12 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+
+ public function efSource()
+ {
+ return $this->belongsTo(ReferenceEfSource::class, 'ef_source_code', 'code');
+ }
+
+ public function scopeGetValue($query, $activityCode, $category, $tag1 = null, $tag2 = null, $tag3 = null)
+ {
+ $output = $query->rowActive()->where('active_status', 1)
+ ->where('activity_code', $activityCode)->where('category', $category)
+ ->where('tag_1', $tag1)->where('tag_2', $tag2)->where('tag_3', $tag3)
+ ->first();
+
+ return $output ? $output->value : 0;
+ }
+}
diff --git a/app/Models/ReferenceEfSource.php b/app/Models/ReferenceEfSource.php
new file mode 100644
index 0000000..b07fc04
--- /dev/null
+++ b/app/Models/ReferenceEfSource.php
@@ -0,0 +1,11 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+
+ public function factorSource()
+ {
+ return $this->belongsTo(ReferenceFactorSource::class, 'factor_source_code', 'code');
+ }
+}
diff --git a/app/Models/ReferenceFactorSource.php b/app/Models/ReferenceFactorSource.php
new file mode 100644
index 0000000..d5ef179
--- /dev/null
+++ b/app/Models/ReferenceFactorSource.php
@@ -0,0 +1,11 @@
+belongsTo(ReferenceGhg::class, 'ghg_code', 'code');
+ }
+
+ public function ar()
+ {
+ return $this->belongsTo(ReferenceAr::class, 'ar_code', 'code');
+ }
+}
diff --git a/app/Models/ReferenceSector.php b/app/Models/ReferenceSector.php
new file mode 100644
index 0000000..e4ba44b
--- /dev/null
+++ b/app/Models/ReferenceSector.php
@@ -0,0 +1,12 @@
+belongsTo(ReferenceSector::class, 'sector_code', 'code');
+ }
+}
diff --git a/app/Models/ReferenceUnit.php b/app/Models/ReferenceUnit.php
new file mode 100644
index 0000000..a95bc8d
--- /dev/null
+++ b/app/Models/ReferenceUnit.php
@@ -0,0 +1,11 @@
+belongsTo(ReferenceUnit::class, 'from_unit_code', 'code');
+ }
+
+ public function toUnit()
+ {
+ return $this->belongsTo(ReferenceUnit::class, 'to_unit_code', 'code');
+ }
+}
diff --git a/app/Models/ReferenceWs.php b/app/Models/ReferenceWs.php
new file mode 100644
index 0000000..c8872e5
--- /dev/null
+++ b/app/Models/ReferenceWs.php
@@ -0,0 +1,43 @@
+whereNull('parent_ws_code');
+ }
+
+ public function scopeIsSub($query)
+ {
+ $wsCode = ['3A2', '3C1', '4A1', '4D1'];
+ return $query->whereNotNull('parent_ws_code')->whereNotIn('ws_code', $wsCode);
+ }
+
+ public function parent(): BelongsTo
+ {
+ return $this->belongsTo(ReferenceWs::class, 'parent_ws_code', 'ws_code');
+ }
+
+ public function children(): HasMany
+ {
+ return $this->hasMany(ReferenceWs::class, 'parent_ws_code', 'ws_code');
+ }
+
+ public function form()
+ {
+ return $this->belongsTo(SettingForm::class, 'code', 'code');
+ }
+}
diff --git a/app/Models/SettingForm.php b/app/Models/SettingForm.php
new file mode 100644
index 0000000..8fedcbe
--- /dev/null
+++ b/app/Models/SettingForm.php
@@ -0,0 +1,69 @@
+ $sector) {
+ $caseStatement .= "WHEN sector = '{$sector}' THEN {$index} ";
+ }
+ $caseStatement .= "ELSE " . (count($order)) . " END";
+
+ $data = self::where('active_status', 1)->where('row_status', 1)
+ ->orderByRaw($caseStatement)->orderBy('row_num')
+ ->get()->toArray();
+
+ $groupedData = [];
+ foreach ($data as $item) {
+ $newData = self::getSectorCaption($item['sector']);
+
+ $sector = $newData;
+ if (!isset($groupedData[$sector])) {
+ $groupedData[$sector] = [];
+ }
+ $groupedData[$sector][] = $item;
+ }
+
+ return $groupedData;
+ }
+
+
+
+ private static function getSectorCaption($sector)
+ {
+ switch ($sector) {
+ case 'energy':
+ case 'energy_gpc':
+ return 'Energi';
+ case 'ippu':
+ return 'IPPU';
+ case 'agriculture':
+ return 'Pertanian';
+ case 'folu':
+ return 'Lahan';
+ case 'waste':
+ return 'Limbah';
+ default:
+ return ucfirst($sector);
+ }
+ }
+}
diff --git a/app/Models/SettingFormDetail.php b/app/Models/SettingFormDetail.php
new file mode 100644
index 0000000..0ae2fa0
--- /dev/null
+++ b/app/Models/SettingFormDetail.php
@@ -0,0 +1,27 @@
+belongsTo(SettingForm::class, 'form_code', 'code');
+ }
+
+ public function activity()
+ {
+ return $this->belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+
+ public function unit()
+ {
+ return $this->belongsTo(ReferenceUnit::class, 'unit_code', 'code');
+ }
+}
diff --git a/app/Models/SigdModel.php b/app/Models/SigdModel.php
new file mode 100644
index 0000000..dedbaaa
--- /dev/null
+++ b/app/Models/SigdModel.php
@@ -0,0 +1,57 @@
+where('row_status', 1);
+ }
+
+ public function scopeIsActive($query)
+ {
+ return $query->where('active_status', 1);
+ }
+
+ public function scopeOrderByRowNum($query)
+ {
+ $table = $this->getTable();
+ if (Schema::hasColumn($table, 'row_num')) {
+ return $query->orderBy('row_num', 'asc');
+ }
+ return $query;
+ }
+
+ // public function getValueAttribute($value)
+ // {
+ // $table = $this->getTable();
+ // if (Schema::hasColumn($table, 'value')) {
+ // $value = (float) $value; // Convert the value to a float to handle scientific notation
+ // $value = number_format($value, 10, ',', '.'); // Convert back to a string with custom formatting
+ // $value = rtrim(rtrim($value, '0'), ','); // Remove unnecessary zeros and trailing commas
+
+ // return $value;
+ // }
+ // return $value;
+ // }
+
+ // public function setValueAttribute($value)
+ // {
+ // $table = $this->getTable();
+ // if (Schema::hasColumn($table, 'value')) {
+ // $value = str_replace(',', '.', str_replace('.', '', $value)); // Remove any thousand separators and replace comma
+ // $this->attributes['value'] = $value;
+ // } else {
+ // $this->attributes['value'] = $value; // Handle default behavior if 'value' column does not exist
+ // }
+ // }
+}
diff --git a/app/Models/SumberDataMitigasi.php b/app/Models/SumberDataMitigasi.php
new file mode 100644
index 0000000..0b7ef9b
--- /dev/null
+++ b/app/Models/SumberDataMitigasi.php
@@ -0,0 +1,26 @@
+belongsTo(KegiatanMitigasi::class, 'kegiatan_mitigasi_id', 'id');
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index fc44b31..bc808bb 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -3,41 +3,25 @@
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
+
+use App\Notifications\ResetPassword;
+use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
-class User extends Authenticatable
+class User extends Authenticatable implements MustVerifyEmail
{
- /** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
- /**
- * The attributes that are mass assignable.
- *
- * @var list
- */
protected $fillable = [
- 'name',
- 'email',
- 'password',
+ 'name', 'email', 'password', 'user_group_id', 'agency_id', 'active_status',
];
- /**
- * The attributes that should be hidden for serialization.
- *
- * @var list
- */
protected $hidden = [
- 'password',
- 'remember_token',
+ 'password', 'remember_token',
];
- /**
- * Get the attributes that should be cast.
- *
- * @return array
- */
protected function casts(): array
{
return [
@@ -46,13 +30,23 @@ class User extends Authenticatable
];
}
- public function group()
+ public function sendPasswordResetNotification($token)
{
- return $this->belongsTo(\App\Models\Master\Group::class,'ms_group_id','MsGroupId');
+ $this->notify(new ResetPassword($token));
}
- public function instansi()
+ public function userGroup()
{
- return $this->belongsTo(\App\Models\InstansiUser::class,'id','user_id');
+ return $this->belongsTo(UserGroup::class);
+ }
+
+ public function agency()
+ {
+ return $this->belongsTo(Agency::class);
+ }
+
+ public function getScope(): string
+ {
+ return $this->agency->scope ?? '';
}
}
diff --git a/app/Models/UserGroup.php b/app/Models/UserGroup.php
new file mode 100644
index 0000000..61413f2
--- /dev/null
+++ b/app/Models/UserGroup.php
@@ -0,0 +1,20 @@
+hasMany(User::class);
+ }
+
+ public function permissions()
+ {
+ return $this->hasMany(Permission::class);
+ }
+}
\ No newline at end of file
diff --git a/app/Models/Waste4A.php b/app/Models/Waste4A.php
new file mode 100644
index 0000000..4953d88
--- /dev/null
+++ b/app/Models/Waste4A.php
@@ -0,0 +1,14 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Waste4APre.php b/app/Models/Waste4APre.php
new file mode 100644
index 0000000..9c13232
--- /dev/null
+++ b/app/Models/Waste4APre.php
@@ -0,0 +1,14 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Waste4B2.php b/app/Models/Waste4B2.php
new file mode 100644
index 0000000..e4c2e32
--- /dev/null
+++ b/app/Models/Waste4B2.php
@@ -0,0 +1,18 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Waste4C1.php b/app/Models/Waste4C1.php
new file mode 100644
index 0000000..5fdacf2
--- /dev/null
+++ b/app/Models/Waste4C1.php
@@ -0,0 +1,13 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Waste4C2b.php b/app/Models/Waste4C2b.php
new file mode 100644
index 0000000..a562e06
--- /dev/null
+++ b/app/Models/Waste4C2b.php
@@ -0,0 +1,13 @@
+belongsTo(ReferenceActivity::class, 'activity_code', 'code');
+ }
+}
diff --git a/app/Models/Waste4D1d.php b/app/Models/Waste4D1d.php
new file mode 100644
index 0000000..e5dac56
--- /dev/null
+++ b/app/Models/Waste4D1d.php
@@ -0,0 +1,14 @@
+hasMany(Menu::class,'parent_id','id');
+ }
+
+ public static function coreMenus($type, array $status = [1]): mixed
+ {
+ return Menu::where('parent_id', '=', 0)
+ ->where('menu_type', '=', $type)
+ ->whereIn('status', $status);
+ }
+
+ public static function coreMenusByParent($id, array $status = [1]): mixed
+ {
+ return Menu::where('parent_id', '=', $id)
+ ->whereIn('status', $status);
+ }
+
+ public static function getMenuByParentPosition($id, $type, array $active = [1], int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('parent_id', '=', $id)
+ ->where('menu_type', '=', $type)
+ ->whereIn('status', $active)
+ ->union(Menu::coreMenus($type, $active))
+ ->orderBy('ordering')
+ ->get();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 12:53
+ *
+ * @param $type
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getParentByType($type, int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('parent_id', '=', 0)
+ ->where('menu_type', '=', $type)
+ ->union(Menu::coreMenus($type))
+ ->orderBy('ordering')
+ ->get();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 18:07
+ *
+ * @param $type
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getMenuByYear($type, int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('parent_id', '=', 0)
+ ->where('menu_type', '=', $type)
+ ->where('status', '=', true)
+ ->orderBy('ordering')
+ ->get();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 12:54
+ *
+ * @param $type
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getParentByTypeStatus($type, int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('parent_id', '=', 0)
+ ->where('menu_type', '=', $type)
+ ->where('status', '=', true)
+ ->union(Menu::coreMenus($type))
+ ->orderBy('ordering')
+ ->get();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 12:54
+ *
+ * @param $id
+ * @param array $active
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getMenuByParent($id, array $active = [1], int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('parent_id', '=', $id)
+ ->union(Menu::coreMenusByParent($id, $active))
+ ->whereIn('status', $active)
+ ->orderBy('ordering')
+ ->get();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 14:54
+ *
+ * @param int $year
+ *
+ * @return mixed
+ */
+ public static function countMenuByYear(int $year): mixed
+ {
+ $model = Menu::where('status', '=', true);
+ return $model->count();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 12:55
+ *
+ * @param $id
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getActiveById($id, int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('id', '=', $id)
+ ->where('status', '=', true)
+ ->first();
+ }
+
+ /**
+ * @author alex.gz
+ * @created 08/12/2023 12:55
+ *
+ * @param $type
+ * @param int|null $year
+ *
+ * @return mixed
+ */
+ public static function getActiveByPosition($type, int $year = null): mixed
+ {
+ if ($year) {
+ $currYear = $year;
+ } else {
+ $currYear = date('Y');
+ }
+
+ return Menu::where('menu_type', '=', $type)
+ ->where('status', '=', true)
+ ->union(Menu::coreMenus($type))
+ ->orderBy('ordering')
+ ->get();
+ }
+}
diff --git a/app/ModelsOld/Master/Sektor.php b/app/ModelsOld/Master/Sektor.php
new file mode 100644
index 0000000..b15603f
--- /dev/null
+++ b/app/ModelsOld/Master/Sektor.php
@@ -0,0 +1,15 @@
+belongsTo(\App\Models\Master\Sektor::class,'ms_sektor_id');
+ }
+}
diff --git a/app/Models/SumberDataEF.php b/app/ModelsOld/SumberDataEF.php
similarity index 100%
rename from app/Models/SumberDataEF.php
rename to app/ModelsOld/SumberDataEF.php
diff --git a/app/Models/Unit.php b/app/ModelsOld/Unit.php
similarity index 100%
rename from app/Models/Unit.php
rename to app/ModelsOld/Unit.php
diff --git a/app/Models/UnitKonversi.php b/app/ModelsOld/UnitKonversi.php
similarity index 100%
rename from app/Models/UnitKonversi.php
rename to app/ModelsOld/UnitKonversi.php
diff --git a/app/ModelsOld/User.php b/app/ModelsOld/User.php
new file mode 100644
index 0000000..fc44b31
--- /dev/null
+++ b/app/ModelsOld/User.php
@@ -0,0 +1,58 @@
+ */
+ use HasFactory, Notifiable;
+
+ /**
+ * The attributes that are mass assignable.
+ *
+ * @var list
+ */
+ protected $fillable = [
+ 'name',
+ 'email',
+ 'password',
+ ];
+
+ /**
+ * The attributes that should be hidden for serialization.
+ *
+ * @var list
+ */
+ protected $hidden = [
+ 'password',
+ 'remember_token',
+ ];
+
+ /**
+ * Get the attributes that should be cast.
+ *
+ * @return array
+ */
+ protected function casts(): array
+ {
+ return [
+ 'email_verified_at' => 'datetime',
+ 'password' => 'hashed',
+ ];
+ }
+
+ public function group()
+ {
+ return $this->belongsTo(\App\Models\Master\Group::class,'ms_group_id','MsGroupId');
+ }
+
+ public function instansi()
+ {
+ return $this->belongsTo(\App\Models\InstansiUser::class,'id','user_id');
+ }
+}
diff --git a/app/Notifications/EmailVerificationNotification.php b/app/Notifications/EmailVerificationNotification.php
new file mode 100644
index 0000000..0f98dac
--- /dev/null
+++ b/app/Notifications/EmailVerificationNotification.php
@@ -0,0 +1,41 @@
+ $notifiable->getKey(),
+ 'hash' => sha1($notifiable->email)
+ ]
+ );
+
+ return (new MailMessage)
+ ->subject('Harap Verifikasi Alamat Email Baru Anda')
+ ->greeting('Halo, ' . Auth::user()->name ?? 'User')
+ ->line('Anda telah berhasil memperbarui alamat email Anda. Silakan klik tombol berikut untuk memverifikasi email Anda:')
+ ->action('Verifikasi Email', $url)
+ ->line('Jika Anda tidak merasa memperbarui email ini, Anda tidak perlu melakukan tindakan apapun.')
+ ->salutation('Salam, Tim SIGD');
+ }
+}
diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php
new file mode 100644
index 0000000..6b84d14
--- /dev/null
+++ b/app/Notifications/ResetPassword.php
@@ -0,0 +1,52 @@
+token = $token;
+ }
+
+ public function via($notifiable)
+ {
+ return ['mail'];
+ }
+
+ public function toMail($notifiable)
+ {
+ $url = URL::route('password.showReset', [
+ 'token' => $this->token,
+ 'email' => $notifiable->getEmailForPasswordReset()
+ ]);
+
+ return (new MailMessage)
+ ->subject('SIGD - Notifikasi Reset Password')
+ ->line('Anda menerima email ini karena kami menerima permintaan reset kata sandi untuk akun Anda. Silahkan klik tombol berikut untuk melakukan reset password:')
+ ->action('Reset Password', $url)
+ ->line('Link password reset ini akan kedaluwarsa dalam waktu :count menit.', ['count' => Config::get('auth.passwords.' . config('auth.defaults.passwords') . '.expire')])
+ ->line('Jika Anda tidak merasa melakukan permintaan reset ini, Anda tidak perlu melakukan tindakan apapun')
+ ->salutation('Salam, Tim SIGD');
+ }
+
+
+ public function toArray($notifiable)
+ {
+ return [
+ //
+ ];
+ }
+}
diff --git a/app/Observers/ActivityCrfObserver.php b/app/Observers/ActivityCrfObserver.php
new file mode 100644
index 0000000..1bde702
--- /dev/null
+++ b/app/Observers/ActivityCrfObserver.php
@@ -0,0 +1,33 @@
+getGWPValues();
+
+ $co2eq =
+ ($crf->co2 ? $crf->co2 * $gwp['CO2']->value : 0) +
+ ($crf->ch4 ? $crf->ch4 * $gwp['CH4']->value : 0) +
+ ($crf->n2o ? $crf->n2o * $gwp['N2O']->value : 0);
+
+ $crf->gwp_co2 = $gwp['CO2']->value;
+ $crf->gwp_ch4 = $gwp['CH4']->value;
+ $crf->gwp_n2o = $gwp['N2O']->value;
+ $crf->co2eq = $co2eq;
+ }
+
+ protected function getGWPValues()
+ {
+ $gwp = ReferenceGwp::whereHas('ar', function ($query) {
+ $query->isActive();
+ })->get();
+
+ return $gwp->keyBy('ghg_code');
+ }
+}
diff --git a/app/Observers/ActivityGpcObserver.php b/app/Observers/ActivityGpcObserver.php
new file mode 100644
index 0000000..ceff639
--- /dev/null
+++ b/app/Observers/ActivityGpcObserver.php
@@ -0,0 +1,33 @@
+getGWPValues();
+
+ $co2eq =
+ ($gpc->co2 ? $gpc->co2 * $gwp['CO2']->value : 0) +
+ ($gpc->ch4 ? $gpc->ch4 * $gwp['CH4']->value : 0) +
+ ($gpc->n2o ? $gpc->n2o * $gwp['N2O']->value : 0);
+
+ $gpc->gwp_co2 = $gwp['CO2']->value;
+ $gpc->gwp_ch4 = $gwp['CH4']->value;
+ $gpc->gwp_n2o = $gwp['N2O']->value;
+ $gpc->co2eq = $co2eq;
+ }
+
+ protected function getGWPValues()
+ {
+ $gwp = ReferenceGwp::whereHas('ar', function ($query) {
+ $query->isActive();
+ })->get();
+
+ return $gwp->keyBy('ghg_code');
+ }
+}
diff --git a/app/Observers/ActivityGpcOutputObserver.php b/app/Observers/ActivityGpcOutputObserver.php
new file mode 100644
index 0000000..86fb2a5
--- /dev/null
+++ b/app/Observers/ActivityGpcOutputObserver.php
@@ -0,0 +1,36 @@
+calculateSum($gpc);
+ $gpcBasic = $gpcSum - ($gpc->i_4_4 ?? 0) - ($gpc->ii_3_3 ?? 0) - ($gpc->ii_4_3 ?? 0);
+ $gpc->gpc_basic = $gpcBasic;
+ }
+
+ private function calculateSum(ActivityGpcOutput $gpc)
+ {
+ $fieldsToSum = [
+ 'i_1_1', 'i_1_2', 'i_1_3', 'i_2_1', 'i_2_2', 'i_2_3', 'i_3_1', 'i_3_2', 'i_3_3', 'i_4_1',
+ 'i_4_2', 'i_4_3', 'i_4_4', 'i_5_1', 'i_5_2', 'i_5_3', 'i_6_1', 'i_6_2', 'i_6_3', 'i_7_1', 'i_8_1',
+ 'ii_1_1', 'ii_1_2', 'ii_1_3', 'ii_2_1', 'ii_2_2', 'ii_2_3', 'ii_3_1',
+ 'ii_3_2', 'ii_3_3', 'ii_4_1', 'ii_4_2', 'ii_4_3', 'ii_5_1', 'ii_5_2', 'ii_5_3',
+ 'iii_1_1', 'iii_1_2', 'iii_1_3', 'iii_2_1', 'iii_2_2', 'iii_2_3', 'iii_3_1', 'iii_3_2', 'iii_3_3',
+ 'iii_4_1', 'iii_4_2', 'iii_4_3', 'iv_1', 'iv_2', 'v_1', 'v_2', 'v_3', 'vi_1',
+ 'credits_i', 'credits_ii', 'credits_iii', 'credits_iv', 'credits_v', 'credits_vi',
+ ];
+
+ $sum = 0;
+
+ foreach ($fieldsToSum as $field) {
+ $sum += $gpc->$field ?? 0;
+ }
+
+ return $sum;
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 452e6b6..8e4bdb3 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -2,6 +2,12 @@
namespace App\Providers;
+use App\Models\ActivityCrf;
+use App\Models\ActivityGpc;
+use App\Models\ActivityGpcOutput;
+use App\Observers\ActivityCrfObserver;
+use App\Observers\ActivityGpcObserver;
+use App\Observers\ActivityGpcOutputObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@@ -9,16 +15,28 @@ class AppServiceProvider extends ServiceProvider
/**
* Register any application services.
*/
- public function register(): void
+ public function register()
{
- //
+ $this->app->bind(
+ \App\Repositories\ActivityDataRepository::class,
+ \App\Repositories\EloquentActivityDataRepository::class
+ );
+
+ // EmissionFactorRepository binding
+ $this->app->bind(
+ \App\Repositories\EmissionFactorRepository::class,
+ \App\Repositories\EloquentEmissionFactorRepository::class
+ );
}
+
/**
* Bootstrap any application services.
*/
public function boot(): void
{
- //
+ ActivityCrf::observe(ActivityCrfObserver::class);
+ ActivityGpcOutput::observe(ActivityGpcOutputObserver::class);
+ ActivityGpc::observe(ActivityGpcObserver::class);
}
}
diff --git a/app/Providers/RepositoryServiceProvider.php b/app/Providers/RepositoryServiceProvider.php
new file mode 100644
index 0000000..3984fa6
--- /dev/null
+++ b/app/Providers/RepositoryServiceProvider.php
@@ -0,0 +1,26 @@
+app->bind(ActivityDataRepository::class, EloquentActivityDataRepository::class);
+ $this->app->bind(EmissionFactorRepository::class, EloquentEmissionFactorRepository::class);
+ $this->app->bind(EmissionReductionRepository::class, EloquentEmissionReductionRepository::class);
+ $this->app->singleton(FormulaEvaluator::class, function() {
+ return new FormulaEvaluator();
+ });
+ }
+
+ public function boot() {}
+}
\ No newline at end of file
diff --git a/app/Repositories/ActivityDataRepository.php b/app/Repositories/ActivityDataRepository.php
new file mode 100644
index 0000000..b998be4
--- /dev/null
+++ b/app/Repositories/ActivityDataRepository.php
@@ -0,0 +1,10 @@
+where('kegiatan_mitigasi_id', $mitigationId)
+ ->select([
+ 'id',
+ 'kegiatan_mitigasi_id',
+ 'mitigation_id',
+ 'sequence',
+ 'value',
+ 'unit',
+ 'values_array',
+ 'type_emission_reduction',
+ ])
+ ->orderBy('sequence')
+ // ->query();
+ ->get();
+ }
+}
\ No newline at end of file
diff --git a/app/Repositories/EloquentEmissionFactorRepository.php b/app/Repositories/EloquentEmissionFactorRepository.php
new file mode 100644
index 0000000..85fb631
--- /dev/null
+++ b/app/Repositories/EloquentEmissionFactorRepository.php
@@ -0,0 +1,15 @@
+get(['sequence', 'unit', 'type', 'value', 'keterangan']);
+ }
+}
\ No newline at end of file
diff --git a/app/Repositories/EloquentEmissionReductionRepository.php b/app/Repositories/EloquentEmissionReductionRepository.php
new file mode 100644
index 0000000..1f419d4
--- /dev/null
+++ b/app/Repositories/EloquentEmissionReductionRepository.php
@@ -0,0 +1,28 @@
+model = $model;
+ }
+
+ public function findByMitigation(string $mitigationId, ?string $typeEmissionReduction = null): ?EmissionReductionMitigation
+ {
+ $q = $this->model->where('mitigation_id', $mitigationId);
+ if ($typeEmissionReduction) $q->where('type_emission_reduction', $typeEmissionReduction);
+ return $q->first();
+ }
+
+ // Tambahkan method ini untuk implementasi interface!
+ public function findAllByMitigation(string $mitigationId)
+ {
+ return $this->model->where('mitigation_id', $mitigationId)->orderBy('id')->get();
+ }
+}
diff --git a/app/Repositories/EmissionFactorRepository.php b/app/Repositories/EmissionFactorRepository.php
new file mode 100644
index 0000000..979bdd2
--- /dev/null
+++ b/app/Repositories/EmissionFactorRepository.php
@@ -0,0 +1,10 @@
+schema . '.' . $this->table)
+ $query = DB::table($this->table)
->where($this->column, $value);
return $query->exists();
diff --git a/app/Rules/UniqueInSchema.php b/app/Rules/UniqueInSchema.php
index b701e65..39f49b3 100644
--- a/app/Rules/UniqueInSchema.php
+++ b/app/Rules/UniqueInSchema.php
@@ -23,7 +23,7 @@ class UniqueInSchema implements ValidationRule
public function passes($attribute, $value)
{
- $query = DB::table($this->schema . '.' . $this->table)
+ $query = DB::table($this->table)
->where($this->column, $value);
if ($this->ignoreId !== null) {
diff --git a/app/Services/Activity/FormKehutananService.php b/app/Services/Activity/FormKehutananService.php
new file mode 100644
index 0000000..9cdc2ba
--- /dev/null
+++ b/app/Services/Activity/FormKehutananService.php
@@ -0,0 +1,179 @@
+where('form_code', $code)
+ ->where('inventory_year', $inventoryYear)
+ ->rowActive()
+ ->orderBy('inventory_year', 'desc');
+
+ if ($agency && $agency != 'none') {
+ if ($agency === 'all') {
+ // return $query->whereNotNull('agency_id')->get();
+ $produsen = $this->getDataApproval($sector, $code, $inventoryYear)
+ ->where('status', 1)->pluck('agency_id')->toArray();
+ return $query->whereIn('agency_id', $produsen);
+ }
+
+ return $query->where('agency_id', $agency)->first();
+ }
+
+ return $query->whereNull('agency_id')->first();
+ }
+
+
+ public function getActivityFormDetails($formId, $agency = null)
+ {
+ if ($agency == 'all') {
+ $results = ActivityFormDetail::whereIn('form_id', $formId)
+ ->rowActive()->groupBy('activity_year', 'activity_code', 'activity_unit_code')
+ ->selectRaw('activity_year, activity_code, activity_unit_code, sum(activity_value) as activity_value')
+ ->orderBy('activity_year', 'desc')->get();
+
+ return $results;
+ }
+
+ return ActivityFormDetail::where('form_id', $formId)
+ ->rowActive()->orderBy('activity_year', 'desc')
+ ->get();
+ }
+
+ public function save($sector, $code, $inventoryYear, $data, $instansi = null)
+ {
+ $query = ActivityForm::where('sector', $sector)
+ ->where('form_code', $code)->where('inventory_year', $inventoryYear)
+ ->whereNull('agency_id')->rowActive();
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $query->where('agency_id', $instansi);
+ } else {
+ $query->whereNull('agency_id');
+ }
+
+ $activityForm = $query->first();
+
+ try {
+ if (!$activityForm) {
+ $instansiId = $instansi === 'all' || $instansi === 'none' ? null : $instansi;
+ $dataForm = [
+ 'sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+
+ 'agency_id' => $instansiId,
+ ];
+
+ $activityForm = $this->create($dataForm);
+ logUserActivity(ActivityType::INSERT_ACTIVITY_DATA, $activityForm->id);
+ } else {
+ $this->update($activityForm, []);
+ logUserActivity(ActivityType::UPDATE_ACTIVITY_DATA, $activityForm->id);
+ }
+
+
+ foreach ($data as $activityCode => $activityValue) {
+ // if (collect($activityValue)->filter(function ($value) {
+ // return $value !== null;
+ // })->isNotEmpty()) {
+ $activityData = [
+ 'year' => $inventoryYear - 1,
+ 'code' => $activityCode,
+ 'value' => $activityValue ?? null
+ ];
+ $this->saveDetail($activityForm, $activityData);
+ // }
+ }
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function saveDetail($activityForm, $activityData)
+ {
+
+ $activityFormDetail = ActivityFormDetail::where('form_id', $activityForm->id)
+ ->where('activity_year', $activityData['year'])
+ ->where('activity_code', $activityData['code'])
+ ->rowActive()
+ ->first();
+
+ if (!empty($activityData['value'])) {
+ $newValue = getOriginalValue($activityData['value']);
+
+ if ($activityFormDetail) {
+ $oldValue = getFormattedValue($activityFormDetail->activity_value);
+
+ if ($oldValue != $activityData['value']) {
+ $this->update($activityFormDetail, ['activity_value' => $newValue]);
+ }
+ } else {
+ $dataFormDetail = [
+ 'form_id' => $activityForm->id,
+ 'activity_year' => $activityData['year'],
+ 'activity_code' => $activityData['code'],
+ 'activity_unit_code' => 'ha',
+ 'activity_value' => $newValue
+ ];
+
+ $this->create($dataFormDetail, ActivityFormDetail::class);
+ }
+ } else {
+ if ($activityFormDetail) {
+ $this->delete($activityFormDetail);
+ }
+ }
+ }
+
+ public function approvalKonsolidasi($form, $sector, $code, $inventoryYear, $agencyId)
+ {
+ $hasData = $this->getDataApproval($sector, $code, $inventoryYear, true)->where([
+ 'form_id' => $form->id,
+ 'agency_id' => $agencyId,
+ ])->rowActive()->first();
+
+ $newStatus = 1;
+ if ($hasData) {
+ $newStatus = $hasData->status == 1 ? 0 : 1;
+ }
+
+ $dataForm = [
+ 'form_id' => $form->id,
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'agency_id' => $agencyId,
+ 'status' => $newStatus,
+ ];
+
+ $this->createOrUpdate([
+ 'form_id' => $form->id,
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'agency_id' => $agencyId,
+ ], $dataForm, ActivityApprovalKonsolidasi::class);
+
+ $activityType = $newStatus == 1 ? ActivityType::APPROVAL_KONSOLIDASI : ActivityType::DISSAPPROVAL_KONSOLIDASI;
+ logUserActivity($activityType, $form->id);
+ }
+}
diff --git a/app/Services/Activity/FormMetadataService.php b/app/Services/Activity/FormMetadataService.php
new file mode 100644
index 0000000..7a1b08a
--- /dev/null
+++ b/app/Services/Activity/FormMetadataService.php
@@ -0,0 +1,65 @@
+where('id', $formId)->first();
+ if ($form) {
+ $storagePath = 'forms/' . $form->sector . '/' . $form->form_code . '/' . $form->inventory_year . '/metadata';
+
+ $metadata = null;
+ if (isset($data['id'])) {
+ $metadata = ActivityFormMetadata::rowActive()->find($data['id']);
+ }
+
+ if ($metadata) {
+ if (isset($data['file_document'])) {
+ $oldFilePath = $storagePath . '/' . $metadata->file_name;
+
+ if ($metadata->file_name != $data['file_document']->hashName()) {
+ Storage::disk('public')->delete($oldFilePath);
+ }
+
+ $data['file_name'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $this->update($metadata, $data);
+ } else {
+ if (isset($data['file_document'])) {
+ $data['file_name'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $metadata = $this->create($data);
+ }
+
+ logUserActivity(ActivityType::INSERT_METADATA, $formId);
+ return $metadata;
+ }
+ }
+
+ public function destroy(ActivityFormMetadata $metadata, $storagePath)
+ {
+ if ($metadata) {
+ $oldFilePath = $storagePath . '/' . $metadata->file_name;
+ Storage::disk('public')->delete($oldFilePath);
+
+ $this->delete($metadata);
+ logUserActivity(ActivityType::DELETE_METADATA, $metadata->form_id);
+ }
+ }
+}
diff --git a/app/Services/Activity/FormMitigasiService.php b/app/Services/Activity/FormMitigasiService.php
new file mode 100644
index 0000000..5185c1c
--- /dev/null
+++ b/app/Services/Activity/FormMitigasiService.php
@@ -0,0 +1,889 @@
+ 'volume',
+ 'kiloliter' => 'volume',
+ 'm3' => 'volume',
+ 'mmbtu' => 'energy',
+ 'mwh' => 'energy',
+ 'boe' => 'energy',
+ 'ton' => 'mass',
+ 'kilogram' => 'mass',
+ 'giga gram' => 'mass',
+ ];
+
+ protected array $unitConversionFactor = [
+ 'liter' => 0.000000001,
+ 'kiloliter' => 0.001,
+ 'm3' => 0.001,
+ 'mmbtu' => 0.00105587,
+ 'mwh' => 0.0036,
+ 'boe' => 0.0058,
+ 'ton' => 0.001,
+ 'kilogram' => 0.000001,
+ 'giga gram' => 1.0,
+ ];
+
+ public function __construct(
+ protected ActivityDataRepository $adRepo,
+ protected EmissionFactorRepository $efRepo,
+ protected EmissionReductionRepository $erRepo,
+ protected FormulaEvaluator $evaluator
+ ) {}
+
+ protected function cast($v)
+ {
+ if (is_null($v)) return 0;
+ if (is_numeric($v)) return $v + 0;
+ if (is_string($v) && is_numeric(trim($v))) return trim($v) + 0;
+ return $v;
+ }
+
+ protected function selectReduction($reductions, $adValues, $typeEmissionReduction = null)
+ {
+ if (!$reductions) return null;
+ if (is_array($reductions)) {
+ $array = $reductions;
+ } elseif (method_exists($reductions, 'all')) {
+ $array = $reductions->all();
+ } else {
+ $array = (array)$reductions;
+ }
+
+ if (count($array) === 0) return null;
+ if (count($array) === 1) return $array[0];
+
+ if (!empty($adValues['AD1'])) {
+ $match = strtolower(trim($adValues['AD1']));
+ foreach ($array as $reduction) {
+ if($reduction['type_emission_reduction'] == 1 && $match == strtolower("PJU sebelumnya terkoneksi dengan lgrid")) {
+ return $reduction;
+ } else if ($reduction['type_emission_reduction'] == 2 && $match == strtolower("PJU sebelumnya terkoneksi dengan PLTD")) {
+ return $reduction;
+ }
+ }
+ }
+
+ if ($typeEmissionReduction !== null) {
+ foreach ($array as $reduction) {
+ $typeEr = is_array($reduction)
+ ? ($reduction['type_emission_reduction'] ?? null)
+ : ($reduction->type_emission_reduction ?? null);
+ if ((int)$typeEr === (int)$typeEmissionReduction) {
+ return $reduction;
+ }
+ }
+ }
+
+ return $array[0];
+ }
+
+ public function calculateAndPersist(string $mitigationId, KegiatanMitigasi $km): void
+ {
+ DB::transaction(function() use ($mitigationId, $km) {
+ logger()->info('--- calculateAndPersist start ---');
+ $adForms = $this->adRepo->getByMitigation($km->id);
+
+ $adValues = [];
+ $adArrays = [];
+ $adUnits = [];
+ $labelMap = [];
+ $typeEmissionReduction = null;
+ foreach ($adForms as $item) {
+ $key = 'AD' . $item->sequence;
+
+ $rawArray = $item->values_array ?: [];
+ if (!is_array($rawArray)) $rawArray = [];
+ if (empty($rawArray) || (count($rawArray) == 1 && $rawArray[0] === null)) {
+ $rawArray = [$item->value];
+ }
+
+ $values = array_map(fn($x) => $this->cast($x), $rawArray);
+ if (empty($values)) $values = [0];
+
+ $adArrays[$key] = $values;
+ $adValues[$key] = (is_array($values) && count($values) > 0) ? end($values) : 0;
+ $adUnits[$key] = strtolower($item->unit ?? '');
+
+ if (property_exists($item, 'label') && $item->label) {
+ $labelMap[$item->label] = $key;
+ }
+ if (!$typeEmissionReduction && !empty($item->type_emission_reduction)) {
+ $typeEmissionReduction = $item->type_emission_reduction;
+ }
+ }
+ logger()->info('ADValues', $adValues);
+ logger()->info('ADArrays', $adArrays);
+ logger()->info('ADUnits', $adUnits);
+ logger()->info('LabelMap', $labelMap);
+ logger()->info('TypeEmissionReduction', ['value' => $typeEmissionReduction]);
+
+ // Build REF_xxx mapping
+ $contextMaps = DB::table('activity.emission_reduction_context_map')
+ ->where('mitigation_id', $mitigationId)
+ ->get();
+
+ $refParams = [];
+ $refContext = [];
+ foreach ($contextMaps as $map) {
+ $adKey = 'AD'.$map->ad_sequence;
+ $val = $adValues[$adKey] ?? null;
+
+ $refParams[$map->ref_key] = [
+ 'param' => $map->param,
+ 'unit' => $map->unit,
+ 'context' => [ $map->context_field => $adKey ],
+ ];
+ if (!isset($refContext[$map->ref_key][$map->context_field]) || $refContext[$map->ref_key][$map->context_field] === null) {
+ if ($val !== null) {
+ $refContext[$map->ref_key][$map->context_field] = $val;
+ }
+ }
+ logger()->info('refContext build', [
+ 'ref_key' => $map->ref_key,
+ 'context_field' => $map->context_field,
+ 'ad_seq' => $map->ad_sequence,
+ 'value' => $val
+ ]);
+ }
+ logger()->info('refParams', $refParams);
+ logger()->info('refContext', $refContext);
+
+ $reductions = $this->erRepo->findAllByMitigation($mitigationId);
+ if (is_object($reductions) && method_exists($reductions, 'toArray')) {
+ logger()->info('DEBUG: REDUCTIONS', $reductions->toArray());
+ } else {
+ logger()->info('DEBUG: REDUCTIONS', (array) $reductions);
+ }
+ logger()->info('REDUCTIONS RAW TYPE', ['type' => gettype($reductions), 'class' => is_object($reductions) ? get_class($reductions) : null]);
+
+ // --- PEMILIHAN REDUCTION PAKE LOGIC BARU ---
+ $chosenReduction = $this->selectReduction($reductions, $adValues, $typeEmissionReduction);
+ if (!$chosenReduction) {
+ logger()->error('REDUCTIONS EMPTY', [
+ 'reductions' => is_object($reductions) ? $reductions->toArray() : $reductions
+ ]);
+ throw new \Exception('Emission reduction formula not found.');
+ }
+
+ $formula = ltrim(is_array($chosenReduction) ? $chosenReduction['emission_reduction'] : $chosenReduction->emission_reduction, '=');
+ logger()->info('FORMULA RAW', ['formula' => $formula]);
+ logger()->info('FORMULA AFTER REF_CF', ['formula' => $formula]);
+
+ $result = $this->evaluateEmissionReductionFormula(
+ $formula,
+ $adValues,
+ $refParams,
+ $refContext,
+ $adArrays,
+ $adUnits,
+ $labelMap
+ );
+ logger()->info('HASIL PERHITUNGAN', ['emission_factor' => $result]);
+ $km->update(['emission_factor' => $result]);
+ logger()->info('--- calculateAndPersist DONE ---');
+ });
+ }
+
+ protected function getRefArray($param, $unit, $context, $adArrays, $adKeySigma)
+ {
+ $arr = [];
+ $adSource = $adArrays[$adKeySigma] ?? [];
+ foreach ($adSource as $i => $v) {
+ $q = \App\Models\EmissionFactorReference::where('param', $param)
+ ->where('unit', $unit);
+ foreach ($context as $field => $adKey) {
+ $q->where('keterangan', $v);
+ }
+ $arr[] = $q->value('value') ?? 0;
+ }
+ return $arr;
+ }
+
+ /**
+ * Parse Σi=ADx*ADy menjadi sum produk per baris.
+ * Contoh: Σi=AD1*AD2 → (AD1[0]*AD2[0]) + (AD1[1]*AD2[1]) + ...
+ * @param string $formula
+ * @param array $adArrays
+ * @param array $adValues
+ * @param string $debugTag
+ * @return string
+ */
+ public function parseSigmaSumProduct($formula, $adArrays, $adValues, $refParams, $refContext, $debugTag = '')
+ {
+ logger()->info("Masuk $debugTag", ['formula' => $formula]);
+
+ return preg_replace_callback(
+ '/Σi=(([A-Za-z0-9_\.]+|\Σi=[A-Za-z0-9_\.]+)(\s*[\*\/]\s*([A-Za-z0-9_\.]+|\Σi=[A-Za-z0-9_\.]+))+)/u',
+ function ($m) use ($adArrays, $adValues, $refParams, $refContext) {
+ $raw = $m[1];
+ $parts = preg_split('/\s*[\*\/]\s*/', $raw);
+ preg_match_all('/[\*\/]/', $raw, $opsRaw);
+ $ops = $opsRaw[0];
+
+ $arrays = [];
+ $maxRows = 1;
+
+ foreach ($parts as $p) {
+ $p = preg_replace('/^Σi=/', '', $p);
+
+ // AD array
+ if (isset($adArrays[$p]) && is_array($adArrays[$p]) && count($adArrays[$p]) > 1) {
+ $arr = array_map('floatval', $adArrays[$p]);
+ }
+ // REF array (array dari replaceREF as_array true)
+ else if (preg_match('/^REF_([A-Z0-9_]+)$/i', $p, $mm)) {
+ $refKey = $mm[1];
+ $arr = [0];
+ if (isset($refParams[$refKey])) {
+ $rawRef = $this->replaceREF("REF_$refKey", $refParams, $refContext, $adArrays, $adValues, [], '', true);
+ if (is_string($rawRef)) $rawRef = explode(',', $rawRef);
+ if (!is_array($rawRef)) $rawRef = [$rawRef];
+ $arr = array_map('floatval', $rawRef);
+ if (!$arr || count($arr) === 0) $arr = [0];
+ }
+ }
+ // Scalar (AD/REF satuan, angka, konstanta)
+ else if (isset($adArrays[$p]) && count($adArrays[$p]) === 1) {
+ $arr = [floatval($adArrays[$p][0])];
+ } else if (isset($adValues[$p])) {
+ $arr = [floatval($adValues[$p])];
+ } else if (is_numeric($p)) {
+ $arr = [floatval($p)];
+ } else {
+ $arr = [0];
+ }
+
+ $arrays[] = $arr;
+ $maxRows = max($maxRows, count($arr));
+ }
+
+ // Expand scalar ke semua baris jika perlu
+ foreach ($arrays as $i => $arr) {
+ if (count($arr) < $maxRows) {
+ $scalar = isset($arr[0]) ? $arr[0] : 0;
+ $arrays[$i] = array_fill(0, $maxRows, $scalar);
+ }
+ }
+
+ // SUMPRODUCT manual per baris
+ $sum = 0;
+ for ($i = 0; $i < $maxRows; $i++) {
+ $val = $arrays[0][$i];
+ for ($j = 1; $j < count($arrays); $j++) {
+ $op = $ops[$j - 1] ?? '*';
+ $v = $arrays[$j][$i];
+ if ($op == '*') $val *= $v;
+ else $val /= ($v != 0 ? $v : 1);
+ }
+ $sum += $val;
+ }
+ return (string)$sum;
+ },
+ $formula
+ );
+ }
+
+
+ /**
+ * Ganti semua blok SUMPRODUCT( … ) dengan hasil angka (Excel-like)
+ * - Support inner expression rumit, nested, pow, persen, kurung
+ * - Support AD/REF array, scalar, mixed, otomatis looping max row
+ * - Support nested SUMPRODUCT di dalam inner (rekursif)
+ * - Tidak support Σi=, Σj= (sigma): Khusus SUMPRODUCT saja
+ * @param string $formula
+ * @param array $adArrays
+ * @param array $adValues
+ * @param array $refParams
+ * @param array $refContext
+ * @return string
+ */
+ public function parseSumproductExcel($formula, $adArrays, $adValues, $refParams, $refContext)
+ {
+ // Selama masih ada SUMPRODUCT(
+ while (preg_match('/SUMPRODUCT\s*\(/i', $formula)) {
+ $formula = preg_replace_callback(
+ '/SUMPRODUCT\s*\(([^()]*(?:\((?:[^()]++|(?1))*\)[^()]*)*)\)/i',
+ function ($m) use ($adArrays, $adValues, $refParams, $refContext) {
+ $inner = $m[1];
+
+ // 1. Cari semua variabel array
+ preg_match_all('/\b(AD[0-9]+|REF_[A-Z0-9_]+)\b/', $inner, $matches);
+ $vars = array_unique($matches[1]);
+
+ // 2. Dapatkan max rows (array terpanjang)
+ $maxRows = 1;
+ foreach ($vars as $v) {
+ if (isset($adArrays[$v]) && is_array($adArrays[$v]))
+ $maxRows = max($maxRows, count($adArrays[$v]));
+ }
+
+ $sum = 0;
+ for ($i = 0; $i < $maxRows; $i++) {
+ // Ganti AD
+ $expr = preg_replace_callback('/AD([0-9]+)/', function($mm) use ($adArrays, $adValues, $i) {
+ $adKey = "AD".$mm[1];
+ return isset($adArrays[$adKey][$i]) ? $adArrays[$adKey][$i] :
+ (isset($adArrays[$adKey][0]) ? $adArrays[$adKey][0] : (isset($adValues[$adKey]) ? $adValues[$adKey] : 0));
+ }, $inner);
+
+ // Ganti REF
+ $expr = preg_replace_callback('/REF_([A-Z0-9_]+)/', function($mm) use ($refParams, $refContext, $adArrays, $adValues, $i) {
+ $key = $mm[1];
+ if (!isset($refParams[$key])) return 0;
+ $map = $refParams[$key];
+ $contextKey = null;
+ foreach ($map['context'] as $field => $adKeyC) {
+ $contextKey = $adKeyC;
+ }
+ $adVal = $contextKey && isset($adArrays[$contextKey][$i]) ? $adArrays[$contextKey][$i] : ($adValues[$contextKey] ?? null);
+ $q = \App\Models\EmissionFactorReference::where('param', $map['param'])
+ ->where('unit', $map['unit'])
+ ->where('keterangan', $adVal);
+ $val = $q->value('value');
+ return $val ?? 0;
+ }, $expr);
+
+ // Ganti persen & pow
+ $expr = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1]/100, $expr);
+ $expr = preg_replace('/([0-9.Ee+\-]+)\s*\^\s*([0-9.Ee+\-]+)/', 'pow($1,$2)', $expr);
+
+ // Eval tiap baris, tambahkan ke sum
+ $expr = str_replace('CONST_', '', $expr);
+
+ // Special case
+ if (strpos($expr, 'SUM(') !== false) {
+ foreach (['AD3', 'AD4'] as $adKey) {
+ if (strpos($expr, "SUM($adKey)") !== false && isset($adArrays[$adKey])) {
+ $expr = str_replace("SUM($adKey)", array_sum($adArrays[$adKey]), $expr);
+ }
+ }
+ // Tambah di sini:
+ $expr = preg_replace('/SUM\(\s*([0-9\.]+)\s*\)/', '$1', $expr);
+
+ // Opsional: hapus SUM lain
+ $expr = str_replace('SUM', '', $expr);
+ }
+
+ try {
+ $sum += eval('return ' . $expr . ';');
+ } catch (\Throwable $e) {
+ logger()->error("[SUMPRODUCT] Eval row $i error: $expr | " . $e->getMessage());
+ }
+ }
+ return (string)$sum;
+ },
+ $formula
+ );
+ }
+ return $formula;
+ }
+
+ public function isSigmaArrayFormula($formula, $adArrays, $refParams) {
+ if (strpos($formula, 'Σi=') === false) return false;
+
+ // Ambil semua yang dalam Σi=(....)
+ if (preg_match('/Σi=\(([^)]+)\)/', $formula, $sumproductPart)) {
+ // Semua variabel AD/REF/CONST
+ preg_match_all('/\b(AD[0-9]+|REF_[A-Z0-9_]+)\b/', $sumproductPart[1], $vars);
+ foreach ($vars[1] as $var) {
+ if (isset($adArrays[$var]) && is_array($adArrays[$var]) && count($adArrays[$var]) > 1) return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Ganti Σi=ADxx dengan hasil sum seluruh array ADxx.
+ * Contoh: Σi=AD1 → 19 (jika [10,5,4])
+ */
+ public function parseSigmaSumOnly($formula, $adArrays, $adValues, $refParams = [], $refContext = [], $debugTag = '')
+ {
+ logger()->info("Masuk $debugTag", ['formula' => $formula]);
+
+ $self = $this; // Closure binding
+
+ // Σi=ADxx atau Σi=REF_xxx
+ $formula = preg_replace_callback('/[Σ∑]i\s*=?\s*([A-Za-z0-9_]+)/u', function ($m) use ($adArrays, $adValues, $refParams, $refContext, $self) {
+ $key = $m[1];
+ // Handle AD array
+ if (isset($adArrays[$key])) {
+ $arr = $adArrays[$key];
+ if (count($arr) === 0 && isset($adValues[$key])) $arr = [$adValues[$key]];
+ $sum = array_sum(array_filter($arr, 'is_numeric'));
+ logger()->info("parseSigmaSumOnly: SUM for $key", ['array' => $arr, 'sum' => $sum]);
+ return $sum;
+ }
+ // Handle REF_xxx (ambil array REF, lalu sum)
+ elseif (preg_match('/^REF_([A-Z0-9_]+)$/i', $key, $mm)) {
+ $refKey = $mm[1];
+ // Pakai replaceREF tapi as_array=true!
+ $refArr = $self->replaceREF(
+ "REF_$refKey",
+ $refParams,
+ $refContext,
+ $adArrays,
+ $adValues,
+ [], // adUnits
+ 'parseSigmaSumOnly_REF',
+ true // AS ARRAY
+ );
+ if (is_string($refArr)) {
+ $refArr = explode(',', $refArr);
+ }
+ if (!is_array($refArr)) $refArr = [$refArr];
+ $arr = array_map('floatval', $refArr);
+ if (!$arr || count($arr) === 0) $arr = [0];
+ $sum = array_sum(array_filter($refArr, 'is_numeric'));
+ logger()->info("parseSigmaSumOnly: SUM for REF $key", ['array' => $refArr, 'sum' => $sum]);
+ return $sum;
+ }
+ // Scalar fallback
+ elseif (isset($adValues[$key]) && is_numeric($adValues[$key])) {
+ return $adValues[$key];
+ }
+ return 0;
+ }, $formula);
+
+ return $formula;
+ }
+
+ /**
+ * Evaluate the emission reduction formula with given parameters.
+ */
+ // public function evaluateEmissionReductionFormula($formula, $adValues, $refParams, $refContext, $adArrays, $adUnits = [], $labelMap = []) {
+ // logger()->info("evaluateEmissionReductionFormula: START", ['formula' => $formula]);
+
+ // if ($this->isSigmaArrayFormula($formula, $adArrays, $refParams)) {
+ // // Hitung maxRows DARI variabel dalam Σi
+ // preg_match('/Σi=\(([^)]+)\)/', $formula, $m);
+ // preg_match_all('/\b(AD[0-9]+|REF_[A-Z0-9_]+)\b/', $m[1] ?? '', $vars);
+ // $maxRows = 1;
+ // foreach ($vars[1] as $var) {
+ // if (isset($adArrays[$var]) && is_array($adArrays[$var]))
+ // $maxRows = max($maxRows, count($adArrays[$var]));
+ // }
+
+ // $resultRows = [];
+ // for ($i = 0; $i < $maxRows; $i++) {
+ // // Build per baris
+ // $adValuesRow = [];
+ // $adArraysRow = [];
+ // foreach ($adArrays as $key => $arr) {
+ // $adArraysRow[$key] = [isset($arr[$i]) ? $arr[$i] : (isset($arr[0]) ? $arr[0] : 0)];
+ // $adValuesRow[$key] = isset($arr[$i]) ? $arr[$i] : (isset($arr[0]) ? $arr[0] : 0);
+ // }
+ // $f = $this->parseSigmaSumProduct($formula, $adArraysRow, $adValuesRow, $refParams, $refContext, "row-$i-parseSigmaSumProduct");
+ // $f = $this->parseSigmaSumOnly($f, $adArraysRow, $adValuesRow, $refParams, $refContext, "row-$i-parseSigmaSumOnly");
+ // $f = $this->replaceADDefault($f, $adArraysRow, $adValuesRow, "row-$i-replaceADDefault");
+ // $f = $this->replaceREF($f, $refParams, $refContext, $adArraysRow, $adValuesRow, $adUnits, "row-$i-replaceREF", false);
+
+ // $f = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1] / 100, $f);
+ // $f = preg_replace('/([A-Za-z0-9_\.]+)\^([0-9]+)/', 'pow($1,$2)', $f);
+
+ // // Clean up kurung, biar ga unmatched
+ // $f = preg_replace('/\)\)+$/', ')', $f);
+ // $open = substr_count($f, '('); $close = substr_count($f, ')');
+ // if ($open > $close) $f .= str_repeat(')', $open - $close);
+ // if ($close > $open) $f = str_repeat('(', $close - $open) . $f;
+
+ // // Remove sigma
+ // $f = preg_replace('/^(b")?([Σ∑Î]i=)/u', '', $f);
+ // logger()->info("BARIS $i - Formula Final Eval", ['formula' => $f]);
+ // try {
+ // $res = eval('return ' . $f . ';');
+ // $resultRows[] = $res;
+ // } catch (\Throwable $e) {
+ // logger()->error("Eval error BARIS $i: $f | " . $e->getMessage());
+ // $resultRows[] = 0;
+ // }
+ // }
+ // $result = array_sum($resultRows);
+ // logger()->info("evaluateEmissionReductionFormula: RESULT TOTAL", ['result' => $result, 'rows' => $resultRows]);
+ // return $result;
+ // }
+
+ // // --- Pipeline normal ---
+ // $formula = $this->parseSigmaSumProduct($formula, $adArrays, $adValues, $refParams, $refContext, 'parseSigmaSumProduct');
+ // $formula = $this->parseSigmaSumOnly($formula, $adArrays, $adValues, $refParams, $refContext, 'parseSigmaSumOnly');
+ // $formula = $this->replaceADDefault($formula, $adArrays, $adValues, 'replaceADDefault');
+ // $formula = $this->replaceREF($formula, $refParams, $refContext, $adArrays, $adValues, $adUnits, 'replaceREF', false);
+ // $formula = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1] / 100, $formula);
+ // $formula = preg_replace('/([A-Za-z0-9_\.]+)\^([0-9]+)/', 'pow($1,$2)', $formula);
+ // $open = substr_count($formula, '('); $close = substr_count($formula, ')');
+ // if ($open > $close) $formula .= str_repeat(')', $open - $close);
+ // if ($close > $open) $formula = str_repeat('(', $close - $open) . $formula;
+ // logger()->info("evaluateEmissionReductionFormula: FINAL FORMULA", ['formula' => $formula]);
+ // try {
+ // $result = eval('return ' . $formula . ';');
+ // logger()->info("evaluateEmissionReductionFormula: RESULT", ['result' => $result]);
+ // return $result;
+ // } catch (\Throwable $e) {
+ // logger()->error("Eval error FINAL: $formula | " . $e->getMessage());
+ // return 0;
+ // }
+ // }
+ public function evaluateEmissionReductionFormula($formula, $adValues, $refParams, $refContext, $adArrays, $adUnits = [], $labelMap = [])
+ {
+ logger()->info("evaluateEmissionReductionFormula: START", ['formula' => $formula]);
+
+ // $formula = $this->parseSumproductExcelLikeV3($formula, $adArrays, $adValues, $refParams, $refContext);
+
+ // 1. PARSE SEMUA BLOK SUMPRODUCT(…) (Excel style)
+ $formula = $this->parseSumproductExcel($formula, $adArrays, $adValues, $refParams, $refContext);
+
+ // 2. Sigma / Σi= pipeline (legacy, kalau ada)
+ if ($this->isSigmaArrayFormula($formula, $adArrays, $refParams)) {
+ preg_match('/Σi=\(([^)]+)\)/', $formula, $m);
+ preg_match_all('/\b(AD[0-9]+|REF_[A-Z0-9_]+)\b/', $m[1] ?? '', $vars);
+ $maxRows = 1;
+ foreach ($vars[1] as $var) {
+ if (isset($adArrays[$var]) && is_array($adArrays[$var]))
+ $maxRows = max($maxRows, count($adArrays[$var]));
+ }
+
+ $resultRows = [];
+ for ($i = 0; $i < $maxRows; $i++) {
+ // Build per baris
+ $adValuesRow = [];
+ $adArraysRow = [];
+ foreach ($adArrays as $key => $arr) {
+ $adArraysRow[$key] = [isset($arr[$i]) ? $arr[$i] : (isset($arr[0]) ? $arr[0] : 0)];
+ $adValuesRow[$key] = isset($arr[$i]) ? $arr[$i] : (isset($arr[0]) ? $arr[0] : 0);
+ }
+ $f = $this->parseSigmaSumProduct($formula, $adArraysRow, $adValuesRow, $refParams, $refContext, "row-$i-parseSigmaSumProduct");
+ $f = $this->parseSigmaSumOnly($f, $adArraysRow, $adValuesRow, $refParams, $refContext, "row-$i-parseSigmaSumOnly");
+ $f = $this->replaceADDefault($f, $adArraysRow, $adValuesRow, "row-$i-replaceADDefault");
+ $f = $this->replaceREF($f, $refParams, $refContext, $adArraysRow, $adValuesRow, $adUnits, "row-$i-replaceREF", false);
+
+ $f = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1] / 100, $f);
+ $f = preg_replace('/([A-Za-z0-9_\.]+)\^([0-9]+)/', 'pow($1,$2)', $f);
+
+ // Clean up kurung
+ $f = preg_replace('/\)\)+$/', ')', $f);
+ $open = substr_count($f, '('); $close = substr_count($f, ')');
+ if ($open > $close) $f .= str_repeat(')', $open - $close);
+ if ($close > $open) $f = str_repeat('(', $close - $open) . $f;
+ $f = preg_replace('/^(b")?([Σ∑Î]i=)/u', '', $f);
+
+ $formula = str_replace('CONST_', '', $formula);
+ $formula = preg_replace('/^(b")?([Σ∑Î][ijk]=)/u', '', $formula);
+
+ logger()->info("BARIS $i - Formula Final Eval", ['formula' => $f]);
+ try {
+ $res = eval('return ' . $f . ';');
+ $resultRows[] = $res;
+ } catch (\Throwable $e) {
+ logger()->error("Eval error BARIS $i: $f | " . $e->getMessage());
+ $resultRows[] = 0;
+ }
+ }
+ $result = array_sum($resultRows);
+ logger()->info("evaluateEmissionReductionFormula: RESULT TOTAL", ['result' => $result, 'rows' => $resultRows]);
+ return $result;
+ }
+
+ // 3. Pipeline normal non-sigma
+ $formula = $this->parseSigmaSumProduct($formula, $adArrays, $adValues, $refParams, $refContext, 'parseSigmaSumProduct');
+ $formula = $this->parseSigmaSumOnly($formula, $adArrays, $adValues, $refParams, $refContext, 'parseSigmaSumOnly');
+ $formula = $this->replaceADDefault($formula, $adArrays, $adValues, 'replaceADDefault');
+ $formula = $this->replaceREF($formula, $refParams, $refContext, $adArrays, $adValues, $adUnits, 'replaceREF', false);
+ $formula = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1] / 100, $formula);
+ $formula = preg_replace('/([A-Za-z0-9_\.]+)\^([0-9]+)/', 'pow($1,$2)', $formula);
+
+ // Balance kurung
+ $open = substr_count($formula, '('); $close = substr_count($formula, ')');
+ if ($open > $close) $formula .= str_repeat(')', $open - $close);
+ if ($close > $open) $formula = str_repeat('(', $close - $open) . $formula;
+
+ // Special case
+ if (strpos($formula, 'SUM(') !== false) {
+ foreach (['AD3', 'AD4'] as $adKey) {
+ if (strpos($formula, "SUM($adKey)") !== false && isset($adArrays[$adKey])) {
+ $formula = str_replace("SUM($adKey)", array_sum($adArrays[$adKey]), $formula);
+ }
+ }
+ // Tambah di sini:
+ $formula = preg_replace('/SUM\(\s*([0-9\.]+)\s*\)/', '$1', $formula);
+
+ // Opsional: hapus SUM lain
+ $formula = str_replace('SUM', '', $formula);
+ }
+
+ logger()->info("evaluateEmissionReductionFormula: FINAL FORMULA", ['formula' => $formula]);
+ try {
+ $result = eval('return ' . $formula . ';');
+ logger()->info("evaluateEmissionReductionFormula: RESULT", ['result' => $result]);
+ return $result;
+ } catch (\Throwable $e) {
+ logger()->error("Eval error FINAL: $formula | " . $e->getMessage());
+ return 0;
+ }
+ }
+
+ function replaceADDefault($formula, $adArrays, $adValues, $debugTag = 'replaceADDefault') {
+ logger()->info("Masuk $debugTag", [
+ 'formula' => $formula,
+ 'adArrays' => $adArrays,
+ 'adValues' => $adValues
+ ]);
+ return preg_replace_callback('/AD([0-9]+)/', function($ad) use ($adArrays, $adValues) {
+ $adFull = "AD".$ad[1];
+ $val = $adArrays[$adFull][0] ?? $adValues[$adFull] ?? 0;
+ if (!is_numeric($val)) {
+ logger()->warning("AD non-numeric (default), replaced with 1", [
+ 'ad' => $adFull, 'value' => $val
+ ]);
+ return 1;
+ }
+ logger()->info("replaceADDefault: replace", [
+ 'ad' => $adFull, 'value' => $val
+ ]);
+ return $val;
+ }, $formula);
+ }
+
+ public function replaceREF(
+ $formula,
+ $refParams,
+ $refContext,
+ $adArrays,
+ $adValues,
+ $adUnits = [],
+ $debugTag = '',
+ $as_array = false
+ ) {
+ logger()->info("Masuk $debugTag", ['formula' => $formula]);
+
+ // Hitung jumlah CF di formula
+ preg_match_all('/REF_CF[0-9]+/i', $formula, $cfMatches);
+ $cfCount = count(array_unique($cfMatches[0]));
+
+ if ($cfCount > 2) {
+ logger()->error("Formula mengandung lebih dari 2 Conversion Factor (CF): $cfCount", [
+ 'formula' => $formula,
+ 'cf_found' => $cfMatches[0]
+ ]);
+ throw new \Exception("Formula hanya boleh mengandung maksimal 2 Conversion Factor (CF), ditemukan: $cfCount");
+ }
+
+ // FIX: Use $as_array in closure
+ return preg_replace_callback('/REF_([A-Z0-9_]+)/', function($mm) use ($refParams, $refContext, $adArrays, $adValues, $adUnits, $as_array) {
+ $key = $mm[1];
+ if (!isset($refParams[$key])) {
+ logger()->error("Mapping untuk REF_$key tidak ditemukan.", [
+ 'key' => $key, 'refParams' => $refParams
+ ]);
+ throw new \Exception("Mapping untuk REF_$key tidak ditemukan.");
+ }
+ $map = $refParams[$key];
+
+ // Special handling: Conversion Factor
+ if (
+ strtoupper(substr($map['param'], 0, 2)) === 'CF'
+ || strtoupper($map['param']) === 'CONVERSION FACTOR'
+ ) {
+ $adKeyUnit = null;
+ foreach ($map['context'] as $field => $adKeyC) {
+ $adKeyUnit = $adKeyC;
+ break;
+ }
+ $unit = $adUnits[$adKeyUnit] ?? null;
+ if (!$unit) {
+ logger()->error("Unit untuk Conversion Factor tidak ditemukan di AD.", [
+ 'param' => $map['param'],
+ 'context' => $map['context'],
+ 'adKeyUnit' => $adKeyUnit,
+ 'adUnits' => $adUnits,
+ 'adValues' => $adValues,
+ 'adArrays' => $adArrays,
+ ]);
+ throw new \Exception("Unit untuk Conversion Factor tidak ditemukan di AD $adKeyUnit.");
+ }
+
+ // Cek kategori unit
+ $category = $this->unitCategoryMap[strtolower($unit)] ?? null;
+ logger()->info("CF Detected", [
+ 'unit' => $unit,
+ 'category' => $category,
+ ]);
+ if (!$category) throw new \Exception("Kategori unit tidak diketahui: $unit");
+
+ // Ambil conversion factor value
+ $q = \App\Models\EmissionFactorReference::where('param', $map['param'])
+ ->whereRaw('LOWER(unit) = ?', [strtolower($unit)]);
+ $cfValue = $q->value('value');
+ logger()->info("REF CF Value", [
+ 'param' => $map['param'],
+ 'unit' => $unit,
+ 'cfValue' => $cfValue
+ ]);
+ if ($cfValue === null) throw new \Exception("CF reference tidak ditemukan (param=$map[param], unit=$unit)");
+
+ // Bangun rumus berdasarkan kategori
+ $formulaCF = '';
+ if ($category == 'volume') {
+ $formulaCF = "($cfValue*REF_BERAT_JENIS*REF_NCV)";
+ } else if ($category == 'mass') {
+ $formulaCF = "($cfValue*REF_NCV)";
+ } else if ($category == 'energy') {
+ $formulaCF = "($cfValue)";
+ } else {
+ throw new \Exception("Kategori unit tidak didukung: $category");
+ }
+ // Recursively replace reference di rumus baru!
+ $finalVal = $this->replaceREF($formulaCF, $refParams, $refContext, $adArrays, $adValues, $adUnits, 'CF_RECURSE');
+ $result = null;
+ eval("\$result = $finalVal;");
+ logger()->info("Eval CF Result", [
+ 'formula' => $finalVal,
+ 'result' => $result
+ ]);
+ return $result;
+ }
+
+ // --- Query reference biasa, ambil dari keterangan/value AD ---
+ $contextKey = null;
+ foreach ($map['context'] as $field => $adKeyC) {
+ $contextKey = $adKeyC;
+ }
+ $contextIsArray = $contextKey && isset($adArrays[$contextKey]) && is_array($adArrays[$contextKey]) && count($adArrays[$contextKey]) > 1;
+
+ if ($contextIsArray) {
+ $adVals = $adArrays[$contextKey];
+ $refVals = [];
+ foreach ($adVals as $v) {
+ $q = \App\Models\EmissionFactorReference::where('param', $map['param'])
+ ->where('unit', $map['unit'])
+ ->where('keterangan', $v);
+ $val = $q->value('value');
+ if ($val !== null) $refVals[] = $val;
+ }
+ if ($as_array) {
+ logger()->info("REF Array Result for $key", [
+ 'adVals' => $adVals,
+ 'refVals' => $refVals
+ ]);
+ return implode(',', $refVals);
+ // return (string)$refVals;
+ }
+ $sum = array_sum($refVals);
+ logger()->info("REF Array SUM for $key", [
+ 'adVals' => $adVals,
+ 'refVals' => $refVals,
+ 'sum' => $sum
+ ]);
+ // dd(strval($sum == 0 ? 1 : $sum));
+ return strval($sum == 0 ? 1 : $sum); // <-- Ini kunci!
+ } else {
+ // default: ambil single value (seperti sebelumnya)
+ $where = [];
+ foreach ($map['context'] as $field => $adKeyC) {
+ $cv = $adArrays[$adKeyC][0] ?? $adValues[$adKeyC] ?? null;
+ if ($cv !== null) $where[] = ['keterangan', '=', $cv];
+ }
+ logger()->info("QUERY REF Single", [
+ 'param' => $map['param'],
+ 'unit' => $map['unit'],
+ 'where' => $where
+ ]);
+ $q = \App\Models\EmissionFactorReference::where('param', $map['param'])
+ ->where('unit', $map['unit']);
+ foreach ($where as $w) $q->where($w[0], $w[2]);
+ $rv = $q->value('value');
+ logger()->info("REF Value Result Single", [
+ 'param' => $map['param'],
+ 'unit' => $map['unit'],
+ 'context' => $map['context'],
+ 'where' => $where,
+ 'value' => $rv
+ ]);
+ return $rv ?? 1;
+ }
+ }, $formula);
+ }
+
+ /**
+ * Parse dan evaluasi semua fungsi SUMPRODUCT pada formula, mendukung konstanta CONST_ADn, ADn, REF_xxx, angka, power, persen, bracket.
+ * SUMPRODUCT(AD8*AD9*0.8/1000*(1/(1-20%)))
+ * SUMPRODUCT(CONST_AD2*AD5*...)+SUMPRODUCT(...)
+ * dst.
+ * @param string $formula
+ * @param array $adArrays
+ * @param array $adValues
+ * @param array $refParams
+ * @param array $refContext
+ * @return string
+ */
+ public function parseSumproductExcelLikeV3($formula, $adArrays, $adValues, $refParams, $refContext)
+ {
+ // Jika terdapat lebih dari satu SUMPRODUCT di formula, gunakan versi multi
+ if (substr_count(strtoupper($formula), 'SUMPRODUCT(') > 1) {
+ return $this->parseSumproductMultiple($formula, $adArrays, $adValues, $refParams, $refContext);
+ }
+
+ // Regex pattern handle nested bracket dalam SUMPRODUCT (recursively, non-greedy)
+ $pattern = '/SUMPRODUCT\s*\(((?:[^()]++|(?R))*?)\)/i';
+ while (preg_match($pattern, $formula)) {
+ $formula = preg_replace_callback($pattern, function($m) use ($adArrays, $adValues, $refParams, $refContext) {
+ $inner = $m[1];
+ $sum = 0;
+
+ // Ganti AD dan REF inline
+ $expr = preg_replace_callback('/AD([0-9]+)/', function($mm) use ($adArrays, $adValues) {
+ $adKey = 'AD' . $mm[1];
+ return $adValues[$adKey] ?? $adArrays[$adKey][0] ?? 0;
+ }, $inner);
+
+ $expr = preg_replace_callback('/REF_([A-Z0-9_]+)/', function($mm) use ($refParams, $refContext, $adArrays, $adValues) {
+ $key = $mm[1];
+ if (!isset($refParams[$key])) return 0;
+ $map = $refParams[$key];
+ $contextKey = null;
+ foreach ($map['context'] as $field => $adKeyC) {
+ $contextKey = $adKeyC;
+ }
+ $adVal = $contextKey && isset($adValues[$contextKey]) ? $adValues[$contextKey] : ($adArrays[$contextKey][0] ?? null);
+ $q = \App\Models\EmissionFactorReference::where('param', $map['param'])
+ ->where('unit', $map['unit'])
+ ->where('keterangan', $adVal);
+ return $q->value('value') ?? 0;
+ }, $expr);
+
+ $expr = preg_replace_callback('/(\d+(?:\.\d+)?)%/', fn($mm) => $mm[1]/100, $expr);
+ $expr = preg_replace('/([0-9.Ee+\-]+)\s*\^\s*([0-9.Ee+\-]+)/', 'pow($1,$2)', $expr);
+
+ try {
+ $sum = eval('return ' . $expr . ';');
+ } catch (\Throwable $e) {
+ logger()->error("[SUMPRODUCT] Eval error: $expr | " . $e->getMessage());
+ $sum = 0;
+ }
+
+ return (string)$sum;
+ }, $formula, 1); // replace 1x per loop
+ }
+ return $formula;
+ }
+
+ public function parseSumproductMultiple($formula, $adArrays, $adValues, $refParams, $refContext)
+ {
+ $pattern = '/SUMPRODUCT\s*\(((?:[^()]++|(?R))*?)\)/i';
+ return preg_replace_callback($pattern, function ($m) use ($adArrays, $adValues, $refParams, $refContext) {
+ $sub = 'SUMPRODUCT(' . $m[1] . ')';
+ return $this->parseSumproductExcelLikeV3($sub, $adArrays, $adValues, $refParams, $refContext);
+ }, $formula);
+ }
+}
\ No newline at end of file
diff --git a/app/Services/Activity/FormService.php b/app/Services/Activity/FormService.php
new file mode 100644
index 0000000..184d3cc
--- /dev/null
+++ b/app/Services/Activity/FormService.php
@@ -0,0 +1,327 @@
+where('form_code', $code)
+ ->where('inventory_year', $inventoryYear)
+ ->rowActive()
+ ->orderBy('inventory_year', 'desc');
+
+ if ($agency && $agency != 'none') {
+ if ($agency === 'all') {
+ // return $query->whereNotNull('agency_id')->get();
+ $produsen = $this->getDataApproval($sector, $code, $inventoryYear)
+ ->where('status', 1)->pluck('agency_id')->toArray();
+ return $query->whereIn('agency_id', $produsen);
+ }
+
+ return $query->where('agency_id', $agency)->first();
+ }
+
+ return $query->whereNull('agency_id')->first();
+ }
+
+
+ public function getActivityFormDetails($formId, $agency = null)
+ {
+ if ($agency == 'all') {
+ $results = ActivityFormDetail::whereIn('form_id', $formId)
+ ->rowActive()->groupBy('activity_year', 'activity_code', 'activity_unit_code')
+ ->selectRaw('activity_year, activity_code, activity_unit_code, sum(activity_value) as activity_value')
+ ->orderBy('activity_year', 'desc')->get();
+
+ return $results->groupBy('activity_year');
+ }
+
+ return ActivityFormDetail::where('form_id', $formId)
+ ->rowActive()->orderBy('activity_year', 'desc')
+ ->get()->groupBy('activity_year');
+ }
+
+ public function convertUnit($fromUnit, $toUnit, $value)
+ {
+ $conversion = ReferenceUnitConversion::where('from_unit_code', $fromUnit)
+ ->where('to_unit_code', $toUnit)->rowActive()
+ ->first();
+
+ if ($conversion) {
+ $convertedValue = $value * $conversion->value;
+
+ return $convertedValue;
+ }
+
+ return $value;
+ }
+
+ public function save($sector, $code, $inventoryYear, $data, $fromUnitCodes = null, $instansi = null)
+ {
+ $activityYears = activityYearRange($inventoryYear);
+ $query = ActivityForm::where('sector', $sector)
+ ->where('form_code', $code)
+ ->where('inventory_year', $inventoryYear)
+ ->rowActive();
+
+ if ($instansi && $instansi != 'all' && $instansi != 'none') {
+ $query->where('agency_id', $instansi);
+ } else {
+ $query->whereNull('agency_id');
+ }
+
+ $activityForm = $query->first();
+
+ try {
+ if (!$activityForm) {
+ $instansiId = $instansi === 'all' || $instansi === 'none' ? null : $instansi;
+ $dataForm = [
+ 'sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+
+ // new column
+ 'agency_id' => $instansiId,
+ ];
+
+ $activityForm = $this->create($dataForm);
+ logUserActivity(ActivityType::INSERT_ACTIVITY_DATA, $activityForm->id);
+ } else {
+ $this->update($activityForm, []);
+ logUserActivity(ActivityType::UPDATE_ACTIVITY_DATA, $activityForm->id);
+ }
+
+ foreach ($activityYears as $year) {
+ // if (isset($data[$year]) && collect($data[$year])->filter(function ($value) {
+ // return $value !== null;
+ // })->isNotEmpty()) {
+ if (isset($data[$year])) {
+ $this->saveDetail($code, $activityForm, $year, $data[$year], $fromUnitCodes);
+ }
+ }
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function saveDetail($formCode, $activityForm, $year, $data, $fromUnitCodes = null)
+ {
+ foreach ($data as $activityCodeUnit => $activityValue) {
+ list($activityCode, $unitCode) = explode('-', $activityCodeUnit);
+
+ $activityFormDetail = ActivityFormDetail::where('form_id', $activityForm->id)
+ ->where('activity_year', $year)
+ ->where('activity_code', $activityCode)
+ ->where('activity_unit_code', $unitCode)
+ ->rowActive()
+ ->first();
+
+ // Default Unit Code = $unitCode
+ // New Unit Code = $fromUnitCodes[$activityCode]
+ $newUnitCode = $fromUnitCodes != null ? $fromUnitCodes[$activityCode] : $unitCode;
+ if ($unitCode != $newUnitCode) {
+ $this->settingUnitCode($formCode, $activityCode, $unitCode, $newUnitCode);
+ }
+
+ if (!empty($activityValue)) {
+ $newValue = getOriginalValue($activityValue);
+ // Convert to Default Unit Code
+ // $newValue = $fromUnitCodes == null ? $newValue : $this->convertUnit($fromUnitCodes[$activityCode], $unitCode, $newValue);
+
+ if ($activityFormDetail) {
+ $oldValue = getFormattedValue($activityFormDetail->activity_value);
+
+ if ($oldValue != $activityValue) {
+ $this->update(
+ $activityFormDetail,
+ [
+ 'activity_value' => $newValue,
+ 'activity_unit_code' => $newUnitCode
+ ]
+ );
+ }
+ } else {
+ $dataFormDetail = [
+ 'form_id' => $activityForm->id,
+ 'activity_year' => $year,
+ 'activity_code' => $activityCode,
+ 'activity_unit_code' => $newUnitCode,
+ 'activity_value' => $newValue
+ ];
+
+ $this->create($dataFormDetail, ActivityFormDetail::class);
+ }
+ } else {
+ if ($activityFormDetail) {
+ $this->delete($activityFormDetail);
+ }
+ }
+ }
+ }
+
+ private function settingUnitCode($formCode, $activityCode, $oldUnitCode, $newUnitCode)
+ {
+ DB::beginTransaction();
+
+ try {
+ $activityFormDetail = SettingFormDetail::where('form_code', $formCode)
+ ->where('activity_code', $activityCode)->where('unit_code', $oldUnitCode)
+ ->rowActive()->first();
+
+ if ($activityFormDetail) {
+ $activityFormDetail->update([
+ 'unit_code' => $newUnitCode,
+ 'updated_by' => auth()->user()->id ?? null
+ ]);
+ }
+
+ DB::commit();
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw new Exception('Failed to update unit code: ' . $e->getMessage());
+ }
+ }
+
+
+
+ public function lockForm($id)
+ {
+ $activityForm = ActivityForm::findOrFail($id);
+ $this->update($activityForm, ['lock_status' => 'locked']);
+
+ logUserActivity(ActivityType::LOCK_ACTIVITY_FORM, $activityForm->id);
+ }
+
+ public function unlockForm($id)
+ {
+ $activityForm = ActivityForm::findOrFail($id);
+ $this->update($activityForm, ['lock_status' => 'open']);
+
+ logUserActivity(ActivityType::UNLOCK_ACTIVITY_FORM, $activityForm->id);
+ }
+
+ public function copyData($sector, $code, $fromYear, $toYear)
+ {
+ DB::beginTransaction();
+
+ try {
+ $activityYears = activityYearRange($toYear);
+ $activityForm = ActivityForm::where('inventory_year', $fromYear)
+ ->where('sector', $sector)->where('form_code', $code)->rowActive()->first();
+
+ if ($activityForm) {
+ $existingForm = ActivityForm::where('inventory_year', $toYear)
+ ->where('sector', $activityForm->sector)
+ ->where('form_code', $activityForm->form_code)
+ ->rowActive()->first();
+
+ if ($existingForm) {
+ $existingForm->update([
+ 'updated_by' => Auth::user()->name,
+ ]);
+
+ $newActivityForm = $existingForm;
+ } else {
+ $dataForm = [
+ 'sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $toYear,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+ ];
+
+ $newActivityForm = $this->create($dataForm);
+ }
+
+ logUserActivity(ActivityType::COPY_ACTIVITY_FORM, $newActivityForm->id);
+ $activityFormDetails = ActivityFormDetail::where('form_id', $activityForm->id)
+ ->whereIn('activity_year', $activityYears)
+ ->rowActive()->get();
+
+ foreach ($activityFormDetails as $detail) {
+ $existingDetail = ActivityFormDetail::where('form_id', $newActivityForm->id)
+ ->where('activity_year', $detail->activity_year)
+ ->where('activity_code', $detail->activity_code)
+ ->rowActive()->first();
+
+ if ($existingDetail) {
+ $existingDetail->update([
+ 'activity_value' => $detail->activity_value,
+ 'updated_by' => Auth::user()->name,
+ ]);
+ } else {
+ $dataFormDetail = [
+ 'form_id' => $newActivityForm->id,
+ 'activity_year' => $detail->activity_year,
+ 'activity_code' => $detail->activity_code,
+ 'activity_unit_code' => $detail->activity_unit_code,
+ 'activity_value' => $detail->activity_value
+ ];
+
+ $newActivityFormDetail = $this->create($dataFormDetail, ActivityFormDetail::class);
+ }
+ }
+ }
+
+ DB::commit();
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function approvalKonsolidasi($form, $sector, $code, $inventoryYear, $agencyId)
+ {
+ $hasData = $this->getDataApproval($sector, $code, $inventoryYear, true)->where([
+ 'form_id' => $form->id,
+ 'agency_id' => $agencyId,
+ ])->rowActive()->first();
+
+ $newStatus = 1;
+ if ($hasData) {
+ $newStatus = $hasData->status == 1 ? 0 : 1;
+ }
+
+ $dataForm = [
+ 'form_id' => $form->id,
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'agency_id' => $agencyId,
+ 'status' => $newStatus,
+ ];
+
+ $this->createOrUpdate([
+ 'form_id' => $form->id,
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ 'agency_id' => $agencyId,
+ ], $dataForm, ActivityApprovalKonsolidasi::class);
+
+ $activityType = $newStatus == 1 ? ActivityType::APPROVAL_KONSOLIDASI : ActivityType::DISSAPPROVAL_KONSOLIDASI;
+ logUserActivity($activityType, $form->id);
+ }
+}
diff --git a/app/Services/Activity/LivestockManureService.php b/app/Services/Activity/LivestockManureService.php
new file mode 100644
index 0000000..2244460
--- /dev/null
+++ b/app/Services/Activity/LivestockManureService.php
@@ -0,0 +1,41 @@
+update([
+ 'active_status' => 0,
+ 'updated_by' => Auth::user()->name
+ ]);
+
+ $lm = LivestockManure::find($id);
+ if ($lm) {
+ $this->update($lm, ['active_status' => 1]);
+ }
+
+ DB::commit();
+
+ return $lm;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/DashboardAdaptationService.php b/app/Services/DashboardAdaptationService.php
new file mode 100644
index 0000000..3b0d8f5
--- /dev/null
+++ b/app/Services/DashboardAdaptationService.php
@@ -0,0 +1,141 @@
+where('tahun_kegiatan', $adaptationYear)
+ ->orderBy('created_at', 'desc')
+ ->get();
+
+ // Normalisasi angka untuk table
+ $rows = $rows->transform(function ($a) {
+ foreach ([
+ 'alokasi_apbn',
+ 'alokasi_apbd',
+ 'alokasi_swasta',
+ 'alokasi_sumber_dana_lain',
+ ] as $field) {
+ $raw = $a->{$field} ?? '0';
+ $norm = str_replace('.', '', $raw);
+ $norm = str_replace(',', '.', $norm);
+ $a->{$field} = (float) $norm;
+ }
+
+ foreach ([
+ 'realisasi_apbn',
+ 'realisasi_apbd',
+ 'realisasi_swasta',
+ 'realisasi_sumber_dana_lain'
+ ] as $field) {
+ $raw = $a->{$field} ?? '0';
+ $norm = str_replace('.', '', $raw);
+ $norm = str_replace(',', '.', $norm);
+ $a->{$field} = (int) round((float) $norm);
+ }
+
+ return $a;
+ });
+
+ $totalAksi = $rows->count();
+
+ // --- JUMLAH DATA PER SEKTOR DI TAHUN TERTENTU ---
+ $years = $rows->pluck('tahun_kegiatan')->unique()->sort()->values();
+
+ $barData = $years->map(fn($year) => [
+ 'year' => $year,
+ 'jumlah' => $rows
+ ->where('tahun_kegiatan', $year)
+ ->groupBy('sektor')
+ ->map(fn($group, $sector) => $group->count())
+ ->toArray(),
+ ])->all();
+
+ // Budget data (tetap sesuai kebutuhan chart anggaran)
+ $budgetData = [
+ 'apbn' => (float) $rows->sum('alokasi_apbn'),
+ 'apbd' => (float) $rows->sum('alokasi_apbd'),
+ 'swasta' => (float) $rows->sum('alokasi_swasta'),
+ 'lainlain' => (float) $rows->sum('alokasi_sumber_dana_lain'),
+ ];
+
+ $realisasiData = [
+ 'apbn' => (float) $rows->sum('realisasi_apbn'),
+ 'apbd' => (float) $rows->sum('realisasi_apbd'),
+ 'swasta' => (float) $rows->sum('realisasi_swasta'),
+ 'lainlain' => (float) $rows->sum('realisasi_sumber_dana_lain'),
+ ];
+
+ $stats = [
+ 'total_aksi' => $totalAksi,
+ 'total_anggaran' => array_sum($budgetData),
+ 'total_alokasi' => array_sum($realisasiData)
+ ];
+
+ $sectorBreakdown = $rows
+ ->groupBy('sektor')
+ ->map(function($group, $sector) use ($totalAksi) {
+ $jumlah = $group->count();
+ $persen = $totalAksi > 0 ? round(($jumlah / $totalAksi) * 100, 2) : 0;
+ return [
+ 'sektor' => $sector,
+ 'jumlah' => $jumlah,
+ 'persen' => $persen,
+ ];
+ })
+ ->values()
+ ->all();
+
+ $charts = [
+ 'aksi' => $sectorBreakdown,
+ 'anggaran' => $rows->groupBy('sektor')->map(function($g, $s) use ($budgetData) {
+ $total = array_sum($budgetData);
+ $val = $g->sum('alokasi_apbn') + $g->sum('alokasi_apbd') + $g->sum('alokasi_swasta') + $g->sum('alokasi_sumber_dana_lain');
+ $persen = $total > 0 ? round(($val / $total) * 100, 2) : 0;
+ return [
+ 'sektor' => $s,
+ 'persen' => $persen,
+ ];
+ })->values()->all(),
+ 'alokasi' => $rows->groupBy('sektor')->map(function($g, $s) use ($realisasiData) {
+ $total = array_sum($realisasiData);
+ $val = $g->sum('realisasi_apbn') + $g->sum('realisasi_apbd') + $g->sum('realisasi_swasta') + $g->sum('realisasi_sumber_dana_lain');
+ $persen = $total > 0 ? round(($val / $total) * 100, 2) : 0;
+ return [
+ 'sektor' => $s,
+ 'persen' => $persen,
+ ];
+ })->values()->all(),
+ ];
+
+ return [
+ 'adaptationYear' => $adaptationYear,
+ 'tableData' => $rows, // ⬅️ sekarang collection biasa
+ 'barData' => $barData,
+ 'budgetData' => $budgetData,
+ 'realisasiData' => $realisasiData,
+ 'stats' => $stats,
+ 'charts' => $charts
+ ];
+ }
+}
diff --git a/app/Services/DashboardMitigationService.php b/app/Services/DashboardMitigationService.php
new file mode 100644
index 0000000..9778455
--- /dev/null
+++ b/app/Services/DashboardMitigationService.php
@@ -0,0 +1,165 @@
+where('tahun_kegiatan', $mitigationYear)
+ ->orderBy('created_at', 'desc')
+ ->get();
+
+ $rows = $rows->transform(function ($a) {
+ foreach ([
+ 'alokasi_apbn',
+ 'alokasi_apbd',
+ 'alokasi_swasta',
+ 'alokasi_sumber_dana_lain',
+ ] as $field) {
+ $raw = $a->{$field} ?? '0';
+ $norm = str_replace('.', '', $raw);
+ $norm = str_replace(',', '.', $norm);
+ $a->{$field} = (float) $norm;
+ }
+
+ foreach ([
+ 'realisasi_apbn',
+ 'realisasi_apbd',
+ 'realisasi_swasta',
+ 'realisasi_sumber_dana_lain'
+ ] as $field) {
+ $raw = $a->{$field} ?? '0';
+ $norm = str_replace('.', '', $raw);
+ $norm = str_replace(',', '.', $norm);
+ $a->{$field} = (int) round((float) $norm);
+ }
+
+ if (!empty($a->emission_factor)) {
+ $raw = $a->emission_factor;
+ $norm = str_replace('.', '', $raw); // hapus ribuan
+ $norm = str_replace(',', '.', $norm); // ubah koma ke titik
+ $a->emission_factor = (float) $norm;
+ } else {
+ $a->emission_factor = 0;
+ }
+
+ return $a;
+ });
+
+ $totalAksi = $rows->count();
+
+ // --- JUMLAH DATA PER SEKTOR DI TAHUN TERTENTU ---
+ $years = $rows->pluck('tahun_kegiatan')->unique()->sort()->values();
+
+ $barData = $years->map(fn($year) => [
+ 'year' => $year,
+ 'jumlah' => $rows
+ ->where('tahun_kegiatan', $year)
+ ->groupBy('sektor')
+ ->map(fn($group, $sector) => $group->count())
+ ->toArray(),
+ ])->all();
+
+ // Budget data (tetap sesuai kebutuhan chart anggaran)
+ $budgetData = [
+ 'apbn' => (float) $rows->sum('alokasi_apbn'),
+ 'apbd' => (float) $rows->sum('alokasi_apbd'),
+ 'swasta' => (float) $rows->sum('alokasi_swasta'),
+ 'lainlain' => (float) $rows->sum('alokasi_sumber_dana_lain'),
+ ];
+
+ $realisasiData = [
+ 'apbn' => (float) $rows->sum('realisasi_apbn'),
+ 'apbd' => (float) $rows->sum('realisasi_apbd'),
+ 'swasta' => (float) $rows->sum('realisasi_swasta'),
+ 'lainlain' => (float) $rows->sum('realisasi_sumber_dana_lain'),
+ ];
+
+ $stats = [
+ 'total_aksi' => $totalAksi,
+ 'total_emisi' => (float) $rows->sum('emission_factor'),
+ 'total_anggaran' => array_sum($budgetData),
+ 'total_alokasi' => array_sum($realisasiData)
+ ];
+
+ // dd($stats);
+
+ $sectorBreakdown = $rows
+ ->groupBy('sektor')
+ ->map(function($group, $sector) use ($totalAksi) {
+ $jumlah = $group->count();
+ $persen = $totalAksi > 0 ? round(($jumlah / $totalAksi) * 100, 2) : 0;
+ return [
+ 'sektor' => $sector,
+ 'jumlah' => $jumlah,
+ 'persen' => $persen,
+ ];
+ })
+ ->values()
+ ->all();
+
+ $charts = [
+ 'aksi' => $sectorBreakdown,
+ 'emisi' => $rows->groupBy('sektor')->map(function($g, $s) use ($rows) {
+ $total = $rows->sum('emission_factor');
+ $val = $g->sum('emission_factor');
+ $persen = $total > 0 ? round(($val / $total) * 100, 2) : 0;
+ return [
+ 'sektor' => $s,
+ 'persen' => $persen,
+ ];
+ })->values()->all(),
+ 'anggaran' => $rows->groupBy('sektor')->map(function($g, $s) use ($budgetData) {
+ $total = array_sum($budgetData);
+ $val = $g->sum('alokasi_apbn') + $g->sum('alokasi_apbd') + $g->sum('alokasi_swasta') + $g->sum('alokasi_sumber_dana_lain');
+ $persen = $total > 0 ? round(($val / $total) * 100, 2) : 0;
+ return [
+ 'sektor' => $s,
+ 'persen' => $persen,
+ ];
+ })->values()->all(),
+ 'alokasi' => $rows->groupBy('sektor')->map(function($g, $s) use ($realisasiData) {
+ $total = array_sum($realisasiData);
+ $val = $g->sum('realisasi_apbn') + $g->sum('realisasi_apbd') + $g->sum('realisasi_swasta') + $g->sum('realisasi_sumber_dana_lain');
+ $persen = $total > 0 ? round(($val / $total) * 100, 2) : 0;
+ return [
+ 'sektor' => $s,
+ 'persen' => $persen,
+ ];
+ })->values()->all(),
+ ];
+
+ return [
+ 'mitigationYear' => $mitigationYear,
+ 'tableData' => $rows,
+ 'barData' => $barData,
+ 'budgetData' => $budgetData,
+ 'realisasiData' => $realisasiData,
+ 'stats' => $stats,
+ 'charts' => $charts
+ ];
+ }
+}
\ No newline at end of file
diff --git a/app/Services/DashboardService.php b/app/Services/DashboardService.php
new file mode 100644
index 0000000..464b7b1
--- /dev/null
+++ b/app/Services/DashboardService.php
@@ -0,0 +1,103 @@
+getActiveGwpRecords()->keyBy('ghg_code');
+
+ $years = activityYearRange($inventoryYear, false, 10);
+
+ $crfData = ActivityCrf::with(['ws.form', 'sektor'])
+ ->where('inventory_year', $inventoryYear)
+ ->whereBetween('activity_year', [$years[0], end($years)])
+ ->orderBy('ws_code', 'asc')->get();
+
+ $aggregatedData = $this->aggregateCrfData($crfData, $gwpData);
+
+ return [
+ 'cardData' => $this->calculateCardData($aggregatedData, $inventoryYear),
+ 'barData' => $this->calculateBarData($aggregatedData, $years),
+ 'pieData' => $this->calculatePieData($aggregatedData, $inventoryYear),
+ 'tableData' => $this->calculateTableData($aggregatedData, $inventoryYear),
+ 'inventoryYear' => $inventoryYear,
+ ];
+ }
+
+ private function aggregateCrfData(Collection $crfData, Collection $gwpData)
+ {
+ return $crfData->map(function ($data) use ($gwpData) {
+
+ $sector = $data->sector;
+ $name = $sector === 'energy' ? $data->ws->form->name : $data->sektor->name;
+
+ return [
+ 'year' => $data->activity_year,
+ 'sector' => $sector,
+ 'name' => $name,
+ 'co2eq' => $data->co2eq,
+ 'co2' => $data->co2,
+ 'ch4' => $data->ch4,
+ 'n2o' => $data->n2o,
+ ];
+ });
+ }
+
+ private function calculateCardData(Collection $aggregatedData, $inventoryYear)
+ {
+ $sectorSums = $aggregatedData->where('year', $inventoryYear - 1)->groupBy('sector')->map->sum('co2eq');
+
+ return [
+ 'totalEmisi' => $aggregatedData->where('year', $inventoryYear - 1)->sum('co2eq'),
+ 'emisiEnergi' => $sectorSums->get('energy', 0),
+ 'emisiIppu' => $sectorSums->get('ippu', 0),
+ 'emisiPertanian' => $sectorSums->get('agriculture', 0),
+ 'emisiLahan' => $sectorSums->get('folu', 0),
+ 'emisiLimbah' => $sectorSums->get('waste', 0),
+ ];
+ }
+
+ private function calculateBarData(Collection $aggregatedData, array $years)
+ {
+ return array_map(function ($year) use ($aggregatedData) {
+ $yearlyData = $aggregatedData->where('year', $year)->groupBy('name')->map->sum('co2eq');
+ $total = $yearlyData->sum();
+
+ return [
+ 'year' => $year,
+ 'total' => $total,
+ 'emisi' => $yearlyData,
+ ];
+ }, $years);
+ }
+
+ private function calculatePieData(Collection $aggregatedData, $inventoryYear)
+ {
+ return $aggregatedData->where('year', $inventoryYear - 1)->groupBy('name')->map->sum('co2eq');
+ }
+
+ private function calculateTableData(Collection $aggregatedData, $inventoryYear)
+ {
+ return $aggregatedData->where('year', $inventoryYear - 1)->groupBy('name')->map(function ($groupedData) {
+ return [
+ 'co2eq' => $groupedData->sum('co2eq'),
+ 'co2' => $groupedData->sum('co2'),
+ 'ch4' => $groupedData->sum('ch4'),
+ 'n2o' => $groupedData->sum('n2o'),
+ ];
+ });
+ }
+
+ private function getActiveGwpRecords()
+ {
+ return ReferenceGwp::whereHas('ar', function ($query) {
+ $query->isActive();
+ })->get();
+ }
+}
diff --git a/app/Services/DashboardService.php.bak b/app/Services/DashboardService.php.bak
new file mode 100644
index 0000000..6d381c6
--- /dev/null
+++ b/app/Services/DashboardService.php.bak
@@ -0,0 +1,101 @@
+getActiveGwpRecords()->keyBy('ghg_code');
+ $years = activityYearRange($inventoryYear, false, 10);
+
+ $crfData = ActivityCrf::with(['ws.form', 'sektor'])
+ ->where('inventory_year', $inventoryYear)
+ ->whereBetween('activity_year', [$years[0], end($years)])
+ ->orderBy('ws_code', 'asc')->get();
+
+ $aggregatedData = $this->aggregateCrfData($crfData, $gwpData);
+
+ return [
+ 'cardData' => $this->calculateCardData($aggregatedData, $inventoryYear),
+ 'barData' => $this->calculateBarData($aggregatedData, $years),
+ 'pieData' => $this->calculatePieData($aggregatedData, $inventoryYear),
+ 'tableData' => $this->calculateTableData($aggregatedData, $inventoryYear),
+ 'inventoryYear' => $inventoryYear,
+ ];
+ }
+
+ private function aggregateCrfData(Collection $crfData, Collection $gwpData)
+ {
+ return $crfData->map(function ($data) use ($gwpData) {
+
+ $sector = $data->sector;
+ $name = $sector === 'energy' ? $data->ws->form->name : $data->sektor->name;
+
+ return [
+ 'year' => $data->activity_year,
+ 'sector' => $sector,
+ 'name' => $name,
+ 'co2eq' => $data->co2eq,
+ 'co2' => $data->co2,
+ 'ch4' => $data->ch4,
+ 'n2o' => $data->n2o,
+ ];
+ });
+ }
+
+ private function calculateCardData(Collection $aggregatedData, $inventoryYear)
+ {
+ $sectorSums = $aggregatedData->where('year', $inventoryYear - 1)->groupBy('sector')->map->sum('co2eq');
+
+ return [
+ 'totalEmisi' => $aggregatedData->where('year', $inventoryYear - 1)->sum('co2eq'),
+ 'emisiEnergi' => $sectorSums->get('energy', 0),
+ 'emisiPertanian' => $sectorSums->get('agriculture', 0),
+ 'emisiLahan' => $sectorSums->get('folu', 0),
+ 'emisiLimbah' => $sectorSums->get('waste', 0),
+ ];
+ }
+
+ private function calculateBarData(Collection $aggregatedData, array $years)
+ {
+ return array_map(function ($year) use ($aggregatedData) {
+ $yearlyData = $aggregatedData->where('year', $year)->groupBy('name')->map->sum('co2eq');
+ $total = $yearlyData->sum();
+
+ return [
+ 'year' => $year,
+ 'total' => $total,
+ 'emisi' => $yearlyData,
+ ];
+ }, $years);
+ }
+
+ private function calculatePieData(Collection $aggregatedData, $inventoryYear)
+ {
+ return $aggregatedData->where('year', $inventoryYear - 1)->groupBy('name')->map->sum('co2eq');
+ }
+
+ private function calculateTableData(Collection $aggregatedData, $inventoryYear)
+ {
+ return $aggregatedData->where('year', $inventoryYear - 1)->groupBy('name')->map(function ($groupedData) {
+ return [
+ 'co2eq' => $groupedData->sum('co2eq'),
+ 'co2' => $groupedData->sum('co2'),
+ 'ch4' => $groupedData->sum('ch4'),
+ 'n2o' => $groupedData->sum('n2o'),
+ ];
+ });
+ }
+
+ private function getActiveGwpRecords()
+ {
+ return ReferenceGwp::whereHas('ar', function ($query) {
+ $query->isActive();
+ })->get();
+ }
+}
diff --git a/app/Services/Emisi/Agriculture3A2bService.php b/app/Services/Emisi/Agriculture3A2bService.php
new file mode 100644
index 0000000..5f73e5b
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3A2bService.php
@@ -0,0 +1,187 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3A2b') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getEfData($activityCode)
+ {
+ $filterTag1 = ['weaning', 'yearling', 'young', 'mature', 'imported'];
+ $filterTag2 = ['pastura', 'dry_lot'];
+
+ // Prepare CASE statements for custom sorting
+ $orderTag1 = 'CASE tag_1 ';
+ foreach ($filterTag1 as $index => $value) {
+ $orderTag1 .= "WHEN '$value' THEN " . ($index + 1) . " ";
+ }
+ $orderTag1 .= "ELSE " . (count($filterTag1) + 1) . " END";
+
+ $orderTag2 = 'CASE tag_2 ';
+ foreach ($filterTag2 as $index => $value) {
+ $orderTag2 .= "WHEN '$value' THEN " . ($index + 1) . " ";
+ }
+ $orderTag2 .= "ELSE " . (count($filterTag2) + 1) . " END";
+
+ $data = ReferenceEf::select('tag_1', 'tag_2')
+ ->selectRaw("$orderTag1 AS order_tag1")
+ ->selectRaw("$orderTag2 AS order_tag2")
+ ->distinct()->where('activity_code', $activityCode)
+ ->where(function ($query) {
+ $query->where(function ($subQuery) {
+ $subQuery->whereNotNull('tag_1')
+ ->whereNotNull('tag_2')
+ ->whereNull('tag_3');
+ })->orWhere(function ($subQuery) {
+ $subQuery->whereNull('tag_1')
+ ->whereNull('tag_2')
+ ->whereNull('tag_3');
+ });
+ })->where('active_status', 1)->where('row_status', 1)
+ ->orderByRaw('order_tag1')->orderByRaw('order_tag2')
+ ->get();
+
+ return $data;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $efs = $this->getEfData($activity);
+ foreach ($efs as $ef) {
+ $ef_proportion = ReferenceEf::getValue($activity, 'proportion', $ef->tag_1);
+ $num_animal = $value == 0 ? 0 : round($value * $ef_proportion / 100, 0);
+
+ $ef_excretion_rate = ReferenceEf::getValue($activity, 'excretion_rate', $ef->tag_1, $ef->tag_2);
+ $ef_tam = ReferenceEf::getValue($activity, 'tam', $ef->tag_1, $ef->tag_2);
+ $nex = $value == 0 ? 0 : $ef_excretion_rate * $ef_tam / 1000 * 365;
+
+ $ef_nitrogen_fraction = ReferenceEf::getValue($activity, 'nitrogen_fraction', $ef->tag_1, $ef->tag_2);
+ $ne_mms = $value == 0 ? 0 : $num_animal * $nex * $ef_nitrogen_fraction / 100;
+
+ $ef_mms = ReferenceEf::getValue($activity, 'mms_ef', $ef->tag_1, $ef->tag_2);
+ $n2o_d = $value == 0 ? 0 : $ne_mms * $ef_mms * 44 / 28;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef->tag_1 ?? null,
+ 'tag_2' => $ef->tag_2 ?? null,
+ 'value' => $value,
+ 'ef_proportion' => $ef_proportion,
+ 'num_animal' => $num_animal,
+ 'ef_excretion_rate' => $ef_excretion_rate,
+ 'ef_tam' => $ef_tam,
+ 'nex' => $nex,
+ 'ef_nitrogen_fraction' => $ef_nitrogen_fraction,
+ 'ne_mms' => $ne_mms,
+ 'ef_mms' => $ef_mms,
+ 'n2o_d' => $n2o_d,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef->tag_1 ?? null,
+ 'tag_2' => $ef->tag_2 ?? null,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o_d')) / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
+// EDIT MONITOR
\ No newline at end of file
diff --git a/app/Services/Emisi/Agriculture3AService.php b/app/Services/Emisi/Agriculture3AService.php
new file mode 100644
index 0000000..05c2f8f
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3AService.php
@@ -0,0 +1,164 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3A') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getEfData($activityCode)
+ {
+ $order = ['weaning', 'yearling', 'young', 'mature', 'imported'];
+
+ // Prepare a CASE statement for custom sorting
+ $orderStat = 'CASE ';
+ foreach ($order as $index => $value) {
+ $orderStat .= "WHEN tag_1 = '$value' THEN " . ($index + 1) . " ";
+ }
+ // If there are other values, place them at the end
+ $orderStat .= "ELSE " . (count($order) + 1) . " END AS order_tag1";
+
+ $data = ReferenceEf::selectRaw("DISTINCT tag_1, $orderStat")
+ ->where('activity_code', $activityCode)
+ ->where(function ($query) {
+ $query->where(function ($subQuery) {
+ $subQuery->whereNotNull('tag_1')
+ ->whereNull('tag_2')
+ ->whereNull('tag_3');
+ })->orWhere(function ($subQuery) {
+ $subQuery->whereNull('tag_1')
+ ->whereNull('tag_2')
+ ->whereNull('tag_3');
+ });
+ })
+ ->isActive()->rowActive()->orderBy('order_tag1')
+ ->pluck('tag_1');
+
+ return $data;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $efs = $this->getEfData($activity);
+
+ foreach ($efs as $ef) {
+ $ef_proportion = ReferenceEf::getValue($activity, 'proportion', $ef);
+ $num_animal = $value == 0 ? 0 : round($value * $ef_proportion / 100, 0);
+ $ef_ef = ReferenceEf::getValue($activity, $ws->code . '_ef', $ef);
+ $ch4 = $value == 0 ? 0 : $num_animal * $ef_ef / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef ?? null,
+ 'value' => $value,
+ 'ef_proportion' => $ef_proportion,
+ 'num_animal' => $num_animal,
+ 'ef' => $ef_ef,
+ 'ch4' => $ch4,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef ?? null,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = array_sum(array_column($dataForms, 'ch4'));
+ $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Agriculture3C1Service.php b/app/Services/Emisi/Agriculture3C1Service.php
new file mode 100644
index 0000000..1030696
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3C1Service.php
@@ -0,0 +1,136 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3C1') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Initialize and get data activities
+ $activity = 'luas_panen_' . $ws->code;
+ $luas_panen = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, 'luas_panen_' . $ws->code);
+ $produktivitas = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, 'produktivitas_' . $ws->code);
+ $ef_burnt_fraction = ReferenceEf::getValue($activity, 'burnt_fraction');
+ $m_b = $luas_panen == 0 ? 0 : $luas_panen * $produktivitas / 10 * 1.4 / $luas_panen;
+
+ $ef_combustion_factor = ReferenceEf::getValue($activity, 'combustion_factor');
+ $ef_ch4 = ReferenceEf::getValue($activity, 'ch4_ef');
+ $ef_co = ReferenceEf::getValue($activity, 'co_ef');
+ $ef_n2o = ReferenceEf::getValue($activity, 'n2o_ef');
+ $ef_nox = ReferenceEf::getValue($activity, 'nox_ef');
+
+ $l_fire_ch4 = $luas_panen == 0 ? 0 : $luas_panen * $ef_burnt_fraction * $m_b * $ef_combustion_factor * $ef_ch4 / 1000;
+ $l_fire_co = $luas_panen == 0 ? 0 : $luas_panen * $ef_burnt_fraction * $m_b * $ef_combustion_factor * $ef_co / 1000;
+ $l_fire_n2o = $luas_panen == 0 ? 0 : $luas_panen * $ef_burnt_fraction * $m_b * $ef_combustion_factor * $ef_n2o / 1000;
+ $l_fire_nox = $luas_panen == 0 ? 0 : $luas_panen * $ef_burnt_fraction * $m_b * $ef_combustion_factor * $ef_nox / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'luas_panen' => $luas_panen,
+ 'produktivitas' => $produktivitas,
+ 'ef_burnt_fraction' => $ef_burnt_fraction,
+ 'm_b' => $m_b,
+ 'ef_combustion_factor' => $ef_combustion_factor,
+ 'ef_ch4' => $ef_ch4,
+ 'ef_co' => $ef_co,
+ 'ef_n2o' => $ef_n2o,
+ 'ef_nox' => $ef_nox,
+ 'l_fire_ch4' => $l_fire_ch4,
+ 'l_fire_co' => $l_fire_co,
+ 'l_fire_n2o' => $l_fire_n2o,
+ 'l_fire_nox' => $l_fire_nox,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = array_sum(array_column($dataForms, 'l_fire_ch4')) / 1000;
+ $n2o = array_sum(array_column($dataForms, 'l_fire_n2o')) / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Agriculture3C3Service.php b/app/Services/Emisi/Agriculture3C3Service.php
new file mode 100644
index 0000000..67e36cd
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3C3Service.php
@@ -0,0 +1,115 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3C3') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+
+ $activity = 'luas_panen_padi_sawah';
+ $urea = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, 'urea');
+
+ $ef_urea = ReferenceEf::getValue($activity, 'urea_ef');
+ $co2_emission = $urea == 0 ? 0 : $urea * $ef_urea * 44 / 12;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'urea' => $urea,
+ 'ef_urea' => $ef_urea,
+ 'co2_emission' => $co2_emission,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = array_sum(array_column($dataForms, 'co2_emission')) / 1000;
+ $ch4 = null;
+ $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Agriculture3C4Service.php b/app/Services/Emisi/Agriculture3C4Service.php
new file mode 100644
index 0000000..4f51805
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3C4Service.php
@@ -0,0 +1,268 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3C4') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $wsCode = $ws->ws_code;
+
+ $ricefields = [
+ 'luas_panen_padi_sawah' => 0,
+ 'luas_panen_padi_ladang' => 0,
+ ];
+
+ $crops = [];
+ $horticultures = [];
+ $fertilizers = [];
+
+ $total_fruit = 0;
+ $total_vegetable = 0;
+ $cropland_production = 0;
+
+ $total_crop = 0;
+ $total_horticulture = 0;
+ $total_area = 0;
+
+ $ef = [];
+
+ try {
+ $no = 1;
+
+ # inisialisasi get data ActivityFormDetail
+ $formTanamanPangan = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, 'tanaman_pangan');
+ $formHortikultura = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, 'hortikultura');
+ $formPupuk = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, 'pupuk');
+
+ # ambil data tanaman pangan
+ foreach ($formTanamanPangan as $row) $crops[$row->activity_code] = $row->activity_value ?? 0;
+
+ # ambil data tanaman hortikultura
+ foreach ($formHortikultura as $row) {
+ $horticultures[$row->activity_code] = $row->activity_value ?? 0;
+ $type = FruitVegetableCategory::getType($row->activity_code);
+ if ($type == 'fruit') $total_fruit += $row->activity_value;
+ else $total_vegetable += $row->activity_value;
+ }
+
+ # ambil data pupuk
+ foreach ($formPupuk as $row) $fertilizers[$row->activity_code] = $row->activity_value ?? 0;
+
+ # ambil data padi ladang dan padi sawah Note: ambil luas panen padi sawah & ladang
+ $formLuasPanen = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, 'sawah', ['luas_panen_padi_sawah', 'luas_panen_padi_ladang']);
+ foreach ($formLuasPanen as $row) $ricefields[$row->activity_code] = $row->activity_value ?? 0;
+
+ # ambil data produksi sawah
+ $formTanamanPangan = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, 'sawah', 'produksi_padi_sawah');
+ foreach ($formTanamanPangan as $row) $cropland_production = $row->activity_value;
+
+ # ambil data faktor emisi
+ $ef['managed_soils'] = ReferenceEf::getValue('luas_panen_padi_ladang', 'managed_soils');
+ $ef['flooded_rice'] = ReferenceEf::getValue('luas_panen_padi_sawah', 'flooded_rice');
+
+ # hitung semuanya
+ foreach ($ricefields as $value) $total_crop += $value;
+ foreach ($crops as $value) $total_crop += $value;
+ foreach ($horticultures as $value) $total_horticulture += $value;
+
+ $total_area = $total_crop + $total_horticulture;
+ $harvest_dry_area = $total_crop + $total_horticulture - $ricefields['luas_panen_padi_sawah'];
+ $harvest_ricefield_area = $ricefields['luas_panen_padi_sawah'];
+
+ $percentage_dry_area = $total_area == 0 ? 0 : (float) ($harvest_dry_area / $total_area);
+ $percentage_ricefield_area = $total_area == 0 ? 0 : (float) ($harvest_ricefield_area / $total_area);
+
+ #-----
+ # DATA PUPUK
+ # Semua variabel $plantations tidak dipake, Jakarta tidak ada kebun sawit
+ #-----
+ $n_urea = 0.46 * ($fertilizers['urea'] ?? 0);
+ $n_npk = 0.15 * ($fertilizers['npk'] ?? 0);
+ $n_za = 0.21 * ($fertilizers['za'] ?? 0);
+
+ $n_sinthetic = $n_urea + $n_npk + $n_za;
+
+ $n_dry_tonne = $percentage_dry_area * $n_sinthetic;
+ $n_ricefield_tonne = $percentage_ricefield_area * $n_sinthetic;
+
+ $n_dry_kg = $n_dry_tonne * 1000;
+ $n_ricefield_kg = $n_ricefield_tonne * 1000;
+ // $n_oil_palm_kg = 250 * $plantations['private_palm'] * 0.46;
+
+ $f_sn_dry = $n_dry_kg; // + $n_oil_palm_kg;
+ $f_sn_ricefield = $n_ricefield_kg;
+
+ $f_on_ricefield_tonne = $ricefields['luas_panen_padi_sawah'] * 2 * 0.16;
+ $f_on_ricefield_kg = $f_on_ricefield_tonne * 1000;
+
+ $ricefield_production_adj = $cropland_production * 1.4;
+ $f_cr_ricefield_tonne = $ricefield_production_adj * 0.3 * 0.005;
+ $f_cr_ricefield_kg = $f_cr_ricefield_tonne * 1000;
+
+ #-----
+ # TOTAL FRUIT = ALPUKAT s.d. SUKUN
+ # TOTAL VEGETABLES = SISANYA
+ #-----
+ $dry_land_non_veg = $total_crop + $total_fruit - $ricefields['luas_panen_padi_sawah'];
+ $f_on_dry_land_non_veg_tonne = $dry_land_non_veg * 2 * 0.16;
+ $f_on_dry_land_non_veg_kg = $f_on_dry_land_non_veg_tonne * 1000;
+
+ $dry_land_veg = $total_vegetable;
+ $f_on_dry_land_veg_tonne = $dry_land_veg * 10 * 0.005;
+ $f_on_dry_land_veg_kg = $f_on_dry_land_veg_tonne * 1000;
+
+ $f_on_dry_land_tonne = $f_on_dry_land_non_veg_tonne + $f_on_dry_land_veg_tonne;
+ $f_on_dry_land_kg = $f_on_dry_land_tonne * 1000;
+
+ $n2o_n_f_sn_managed_soils = $f_sn_dry * $ef['managed_soils']; # Masukkan tabel EF -- aktivitas = luas panen padi ladang
+ $n2o_n_f_on_managed_soils = $f_on_dry_land_kg * $ef['managed_soils'];
+
+ $n2o_n_f_sn_flooded_rice = $f_sn_ricefield * $ef['flooded_rice']; # Masukkan tabel EF -- aktivitas = luas panen padi sawah
+ $n2o_n_f_on_flooded_rice = $f_on_ricefield_kg * $ef['flooded_rice'];
+ $n2o_n_f_cr_flooded_rice = $f_cr_ricefield_kg * $ef['flooded_rice'];
+
+ $n2o_n_total =
+ $n2o_n_f_sn_managed_soils +
+ $n2o_n_f_on_managed_soils +
+ $n2o_n_f_sn_flooded_rice +
+ $n2o_n_f_on_flooded_rice +
+ $n2o_n_f_cr_flooded_rice;
+
+ # hitung emisi
+ $total_n2o = $n2o_n_total * 44 / 28;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'crop_area' => $total_crop,
+ 'horticulture_area' => $total_horticulture,
+ 'total_area' => $total_area,
+ 'harvest_dry_area' => $harvest_dry_area,
+ 'harvest_ricefield_area' => $harvest_ricefield_area,
+ 'percentage_dry_area' => $percentage_dry_area,
+ 'percentage_ricefield_area' => $percentage_ricefield_area,
+ 'urea' => $fertilizers['urea'] ?? 0,
+ 'npk' => $fertilizers['npk'] ?? 0,
+ 'za' => $fertilizers['za'] ?? 0,
+ 'n_urea' => $n_urea,
+ 'n_npk' => $n_npk,
+ 'n_za' => $n_za,
+ 'n_sinthetic' => $n_sinthetic,
+ 'n_dry_tonne' => $n_dry_tonne,
+ 'n_ricefield_tonne' => $n_ricefield_tonne,
+ 'n_dry_kg' => $n_dry_kg,
+ 'n_ricefield_kg' => $n_ricefield_kg,
+ 'f_sn_dry' => $f_sn_dry,
+ 'f_sn_ricefield' => $f_sn_ricefield,
+ 'f_on_ricefield_tonne' => $f_on_ricefield_tonne,
+ 'f_on_ricefield_kg' => $f_on_ricefield_kg,
+ 'ricefield_production' => $cropland_production,
+ 'ricefield_production_adj' => $ricefield_production_adj,
+ 'f_cr_ricefield_tonne' => $f_cr_ricefield_tonne,
+ 'f_cr_ricefield_kg' => $f_cr_ricefield_kg,
+ 'dry_land_non_veg' => $dry_land_non_veg,
+ 'f_on_dry_land_non_veg_tonne' => $f_on_dry_land_non_veg_tonne,
+ 'f_on_dry_land_non_veg_kg' => $f_on_dry_land_non_veg_kg,
+ 'dry_land_veg' => $dry_land_veg,
+ 'f_on_dry_land_veg_tonne' => $f_on_dry_land_veg_tonne,
+ 'f_on_dry_land_veg_kg' => $f_on_dry_land_veg_kg,
+ 'f_on_dry_land_tonne' => $f_on_dry_land_tonne,
+ 'f_on_dry_land_kg' => $f_on_dry_land_kg,
+ 'ef_managed_soils' => $ef['managed_soils'],
+ 'ef_flooded_rice' => $ef['flooded_rice'],
+ 'n2o_n_f_sn_managed_soils' => $n2o_n_f_sn_managed_soils,
+ 'n2o_n_f_on_managed_soils' => $n2o_n_f_on_managed_soils,
+ 'n2o_n_f_sn_flooded_rice' => $n2o_n_f_sn_flooded_rice,
+ 'n2o_n_f_on_flooded_rice' => $n2o_n_f_on_flooded_rice,
+ 'n2o_n_f_cr_flooded_rice' => $n2o_n_f_cr_flooded_rice,
+ 'n2o_n_total' => $total_n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o_n_total'));
+ $n2o = $n2o / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Agriculture3C5Service.php b/app/Services/Emisi/Agriculture3C5Service.php
new file mode 100644
index 0000000..37c904a
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3C5Service.php
@@ -0,0 +1,188 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3C5') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getAgriculture3A2b($inventoryYear, $activityYear)
+ {
+ $tags = ['weaning', 'yearling', 'young', 'mature', 'imported'];
+ $query = Agriculture3A2b::where('activity_code', 'sapi_potong')
+ ->where(function ($query) use ($tags) {
+ foreach ($tags as $tag) {
+ $query->orWhere(function ($query) use ($tag) {
+ $query->where('tag_1', $tag)
+ ->where('tag_2', 'pastura');
+ });
+ }
+ })
+ ->where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->get();
+
+ return $query;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // initialize variables
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ $data = [
+ 'grassland' => [
+ 'f_sn' => 0,
+ 'f_on' => 0,
+ 'f_prp' => 0,
+ ],
+ 'cropland' => [
+ 'f_sn' => 0,
+ 'f_on' => 0,
+ 'f_prp' => 0,
+ ],
+ ];
+
+ $ef = []; // Empty array for additional data
+
+ try {
+ $ws3c4 = Agriculture3C4::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)->rowActive()->first();
+
+ if ($ws3c4) {
+ # -----
+ # Dari worksheet 3A2, ambil NE MMS dari:
+ # 'beef_cattle_weaning_pastura', 'beef_cattle_yearling_pastura', 'beef_cattle_young_pastura', 'beef_cattle_mature_pastura', 'beef_cattle_imported_pastura'
+ # -----
+ $ws3a2b = $this->getAgriculture3A2b($inventoryYear, $activityYear);
+ $ne_mms = 0;
+ foreach ($ws3a2b as $p) {
+ $ne_mms += $p->ne_mms;
+ }
+
+ # -----
+ # Ambil data 3C4
+ # grassland = ladang
+ # cropland = sawah
+ # -----
+ $data['grassland']['f_sn'] = $ws3c4->f_sn_dry;
+ $data['grassland']['f_on'] = $ws3c4->f_on_dry_land_kg;
+ $data['grassland']['f_prp'] = $ne_mms;
+
+ $data['cropland']['f_sn'] = $ws3c4->f_sn_ricefield;
+ $data['cropland']['f_on'] = $ws3c4->f_on_ricefield_kg;
+ $data['cropland']['f_prp'] = 0;
+ }
+
+ # ambil data emisi
+ $ef['Frac_GASF'] = ReferenceEf::getValue('luas_panen_padi_sawah', 'frac_gasf');
+ $ef['Frac_GASM'] = ReferenceEf::getValue('luas_panen_padi_sawah', 'frac_gasm');
+ $ef['EF4'] = ReferenceEf::getValue('luas_panen_padi_sawah', 'ef4');
+
+ # hitung emisi
+ $no = 1;
+ foreach ($data as $land => $item) {
+ if ((float)$item['f_sn'] === 0.0 && (float)$item['f_on'] === 0.0 && (float)$item['f_prp'] === 0.0) {
+ $n2o_n = 0;
+ } else {
+ $n2o_n = ($item['f_sn'] * $ef['Frac_GASF'] + ($item['f_on'] + $item['f_prp']) * $ef['Frac_GASM']) * $ef['EF4'] * 44 / 28;
+ }
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'activity' => $land,
+ 'f_sn' => $item['f_sn'],
+ 'frac_gasf' => $ef['Frac_GASF'],
+ 'f_on' => $item['f_on'],
+ 'f_prp' => $item['f_prp'],
+ 'frac_gasm' => $ef['Frac_GASM'],
+ 'ef4' => $ef['EF4'],
+ 'n2o_n' => $n2o_n,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'activity' => $land,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o_n')) / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
+// EDIT MONITOR
\ No newline at end of file
diff --git a/app/Services/Emisi/Agriculture3C6Service.php b/app/Services/Emisi/Agriculture3C6Service.php
new file mode 100644
index 0000000..a442269
--- /dev/null
+++ b/app/Services/Emisi/Agriculture3C6Service.php
@@ -0,0 +1,199 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Agriculture3C6') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getEfData($activityCode)
+ {
+ $filterTag1 = ['weaning', 'yearling', 'young', 'mature', 'imported'];
+ $filterTag2 = ['pastura', 'dry_lot'];
+
+ // Prepare CASE statements for custom sorting
+ $orderTag1 = 'CASE tag_1 ';
+ foreach ($filterTag1 as $index => $value) {
+ $orderTag1 .= "WHEN '$value' THEN " . ($index + 1) . " ";
+ }
+ $orderTag1 .= "ELSE " . (count($filterTag1) + 1) . " END";
+
+ $orderTag2 = 'CASE tag_2 ';
+ foreach ($filterTag2 as $index => $value) {
+ $orderTag2 .= "WHEN '$value' THEN " . ($index + 1) . " ";
+ }
+ $orderTag2 .= "ELSE " . (count($filterTag2) + 1) . " END";
+
+ $data = ReferenceEf::select('tag_1', 'tag_2')
+ ->selectRaw("$orderTag1 AS order_tag1")
+ ->selectRaw("$orderTag2 AS order_tag2")
+ ->distinct()->where('activity_code', $activityCode)
+ ->where(function ($query) {
+ $query->where(function ($subQuery) {
+ $subQuery->whereNotNull('tag_1')
+ ->whereNotNull('tag_2')
+ ->whereNull('tag_3');
+ })->orWhere(function ($subQuery) {
+ $subQuery->whereNull('tag_1')
+ ->whereNull('tag_2')
+ ->whereNull('tag_3');
+ });
+ })
+ ->isActive()->rowActive()
+ ->orderByRaw('order_tag1')->orderByRaw('order_tag2')
+ ->get();
+
+ return $data;
+ }
+
+ private function getAgriculture3A2bData($array)
+ {
+ $query = Agriculture3A2b::query();
+
+ foreach ($array as $key => $value) {
+ $query->where($key, $value);
+ }
+
+ $data = $query->rowActive()->first();
+
+ return $data;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $efs = $this->getEfData($activity);
+
+ foreach ($efs as $ef) {
+ $param3A2B = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => '3A2b',
+ 'tag_1' => $ef->tag_1,
+ 'tag_2' => $ef->tag_2,
+ ];
+
+ $ne_mms = $this->getAgriculture3A2bData($param3A2B)->ne_mms ?? 0;
+ $ef_frac = ReferenceEf::getValue($activity, 'volatilised_fraction', $ef->tag_1, $ef->tag_2);
+ $n_volatilization_mms = $ne_mms * $ef_frac;
+ $ef_n2o = ReferenceEf::getValue($activity, 'n2o_ef', $ef->tag_1, $ef->tag_2);
+ $n2o_g = $n_volatilization_mms * $ef_n2o * 44 / 28;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef->tag_1 ?? null,
+ 'tag_2' => $ef->tag_2 ?? null,
+ 'value' => $value,
+ 'ne_mms' => $ne_mms,
+ 'ef_frac' => $ef_frac,
+ 'n_volatilization_mms' => $n_volatilization_mms,
+ 'ef_n2o' => $ef_n2o,
+ 'n2o_g' => $n2o_g,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'tag_1' => $ef->tag_1 ?? null,
+ 'tag_2' => $ef->tag_2 ?? null,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o_g')) / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Energy1AService.php b/app/Services/Emisi/Energy1AService.php
new file mode 100644
index 0000000..6a89de7
--- /dev/null
+++ b/app/Services/Emisi/Energy1AService.php
@@ -0,0 +1,134 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Energy1A') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $ws->code;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $ef_cf = ReferenceEf::getValue($activity, 'cf');
+ $ef_co2 = ReferenceEf::getValue($activity, 'co2_ef');
+ $ef_ch4 = ReferenceEf::getValue($activity, 'ch4_ef');
+ $ef_n2o = ReferenceEf::getValue($activity, 'n2o_ef');
+
+ $consumption_tj = $value * $ef_cf;
+ $emission_co2 = $consumption_tj * $ef_co2 / 1000000;
+ $emission_ch4 = $consumption_tj * $ef_ch4 / 1000000;
+ $emission_n2o = $consumption_tj * $ef_n2o / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'value' => $value,
+ 'ef_cf' => $ef_cf,
+ 'consumption_tj' => $consumption_tj,
+ 'ef_co2' => $ef_co2,
+ 'emission_co2' => $emission_co2,
+ 'ef_ch4' => $ef_ch4,
+ 'emission_ch4' => $emission_ch4,
+ 'ef_n2o' => $ef_n2o,
+ 'emission_n2o' => $emission_n2o,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = array_sum(array_column($dataForms, 'emission_co2'));
+ $ch4 = array_sum(array_column($dataForms, 'emission_ch4'));
+ $n2o = array_sum(array_column($dataForms, 'emission_n2o'));
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => 'energy',
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/EnergyGPCService.php b/app/Services/Emisi/EnergyGPCService.php
new file mode 100644
index 0000000..f7b335c
--- /dev/null
+++ b/app/Services/Emisi/EnergyGPCService.php
@@ -0,0 +1,333 @@
+model = $model;
+ }
+
+ public function save($inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $years = activityYearRange($inventoryYear);
+
+ foreach ($years as $year) {
+ $dataBatch[$year] = $this->calcAndSave($inventoryYear, $year);
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+
+ public function calcAndSave($inventoryYear, $activityYear)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ try {
+ // Initialize activities
+ $calc_i_1_3 = $this->calc_i_1_3($inventoryYear, $activityYear);
+ $calc_i_4_1 = $this->calc_i_4_1($inventoryYear, $activityYear);
+ $calc_i_4_2 = $this->calc_i_4_2($inventoryYear, $activityYear);
+ $calc_i_5_1 = $this->calc_i_5_1($inventoryYear, $activityYear);
+
+ $dataForms['calc_i_1_3'] = $calc_i_1_3;
+ $dataForms['calc_i_4_1'] = $calc_i_4_1;
+ $dataForms['calc_i_4_2'] = $calc_i_4_2;
+ $dataForms['calc_i_5_1'] = $calc_i_5_1;
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calc_i_1_3($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sectorCode = $this->sectorCode;
+ $formCode = 'transmisi_distribusi';
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sectorCode, $formCode);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sectorCode, $formCode);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $faktor_emisi = $activities['faktor_emisi'] ?? 0;
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ if ($activity != 'faktor_emisi') {
+ $co2_ton = $value * $faktor_emisi;
+ $co2_gg = $co2_ton / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'value' => $value,
+ 'faktor_emisi' => $faktor_emisi,
+ 'co2_ton' => $co2_ton,
+ 'co2_gg' => $co2_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'row_status' => 1,
+ ], $dataForm, EnergyGpcI13::class);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveGPCEmission($inventoryYear, $activityYear, $dataForms, 'i_1_3', 'co2_gg', null, null);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calc_i_4_1($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sectorCode = $this->sectorCode;
+ $formCode = 'penyulingan';
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sectorCode, $formCode);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sectorCode, $formCode);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $ef_co2 = ReferenceEf::getValue('energi_minyak_mentah', 'co2_ef');
+ $ef_ch4 = ReferenceEf::getValue('energi_minyak_mentah', 'ch4_ef');
+ $ef_n2o = ReferenceEf::getValue('energi_minyak_mentah', 'n2o_ef');
+
+ $tj = $activities['energi_minyak_mentah'] ?? 0;
+
+ $co2_ton = $tj == 0 ? 0 : $tj * $ef_co2;
+ $ch4_ton = $tj == 0 ? 0 : $tj * $ef_ch4;
+ $n2o_ton = $tj == 0 ? 0 : $tj * $ef_n2o;
+
+ $co2_gg = $tj == 0 ? 0 : $co2_ton / 1000;
+ $ch4_gg = $tj == 0 ? 0 : $ch4_ton / 1000;
+ $n2o_gg = $tj == 0 ? 0 : $n2o_ton / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => 'energi_minyak_mentah',
+ 'value_tj' => $tj,
+ 'ef_co2' => $ef_co2,
+ 'ef_ch4' => $ef_ch4,
+ 'ef_n2o' => $ef_n2o,
+ 'co2_ton' => $co2_ton,
+ 'ch4_ton' => $ch4_ton,
+ 'n2o_ton' => $n2o_ton,
+ 'co2_gg' => $co2_gg,
+ 'ch4_gg' => $ch4_gg,
+ 'n2o_gg' => $n2o_gg,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => 'energi_minyak_mentah',
+ 'row_status' => 1,
+ ], $dataForm, EnergyGpcI41::class);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveGPCEmission($inventoryYear, $activityYear, $dataForms, 'i_4_1', 'co2_gg', 'ch4_gg', 'n2o_gg');
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calc_i_4_2($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sectorCode = $this->sectorCode;
+ $formCode = 'penggunaan_tambahan';
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sectorCode, $formCode);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sectorCode, $formCode);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $faktor_emisi = $activities['faktor_emisi'] ?? 0;
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ if ($activity != 'faktor_emisi') {
+ $co2_ton = $value * $faktor_emisi;
+ $co2_gg = $co2_ton / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'value' => $value,
+ 'faktor_emisi' => $faktor_emisi,
+ 'co2_ton' => $co2_ton,
+ 'co2_gg' => $co2_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'row_status' => 1,
+ ], $dataForm, EnergyGpcI42::class);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveGPCEmission($inventoryYear, $activityYear, $dataForms, 'i_4_2', 'co2_gg', null, null);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calc_i_5_1($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sectorCode = $this->sectorCode;
+ $formCode = 'bangunan_pertanian';
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sectorCode, $formCode);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sectorCode, $formCode);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $ef_cf = ReferenceEf::getValue($activity, 'cf');
+ $ef_co2 = ReferenceEf::getValue($activity, 'co2_ef');
+ $ef_ch4 = ReferenceEf::getValue($activity, 'ch4_ef');
+ $ef_n2o = ReferenceEf::getValue($activity, 'n2o_ef');
+
+ $consumption_tj = $value * $ef_cf;
+ $co2_ton = $consumption_tj * $ef_co2 / 1000;
+ $ch4_ton = $consumption_tj * $ef_ch4 / 1000;
+ $n2o_ton = $consumption_tj * $ef_n2o / 1000;
+
+ $co2_gg = $co2_ton / 1000;
+ $ch4_gg = $ch4_ton / 1000;
+ $n2o_gg = $n2o_ton / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'value' => $value,
+ 'ef_cf' => $ef_cf,
+ 'consumption_tj' => $consumption_tj,
+ 'ef_co2' => $ef_co2,
+ 'ef_ch4' => $ef_ch4,
+ 'ef_n2o' => $ef_n2o,
+ 'co2_ton' => $co2_ton,
+ 'ch4_ton' => $ch4_ton,
+ 'n2o_ton' => $n2o_ton,
+ 'co2_gg' => $co2_gg,
+ 'ch4_gg' => $ch4_gg,
+ 'n2o_gg' => $n2o_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'row_status' => 1,
+ ], $dataForm, EnergyGpcI51::class);
+
+ $this->saveGPCEmission($inventoryYear, $activityYear, $dataForms, 'i_5_1', 'co2_gg', 'ch4_gg', 'n2o_gg');
+
+ $dataForms[] = $dataForm;
+ }
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveGPCEmission($inventoryYear, $activityYear, $dataForms, $gpcCode, $co2Code, $ch4Code, $n2oCode)
+ {
+ try {
+ $co2 = $co2Code ? array_sum(array_column($dataForms, $co2Code)) : null;
+ $ch4 = $ch4Code ? array_sum(array_column($dataForms, $ch4Code)) : null;
+ $n2o = $n2oCode ? array_sum(array_column($dataForms, $n2oCode)) : null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => 'energy_gpc',
+ 'gpc_code' => $gpcCode,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'gpc_code' => $gpcCode,
+ 'row_status' => 1,
+ ], $dataForm, ActivityGpc::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Folu3BService.php b/app/Services/Emisi/Folu3BService.php
new file mode 100644
index 0000000..83faa5f
--- /dev/null
+++ b/app/Services/Emisi/Folu3BService.php
@@ -0,0 +1,182 @@
+model = $model;
+ }
+
+ public function getDataLandCategories(string $fromKey, string $toKey): array
+ {
+ $fromCategory = LandCategory::tryFrom($fromKey);
+ $toCategory = LandCategory::tryFrom($toKey);
+
+ if ($toCategory === null) {
+ throw new \InvalidArgumentException("Invalid Key: {$toKey}");
+ }
+
+ $dataTo = LandCategory::getSubcategories($toCategory);
+ if ($fromCategory !== null) {
+ $dataFrom = LandCategory::getSubcategories($fromCategory);
+ } else {
+ $allSubcategories = [];
+ foreach (LandCategory::cases() as $category) {
+ if ($category !== $toCategory) {
+ $allSubcategories = array_merge($allSubcategories, LandCategory::getSubcategories($category));
+ }
+ }
+ $dataFrom = array_diff($allSubcategories, $dataTo);
+ }
+
+
+ return ['dataFrom' => array_values($dataFrom), 'dataTo' => array_values($dataTo)];
+ // return $this->getLandActivityCodes($dataFrom, $dataTo);
+ }
+
+ public function getLandActivityCodes($lands1, $lands2)
+ {
+ $activityCodes = [];
+ foreach ($lands1 as $land1) {
+ foreach ($lands2 as $land2) {
+ $activityCodes[] = $land1 . '_' . $land2;
+ }
+ }
+
+ return $activityCodes;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+ // $activityYear = $inventoryYear - 1;
+
+ list($fromKey, $toKey) = explode('_', $code);
+ $lands = $this->getDataLandCategories($fromKey, $toKey);
+
+ if ($ws && class_basename($ws->model) == 'Folu3B') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws, $lands));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws, $lands)
+ {
+ // Initialize variables
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ $lands1 = $lands['dataFrom'];
+ $lands2 = $lands['dataTo'];
+
+ try {
+ // Initialize and get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($activityYear + 1, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $no = 1;
+ foreach ($lands2 as $land2) {
+ foreach ($lands1 as $land1) {
+ $activity = $land1 . '_' . $land2;
+
+ $area = $activities[$land1 . '_' . $land2] ?? 0;
+ $ef_agb_before = ReferenceEf::getValue($land1 . '_' . $land1, 'agb');
+ $c_before = $area * ($ef_agb_before + 0.37);
+ $ef_agb_after = ReferenceEf::getValue($land2 . '_' . $land2, 'agb');
+ $c_after = $area * ($ef_agb_after + 0.37);
+ $c_change = $c_after - $c_before;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'before' => $land1,
+ 'after' => $land2,
+ 'area' => $area,
+ 'ef_agb_before' => $ef_agb_before,
+ 'c_before' => $c_before,
+ 'ef_agb_after' => $ef_agb_after,
+ 'c_after' => $c_after,
+ 'c_change' => $c_change,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'before' => $land1,
+ 'after' => $land2,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = array_sum(array_column($dataForms, 'c_change'));
+ $co2 = -1 * $co2 * 44 / 12 / 1000;
+ $ch4 = null;
+ $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/GpcMappingService.php b/app/Services/Emisi/GpcMappingService.php
new file mode 100644
index 0000000..07856b0
--- /dev/null
+++ b/app/Services/Emisi/GpcMappingService.php
@@ -0,0 +1,233 @@
+model = $model;
+ }
+
+ public function save($inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $years = activityYearRange($inventoryYear);
+
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year));
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function calcPlnEmission($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sectorCode = 'energy';
+ $formCode = 'pln';
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sectorCode, $formCode);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sectorCode, $formCode);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $ef_listrik_terkoreksi = $activities['ef_listrik_terkoreksi'];
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ if ($activity != 'ef_listrik_terkoreksi') {
+ $co2_ton = $value * $ef_listrik_terkoreksi;
+ $co2_gg = $co2_ton / 1000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'value' => $value,
+ 'ef_listrik_terkoreksi' => $ef_listrik_terkoreksi,
+ 'co2_ton' => $co2_ton,
+ 'co2_gg' => $co2_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'row_status' => 1,
+ ], $dataForm, EnergyPLN::class);
+
+ $dataForms[] = $dataForm;
+ }
+ }
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getDataGpcList()
+ {
+ $query = ReferenceGpc::rowActive()->orderByRowNum()->get();
+ return $query;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ try {
+ $this->calcPlnEmission($inventoryYear, $activityYear);
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, 'waste', 'kependudukan');
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $gpc_output['inventory_year'] = $inventoryYear;
+ $gpc_output['activity_year'] = $activityYear;
+
+ $gpc_output['population'] = $activities['jumlah_penduduk'] ?? 0;
+ $gpc_output['area'] = $activities['luas_wilayah'] ?? 0;
+ $gpc_output['gdp'] = $activities['pdb'] ?? 0;
+
+ $gpcList = $this->getDataGpcList();
+
+ foreach ($gpcList as $gpc) {
+ $columnName = strtolower(str_replace('.', '_', $gpc->gpc_code));
+ $gpc_output[$columnName] = null;
+
+ // Handle PLN listrik sector
+ if (strpos($gpc->sub_sector, 'pln_listrik_') === 0) {
+ list(, $activityCode) = explode('_', $gpc->sub_sector, 2);
+
+ $pln = EnergyPLN::rowActive()
+ ->where('activity_code', $activityCode)
+ ->where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->first();
+
+ $gpc_output[$columnName] = $pln->co2_gg ?? null;
+ continue;
+ }
+
+ // Handle transportation sector
+ if ($gpc->sector === 'transportation' && $gpc->sub_sector !== null) {
+ $transCategories = TransportationCategory::getTransportationCategories($gpc->sub_sector);
+
+ $activities = Energy1A::rowActive()->where('category', $gpc->ipcc_code)
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->whereIn('activity_code', $transCategories)->get();
+
+ $co2eq = $this->calculateCO2eq($activities);
+ $gpc_output[$columnName] = $co2eq ?? null;
+ continue;
+ }
+
+ // Handle CRF (3A, 3B, 3C) related IPCC codes
+ if (!is_null($gpc->ipcc_code)) {
+ if (in_array($gpc->ipcc_code, ['3A', '3B', '3C'])) {
+ $gpc_output[$columnName] = $this->getCrfSumForCode($gpc->ipcc_code, $inventoryYear, $activityYear);
+ } else {
+ $crf = ActivityCrf::rowActive()->where('ws_code', $gpc->ipcc_code)
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->first();
+
+ $gpc_output[$columnName] = $crf->co2eq ?? null;
+ }
+ continue;
+ }
+
+ // Handle energy_gpc sector
+ if ($gpc->sector === 'energy_gpc') {
+ $gpc_output[$columnName] = $this->getEnergyGpcValue($columnName, $gpc, $inventoryYear, $activityYear);
+ }
+ }
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'row_status' => 1,
+ ], $gpc_output);
+
+ $dataForms[] = $gpc_output;
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function calculateCO2eq($activities)
+ {
+ $co2 = $activities->sum('emission_co2');
+ $ch4 = $activities->sum('emission_ch4');
+ $n2o = $activities->sum('emission_n2o');
+ $gwp = $this->getGWPValues();
+
+ return ($co2 ? $co2 * $gwp['CO2']->value : 0) +
+ ($ch4 ? $ch4 * $gwp['CH4']->value : 0) +
+ ($n2o ? $n2o * $gwp['N2O']->value : 0);
+ }
+
+ // Helper function to handle CRF code 3A, 3B, 3C queries
+ private function getCrfSumForCode($ipccCode, $inventoryYear, $activityYear)
+ {
+ $crfQuery = ActivityCrf::rowActive()->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear);
+
+ if ($ipccCode == '3B') {
+ $crfQuery->where('ws_code', 'like', '3B%')->orWhere('ws_code', '3C1');
+ } elseif ($ipccCode == '3C') {
+ $crfQuery->where('ws_code', 'like', '3C%')->where('ws_code', '!=', '3C1');
+ } else {
+ $crfQuery->where('ws_code', 'like', '3A%');
+ }
+
+ return $crfQuery->sum('co2eq') ?: null;
+ }
+
+ // Helper function to handle energy_gpc values based on gpc code and subsector
+ private function getEnergyGpcValue($gpcCode, $gpc, $inventoryYear, $activityYear)
+ {
+ if ($gpcCode == 'i_4_1') {
+ $gpcQ = ActivityGpc::rowActive()->where('gpc_code', $gpcCode)
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->first();
+
+ return (float)$gpcQ->co2eq != 0.0 ? $gpcQ->co2eq :
+ ActivityFormDetail::getValue($inventoryYear, $activityYear, $gpc->sector, 'penyulingan', 'emisi_minyak_mentah') ?? null;
+ }
+
+ if (in_array($gpcCode, ['i_7_1', 'i_8_1'])) {
+ return ActivityFormDetail::getValue($inventoryYear, $activityYear, $gpc->sector, $gpc->sub_sector, 'emisi') ?? null;
+ }
+
+ $crf = ActivityGpc::rowActive()
+ ->where('sector', $gpc->sector)->where('gpc_code', $gpcCode)
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->first();
+
+ return $crf->co2eq ?? null;
+ }
+}
diff --git a/app/Services/Emisi/Ippu1AService.php b/app/Services/Emisi/Ippu1AService.php
new file mode 100644
index 0000000..13ca528
--- /dev/null
+++ b/app/Services/Emisi/Ippu1AService.php
@@ -0,0 +1,191 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Ippu1A') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $ws->code;
+ $wsCode = $ws->ws_code;
+
+ // dd($sector, $code, $wsCode);
+
+ try {
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ //cf
+ // IPPU / Produksi:
+ // - Klinker EF: 0.52 ton CO2/ton
+ // - Kapur EF: 0.75 ton CO2/ton
+ // - Amonia EF: 3.273 ton CO2/ton
+ // - Asam Nitrat EF: 0.009 ton N2O/ton
+ // - Carbon Black EF: 2.62 ton CO2/ton + 0.0006 ton CH4/ton
+ // - Etilen EF: 1.74 ton CO2/ton + 0.003 ton CH4/ton
+ // - Etilen Diklorida EF: 0.196 ton CO2/ton + 0.00179 ton CH4/ton
+ // - Vinil Klorida EF: 0.294 ton CO2/ton + 0.000226 ton CH4/ton
+ $co2Ef = [
+ "klinker" => 0.52,
+ "kapur" => 0.75,
+ "amonia" => 3.273,
+ "urea" => 0,
+ "asam_nitrat" => 0.009,
+ "asam_nitrat_tambahan" => 0,
+ "silikon_karbida" => 0,
+ "kalsium_karbida" => 0,
+ "metanol" => 0,
+ "etilen" => 1.74,
+ "etilen_diklorida" => 0.196,
+ "vinil_klorida" => 0.294,
+ "carbon_black" => 2.62,
+ "basic_oxygen_furnace" => 0,
+ "pig_iron" => 0,
+ "direct_reducted_iron" => 0,
+ "electric_arc_furnace" => 0,
+ "aluminium" => 0,
+ "timbal" => 0,
+ "zinc" => 0,
+ ];
+
+ $ch4Ef = [
+ "klinker" => 0,
+ "kapur" => 0,
+ "amonia" => 0,
+ "urea" => 0,
+ "asam_nitrat" => 0,
+ "asam_nitrat_tambahan" => 0,
+ "silikon_karbida" => 0,
+ "kalsium_karbida" => 0,
+ "metanol" => 0,
+ "etilen" => 0.003,
+ "etilen_diklorida" => 0.00179,
+ "vinil_klorida" => 0.000226,
+ "carbon_black" => 0.0006,
+ "basic_oxygen_furnace" => 0,
+ "pig_iron" => 0,
+ "direct_reducted_iron" => 0,
+ "electric_arc_furnace" => 0,
+ "aluminium" => 0,
+ "timbal" => 0,
+ "zinc" => 0,
+ ];
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $ef_cf = 0;
+ $ef_co2 = $co2Ef[$activity];
+ $ef_ch4 = $ch4Ef[$activity];
+ $ef_n2o = 0;
+
+ $consumption_tj = 0;
+ $emission_co2 = $ef_co2 * $value;
+ $emission_ch4 = $ef_ch4 * $value;
+ $emission_n2o = $ef_n2o * $value;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'value' => $value,
+ 'ef_cf' => $ef_cf,
+ 'consumption_tj' => $consumption_tj,
+ 'ef_co2' => $ef_co2,
+ 'emission_co2' => $emission_co2,
+ 'ef_ch4' => $ef_ch4,
+ 'emission_ch4' => $emission_ch4,
+ 'ef_n2o' => $ef_n2o,
+ 'emission_n2o' => $emission_n2o,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = array_sum(array_column($dataForms, 'emission_co2'));
+ $ch4 = array_sum(array_column($dataForms, 'emission_ch4'));
+ $n2o = array_sum(array_column($dataForms, 'emission_n2o'));
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => $ws->ws_code,
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4AMethaneService.php b/app/Services/Emisi/Waste4AMethaneService.php
new file mode 100644
index 0000000..a015f24
--- /dev/null
+++ b/app/Services/Emisi/Waste4AMethaneService.php
@@ -0,0 +1,138 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear, false);
+
+ if ($ws && class_basename($ws->model) == 'Waste4AMethane') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ # deklarasi variabel
+ $items = ['sisa_makanan', 'kertas', 'nappies', 'taman', 'kayu', 'tekstil'];
+ $activities = [];
+
+ # inisialisasi data aktivitas
+ foreach ($items as $item) {
+ $activities[$item . '_amount'] = 0;
+ $activities[$item . '_dry_matter'] = 0;
+ }
+
+ try {
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ # ambil data aktivitas
+ $ws4a_pre = Waste4APre::whereIn('activity', ['amount', 'dry_matter'])
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->get();
+
+ foreach ($ws4a_pre as $row) {
+ foreach ($items as $item) {
+ $activities[$item . '_' . $row->activity] = $row->$item;
+ }
+ }
+
+ # ambil ddocm_accumulated tahun sebelumnya
+ $no = 1;
+ foreach ($items as $item) {
+ $ws4a_methane = [];
+ if (abs($activityYear - $inventoryYear) == 15) {
+ $ws4a_methane = Waste4AMethane::where('activity_year', $activityYear - 1)
+ ->where('activity_code', $item)->rowActive()->orderBy('updated_at', 'DESC')->first();
+ } else {
+ $ws4a_methane = Waste4AMethane::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear - 1)
+ ->where('activity_code', $item)->rowActive()->orderBy('updated_at', 'DESC')->first();
+ }
+
+ $ddocm_accumulated_prev = $ws4a_methane->ddocm_accumulated ?? 0;
+ $ef_doc = ReferenceEf::getValue($item, 'DOC');
+ $ef_docf = ReferenceEf::getValue($item, 'DOCf');
+ $ef_exp1 = ReferenceEf::getValue($item, 'exp1');
+ $ef_exp2 = ReferenceEf::getValue($item, 'exp2');
+ $ef_f = ReferenceEf::getValue($item, 'F');
+ $ef_mcf = ReferenceEf::getValue('timbulan_sampah', 'total_weighted_mcf');
+
+ $amount = $activities[$item . '_amount'] ?? 0;
+ $dry_matter = $activities[$item . '_dry_matter'] ? $activities[$item . '_dry_matter'] / 100 : 0;
+
+ $ddocm_deposited = $amount * $dry_matter * $ef_doc * $ef_docf * $ef_mcf;
+ $ddocm_unreacted = $ddocm_deposited * $ef_exp2;
+ $ddocm_decomposed_1 = $ddocm_deposited * (1 - $ef_exp2);
+ $ddocm_accumulated = $ddocm_unreacted + ($ddocm_accumulated_prev * $ef_exp1);
+ $ddocm_decomposed_2 = $ddocm_accumulated_prev * (1 - $ef_exp1) + $ddocm_decomposed_1;
+ $ch4 = $ddocm_decomposed_2 * $ef_f * 16 / 12;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'activity_code' => $item,
+ 'amount' => $amount,
+ 'dry_matter' => $dry_matter,
+ 'ef_doc' => $ef_doc,
+ 'ef_docf' => $ef_docf,
+ 'ef_exp1' => $ef_exp1,
+ 'ef_exp2' => $ef_exp2,
+ 'ef_f' => $ef_f,
+ 'ef_mcf' => $ef_mcf,
+
+ 'ddocm_deposited' => $ddocm_deposited,
+ 'ddocm_unreacted' => $ddocm_unreacted,
+ 'ddocm_decomposed_1' => $ddocm_decomposed_1,
+ 'ddocm_accumulated' => $ddocm_accumulated,
+ 'ddocm_accumulated_prev' => $ddocm_accumulated_prev,
+ 'ddocm_decomposed_2' => $ddocm_decomposed_2,
+ 'ch4' => $ch4,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'activity_code' => $item,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4APreService.php b/app/Services/Emisi/Waste4APreService.php
new file mode 100644
index 0000000..faee778
--- /dev/null
+++ b/app/Services/Emisi/Waste4APreService.php
@@ -0,0 +1,107 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4APre') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ $items = ['sisa_makanan', 'kertas', 'nappies', 'taman', 'kayu', 'tekstil', 'karet_kulit', 'plastik', 'logam', 'kaca', 'anorganik_lainnya'];
+ $activities = [];
+ $total_waste = 0;
+
+ try {
+ $activity = 'timbulan_sampah';
+ $value = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, $activity);
+ $total_waste = $value / 1000;
+
+ foreach ($items as $item) {
+ $activities['composition'][$item] = 0;
+ $activities['dry_matter'][$item] = 0;
+ $activities['amount'][$item] = 0;
+ }
+
+ $formBahanSampah = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $this->sectorCode, 'bahan_kering_sampah');
+ foreach ($formBahanSampah as $row) {
+ if (!preg_match('/_bahan_kering$/', $row->activity_code)) {
+ $activities['composition'][$row->activity_code] = $row->activity_value;
+ $activities['amount'][$row->activity_code] = $total_waste * $row->activity_value / 100;
+ } else {
+ $strCode = str_replace('_bahan_kering', '', $row->activity_code);
+ $activities['dry_matter'][$strCode] = $row->activity_value;
+ }
+ }
+
+ # hitung emisi
+ $no = 1;
+ foreach ($activities as $activity => $row) {
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'activity' => $activity,
+ 'value' => $value,
+ 'total_waste' => $total_waste,
+ 'row_num' => $no++,
+ ];
+
+ foreach ($items as $item) {
+ $dataForm[$item] = $row[$item];
+ }
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'activity' => $activity,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4AService.php b/app/Services/Emisi/Waste4AService.php
new file mode 100644
index 0000000..03473f7
--- /dev/null
+++ b/app/Services/Emisi/Waste4AService.php
@@ -0,0 +1,130 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear, false);
+
+ if ($ws && class_basename($ws->model) == 'Waste4A') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ # deklarasi variabel
+ $items = ['sisa_makanan', 'kertas', 'nappies', 'taman', 'kayu', 'tekstil'];
+ $activities = [];
+ $ch4_recovery = 0;
+ $total = 0;
+
+ # inisialisasi data aktivitas
+ foreach ($items as $item) {
+ $activities[$item] = 0;
+ }
+
+ try {
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ # ambil data aktivitas
+ $ws4a_methane = Waste4AMethane::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->rowActive()->get();
+
+ foreach ($ws4a_methane as $row) {
+ $activities[$row->activity_code] = $row->ch4 ?? 0;
+ }
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'row_num' => $no++,
+ ];
+
+ foreach ($activities as $activity => $value) {
+ $total += $value;
+ $dataForm[$activity] = $value;
+ }
+
+ $dataForm['total'] = $total;
+ $dataForm['ch4_recovery'] = $ch4_recovery;
+ $dataForm['ch4'] = $total - $ch4_recovery;
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ // 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = array_sum(array_column($dataForms, 'ch4'));
+ $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4A1',
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4A1',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4B1Service.php b/app/Services/Emisi/Waste4B1Service.php
new file mode 100644
index 0000000..81094e1
--- /dev/null
+++ b/app/Services/Emisi/Waste4B1Service.php
@@ -0,0 +1,144 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4B1') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getKomposBasedOnInventoryYear($inventoryYear, $activityYear)
+ {
+ $form = ActivityForm::where('inventory_year', $inventoryYear)
+ ->where('sector', 'waste')->where('form_code', 'pengelolaan_sampah')->whereNull('agency_id')
+ ->rowActive()->first();
+
+ if ($form) {
+ $activityFormDetail = ActivityFormDetail::where('form_id', $form->id)
+ ->where('activity_year', $activityYear)
+ ->where('activity_code', 'kompos')
+ ->rowActive()
+ ->first();
+
+ return $activityFormDetail ? $activityFormDetail->activity_value : 0;
+ }
+
+ return 0;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ $activity = 'timbulan_sampah';
+ $value = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, $activity);
+
+ $kompos = $this->getKomposBasedOnInventoryYear($inventoryYear, $activityYear);
+ $num_waste = $value / 1000 * $kompos / 100;
+ $ef = ReferenceEf::getValue($activity, 'ef_ch4', 'kompos');
+ $ch4 = $num_waste * 0.5053375 * $ef / 1000;
+ $ch4_recovery = 0.00;
+ $ch4_final = $ch4 - $ch4_recovery;
+
+ $no = 1;
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'value' => $value,
+ 'kompos' => $kompos,
+ 'num_waste' => $num_waste,
+ 'ef' => $ef,
+ 'ch4' => $ch4,
+ 'ch4_recovery' => $ch4_recovery,
+ 'ch4_final' => $ch4_final,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ $ch4 = array_sum(array_column($dataForms, 'ch4_final'));
+ // $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4B',
+ 'co2' => $co2,
+ 'ch4' => $ch4,
+ // 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4B',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4B2Service.php b/app/Services/Emisi/Waste4B2Service.php
new file mode 100644
index 0000000..cc67fe3
--- /dev/null
+++ b/app/Services/Emisi/Waste4B2Service.php
@@ -0,0 +1,140 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4B2') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function getKomposBasedOnInventoryYear($inventoryYear, $activityYear)
+ {
+ $form = ActivityForm::where('inventory_year', $inventoryYear)
+ ->where('sector', 'waste')->where('form_code', 'pengelolaan_sampah')->whereNull('agency_id')
+ ->rowActive()->first();
+
+ if ($form) {
+ $activityFormDetail = ActivityFormDetail::where('form_id', $form->id)
+ ->where('activity_year', $activityYear)
+ ->where('activity_code', 'kompos')
+ ->rowActive()
+ ->first();
+
+ return $activityFormDetail ? $activityFormDetail->activity_value : 0;
+ }
+
+ return 0;
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ // Initialize variables
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ $activity = 'timbulan_sampah';
+ $value = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, $activity);
+
+ $kompos = $this->getKomposBasedOnInventoryYear($inventoryYear, $activityYear);
+ $num_waste = $value / 1000 * $kompos / 100;
+ $ef = ReferenceEf::getValue($activity, 'ef_n2o', 'kompos');
+ $n2o = $num_waste * 0.5053375 * $ef / 1000;
+
+ $no = 1;
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'value' => $value,
+ 'kompos' => $kompos,
+ 'num_waste' => $num_waste,
+ 'ef' => $ef,
+ 'n2o' => $n2o,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = null;
+ // $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o'));
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4B',
+ 'co2' => $co2,
+ // 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4B',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4C1Service.php b/app/Services/Emisi/Waste4C1Service.php
new file mode 100644
index 0000000..3a57318
--- /dev/null
+++ b/app/Services/Emisi/Waste4C1Service.php
@@ -0,0 +1,86 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4C1') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+
+ // ambil data aktivitas
+ $population = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, 'jumlah_penduduk');
+ $fraction = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, 'pengelolaan_sampah', 'dibakar');
+ $waste_rate = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, 'sampah', 'laju_timbulan_sampah');
+
+ $ef_b_frac = ReferenceEf::getValue('laju_timbulan_sampah', 'b_frac');
+ $msw_b = $population * ($fraction / 100) * $waste_rate * ($ef_b_frac / 100) / 1000;
+
+ $no = 1;
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'population' => $population,
+ 'fraction' => $fraction,
+ 'msw_p' => $waste_rate,
+ 'ef_b_frac' => $ef_b_frac,
+ 'msw_b' => $msw_b,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4C2aService.php b/app/Services/Emisi/Waste4C2aService.php
new file mode 100644
index 0000000..0e8489f
--- /dev/null
+++ b/app/Services/Emisi/Waste4C2aService.php
@@ -0,0 +1,150 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4C2a') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ # deklarasi variabel
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ $items = ['kertas', 'tekstil', 'nappies', 'karet_kulit', 'plastik', 'anorganik_lainnya'];
+ $activities = [];
+ $open_burned = 0;
+
+ # inisialisasi data aktivitas
+ foreach ($items as $item) {
+ $activities[$item . '_composition'] = 0;
+ $activities[$item . '_dry_matter'] = 0;
+ }
+
+ try {
+ # ambil data aktivitas
+ $ws4a_pre = Waste4APre::whereIn('activity', ['composition', 'dry_matter'])
+ ->where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->get();
+
+ foreach ($ws4a_pre as $row) {
+ foreach ($items as $item) {
+ $activities[$item . '_' . $row->activity] = $row->$item;
+ }
+ }
+
+ $ws4c1 = Waste4C1::where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->first();
+ $msw_b = $ws4c1->msw_b ?? 0;
+
+ $no = 1;
+ foreach ($items as $item) {
+ $open_burned = $activities[$item . '_composition'] * $msw_b / 100;
+
+ $ef_carbon_f = ReferenceEf::getValue($item, 'carbon_f');
+ $ef_fossil_carbon_f = ReferenceEf::getValue($item, 'fossil_carbon_f');
+ $ef_oxidation_f = ReferenceEf::getValue($item, 'oxidation_f');
+ $ef_cf = ReferenceEf::getValue($item, 'cf');
+
+ $co2 = $open_burned * ($activities[$item . '_dry_matter'] / 100) * $ef_carbon_f * $ef_fossil_carbon_f * $ef_oxidation_f * $ef_cf;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'activity_code' => $item,
+ 'composition' => $activities[$item . '_composition'],
+ 'msw_b' => $msw_b,
+ 'open_burned' => $open_burned,
+ 'dry_matter' => $activities[$item . '_dry_matter'],
+ 'ef_carbon_f' => $ef_carbon_f,
+ 'ef_fossil_carbon_f' => $ef_fossil_carbon_f,
+ 'ef_oxidation_f' => $ef_oxidation_f,
+ 'ef_cf' => $ef_cf,
+ 'co2' => $co2,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'activity_code' => $item,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ $co2 = array_sum(array_column($dataForms, 'co2'));
+ // $ch4 = null;
+ // $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ 'co2' => $co2,
+ // 'ch4' => $ch4,
+ // 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4C2bService.php b/app/Services/Emisi/Waste4C2bService.php
new file mode 100644
index 0000000..5274a66
--- /dev/null
+++ b/app/Services/Emisi/Waste4C2bService.php
@@ -0,0 +1,115 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4C2b') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ # deklarasi variabel
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ $open_burned = 0;
+
+ try {
+ # ambil data aktivitas
+ $ws4c1 = Waste4C1::where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->first();
+
+ $open_burned = $ws4c1->msw_b ?? 0;
+ $methane_ef = ReferenceEf::getValue('laju_timbulan_sampah', 'methane_ef');
+ $ch4 = $open_burned * $methane_ef / 1000000;
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'open_burned' => $open_burned,
+ 'ef' => $methane_ef,
+ 'ch4' => $ch4,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ // $co2 = null
+ $ch4 = array_sum(array_column($dataForms, 'ch4'));
+ // $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ // 'co2' => $co2,
+ 'ch4' => $ch4,
+ // 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4C2cService.php b/app/Services/Emisi/Waste4C2cService.php
new file mode 100644
index 0000000..ea3002b
--- /dev/null
+++ b/app/Services/Emisi/Waste4C2cService.php
@@ -0,0 +1,118 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4C2c') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ # deklarasi variabel
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ $open_burned = 0;
+
+ try {
+ # ambil data aktivitas
+ $ws4c1 = Waste4C1::where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->first();
+
+ $open_burned = $ws4c1->msw_b ?? 0;
+ $ef_msw = ReferenceEf::getValue('laju_timbulan_sampah', 'msw');
+ $ef_nitrous_oxide = ReferenceEf::getValue('laju_timbulan_sampah', 'nitrous_oxide_ef');
+ $n2o = $open_burned * $ef_msw * $ef_nitrous_oxide / 1000000;
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'open_burned' => $open_burned,
+ 'ef_msw' => $ef_msw,
+ 'ef_nitrous_oxide' => $ef_nitrous_oxide,
+ 'n2o' => $n2o,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ // $co2 = null;
+ // $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o'));
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ // 'co2' => $co2,
+ // 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4C',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4D1aService.php b/app/Services/Emisi/Waste4D1aService.php
new file mode 100644
index 0000000..c6bab3e
--- /dev/null
+++ b/app/Services/Emisi/Waste4D1aService.php
@@ -0,0 +1,83 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4D1a') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ $dataForms = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // ambil data aktivitas
+ $population = ActivityFormDetail::getValue($inventoryYear, $activityYear, $sector, $code, 'jumlah_penduduk');
+ $ef_bod = ReferenceEf::getValue('jumlah_penduduk', 'BOD');
+ $ef_cf = ReferenceEf::getValue('jumlah_penduduk', 'CF');
+ $tow = $population * $ef_bod * $ef_cf;
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'population' => $population,
+ 'ef_bod' => $ef_bod,
+ 'ef_correction_factor' => $ef_cf,
+ 'tow' => $tow,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4D1cService.php b/app/Services/Emisi/Waste4D1cService.php
new file mode 100644
index 0000000..1397e1c
--- /dev/null
+++ b/app/Services/Emisi/Waste4D1cService.php
@@ -0,0 +1,140 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4D1c') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ $group_fraction = 100;
+
+ try {
+ // ambil data aktivitas
+ // Initialize activities
+ $formSetting = $this->getDataSettingFormDetail($sector, $code);
+ foreach ($formSetting as $row) $activities[$row->activity_code] = 0;
+
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $ws4d1a = Waste4D1a::where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->first();
+ $tow = $ws4d1a->tow ?? 0;
+
+ $no = 1;
+ foreach ($activities as $activity => $value) {
+ $usage_level = $value / 100;
+ $ef = ReferenceEf::getValue($activity, 'ef');
+ $ef_sludge_removed = ReferenceEf::getValue($activity, 'sludge_removed');
+ $ef_methane_flared = ReferenceEf::getValue($activity, 'methane_flared');
+ $ch4_kg = ($group_fraction / 100) * ($value / 100) * $ef * $tow;
+ $ch4_gg = $ch4_kg / 1000000;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'group_fraction' => $group_fraction,
+ 'value' => $value,
+ 'usage_level' => $usage_level,
+ 'ef' => $ef,
+ 'tow' => $tow,
+ 'ef_sludge_removed' => $ef_sludge_removed,
+ 'ef_methane_flared' => $ef_methane_flared,
+ 'ch4_kg' => $ch4_kg,
+ 'ch4_gg' => $ch4_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'activity_code' => $activity,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+ }
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ // $co2 = null;
+ $ch4 = array_sum(array_column($dataForms, 'ch4_gg'));
+ // $n2o = null;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4D1',
+ // 'co2' => $co2,
+ 'ch4' => $ch4,
+ // 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4D1',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4D1dService.php b/app/Services/Emisi/Waste4D1dService.php
new file mode 100644
index 0000000..644bdbd
--- /dev/null
+++ b/app/Services/Emisi/Waste4D1dService.php
@@ -0,0 +1,94 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4D1d') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ $dataForms = [];
+ $activities = [];
+
+ $sector = $this->sectorCode;
+ $code = $this->formCode;
+ $wsCode = $ws->ws_code;
+
+ try {
+ // Get data activities
+ $formActivity = $this->getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $code);
+ foreach ($formActivity as $row) $activities[$row->activity_code] = $row->activity_value ?? 0;
+
+ $population = $activities['jumlah_penduduk'] ?? 0;
+ $protein = $activities['protein_per_kapita'] ?? 0;
+
+ $ef_f_npr = ReferenceEf::getValue('protein_per_kapita', 'F_NPR');
+ $ef_f_non_con = ReferenceEf::getValue('protein_per_kapita', 'F_NON_CON');
+ $ef_f_ind_com = ReferenceEf::getValue('protein_per_kapita', 'F_IND_COM');
+ $ef_n_sludge = ReferenceEf::getValue('protein_per_kapita', 'N_sludge');
+
+ $n_effluent = ($population * $protein * $ef_f_npr * $ef_f_non_con * $ef_f_ind_com) - $ef_n_sludge;
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'population' => $population,
+ 'protein' => $protein,
+ 'ef_f_npr' => $ef_f_npr,
+ 'ef_f_non_con' => $ef_f_non_con,
+ 'ef_f_ind_com' => $ef_f_ind_com,
+ 'ef_n_sludge' => $ef_n_sludge,
+ 'n_effluent' => $n_effluent,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Emisi/Waste4D1eService.php b/app/Services/Emisi/Waste4D1eService.php
new file mode 100644
index 0000000..a1594c0
--- /dev/null
+++ b/app/Services/Emisi/Waste4D1eService.php
@@ -0,0 +1,117 @@
+model = $model;
+ }
+
+ public function save($code, $inventoryYear)
+ {
+ try {
+ $dataBatch = [];
+ $ws = $this->getWs($code);
+ $years = activityYearRange($inventoryYear);
+
+ if ($ws && class_basename($ws->model) == 'Waste4D1e') {
+ foreach ($years as $year) {
+ $dataBatch = array_merge($dataBatch, $this->calcAndSave($inventoryYear, $year, $ws));
+ }
+ } else {
+ throw new \Exception("Forbidden");
+ }
+
+ return $dataBatch;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function calcAndSave($inventoryYear, $activityYear, $ws)
+ {
+ $dataForms = [];
+ $wsCode = $ws->ws_code;
+
+ try {
+ $ws4d1d = Waste4D1d::where('inventory_year', $inventoryYear)->where('activity_year', $activityYear)
+ ->rowActive()->first();
+ $n_effluent = $ws4d1d->n_effluent ?? 0;
+
+ $ef = ReferenceEf::getValue('protein_per_kapita', 'ef');
+ $ef_cf = ReferenceEf::getValue('protein_per_kapita', 'cf');
+ $ef_ipal_emission = ReferenceEf::getValue('protein_per_kapita', 'ipal_emission');
+
+ $n2o_kg = ($n_effluent * $ef * $ef_cf) - $ef_ipal_emission;
+ $n2o_gg = $n2o_kg / 1000000;
+
+ $no = 1;
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'n_effluent' => $n_effluent,
+ 'ef' => $ef,
+ 'ef_conversion_factor' => $ef_cf,
+ 'ef_ipal_emission' => $ef_ipal_emission,
+ 'n2o_kg' => $n2o_kg,
+ 'n2o_gg' => $n2o_gg,
+ 'row_num' => $no++,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'category' => $wsCode,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ $dataForms[] = $dataForm;
+
+ $this->saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms);
+
+ return $dataForms;
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function saveCrfEmission($inventoryYear, $activityYear, $ws, $dataForms)
+ {
+ try {
+ // $co2 = null;
+ // $ch4 = null;
+ $n2o = array_sum(array_column($dataForms, 'n2o_gg'));
+
+ $dataForm = [
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4D1',
+ // 'co2' => $co2,
+ // 'ch4' => $ch4,
+ 'n2o' => $n2o,
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $inventoryYear,
+ 'activity_year' => $activityYear,
+ 'sector' => $this->sectorCode,
+ 'ws_code' => '4D1',
+ 'row_status' => 1,
+ ], $dataForm, ActivityCrf::class);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Reports/CrfService.php b/app/Services/Reports/CrfService.php
new file mode 100644
index 0000000..bd0c308
--- /dev/null
+++ b/app/Services/Reports/CrfService.php
@@ -0,0 +1,26 @@
+isActive();
+ })->get();
+
+ return $activeGwpRecords;
+ }
+}
diff --git a/app/Services/Reports/GcomCrfService.php b/app/Services/Reports/GcomCrfService.php
new file mode 100644
index 0000000..8675a0d
--- /dev/null
+++ b/app/Services/Reports/GcomCrfService.php
@@ -0,0 +1,14 @@
+where('sector', $code)
+ ->orderByRowNum()->isSub()
+ ->get();
+ }
+
+ public function getWorksheet($code, $wsCode)
+ {
+ return ReferenceWs::where('sector', $code)->where('ws_code', $wsCode)->rowActive()->first();
+ }
+
+ public function getEmissionsData($modelClass, $inventoryYear, $activityYear, $wsCode = null)
+ {
+ // Check if the model class exists
+ if (!class_exists($modelClass)) {
+ return collect();
+ }
+
+ // Fetch emissions data
+ $query = $modelClass::where('inventory_year', $inventoryYear)
+ ->where('activity_year', $activityYear)
+ ->orderByRowNum()
+ ->rowActive();
+
+ // Get the table name from the model
+ $table = (new $modelClass)->getTable();
+
+ // Check if the 'category' column exists in the table
+ if (Schema::hasColumn($table, 'category')) {
+ $query->where('category', $wsCode);
+ }
+
+ return $query->get();
+ }
+}
diff --git a/app/Services/Setting/ArService.php b/app/Services/Setting/ArService.php
new file mode 100644
index 0000000..6c95f06
--- /dev/null
+++ b/app/Services/Setting/ArService.php
@@ -0,0 +1,40 @@
+update([
+ 'active_status' => 0,
+ 'updated_by' => Auth::user()->name
+ ]);
+
+ $ar = ReferenceAr::find($id);
+ if ($ar) {
+ $this->update($ar, ['active_status' => 1]);
+ }
+
+ DB::commit();
+
+ return $ar;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Setting/DataAktivitasService.php b/app/Services/Setting/DataAktivitasService.php
new file mode 100644
index 0000000..b70f251
--- /dev/null
+++ b/app/Services/Setting/DataAktivitasService.php
@@ -0,0 +1,72 @@
+orderByRowNum()->get();
+ // return Sector::toArray();
+ }
+
+ public function save($data)
+ {
+ $id = $data['id'] ?? null;
+ $file = CmsFileDataAktivitas::rowActive()->where('id', $id)->first();
+ $storagePath = 'data_aktivitas/' . $data['sector'] . '/' . $data['inventory_year'];
+
+ if ($file) {
+ $currentFilePath = 'data_aktivitas/' . $file->sector . '/' . $file->inventory_year . '/' . $file->file_upload;
+
+ if ($file->inventory_year !== $data['inventory_year'] || $file->sector !== $data['sector']) {
+ if (Storage::disk('public')->exists($currentFilePath)) {
+ $newFilePath = $storagePath . '/' . $file->file_upload;
+ Storage::disk('public')->move($currentFilePath, $newFilePath);
+ }
+ }
+
+ $data['file_upload'] = $file->file_upload;
+ if (isset($data['file_document'])) {
+ $oldFilePath = $storagePath . '/' . $file->file_upload;
+
+ if ($file->file_upload != $data['file_document']->hashName()) {
+ Storage::disk('public')->delete($oldFilePath);
+ }
+
+ $data['file_upload'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $this->update($file, $data);
+ } else {
+ if (isset($data['file_document'])) {
+ $data['file_upload'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $file = $this->create($data);
+ }
+
+ return $file;
+ }
+
+ public function destroy(CmsFileDataAktivitas $fileData, $storagePath)
+ {
+ if ($fileData) {
+ $oldFilePath = $storagePath . '/' . $fileData->file_upload;
+ Storage::disk('public')->delete($oldFilePath);
+
+ $this->delete($fileData);
+ }
+ }
+}
diff --git a/app/Services/Setting/EfService.php b/app/Services/Setting/EfService.php
new file mode 100644
index 0000000..0bc2443
--- /dev/null
+++ b/app/Services/Setting/EfService.php
@@ -0,0 +1,47 @@
+select('code', 'name')
+ ->orderBy('name','ASC')
+ ->get();
+
+ return $activities;
+ }
+
+ public function getCategories($activityCode = null)
+ {
+ if ($activityCode == 'SEMUA AKTIVITAS' || is_null($activityCode)) {
+ return ReferenceEf::distinct()->rowActive()->pluck('category');
+ }
+
+ return ReferenceEf::distinct()
+ ->rowActive()
+ ->where('activity_code', $activityCode)
+ ->pluck('category');
+ }
+
+ public function getEfSources()
+ {
+ $efSource = ReferenceEfSource::rowActive()
+ ->select('code', 'name')
+ ->get();
+
+ return $efSource;
+ }
+}
diff --git a/app/Services/Setting/EfSourceService.php b/app/Services/Setting/EfSourceService.php
new file mode 100644
index 0000000..ef65497
--- /dev/null
+++ b/app/Services/Setting/EfSourceService.php
@@ -0,0 +1,16 @@
+model->select('ghg_code', 'ar_code', 'value')
+ ->orderBy('ghg_code')
+ ->orderBy('ar_code')
+ ->rowActive()
+ ->get()
+ ->groupBy('ghg_code')
+ ->map(function ($item) {
+ return $item->keyBy('ar_code');
+ });
+ }
+
+ public function save(array $data)
+ {
+ DB::transaction(function () use ($data) {
+ foreach ($data['gwp'] as $ghgCode => $values) {
+ foreach ($values as $arCode => $value) {
+ $isExist = $this->model
+ ->where('ghg_code', $ghgCode)
+ ->where('ar_code', $arCode)
+ ->rowActive()
+ ->first();
+
+ if (!empty($value)) {
+ $newValue = getOriginalValue($value);
+ if ($isExist) {
+ $oldValue = (float) rtrim(rtrim($isExist->value, '0'), ',');
+ if ($oldValue != $newValue) {
+ $this->update($isExist, ['value' => $newValue]);
+ }
+ } else {
+ // Create new record
+ $this->create([
+ 'ghg_code' => $ghgCode,
+ 'ar_code' => $arCode,
+ 'value' => $newValue,
+ ]);
+ }
+ } else {
+ if ($isExist) {
+ $this->delete($isExist);
+ }
+ }
+ }
+ }
+ });
+ }
+
+ // private function defaultNumber($value)
+ // {
+ // $value = str_replace('.', '', $value); // Remove periods
+ // $value = str_replace(',', '.', $value); // Replace commas with periods
+
+ // if (is_numeric($value)) {
+ // return (float) $value;
+ // }
+
+ // return null;
+ // }
+
+ // private function defaultNumber($value)
+ // {
+ // $value = str_replace(',', '', $value); // Remove periods
+
+ // if (is_numeric($value)) {
+ // return (float) $value;
+ // }
+
+ // return null;
+ // }
+}
diff --git a/app/Services/Setting/PeraturanService.php b/app/Services/Setting/PeraturanService.php
new file mode 100644
index 0000000..2d9cf97
--- /dev/null
+++ b/app/Services/Setting/PeraturanService.php
@@ -0,0 +1,56 @@
+where('id', $id)->first();
+ $storagePath = 'peraturan';
+
+ if ($file) {
+ $data['file_upload'] = $file->file_upload;
+ if (isset($data['file_document'])) {
+ $oldFilePath = $storagePath . '/' . $file->file_upload;
+
+ if ($file->file_upload != $data['file_document']->hashName()) {
+ Storage::disk('public')->delete($oldFilePath);
+ }
+
+ $data['file_upload'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $this->update($file, $data);
+ } else {
+ if (isset($data['file_document'])) {
+ $data['file_upload'] = basename($data['file_document']->store($storagePath, 'public'));
+ }
+
+ $file = $this->create($data);
+ }
+
+ return $file;
+ }
+
+ public function destroy(CmsFilePeraturan $fileData, $storagePath)
+ {
+ if ($fileData) {
+ $oldFilePath = $storagePath . '/' . $fileData->file_upload;
+ Storage::disk('public')->delete($oldFilePath);
+
+ $this->delete($fileData);
+ }
+ }
+}
diff --git a/app/Services/Setting/UnitConversionService.php b/app/Services/Setting/UnitConversionService.php
new file mode 100644
index 0000000..e0eaa0a
--- /dev/null
+++ b/app/Services/Setting/UnitConversionService.php
@@ -0,0 +1,72 @@
+rowActive()->pluck('category');
+ }
+
+ public function getUnitsByCategory($category)
+ {
+ return ReferenceUnit::where('category', $category)->rowActive()->orderByRowNum()->get();
+ }
+
+ public function getConversionsByCategory($category)
+ {
+ return ReferenceUnitConversion::where('category', $category)
+ ->rowActive()->get()
+ ->groupBy('from_unit_code')->map(function ($item) {
+ return $item->keyBy('to_unit_code');
+ });
+ }
+
+ public function save($category, array $conversions)
+ {
+ DB::transaction(function () use ($category, $conversions) {
+ foreach ($conversions as $fromUnitCode => $values) {
+ foreach ($values as $toUnitCode => $value) {
+ $isExist = ReferenceUnitConversion::where('category', $category)
+ ->where('from_unit_code', $fromUnitCode)
+ ->where('to_unit_code', $toUnitCode)
+ ->rowActive()
+ ->first();
+
+ if (!empty($value)) {
+ $newValue = getOriginalValue($value);
+ if ($isExist) {
+ $oldValue = (float) rtrim(rtrim($isExist->value, '0'), ',');
+ if ($oldValue != $newValue) {
+ $this->update($isExist, ['value' => $newValue]);
+ }
+ } else {
+ // Create new record
+ $this->create([
+ 'category' => $category,
+ 'from_unit_code' => $fromUnitCode,
+ 'to_unit_code' => $toUnitCode,
+ 'value' => $newValue,
+ ]);
+ }
+ } else {
+ if ($isExist) {
+ $this->delete($isExist);
+ }
+ }
+ }
+ }
+ });
+ }
+}
diff --git a/app/Services/Setting/UnitService.php b/app/Services/Setting/UnitService.php
new file mode 100644
index 0000000..199e1fe
--- /dev/null
+++ b/app/Services/Setting/UnitService.php
@@ -0,0 +1,19 @@
+rowActive()->pluck('category');
+ }
+}
diff --git a/app/Services/SigdCrudService.php b/app/Services/SigdCrudService.php
new file mode 100644
index 0000000..f5511e1
--- /dev/null
+++ b/app/Services/SigdCrudService.php
@@ -0,0 +1,237 @@
+model = $model;
+ }
+
+ public function getAll()
+ {
+ return $this->model->rowActive()->orderByRowNum()->get();
+ }
+
+ public function getRawAll()
+ {
+ return $this->model->rowActive()->orderByRowNum();
+ }
+
+ public function find($id)
+ {
+ return $this->model->rowActive()->findOrFail($id);
+ }
+
+ public function create(array $data, $modelClass = null)
+ {
+ try {
+ DB::beginTransaction();
+
+ $uuid = (string) Str::uuid();
+
+ $data['id'] = $uuid;
+ $data['created_by'] = Auth::user()->name ?? 'superadmin';
+
+ if (!$modelClass) {
+ $model = $this->model->create($data);
+ } else {
+ $model = new $modelClass;
+ $model->fill($data);
+ $model->save();
+ }
+
+ DB::commit();
+
+ return $model;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function update(Model $model, array $data)
+ {
+ try {
+ DB::beginTransaction();
+
+ $data['updated_by'] = Auth::user()->name;
+ $model->update($data);
+
+ DB::commit();
+
+ return $model;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function createOrUpdate(array $attributes, array $values, $modelClass = null)
+ {
+ try {
+ DB::beginTransaction();
+
+ $model = $modelClass ? new $modelClass : $this->model;
+
+ $record = $model->where($attributes)->first();
+
+ if ($record) {
+ $values['updated_by'] = Auth::user()->name ?? 'superadmin';
+ $record->update($values);
+ } else {
+ $values['id'] = (string) Str::uuid();
+ $values['created_by'] = Auth::user()->name ?? 'superadmin';
+ $record = $model->create($values);
+ }
+
+ DB::commit();
+
+ return $record;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function delete(Model $model)
+ {
+ try {
+ DB::beginTransaction();
+
+ $model->row_status = 0;
+ $model->updated_at = now();
+ $model->updated_by = Auth::user()->name ?? 'superadmin';
+ $model->save();
+
+ DB::commit();
+
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function getActivityForm($sector, $code, $inventoryYear)
+ {
+ return ActivityForm::where('sector', $sector)
+ ->where('form_code', $code)->where('inventory_year', $inventoryYear)->whereNull('agency_id')
+ ->rowActive()->orderBy('inventory_year', 'desc')
+ ->first();
+ }
+
+ public function getActivityFormDetails($formId)
+ {
+ return ActivityFormDetail::where('form_id', $formId)
+ ->rowActive()->orderBy('activity_year', 'desc')
+ ->get()->groupBy('activity_year');
+ }
+
+ public function getWs($wsCode)
+ {
+ return ReferenceWs::select('code', 'ws_code', 'model')
+ ->where('code', $wsCode)
+ ->rowActive()->first();
+ }
+
+ public static function getActivityFormDetailsByYear($inventoryYear, $activityYear, $sector, $formCode, $activityCodes = null)
+ {
+ $form = ActivityForm::where('inventory_year', $inventoryYear)
+ ->where('sector', $sector)
+ ->where('form_code', $formCode)->whereNull('agency_id')
+ ->rowActive()
+ ->first();
+
+ if ($form) {
+ $query = ActivityFormDetail::where('form_id', $form->id)
+ ->where('activity_year', $activityYear)
+ ->rowActive();
+
+ if ($activityCodes !== null) {
+ if (is_array($activityCodes)) {
+ $query->whereIn('activity_code', $activityCodes);
+ } else {
+ $query->where('activity_code', $activityCodes);
+ }
+ }
+
+ $activityFormDetail = $query->get();
+ return $activityFormDetail->isNotEmpty() ? $activityFormDetail : [];
+ }
+
+ return [];
+ }
+
+ public static function getActivityFormDetailsGroupedByYear($inventoryYear, $sector, $formCode)
+ {
+ $form = ActivityForm::where('inventory_year', $inventoryYear)
+ ->where('sector', $sector)->where('form_code', $formCode)->whereNull('agency_id')
+ ->rowActive()->orderBy('inventory_year', 'desc')
+ ->first();
+
+ if ($form) {
+ $query = ActivityFormDetail::where('form_id', $form->id)
+ ->rowActive()->orderBy('activity_year', 'desc')
+ ->get()->groupBy('activity_year');
+
+ $activityFormDetail = $query;
+ return $activityFormDetail->isNotEmpty() ? $activityFormDetail : [];
+ }
+
+ return [];
+ }
+
+ public static function getDataSettingFormDetail($sector, $code)
+ {
+ $form = SettingForm::rowActive()->where('sector', $sector)->where('code', $code)->first();
+
+ if ($form) {
+ $formDetails = SettingFormDetail::rowActive()->where('form_code', $code)->orderByRowNum()->get();
+ return $formDetails;
+ }
+
+ return [];
+ }
+
+ public function getGWPValues()
+ {
+ $gwp = ReferenceGwp::whereHas('ar', function ($query) {
+ $query->isActive();
+ })->get();
+
+ return $gwp->keyBy('ghg_code');
+ }
+
+ public function getDataApproval($sector, $code, $inventoryYear, $isRaw = false)
+ {
+ $query = ActivityApprovalKonsolidasi::where([
+ 'form_sector' => $sector,
+ 'form_code' => $code,
+ 'inventory_year' => $inventoryYear,
+ ])->rowActive();
+
+ if (!$isRaw) {
+ $query->get();
+ }
+
+ return $query;
+ }
+}
diff --git a/app/Services/Tool/CalculationService.php b/app/Services/Tool/CalculationService.php
new file mode 100644
index 0000000..14024dd
--- /dev/null
+++ b/app/Services/Tool/CalculationService.php
@@ -0,0 +1,20 @@
+orderByRowNum()->get();
+ }
+}
diff --git a/app/Services/Tool/CopyActivityService.php b/app/Services/Tool/CopyActivityService.php
new file mode 100644
index 0000000..6534d96
--- /dev/null
+++ b/app/Services/Tool/CopyActivityService.php
@@ -0,0 +1,149 @@
+whereNot('sector', 'folu')->rowActive()->get();
+
+ // Delete existing ActivityForm and ActivityFormDetail for the toYear
+ ActivityForm::where('inventory_year', $toYear)
+ ->whereNot('sector', 'folu')->rowActive()
+ ->each(function ($form) {
+ $formDetail = ActivityFormDetail::where('form_id', $form->id)->get();
+ foreach ($formDetail as $item) {
+ $this->delete($item);
+ };
+
+ $this->delete($form);
+ });
+
+ foreach ($activityForms as $activityForm) {
+ $dataForm = [
+ 'sector' => $activityForm->sector,
+ 'form_code' => $activityForm->form_code,
+ 'inventory_year' => $toYear,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+ 'agency_id' => $activityForm->agency_id, // new column
+ ];
+
+ $newActivityForm = $this->create($dataForm, ActivityForm::class);
+ logUserActivity(ActivityType::COPY_ACTIVITY_FORM, $newActivityForm->id);
+
+ $activityFormDetails = ActivityFormDetail::where('form_id', $activityForm->id)
+ ->whereIn('activity_year', $activityYears)->rowActive()->get();
+
+ foreach ($activityFormDetails as $detail) {
+ $dataFormDetail = [
+ 'form_id' => $newActivityForm->id,
+ 'activity_year' => $detail->activity_year,
+ 'activity_code' => $detail->activity_code,
+ 'activity_unit_code' => $detail->activity_unit_code,
+ 'activity_value' => $detail->activity_value,
+ ];
+
+ $newActivityFormDetail = $this->create($dataFormDetail, ActivityFormDetail::class);
+ }
+ }
+
+ DB::commit();
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+
+ // CopyDataAll if exist replace
+ // public function copyAllData($fromYear, $toYear)
+ // {
+ // DB::beginTransaction();
+
+ // try {
+ // $activityYears = activityYearRange($toYear);
+ // $activityForms = ActivityForm::where('inventory_year', $fromYear)
+ // ->whereNot('sector', 'folu')->rowActive()->get();
+
+ // foreach ($activityForms as $activityForm) {
+ // $existingForm = ActivityForm::where('inventory_year', $toYear)
+ // ->where('form_code', $activityForm->form_code)
+ // ->whereNot('sector', 'folu')->rowActive()->first();
+
+ // if ($existingForm) {
+ // $existingForm->update([
+ // 'updated_by' => Auth::user()->name,
+ // ]);
+
+ // $newActivityForm = $existingForm;
+ // } else {
+ // $dataForm = [
+ // 'sector' => $activityForm->sector,
+ // 'form_code' => $activityForm->form_code,
+ // 'inventory_year' => $toYear,
+ // 'verification_status' => 'unverified',
+ // 'validation_status' => 'unvalidated',
+ // 'lock_status' => 'open',
+ // ];
+
+ // $newActivityForm = $this->create($dataForm, ActivityForm::class);
+ // }
+
+ // logUserActivity(ActivityType::COPY_ACTIVITY_FORM, $newActivityForm->id);
+ // $activityFormDetails = ActivityFormDetail::where('form_id', $activityForm->id)
+ // ->whereIn('activity_year', $activityYears)->rowActive()->get();
+
+ // foreach ($activityFormDetails as $detail) {
+ // $existingDetail = ActivityFormDetail::where('form_id', $newActivityForm->id)
+ // ->where('activity_year', $detail->activity_year)
+ // ->where('activity_code', $detail->activity_code)
+ // ->rowActive()->first();
+
+ // if ($existingDetail) {
+ // $existingDetail->update([
+ // 'activity_value' => $detail->activity_value,
+ // 'updated_by' => Auth::user()->name,
+ // ]);
+ // } else {
+ // $dataFormDetail = [
+ // 'form_id' => $newActivityForm->id,
+ // 'activity_year' => $detail->activity_year,
+ // 'activity_code' => $detail->activity_code,
+ // 'activity_unit_code' => $detail->activity_unit_code,
+ // 'activity_value' => $detail->activity_value,
+ // ];
+
+ // $newActivityFormDetail = $this->create($dataFormDetail, ActivityFormDetail::class);
+ // }
+ // }
+ // }
+
+ // DB::commit();
+ // return true;
+ // } catch (\Exception $e) {
+ // DB::rollBack();
+ // throw $e;
+ // }
+ // }
+}
diff --git a/app/Services/Tool/LockActivityService.php b/app/Services/Tool/LockActivityService.php
new file mode 100644
index 0000000..4959e6f
--- /dev/null
+++ b/app/Services/Tool/LockActivityService.php
@@ -0,0 +1,139 @@
+model = $model;
+ }
+
+ public function lock(int $year)
+ {
+ $dataForm = [
+ 'inventory_year' => $year,
+ 'lock_status' => 'locked',
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $year,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ logUserActivity(ActivityType::LOCK_ACTIVITY_FORM);
+ }
+
+ public function unlock(int $year)
+ {
+ $dataForm = [
+ 'inventory_year' => $year,
+ 'lock_status' => 'open',
+ ];
+
+ $this->createOrUpdate([
+ 'inventory_year' => $year,
+ 'row_status' => 1,
+ ], $dataForm);
+
+ logUserActivity(ActivityType::UNLOCK_ACTIVITY_FORM);
+ }
+
+ public function isYearLocked(int $year): bool
+ {
+ $lock = ActivityLock::where('inventory_year', $year)->first();
+ return $lock ? $lock->lock_status : 'open';
+ }
+
+ public function copyActivityToNextYear($year)
+ {
+ try {
+ $executeTime = now();
+ $this->copyAllData($year, $year + 1);
+ $this->logCopyActivity($year, $year + 1, $executeTime);
+ } catch (\Exception $e) {
+ throw $e;
+ }
+ }
+
+ public function logCopyActivity($year, $nextYear, $time)
+ {
+ $copyRequest = [
+ 'from_year' => $year,
+ 'to_year' => $nextYear,
+ 'executed_time' => $time,
+ 'finished_time' => now(),
+ 'status' => SigdStatus::SELESAI,
+ ];
+
+ $this->create($copyRequest, ActivityCopy::class);
+ }
+
+ public function copyAllData($fromYear, $toYear)
+ {
+ DB::beginTransaction();
+
+ try {
+ $activityYears = activityYearRange($toYear);
+ $activityForms = ActivityForm::where('inventory_year', $fromYear)
+ ->whereNot('sector', 'folu')->rowActive()->get();
+
+ // Delete existing ActivityForm and ActivityFormDetail for the toYear
+ ActivityForm::where('inventory_year', $toYear)
+ ->whereNot('sector', 'folu')->rowActive()
+ ->each(function ($form) {
+ $formDetail = ActivityFormDetail::where('form_id', $form->id)->get();
+ foreach ($formDetail as $item) {
+ $this->delete($item);
+ };
+
+ $this->delete($form);
+ });
+
+ foreach ($activityForms as $activityForm) {
+ $dataForm = [
+ 'sector' => $activityForm->sector,
+ 'form_code' => $activityForm->form_code,
+ 'inventory_year' => $toYear,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+ 'agency_id' => $activityForm->agency_id, // new column
+ ];
+
+ $newActivityForm = $this->create($dataForm, ActivityForm::class);
+ logUserActivity(ActivityType::COPY_ACTIVITY_FORM, $newActivityForm->id);
+
+ $activityFormDetails = ActivityFormDetail::where('form_id', $activityForm->id)
+ ->whereIn('activity_year', $activityYears)->rowActive()->get();
+
+ foreach ($activityFormDetails as $detail) {
+ $dataFormDetail = [
+ 'form_id' => $newActivityForm->id,
+ 'activity_year' => $detail->activity_year,
+ 'activity_code' => $detail->activity_code,
+ 'activity_unit_code' => $detail->activity_unit_code,
+ 'activity_value' => $detail->activity_value,
+ ];
+
+ $newActivityFormDetail = $this->create($dataFormDetail, ActivityFormDetail::class);
+ }
+ }
+
+ DB::commit();
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/Tool/ProdusenCalculateService.php b/app/Services/Tool/ProdusenCalculateService.php
new file mode 100644
index 0000000..a00c01e
--- /dev/null
+++ b/app/Services/Tool/ProdusenCalculateService.php
@@ -0,0 +1,102 @@
+where('status', 1)->pluck('agency_id')->toArray();
+
+ $activityForms = ActivityForm::where('inventory_year', $inventoryYear)
+ ->whereNotNull('agency_id')->whereIn('agency_id', $produsen)->rowActive()->get();
+ $formIds = $activityForms->pluck('id')->toArray();
+
+ $distinctActivity = ActivityForm::where('inventory_year', $inventoryYear)
+ ->whereNotNull('agency_id')->whereIn('agency_id', $produsen)->rowActive()
+ ->select('sector', 'form_code', 'inventory_year')->distinct()->get();
+
+ foreach ($distinctActivity as $activityForm) {
+ ActivityForm::rowActive()
+ ->where('sector', $activityForm->sector)->where('form_code', $activityForm->form_code)
+ ->where('inventory_year', $activityForm->inventory_year)
+ ->whereNull('agency_id')->each(function ($form) {
+ $formDetail = ActivityFormDetail::where('form_id', $form->id)->get();
+ foreach ($formDetail as $item) {
+ $this->delete($item);
+ };
+
+ $this->delete($form);
+ });
+
+ $dataForm = [
+ 'sector' => $activityForm->sector,
+ 'form_code' => $activityForm->form_code,
+ 'inventory_year' => $activityForm->inventory_year,
+ 'verification_status' => 'unverified',
+ 'validation_status' => 'unvalidated',
+ 'lock_status' => 'open',
+ ];
+
+ $mainActivityForm = $this->create($dataForm, ActivityForm::class);
+ logUserActivity(ActivityType::PRODUSEN_CALCULATE, $mainActivityForm->id);
+
+ $activityFormDetails = ActivityFormDetail::whereIn('form_id', $formIds)
+ ->whereHas('form', function ($query) use ($activityForm) {
+ $query->where('sector', $activityForm->sector)
+ ->where('form_code', $activityForm->form_code)
+ ->where('inventory_year', $activityForm->inventory_year);
+ })
+ ->rowActive()->groupBy('activity_year', 'activity_code', 'activity_unit_code')
+ ->selectRaw('activity_year, activity_code, activity_unit_code, SUM(activity_value) AS activity_value')
+ ->whereIn('activity_year', $activityYears)
+ ->get();
+
+ foreach ($activityFormDetails as $detail) {
+ $dataFormDetail = [
+ 'form_id' => $mainActivityForm->id,
+ 'activity_year' => $detail->activity_year,
+ 'activity_code' => $detail->activity_code,
+ 'activity_unit_code' => $detail->activity_unit_code,
+ 'activity_value' => $detail->activity_value,
+ ];
+
+ $this->createOrUpdate([
+ 'form_id' => $mainActivityForm->id,
+ 'activity_year' => $detail->activity_year,
+ 'activity_code' => $detail->activity_code,
+ 'activity_unit_code' => $detail->activity_unit_code,
+ 'row_status' => 1,
+ ], $dataFormDetail, ActivityFormDetail::class);
+ }
+ }
+
+ DB::commit();
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/User/AgencyService.php b/app/Services/User/AgencyService.php
new file mode 100644
index 0000000..102ccde
--- /dev/null
+++ b/app/Services/User/AgencyService.php
@@ -0,0 +1,43 @@
+agencyActivity()->delete();
+
+ foreach ($permissions as $permission) {
+ list($sector, $code) = explode('|', $permission);
+ $dataForms = [
+ 'agency_id' => $agency->id,
+ 'form_sector' => $sector,
+ 'form_code' => $code
+ ];
+
+ $this->create($dataForms, AgencyActivity::class);
+ }
+
+ DB::commit();
+
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/User/UserGroupService.php b/app/Services/User/UserGroupService.php
new file mode 100644
index 0000000..b220d02
--- /dev/null
+++ b/app/Services/User/UserGroupService.php
@@ -0,0 +1,89 @@
+first();
+ if ($dasborMenu) {
+ $userGroup->permissions()->create(['menu_id' => $dasborMenu->id]);
+ }
+
+ DB::commit();
+
+ return $userGroup;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function update(UserGroup $userGroup, array $data)
+ {
+ try {
+ DB::beginTransaction();
+
+ $userGroup->update($data);
+
+ DB::commit();
+
+ return $userGroup;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function delete(UserGroup $userGroup)
+ {
+ try {
+ DB::beginTransaction();
+
+ $userGroup->delete();
+
+ DB::commit();
+
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function updatePermissions(UserGroup $userGroup, array $permissions)
+ {
+ try {
+ DB::beginTransaction();
+
+ $userGroup->permissions()->delete();
+
+ foreach ($permissions as $menuId) {
+ Permission::create(['user_group_id' => $userGroup->id, 'menu_id' => $menuId]);
+ }
+
+ DB::commit();
+
+ return true;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+}
diff --git a/app/Services/User/UserService.php b/app/Services/User/UserService.php
new file mode 100644
index 0000000..bac9ada
--- /dev/null
+++ b/app/Services/User/UserService.php
@@ -0,0 +1,89 @@
+ $data['name'],
+ 'email' => $data['email'],
+ 'password' => Hash::make($data['password']),
+ 'user_group_id' => $data['user_group_id'],
+ 'agency_id' => $data['agency_id'],
+ ]);
+
+ DB::commit();
+
+ return $user;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function update(User $user, array $data)
+ {
+ try {
+ DB::beginTransaction();
+
+ // $emailChanged = $user->email !== $data['email'];
+
+ $user->update([
+ 'name' => $data['name'],
+ 'email' => $data['email'],
+ 'user_group_id' => $data['user_group_id'],
+ 'agency_id' => $data['agency_id'],
+ ]);
+
+ // if ($emailChanged) {
+ // $user->notify(new EmailVerificationNotification());
+ // }
+
+ DB::commit();
+
+ return $user;
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function delete(User $user)
+ {
+ try {
+ DB::beginTransaction();
+
+ $user->delete();
+
+ DB::commit();
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw $e;
+ }
+ }
+
+ public function getAgencies()
+ {
+ $data = Agency::rowActive()->orderBy('name','ASC')->get();
+ return $data;
+ }
+
+ public function getUserGroups()
+ {
+ $data = UserGroup::orderBy('name','ASC')->get();
+ return $data;
+ }
+
+}
diff --git a/app/View/Components/ActivityYearSelect.php b/app/View/Components/ActivityYearSelect.php
new file mode 100644
index 0000000..67efc96
--- /dev/null
+++ b/app/View/Components/ActivityYearSelect.php
@@ -0,0 +1,24 @@
+selectedYear = $selectedYear;
+ $this->inventoryYear = $inventoryYear ?? date('Y');
+ }
+
+ public function render(): View|Closure|string
+ {
+ return view('components.activity-year-select');
+ }
+}
diff --git a/app/View/Components/InventoryYearSelect.php b/app/View/Components/InventoryYearSelect.php
new file mode 100644
index 0000000..aa4e3bc
--- /dev/null
+++ b/app/View/Components/InventoryYearSelect.php
@@ -0,0 +1,24 @@
+selectedYear = $selectedYear;
+ $this->name = $name;
+ }
+
+ public function render(): View|Closure|string
+ {
+ return view('components.inventory-year-select');
+ }
+}
diff --git a/app/helpers.php b/app/helpers.php
new file mode 100644
index 0000000..6ecd531
--- /dev/null
+++ b/app/helpers.php
@@ -0,0 +1,97 @@
+ $uuid,
+ 'user_id' => $user->id,
+ 'activity_type' => $activityType->value,
+ 'ip_address' => Request::ip(),
+ 'form_id' => $formId,
+ 'created_by' => $user->name,
+ 'updated_by' => $user->name,
+ ]);
+
+ DB::commit();
+ } catch (\Exception $e) {
+ DB::rollBack();
+ }
+ }
+}
+
+if (!function_exists('activityYearRange')) {
+ function activityYearRange(int $inventoryYear, $isDesc = true, int $range = 15): array
+ {
+ if ($isDesc == true) {
+ return range($inventoryYear - 1, $inventoryYear - $range);
+ } else {
+ return range($inventoryYear - $range, $inventoryYear - 1);
+ }
+ }
+}
diff --git a/composer.json b/composer.json
index f10e318..4936b0e 100644
--- a/composer.json
+++ b/composer.json
@@ -9,7 +9,10 @@
"php": "^8.2",
"laravel/framework": "^11.31",
"laravel/tinker": "^2.9",
- "laravel/ui": "^4.6"
+ "laravel/ui": "^4.6",
+ "maatwebsite/excel": "^3.1",
+ "realrashid/sweet-alert": "^7.2",
+ "yajra/laravel-datatables": "^11.0"
},
"require-dev": {
"fakerphp/faker": "^1.23",
@@ -32,7 +35,8 @@
"Tests\\": "tests/"
},
"files": [
- "app/Helpers/custom.php"
+ "app/Helpers/custom.php",
+ "app/helpers.php"
]
},
"scripts": {
diff --git a/composer.lock b/composer.lock
index 96d9a54..61616ff 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a7159c5237c3c2e75dbd1d23c85e732c",
+ "content-hash": "b1787b324041390419ca8c585a294fd2",
"packages": [
{
"name": "brick/math",
- "version": "0.14.0",
+ "version": "0.14.1",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
+ "reference": "f05858549e5f9d7bb45875a75583240a38a281d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
- "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0",
+ "reference": "f05858549e5f9d7bb45875a75583240a38a281d0",
"shasum": ""
},
"require": {
@@ -56,7 +56,7 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.14.0"
+ "source": "https://github.com/brick/math/tree/0.14.1"
},
"funding": [
{
@@ -64,7 +64,7 @@
"type": "github"
}
],
- "time": "2025-08-29T12:40:03+00:00"
+ "time": "2025-11-24T14:40:29+00:00"
},
{
"name": "carbonphp/carbon-doctrine-types",
@@ -135,6 +135,162 @@
],
"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",
"version": "v3.0.3",
@@ -509,32 +665,93 @@
"time": "2025-03-06T22:45:56+00:00"
},
{
- "name": "fruitcake/php-cors",
- "version": "v1.3.0",
+ "name": "ezyang/htmlpurifier",
+ "version": "v4.19.0",
"source": {
"type": "git",
- "url": "https://github.com/fruitcake/php-cors.git",
- "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b"
+ "url": "https://github.com/ezyang/htmlpurifier.git",
+ "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b",
- "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b",
+ "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/b287d2a16aceffbf6e0295559b39662612b77fcf",
+ "reference": "b287d2a16aceffbf6e0295559b39662612b77fcf",
"shasum": ""
},
"require": {
- "php": "^7.4|^8.0",
- "symfony/http-foundation": "^4.4|^5.4|^6|^7"
+ "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 || ~8.5.0"
},
"require-dev": {
- "phpstan/phpstan": "^1.4",
+ "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.19.0"
+ },
+ "time": "2025-10-17T16:34:55+00:00"
+ },
+ {
+ "name": "fruitcake/php-cors",
+ "version": "v1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fruitcake/php-cors.git",
+ "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379",
+ "reference": "38aaa6c3fd4c157ffe2a4d10aa8b9b16ba8de379",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1",
+ "symfony/http-foundation": "^5.4|^6.4|^7.3|^8"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^2",
"phpunit/phpunit": "^9",
- "squizlabs/php_codesniffer": "^3.5"
+ "squizlabs/php_codesniffer": "^4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2-dev"
+ "dev-master": "1.3-dev"
}
},
"autoload": {
@@ -565,7 +782,7 @@
],
"support": {
"issues": "https://github.com/fruitcake/php-cors/issues",
- "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0"
+ "source": "https://github.com/fruitcake/php-cors/tree/v1.4.0"
},
"funding": [
{
@@ -577,28 +794,28 @@
"type": "github"
}
],
- "time": "2023-10-12T05:21:21+00:00"
+ "time": "2025-12-03T09:33:47+00:00"
},
{
"name": "graham-campbell/result-type",
- "version": "v1.1.3",
+ "version": "v1.1.4",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git",
- "reference": "3ba905c11371512af9d9bdd27d99b782216b6945"
+ "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945",
- "reference": "3ba905c11371512af9d9bdd27d99b782216b6945",
+ "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b",
+ "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
- "phpoption/phpoption": "^1.9.3"
+ "phpoption/phpoption": "^1.9.5"
},
"require-dev": {
- "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+ "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
},
"type": "library",
"autoload": {
@@ -627,7 +844,7 @@
],
"support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
- "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3"
+ "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4"
},
"funding": [
{
@@ -639,7 +856,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-20T21:45:45+00:00"
+ "time": "2025-12-27T19:43:20+00:00"
},
{
"name": "guzzlehttp/guzzle",
@@ -1054,16 +1271,16 @@
},
{
"name": "laravel/framework",
- "version": "v11.46.1",
+ "version": "v11.47.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "5fd457f807570a962a53b403b1346efe4cc80bb8"
+ "reference": "86693ffa1ba32f56f8c44e31416c6665095a62c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/5fd457f807570a962a53b403b1346efe4cc80bb8",
- "reference": "5fd457f807570a962a53b403b1346efe4cc80bb8",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/86693ffa1ba32f56f8c44e31416c6665095a62c5",
+ "reference": "86693ffa1ba32f56f8c44e31416c6665095a62c5",
"shasum": ""
},
"require": {
@@ -1265,20 +1482,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2025-09-30T14:51:32+00:00"
+ "time": "2025-11-28T18:20:11+00:00"
},
{
"name": "laravel/prompts",
- "version": "v0.3.7",
+ "version": "v0.3.8",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc"
+ "reference": "096748cdfb81988f60090bbb839ce3205ace0d35"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/a1891d362714bc40c8d23b0b1d7090f022ea27cc",
- "reference": "a1891d362714bc40c8d23b0b1d7090f022ea27cc",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/096748cdfb81988f60090bbb839ce3205ace0d35",
+ "reference": "096748cdfb81988f60090bbb839ce3205ace0d35",
"shasum": ""
},
"require": {
@@ -1294,7 +1511,7 @@
"require-dev": {
"illuminate/collections": "^10.0|^11.0|^12.0",
"mockery/mockery": "^1.5",
- "pestphp/pest": "^2.3|^3.4",
+ "pestphp/pest": "^2.3|^3.4|^4.0",
"phpstan/phpstan": "^1.12.28",
"phpstan/phpstan-mockery": "^1.1.3"
},
@@ -1322,22 +1539,22 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
- "source": "https://github.com/laravel/prompts/tree/v0.3.7"
+ "source": "https://github.com/laravel/prompts/tree/v0.3.8"
},
- "time": "2025-09-19T13:47:56+00:00"
+ "time": "2025-11-21T20:52:52+00:00"
},
{
"name": "laravel/serializable-closure",
- "version": "v2.0.6",
+ "version": "v2.0.7",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "038ce42edee619599a1debb7e81d7b3759492819"
+ "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/038ce42edee619599a1debb7e81d7b3759492819",
- "reference": "038ce42edee619599a1debb7e81d7b3759492819",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/cb291e4c998ac50637c7eeb58189c14f5de5b9dd",
+ "reference": "cb291e4c998ac50637c7eeb58189c14f5de5b9dd",
"shasum": ""
},
"require": {
@@ -1346,7 +1563,7 @@
"require-dev": {
"illuminate/support": "^10.0|^11.0|^12.0",
"nesbot/carbon": "^2.67|^3.0",
- "pestphp/pest": "^2.36|^3.0",
+ "pestphp/pest": "^2.36|^3.0|^4.0",
"phpstan/phpstan": "^2.0",
"symfony/var-dumper": "^6.2.0|^7.0.0"
},
@@ -1385,20 +1602,20 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2025-10-09T13:42:30+00:00"
+ "time": "2025-11-21T20:52:36+00:00"
},
{
"name": "laravel/tinker",
- "version": "v2.10.1",
+ "version": "v2.10.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/tinker.git",
- "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3"
+ "reference": "3bcb5f62d6f837e0f093a601e26badafb127bd4c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3",
- "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3",
+ "url": "https://api.github.com/repos/laravel/tinker/zipball/3bcb5f62d6f837e0f093a601e26badafb127bd4c",
+ "reference": "3bcb5f62d6f837e0f093a601e26badafb127bd4c",
"shasum": ""
},
"require": {
@@ -1449,9 +1666,9 @@
],
"support": {
"issues": "https://github.com/laravel/tinker/issues",
- "source": "https://github.com/laravel/tinker/tree/v2.10.1"
+ "source": "https://github.com/laravel/tinker/tree/v2.10.2"
},
- "time": "2025-01-27T14:24:01+00:00"
+ "time": "2025-11-20T16:29:12+00:00"
},
{
"name": "laravel/ui",
@@ -1518,16 +1735,16 @@
},
{
"name": "league/commonmark",
- "version": "2.7.1",
+ "version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
- "reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
+ "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
- "reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
+ "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
+ "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
"shasum": ""
},
"require": {
@@ -1564,7 +1781,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "2.8-dev"
+ "dev-main": "2.9-dev"
}
},
"autoload": {
@@ -1621,7 +1838,7 @@
"type": "tidelift"
}
],
- "time": "2025-07-20T12:47:49+00:00"
+ "time": "2025-11-26T21:48:24+00:00"
},
{
"name": "league/config",
@@ -1837,6 +2054,76 @@
},
"time": "2025-11-10T11:23:37+00:00"
},
+ {
+ "name": "league/fractal",
+ "version": "0.20.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/fractal.git",
+ "reference": "573ca2e0e348a7fe573a3e8fbc29a6588ece8c4e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/fractal/zipball/573ca2e0e348a7fe573a3e8fbc29a6588ece8c4e",
+ "reference": "573ca2e0e348a7fe573a3e8fbc29a6588ece8c4e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "doctrine/orm": "^2.5",
+ "illuminate/contracts": "~5.0",
+ "laminas/laminas-paginator": "~2.12",
+ "mockery/mockery": "^1.3",
+ "pagerfanta/pagerfanta": "~1.0.0|~4.0.0",
+ "phpstan/phpstan": "^1.4",
+ "phpunit/phpunit": "^9.5",
+ "squizlabs/php_codesniffer": "~3.4",
+ "vimeo/psalm": "^4.30"
+ },
+ "suggest": {
+ "illuminate/pagination": "The Illuminate Pagination component.",
+ "laminas/laminas-paginator": "Laminas Framework Paginator",
+ "pagerfanta/pagerfanta": "Pagerfanta Paginator"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.20.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Fractal\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Phil Sturgeon",
+ "email": "me@philsturgeon.uk",
+ "homepage": "http://philsturgeon.uk/",
+ "role": "Developer"
+ }
+ ],
+ "description": "Handle the output of complex data structures ready for API output.",
+ "homepage": "http://fractal.thephpleague.com/",
+ "keywords": [
+ "api",
+ "json",
+ "league",
+ "rest"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/fractal/issues",
+ "source": "https://github.com/thephpleague/fractal/tree/0.20.2"
+ },
+ "time": "2025-02-14T21:33:14+00:00"
+ },
{
"name": "league/mime-type-detection",
"version": "1.16.0",
@@ -1895,33 +2182,38 @@
},
{
"name": "league/uri",
- "version": "7.5.1",
+ "version": "7.7.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri.git",
- "reference": "81fb5145d2644324614cc532b28efd0215bda430"
+ "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430",
- "reference": "81fb5145d2644324614cc532b28efd0215bda430",
+ "url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
+ "reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
"shasum": ""
},
"require": {
- "league/uri-interfaces": "^7.5",
- "php": "^8.1"
+ "league/uri-interfaces": "^7.7",
+ "php": "^8.1",
+ "psr/http-factory": "^1"
},
"conflict": {
"league/uri-schemes": "^1.0"
},
"suggest": {
"ext-bcmath": "to improve IPV4 host parsing",
+ "ext-dom": "to convert the URI into an HTML anchor tag",
"ext-fileinfo": "to create Data URI from file contennts",
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
+ "ext-uri": "to use the PHP native URI class",
"jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
"league/uri-components": "Needed to easily manipulate URI objects components",
+ "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
"php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle WHATWG URL",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@@ -1949,6 +2241,7 @@
"description": "URI manipulation library",
"homepage": "https://uri.thephpleague.com",
"keywords": [
+ "URN",
"data-uri",
"file-uri",
"ftp",
@@ -1961,9 +2254,11 @@
"psr-7",
"query-string",
"querystring",
+ "rfc2141",
"rfc3986",
"rfc3987",
"rfc6570",
+ "rfc8141",
"uri",
"uri-template",
"url",
@@ -1973,7 +2268,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
- "source": "https://github.com/thephpleague/uri/tree/7.5.1"
+ "source": "https://github.com/thephpleague/uri/tree/7.7.0"
},
"funding": [
{
@@ -1981,26 +2276,25 @@
"type": "github"
}
],
- "time": "2024-12-08T08:40:02+00:00"
+ "time": "2025-12-07T16:02:06+00:00"
},
{
"name": "league/uri-interfaces",
- "version": "7.5.0",
+ "version": "7.7.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git",
- "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742"
+ "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742",
- "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742",
+ "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
+ "reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
"shasum": ""
},
"require": {
"ext-filter": "*",
"php": "^8.1",
- "psr/http-factory": "^1",
"psr/http-message": "^1.1 || ^2.0"
},
"suggest": {
@@ -2008,6 +2302,7 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle WHATWG URL",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@@ -2032,7 +2327,7 @@
"homepage": "https://nyamsprod.com"
}
],
- "description": "Common interfaces and classes for URI representation and interaction",
+ "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
"homepage": "https://uri.thephpleague.com",
"keywords": [
"data-uri",
@@ -2057,7 +2352,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
- "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0"
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0"
},
"funding": [
{
@@ -2065,20 +2360,362 @@
"type": "github"
}
],
- "time": "2024-12-08T08:18:47+00:00"
+ "time": "2025-12-07T16:03:21+00:00"
},
{
- "name": "monolog/monolog",
- "version": "3.9.0",
+ "name": "livewire/livewire",
+ "version": "v3.7.3",
"source": {
"type": "git",
- "url": "https://github.com/Seldaek/monolog.git",
- "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
+ "url": "https://github.com/livewire/livewire.git",
+ "reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
- "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
+ "reference": "a5384df9fbd3eaf02e053bc49aabc8ace293fc1c",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/database": "^10.0|^11.0|^12.0",
+ "illuminate/routing": "^10.0|^11.0|^12.0",
+ "illuminate/support": "^10.0|^11.0|^12.0",
+ "illuminate/validation": "^10.0|^11.0|^12.0",
+ "laravel/prompts": "^0.1.24|^0.2|^0.3",
+ "league/mime-type-detection": "^1.9",
+ "php": "^8.1",
+ "symfony/console": "^6.0|^7.0",
+ "symfony/http-kernel": "^6.2|^7.0"
+ },
+ "require-dev": {
+ "calebporzio/sushi": "^2.1",
+ "laravel/framework": "^10.15.0|^11.0|^12.0",
+ "mockery/mockery": "^1.3.1",
+ "orchestra/testbench": "^8.21.0|^9.0|^10.0",
+ "orchestra/testbench-dusk": "^8.24|^9.1|^10.0",
+ "phpunit/phpunit": "^10.4|^11.5",
+ "psy/psysh": "^0.11.22|^0.12"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Livewire": "Livewire\\Livewire"
+ },
+ "providers": [
+ "Livewire\\LivewireServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Livewire\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Caleb Porzio",
+ "email": "calebporzio@gmail.com"
+ }
+ ],
+ "description": "A front-end framework for Laravel.",
+ "support": {
+ "issues": "https://github.com/livewire/livewire/issues",
+ "source": "https://github.com/livewire/livewire/tree/v3.7.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/livewire",
+ "type": "github"
+ }
+ ],
+ "time": "2025-12-19T02:00:29+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": "monolog/monolog",
+ "version": "3.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0",
+ "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0",
"shasum": ""
},
"require": {
@@ -2096,7 +2733,7 @@
"graylog2/gelf-php": "^1.4.2 || ^2.0",
"guzzlehttp/guzzle": "^7.4.5",
"guzzlehttp/psr7": "^2.2",
- "mongodb/mongodb": "^1.8",
+ "mongodb/mongodb": "^1.8 || ^2.0",
"php-amqplib/php-amqplib": "~2.4 || ^3",
"php-console/php-console": "^3.1.8",
"phpstan/phpstan": "^2",
@@ -2156,7 +2793,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
- "source": "https://github.com/Seldaek/monolog/tree/3.9.0"
+ "source": "https://github.com/Seldaek/monolog/tree/3.10.0"
},
"funding": [
{
@@ -2168,20 +2805,20 @@
"type": "tidelift"
}
],
- "time": "2025-03-24T10:02:05+00:00"
+ "time": "2026-01-02T08:56:05+00:00"
},
{
"name": "nesbot/carbon",
- "version": "3.10.3",
+ "version": "3.11.0",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
- "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f"
+ "reference": "bdb375400dcd162624531666db4799b36b64e4a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f",
- "reference": "8e3643dcd149ae0fe1d2ff4f2c8e4bbfad7c165f",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/bdb375400dcd162624531666db4799b36b64e4a1",
+ "reference": "bdb375400dcd162624531666db4799b36b64e4a1",
"shasum": ""
},
"require": {
@@ -2189,9 +2826,9 @@
"ext-json": "*",
"php": "^8.1",
"psr/clock": "^1.0",
- "symfony/clock": "^6.3.12 || ^7.0",
+ "symfony/clock": "^6.3.12 || ^7.0 || ^8.0",
"symfony/polyfill-mbstring": "^1.0",
- "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0"
+ "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0 || ^8.0"
},
"provide": {
"psr/clock-implementation": "1.0"
@@ -2273,7 +2910,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-06T13:39:36+00:00"
+ "time": "2025-12-02T21:04:28+00:00"
},
{
"name": "nette/schema",
@@ -2342,20 +2979,20 @@
},
{
"name": "nette/utils",
- "version": "v4.0.8",
+ "version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede"
+ "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede",
- "reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede",
+ "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72",
+ "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72",
"shasum": ""
},
"require": {
- "php": "8.0 - 8.5"
+ "php": "8.2 - 8.5"
},
"conflict": {
"nette/finder": "<3",
@@ -2378,7 +3015,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-master": "4.1-dev"
}
},
"autoload": {
@@ -2425,22 +3062,22 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
- "source": "https://github.com/nette/utils/tree/v4.0.8"
+ "source": "https://github.com/nette/utils/tree/v4.1.1"
},
- "time": "2025-08-06T21:43:34+00:00"
+ "time": "2025-12-22T12:14:32+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v5.6.2",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "3a454ca033b9e06b63282ce19562e892747449bb"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
- "reference": "3a454ca033b9e06b63282ce19562e892747449bb",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -2483,37 +3120,37 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
},
- "time": "2025-10-21T19:32:17+00:00"
+ "time": "2025-12-06T11:56:16+00:00"
},
{
"name": "nunomaduro/termwind",
- "version": "v2.3.2",
+ "version": "v2.3.3",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/termwind.git",
- "reference": "eb61920a53057a7debd718a5b89c2178032b52c0"
+ "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/eb61920a53057a7debd718a5b89c2178032b52c0",
- "reference": "eb61920a53057a7debd718a5b89c2178032b52c0",
+ "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017",
+ "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^8.2",
- "symfony/console": "^7.3.4"
+ "symfony/console": "^7.3.6"
},
"require-dev": {
"illuminate/console": "^11.46.1",
"laravel/pint": "^1.25.1",
"mockery/mockery": "^1.6.12",
- "pestphp/pest": "^2.36.0 || ^3.8.4",
+ "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3",
"phpstan/phpstan": "^1.12.32",
"phpstan/phpstan-strict-rules": "^1.6.2",
- "symfony/var-dumper": "^7.3.4",
+ "symfony/var-dumper": "^7.3.5",
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
},
"type": "library",
@@ -2556,7 +3193,7 @@
],
"support": {
"issues": "https://github.com/nunomaduro/termwind/issues",
- "source": "https://github.com/nunomaduro/termwind/tree/v2.3.2"
+ "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3"
},
"funding": [
{
@@ -2572,20 +3209,219 @@
"type": "github"
}
],
- "time": "2025-10-18T11:10:27+00:00"
+ "time": "2025-11-20T02:34:59+00:00"
},
{
- "name": "phpoption/phpoption",
- "version": "1.9.4",
+ "name": "openspout/openspout",
+ "version": "v4.28.5",
"source": {
"type": "git",
- "url": "https://github.com/schmittjoh/php-option.git",
- "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d"
+ "url": "https://github.com/openspout/openspout.git",
+ "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
- "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
+ "url": "https://api.github.com/repos/openspout/openspout/zipball/ab05a09fe6fce57c90338f83280648a9786ce36b",
+ "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-fileinfo": "*",
+ "ext-filter": "*",
+ "ext-libxml": "*",
+ "ext-xmlreader": "*",
+ "ext-zip": "*",
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0"
+ },
+ "require-dev": {
+ "ext-zlib": "*",
+ "friendsofphp/php-cs-fixer": "^3.68.3",
+ "infection/infection": "^0.29.10",
+ "phpbench/phpbench": "^1.4.0",
+ "phpstan/phpstan": "^2.1.2",
+ "phpstan/phpstan-phpunit": "^2.0.4",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^11.5.4"
+ },
+ "suggest": {
+ "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
+ "ext-mbstring": "To handle non UTF-8 CSV files (if \"iconv\" is not already installed)"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "OpenSpout\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Adrien Loison",
+ "email": "adrien@box.com"
+ }
+ ],
+ "description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way",
+ "homepage": "https://github.com/openspout/openspout",
+ "keywords": [
+ "OOXML",
+ "csv",
+ "excel",
+ "memory",
+ "odf",
+ "ods",
+ "office",
+ "open",
+ "php",
+ "read",
+ "scale",
+ "spreadsheet",
+ "stream",
+ "write",
+ "xlsx"
+ ],
+ "support": {
+ "issues": "https://github.com/openspout/openspout/issues",
+ "source": "https://github.com/openspout/openspout/tree/v4.28.5"
+ },
+ "funding": [
+ {
+ "url": "https://paypal.me/filippotessarotto",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/Slamdunk",
+ "type": "github"
+ }
+ ],
+ "time": "2025-01-30T13:51:11+00:00"
+ },
+ {
+ "name": "phpoffice/phpspreadsheet",
+ "version": "1.30.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
+ "reference": "fa8257a579ec623473eabfe49731de5967306c4c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fa8257a579ec623473eabfe49731de5967306c4c",
+ "reference": "fa8257a579ec623473eabfe49731de5967306c4c",
+ "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.0 <8.5.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.1"
+ },
+ "time": "2025-10-26T16:01:04+00:00"
+ },
+ {
+ "name": "phpoption/phpoption",
+ "version": "1.9.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/schmittjoh/php-option.git",
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be",
+ "reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
"shasum": ""
},
"require": {
@@ -2635,7 +3471,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
- "source": "https://github.com/schmittjoh/php-option/tree/1.9.4"
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
},
"funding": [
{
@@ -2647,7 +3483,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-21T11:53:16+00:00"
+ "time": "2025-12-27T19:41:33+00:00"
},
{
"name": "psr/clock",
@@ -3063,16 +3899,16 @@
},
{
"name": "psy/psysh",
- "version": "v0.12.14",
+ "version": "v0.12.18",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
- "reference": "95c29b3756a23855a30566b745d218bee690bef2"
+ "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/bobthecow/psysh/zipball/95c29b3756a23855a30566b745d218bee690bef2",
- "reference": "95c29b3756a23855a30566b745d218bee690bef2",
+ "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ddff0ac01beddc251786fe70367cd8bbdb258196",
+ "reference": "ddff0ac01beddc251786fe70367cd8bbdb258196",
"shasum": ""
},
"require": {
@@ -3080,8 +3916,8 @@
"ext-tokenizer": "*",
"nikic/php-parser": "^5.0 || ^4.0",
"php": "^8.0 || ^7.4",
- "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4",
- "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4"
+ "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4",
+ "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4"
},
"conflict": {
"symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4"
@@ -3136,9 +3972,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
- "source": "https://github.com/bobthecow/psysh/tree/v0.12.14"
+ "source": "https://github.com/bobthecow/psysh/tree/v0.12.18"
},
- "time": "2025-10-27T17:15:31+00:00"
+ "time": "2025-12-17T14:35:46+00:00"
},
{
"name": "ralouphie/getallheaders",
@@ -3262,20 +4098,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.9.1",
+ "version": "4.9.2",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
+ "reference": "8429c78ca35a09f27565311b98101e2826affde0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
- "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0",
+ "reference": "8429c78ca35a09f27565311b98101e2826affde0",
"shasum": ""
},
"require": {
- "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+ "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
},
@@ -3334,22 +4170,112 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.9.1"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.2"
},
- "time": "2025-09-04T20:59:21+00:00"
+ "time": "2025-12-14T04:43:48+00:00"
},
{
- "name": "symfony/clock",
+ "name": "realrashid/sweet-alert",
"version": "v7.3.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/clock.git",
- "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24"
+ "url": "https://github.com/realrashid/sweet-alert.git",
+ "reference": "d54b1663970da8d416eb09e8719a8561a45fb2d9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
- "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
+ "url": "https://api.github.com/repos/realrashid/sweet-alert/zipball/d54b1663970da8d416eb09e8719a8561a45fb2d9",
+ "reference": "d54b1663970da8d416eb09e8719a8561a45fb2d9",
+ "shasum": ""
+ },
+ "require": {
+ "laravel/framework": "^5.6|^6.0|^7.0|^8.0|^9.0|^9.11|9.14.*|^10.0|^11.0|^12.0",
+ "php": "^7.2|^8.0|^8.1|^8.2|^8.3"
+ },
+ "require-dev": {
+ "symfony/thanks": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Alert": "RealRashid\\SweetAlert\\Facades\\Alert"
+ },
+ "providers": [
+ "RealRashid\\SweetAlert\\SweetAlertServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "RealRashid\\SweetAlert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Rashid Ali",
+ "email": "realrashid05@gmail.com",
+ "homepage": "https://realrashid.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Laravel Sweet Alert Is A Package For Laravel Provides An Easy Way To Display Alert Messages Using The SweetAlert2 Library.",
+ "homepage": "https://github.com/realrashid/sweet-alert",
+ "keywords": [
+ "alert",
+ "laravel",
+ "laravel-package",
+ "notifier",
+ "noty",
+ "sweet-alert",
+ "sweet-alert2",
+ "toast"
+ ],
+ "support": {
+ "docs": "https://realrashid.github.io/sweet-alert/",
+ "email": "realrashid05@gmail.com",
+ "issues": "https://github.com/realrashid/sweet-alert/issues",
+ "source": "https://github.com/realrashid/sweet-alert"
+ },
+ "funding": [
+ {
+ "url": "https://ko-fi.com/realrashid",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.buymeacoffee.com/realrashid",
+ "type": "custom"
+ },
+ {
+ "url": "https://issuehunt.io/r/realrashid",
+ "type": "issuehunt"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/realrashid/sweet-alert",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-25T21:11:49+00:00"
+ },
+ {
+ "name": "symfony/clock",
+ "version": "v7.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/clock.git",
+ "reference": "9169f24776edde469914c1e7a1442a50f7a4e110"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110",
+ "reference": "9169f24776edde469914c1e7a1442a50f7a4e110",
"shasum": ""
},
"require": {
@@ -3394,7 +4320,7 @@
"time"
],
"support": {
- "source": "https://github.com/symfony/clock/tree/v7.3.0"
+ "source": "https://github.com/symfony/clock/tree/v7.4.0"
},
"funding": [
{
@@ -3405,25 +4331,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-25T14:21:43+00:00"
+ "time": "2025-11-12T15:39:26+00:00"
},
{
"name": "symfony/console",
- "version": "v7.3.6",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a"
+ "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
- "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
+ "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
+ "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
"shasum": ""
},
"require": {
@@ -3431,7 +4361,7 @@
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/string": "^7.2"
+ "symfony/string": "^7.2|^8.0"
},
"conflict": {
"symfony/dependency-injection": "<6.4",
@@ -3445,16 +4375,16 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/lock": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/lock": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -3488,7 +4418,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.3.6"
+ "source": "https://github.com/symfony/console/tree/v7.4.3"
},
"funding": [
{
@@ -3508,20 +4438,20 @@
"type": "tidelift"
}
],
- "time": "2025-11-04T01:21:42+00:00"
+ "time": "2025-12-23T14:50:43+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v7.3.6",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "84321188c4754e64273b46b406081ad9b18e8614"
+ "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/84321188c4754e64273b46b406081ad9b18e8614",
- "reference": "84321188c4754e64273b46b406081ad9b18e8614",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135",
+ "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135",
"shasum": ""
},
"require": {
@@ -3557,7 +4487,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v7.3.6"
+ "source": "https://github.com/symfony/css-selector/tree/v7.4.0"
},
"funding": [
{
@@ -3577,7 +4507,7 @@
"type": "tidelift"
}
],
- "time": "2025-10-29T17:24:25+00:00"
+ "time": "2025-10-30T13:39:42+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3648,32 +4578,33 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.3.6",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "bbe40bfab84323d99dab491b716ff142410a92a8"
+ "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/bbe40bfab84323d99dab491b716ff142410a92a8",
- "reference": "bbe40bfab84323d99dab491b716ff142410a92a8",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/48be2b0653594eea32dcef130cca1c811dcf25c2",
+ "reference": "48be2b0653594eea32dcef130cca1c811dcf25c2",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/log": "^1|^2|^3",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/polyfill-php85": "^1.32",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"conflict": {
"symfony/deprecation-contracts": "<2.5",
"symfony/http-kernel": "<6.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4|^7.0|^8.0",
"symfony/webpack-encore-bundle": "^1.0|^2.0"
},
"bin": [
@@ -3705,7 +4636,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v7.3.6"
+ "source": "https://github.com/symfony/error-handler/tree/v7.4.0"
},
"funding": [
{
@@ -3725,20 +4656,20 @@
"type": "tidelift"
}
],
- "time": "2025-10-31T19:12:50+00:00"
+ "time": "2025-11-05T14:29:59+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.3.3",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191"
+ "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191",
- "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9dddcddff1ef974ad87b3708e4b442dc38b2261d",
+ "reference": "9dddcddff1ef974ad87b3708e4b442dc38b2261d",
"shasum": ""
},
"require": {
@@ -3755,13 +4686,14 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/error-handler": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/framework-bundle": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^6.4|^7.0"
+ "symfony/stopwatch": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -3789,7 +4721,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.0"
},
"funding": [
{
@@ -3809,7 +4741,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-13T11:49:31+00:00"
+ "time": "2025-10-28T09:38:46+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -3889,23 +4821,23 @@
},
{
"name": "symfony/finder",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "9f696d2f1e340484b4683f7853b273abff94421f"
+ "reference": "fffe05569336549b20a1be64250b40516d6e8d06"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f",
- "reference": "9f696d2f1e340484b4683f7853b273abff94421f",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06",
+ "reference": "fffe05569336549b20a1be64250b40516d6e8d06",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
"require-dev": {
- "symfony/filesystem": "^6.4|^7.0"
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -3933,7 +4865,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.3.5"
+ "source": "https://github.com/symfony/finder/tree/v7.4.3"
},
"funding": [
{
@@ -3953,27 +4885,26 @@
"type": "tidelift"
}
],
- "time": "2025-10-15T18:45:57+00:00"
+ "time": "2025-12-23T14:50:43+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v7.3.7",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4"
+ "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4",
- "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52",
+ "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3.0",
- "symfony/polyfill-mbstring": "~1.1",
- "symfony/polyfill-php83": "^1.27"
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
"doctrine/dbal": "<3.6",
@@ -3982,13 +4913,13 @@
"require-dev": {
"doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
- "symfony/cache": "^6.4.12|^7.1.5",
- "symfony/clock": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/rate-limiter": "^6.4|^7.0"
+ "symfony/cache": "^6.4.12|^7.1.5|^8.0",
+ "symfony/clock": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/mime": "^6.4|^7.0|^8.0",
+ "symfony/rate-limiter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -4016,7 +4947,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.3.7"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.4.3"
},
"funding": [
{
@@ -4036,29 +4967,29 @@
"type": "tidelift"
}
],
- "time": "2025-11-08T16:41:12+00:00"
+ "time": "2025-12-23T14:23:49+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.3.7",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce"
+ "reference": "885211d4bed3f857b8c964011923528a55702aa5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b8e9b748ea95fa4539c208e2487c435d3c87ce",
- "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5",
+ "reference": "885211d4bed3f857b8c964011923528a55702aa5",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/log": "^1|^2|^3",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/event-dispatcher": "^7.3",
- "symfony/http-foundation": "^7.3",
+ "symfony/error-handler": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^7.3|^8.0",
+ "symfony/http-foundation": "^7.4|^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
@@ -4068,6 +4999,7 @@
"symfony/console": "<6.4",
"symfony/dependency-injection": "<6.4",
"symfony/doctrine-bridge": "<6.4",
+ "symfony/flex": "<2.10",
"symfony/form": "<6.4",
"symfony/http-client": "<6.4",
"symfony/http-client-contracts": "<2.5",
@@ -4085,27 +5017,27 @@
},
"require-dev": {
"psr/cache": "^1.0|^2.0|^3.0",
- "symfony/browser-kit": "^6.4|^7.0",
- "symfony/clock": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/css-selector": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/dom-crawler": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
+ "symfony/browser-kit": "^6.4|^7.0|^8.0",
+ "symfony/clock": "^6.4|^7.0|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/css-selector": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/dom-crawler": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
"symfony/http-client-contracts": "^2.5|^3",
- "symfony/process": "^6.4|^7.0",
- "symfony/property-access": "^7.1",
- "symfony/routing": "^6.4|^7.0",
- "symfony/serializer": "^7.1",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/property-access": "^7.1|^8.0",
+ "symfony/routing": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^7.1|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/translation": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^6.4|^7.0",
- "symfony/validator": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0",
- "symfony/var-exporter": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0|^8.0",
+ "symfony/validator": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0",
+ "symfony/var-exporter": "^6.4|^7.0|^8.0",
"twig/twig": "^3.12"
},
"type": "library",
@@ -4134,7 +5066,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v7.3.7"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.4.3"
},
"funding": [
{
@@ -4154,20 +5086,20 @@
"type": "tidelift"
}
],
- "time": "2025-11-12T11:38:40+00:00"
+ "time": "2025-12-31T08:43:57+00:00"
},
{
"name": "symfony/mailer",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba"
+ "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/fd497c45ba9c10c37864e19466b090dcb60a50ba",
- "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/e472d35e230108231ccb7f51eb6b2100cac02ee4",
+ "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4",
"shasum": ""
},
"require": {
@@ -4175,8 +5107,8 @@
"php": ">=8.2",
"psr/event-dispatcher": "^1",
"psr/log": "^1|^2|^3",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/mime": "^7.2",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/mime": "^7.2|^8.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
@@ -4187,10 +5119,10 @@
"symfony/twig-bridge": "<6.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0"
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/twig-bridge": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -4218,7 +5150,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v7.3.5"
+ "source": "https://github.com/symfony/mailer/tree/v7.4.3"
},
"funding": [
{
@@ -4238,24 +5170,25 @@
"type": "tidelift"
}
],
- "time": "2025-10-24T14:27:20+00:00"
+ "time": "2025-12-16T08:02:06+00:00"
},
{
"name": "symfony/mime",
- "version": "v7.3.4",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35"
+ "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/b1b828f69cbaf887fa835a091869e55df91d0e35",
- "reference": "b1b828f69cbaf887fa835a091869e55df91d0e35",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/bdb02729471be5d047a3ac4a69068748f1a6be7a",
+ "reference": "bdb02729471be5d047a3ac4a69068748f1a6be7a",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
@@ -4270,11 +5203,11 @@
"egulias/email-validator": "^2.1.10|^3.1|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/serializer": "^6.4.3|^7.0.3"
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/property-info": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4.3|^7.0.3|^8.0"
},
"type": "library",
"autoload": {
@@ -4306,7 +5239,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.3.4"
+ "source": "https://github.com/symfony/mime/tree/v7.4.0"
},
"funding": [
{
@@ -4326,7 +5259,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-16T08:38:17+00:00"
+ "time": "2025-11-16T10:14:42+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -4914,6 +5847,86 @@
],
"time": "2025-07-08T02:45:35+00:00"
},
+ {
+ "name": "symfony/polyfill-php85",
+ "version": "v1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php85.git",
+ "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+ "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php85\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-06-23T16:12:55+00:00"
+ },
{
"name": "symfony/polyfill-uuid",
"version": "v1.33.0",
@@ -4999,16 +6012,16 @@
},
{
"name": "symfony/process",
- "version": "v7.3.4",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b"
+ "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b",
- "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b",
+ "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
+ "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
"shasum": ""
},
"require": {
@@ -5040,7 +6053,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.3.4"
+ "source": "https://github.com/symfony/process/tree/v7.4.3"
},
"funding": [
{
@@ -5060,20 +6073,20 @@
"type": "tidelift"
}
],
- "time": "2025-09-11T10:12:26+00:00"
+ "time": "2025-12-19T10:00:43+00:00"
},
{
"name": "symfony/routing",
- "version": "v7.3.6",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091"
+ "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/c97abe725f2a1a858deca629a6488c8fc20c3091",
- "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
+ "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
"shasum": ""
},
"require": {
@@ -5087,11 +6100,11 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5125,7 +6138,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.3.6"
+ "source": "https://github.com/symfony/routing/tree/v7.4.3"
},
"funding": [
{
@@ -5145,7 +6158,7 @@
"type": "tidelift"
}
],
- "time": "2025-11-05T07:57:47+00:00"
+ "time": "2025-12-19T10:00:43+00:00"
},
{
"name": "symfony/service-contracts",
@@ -5236,22 +6249,23 @@
},
{
"name": "symfony/string",
- "version": "v7.3.4",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "f96476035142921000338bad71e5247fbc138872"
+ "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872",
- "reference": "f96476035142921000338bad71e5247fbc138872",
+ "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003",
+ "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003",
"shasum": ""
},
"require": {
"php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3.0",
"symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-grapheme": "~1.33",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
@@ -5259,11 +6273,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/emoji": "^7.1",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
+ "symfony/emoji": "^7.1|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5302,7 +6316,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.3.4"
+ "source": "https://github.com/symfony/string/tree/v7.4.0"
},
"funding": [
{
@@ -5322,27 +6336,27 @@
"type": "tidelift"
}
],
- "time": "2025-09-11T14:36:48+00:00"
+ "time": "2025-11-27T13:27:24+00:00"
},
{
"name": "symfony/translation",
- "version": "v7.3.4",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "ec25870502d0c7072d086e8ffba1420c85965174"
+ "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/ec25870502d0c7072d086e8ffba1420c85965174",
- "reference": "ec25870502d0c7072d086e8ffba1420c85965174",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/7ef27c65d78886f7599fdd5c93d12c9243ecf44d",
+ "reference": "7ef27c65d78886f7599fdd5c93d12c9243ecf44d",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
- "symfony/translation-contracts": "^2.5|^3.0"
+ "symfony/translation-contracts": "^2.5.3|^3.3"
},
"conflict": {
"nikic/php-parser": "<5.0",
@@ -5361,17 +6375,17 @@
"require-dev": {
"nikic/php-parser": "^5.0",
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
"symfony/http-client-contracts": "^2.5|^3.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5402,7 +6416,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.3.4"
+ "source": "https://github.com/symfony/translation/tree/v7.4.3"
},
"funding": [
{
@@ -5422,7 +6436,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-07T11:39:36+00:00"
+ "time": "2025-12-29T09:31:36+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -5508,16 +6522,16 @@
},
{
"name": "symfony/uid",
- "version": "v7.3.1",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
- "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb"
+ "reference": "2498e9f81b7baa206f44de583f2f48350b90142c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb",
- "reference": "a69f69f3159b852651a6bf45a9fdd149520525bb",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/2498e9f81b7baa206f44de583f2f48350b90142c",
+ "reference": "2498e9f81b7baa206f44de583f2f48350b90142c",
"shasum": ""
},
"require": {
@@ -5525,7 +6539,7 @@
"symfony/polyfill-uuid": "^1.15"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0"
+ "symfony/console": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -5562,7 +6576,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v7.3.1"
+ "source": "https://github.com/symfony/uid/tree/v7.4.0"
},
"funding": [
{
@@ -5573,25 +6587,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-06-27T19:55:54+00:00"
+ "time": "2025-09-25T11:02:55+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v7.3.5",
+ "version": "v7.4.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d"
+ "reference": "7e99bebcb3f90d8721890f2963463280848cba92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
- "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92",
+ "reference": "7e99bebcb3f90d8721890f2963463280848cba92",
"shasum": ""
},
"require": {
@@ -5603,10 +6621,10 @@
"symfony/console": "<6.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/uid": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/uid": "^6.4|^7.0|^8.0",
"twig/twig": "^3.12"
},
"bin": [
@@ -5645,7 +6663,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.3.5"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.4.3"
},
"funding": [
{
@@ -5665,27 +6683,27 @@
"type": "tidelift"
}
],
- "time": "2025-09-27T09:00:46+00:00"
+ "time": "2025-12-18T07:04:31+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
- "version": "v2.3.0",
+ "version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/tijsverkoyen/CssToInlineStyles.git",
- "reference": "0d72ac1c00084279c1816675284073c5a337c20d"
+ "reference": "f0292ccf0ec75843d65027214426b6b163b48b41"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d",
- "reference": "0d72ac1c00084279c1816675284073c5a337c20d",
+ "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/f0292ccf0ec75843d65027214426b6b163b48b41",
+ "reference": "f0292ccf0ec75843d65027214426b6b163b48b41",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"php": "^7.4 || ^8.0",
- "symfony/css-selector": "^5.4 || ^6.0 || ^7.0"
+ "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^2.0",
@@ -5718,32 +6736,32 @@
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
"support": {
"issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues",
- "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0"
+ "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.4.0"
},
- "time": "2024-12-21T16:25:41+00:00"
+ "time": "2025-12-02T11:56:42+00:00"
},
{
"name": "vlucas/phpdotenv",
- "version": "v5.6.2",
+ "version": "v5.6.3",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
- "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
+ "reference": "955e7815d677a3eaa7075231212f2110983adecc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
- "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc",
+ "reference": "955e7815d677a3eaa7075231212f2110983adecc",
"shasum": ""
},
"require": {
"ext-pcre": "*",
- "graham-campbell/result-type": "^1.1.3",
+ "graham-campbell/result-type": "^1.1.4",
"php": "^7.2.5 || ^8.0",
- "phpoption/phpoption": "^1.9.3",
- "symfony/polyfill-ctype": "^1.24",
- "symfony/polyfill-mbstring": "^1.24",
- "symfony/polyfill-php80": "^1.24"
+ "phpoption/phpoption": "^1.9.5",
+ "symfony/polyfill-ctype": "^1.26",
+ "symfony/polyfill-mbstring": "^1.26",
+ "symfony/polyfill-php80": "^1.26"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
@@ -5792,7 +6810,7 @@
],
"support": {
"issues": "https://github.com/vlucas/phpdotenv/issues",
- "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
+ "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3"
},
"funding": [
{
@@ -5804,7 +6822,7 @@
"type": "tidelift"
}
],
- "time": "2025-04-30T23:37:27+00:00"
+ "time": "2025-12-27T19:49:13+00:00"
},
{
"name": "voku/portable-ascii",
@@ -5879,6 +6897,543 @@
}
],
"time": "2024-11-21T01:49:47+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables",
+ "version": "v11.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/datatables.git",
+ "reference": "5ab0fccf229161df95e435582ed123efa8aa3f50"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/datatables/zipball/5ab0fccf229161df95e435582ed123efa8aa3f50",
+ "reference": "5ab0fccf229161df95e435582ed123efa8aa3f50",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.2",
+ "yajra/laravel-datatables-buttons": "^11",
+ "yajra/laravel-datatables-editor": "^11",
+ "yajra/laravel-datatables-export": "^11",
+ "yajra/laravel-datatables-fractal": "^11",
+ "yajra/laravel-datatables-html": "^11",
+ "yajra/laravel-datatables-oracle": "^11"
+ },
+ "require-dev": {
+ "larastan/larastan": "^2.9.1",
+ "laravel/pint": "^1.14",
+ "orchestra/testbench": "^9",
+ "rector/rector": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "11.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables Complete Package.",
+ "keywords": [
+ "datatables",
+ "jquery",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/datatables/issues",
+ "source": "https://github.com/yajra/datatables/tree/v11.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/yajra",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-16T04:34:31+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-buttons",
+ "version": "v11.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables-buttons.git",
+ "reference": "78c84636f4bb56efb149f694b67784ed651cf0ad"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables-buttons/zipball/78c84636f4bb56efb149f694b67784ed651cf0ad",
+ "reference": "78c84636f4bb56efb149f694b67784ed651cf0ad",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/console": "^11",
+ "php": "^8.2",
+ "yajra/laravel-datatables-html": "^11",
+ "yajra/laravel-datatables-oracle": "^11"
+ },
+ "require-dev": {
+ "larastan/larastan": "^2.9.2",
+ "laravel/pint": "^1.14",
+ "maatwebsite/excel": "^3.1.55",
+ "orchestra/testbench": "^9",
+ "rap2hpoutre/fast-excel": "^5.4",
+ "rector/rector": "^1.0.2"
+ },
+ "suggest": {
+ "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view.",
+ "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.",
+ "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.",
+ "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.",
+ "yajra/laravel-datatables-export": "Exporting of dataTables (excel, csv and PDF) via livewire and queue worker."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Yajra\\DataTables\\ButtonsServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables Buttons Plugin.",
+ "keywords": [
+ "buttons",
+ "datatables",
+ "jquery",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables-buttons/issues",
+ "source": "https://github.com/yajra/laravel-datatables-buttons/tree/v11.2.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/yajra",
+ "type": "github"
+ }
+ ],
+ "time": "2025-01-18T11:12:52+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-editor",
+ "version": "v11.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables-editor.git",
+ "reference": "f49f2bcfab26d4233d04280aab7787418d9d6334"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables-editor/zipball/f49f2bcfab26d4233d04280aab7787418d9d6334",
+ "reference": "f49f2bcfab26d4233d04280aab7787418d9d6334",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/console": "^11",
+ "illuminate/database": "^11",
+ "illuminate/http": "^11",
+ "illuminate/validation": "^11",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "larastan/larastan": "^2.9.1",
+ "laravel/pint": "^1.14",
+ "orchestra/testbench": "^9.0",
+ "rector/rector": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Yajra\\DataTables\\EditorServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables Editor plugin for Laravel 5.5+.",
+ "keywords": [
+ "JS",
+ "datatables",
+ "editor",
+ "html",
+ "jquery",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables-editor/issues",
+ "source": "https://github.com/yajra/laravel-datatables-editor/tree/v11.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/yajra",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/yajra",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/yajra",
+ "type": "patreon"
+ }
+ ],
+ "time": "2024-09-20T02:44:39+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-export",
+ "version": "v11.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables-export.git",
+ "reference": "a978a42c82f6177fd5301c6a1a2a46089745adea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables-export/zipball/a978a42c82f6177fd5301c6a1a2a46089745adea",
+ "reference": "a978a42c82f6177fd5301c6a1a2a46089745adea",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "livewire/livewire": "^2.11.2|^3.5.6",
+ "openspout/openspout": "^4.24.5",
+ "php": "^8.2",
+ "phpoffice/phpspreadsheet": "^1.29.9|^2.3.7",
+ "yajra/laravel-datatables-buttons": "^11.0"
+ },
+ "require-dev": {
+ "larastan/larastan": "^2.9.8",
+ "laravel/pint": "^1.17.2",
+ "orchestra/testbench": "^9.4.0",
+ "pestphp/pest": "^2.35.1",
+ "pestphp/pest-plugin-laravel": "^2.4",
+ "rector/rector": "^1.2.4"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Yajra\\DataTables\\ExportServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables Queued Export Plugin.",
+ "keywords": [
+ "datatables",
+ "excel",
+ "export",
+ "laravel",
+ "livewire",
+ "queue"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables-export/issues",
+ "source": "https://github.com/yajra/laravel-datatables-export/tree/v11.4.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/yajra",
+ "type": "github"
+ }
+ ],
+ "time": "2025-04-12T13:01:17+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-fractal",
+ "version": "v11.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables-fractal.git",
+ "reference": "94141d03aff187aeb3f98a0a735e1c89ae50ad06"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables-fractal/zipball/94141d03aff187aeb3f98a0a735e1c89ae50ad06",
+ "reference": "94141d03aff187aeb3f98a0a735e1c89ae50ad06",
+ "shasum": ""
+ },
+ "require": {
+ "league/fractal": "^0.20.1",
+ "php": "^8.2",
+ "yajra/laravel-datatables-oracle": "^11.0"
+ },
+ "require-dev": {
+ "nunomaduro/larastan": "^2.9.2",
+ "orchestra/testbench": "^9"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Yajra\\DataTables\\FractalServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables Fractal Plugin.",
+ "keywords": [
+ "api",
+ "datatables",
+ "fractal",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables-fractal/issues",
+ "source": "https://github.com/yajra/laravel-datatables-fractal/tree/v11.0.0"
+ },
+ "time": "2024-03-14T06:16:28+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-html",
+ "version": "v11.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables-html.git",
+ "reference": "76cb7a423c84fa81cc5c6418cbb8c3c95d1a4f89"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables-html/zipball/76cb7a423c84fa81cc5c6418cbb8c3c95d1a4f89",
+ "reference": "76cb7a423c84fa81cc5c6418cbb8c3c95d1a4f89",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^8.2",
+ "yajra/laravel-datatables-oracle": "^11.0"
+ },
+ "require-dev": {
+ "larastan/larastan": "^2.9.1",
+ "laravel/pint": "^1.14",
+ "livewire/livewire": "^3.4",
+ "orchestra/testbench": "^9",
+ "rector/rector": "^1.0"
+ },
+ "suggest": {
+ "laravel/livewire": "Required for Livewire layout support."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Yajra\\DataTables\\HtmlServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "Laravel DataTables HTML builder plugin",
+ "keywords": [
+ "JS",
+ "datatables",
+ "html",
+ "jquery",
+ "laravel",
+ "yajra"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables-html/issues",
+ "source": "https://github.com/yajra/laravel-datatables-html/tree/v11.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/yajra",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/yajra",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/yajra",
+ "type": "patreon"
+ }
+ ],
+ "time": "2025-02-19T02:11:43+00:00"
+ },
+ {
+ "name": "yajra/laravel-datatables-oracle",
+ "version": "v11.1.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/yajra/laravel-datatables.git",
+ "reference": "b48eb614d0474c23a9c8041563beef9dda39656d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/b48eb614d0474c23a9c8041563beef9dda39656d",
+ "reference": "b48eb614d0474c23a9c8041563beef9dda39656d",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/database": "^11",
+ "illuminate/filesystem": "^11",
+ "illuminate/http": "^11",
+ "illuminate/support": "^11",
+ "illuminate/view": "^11",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "algolia/algoliasearch-client-php": "^3.4.1",
+ "larastan/larastan": "^2.9.1",
+ "laravel/pint": "^1.14",
+ "laravel/scout": "^10.8.3",
+ "meilisearch/meilisearch-php": "^1.6.1",
+ "orchestra/testbench": "^9",
+ "rector/rector": "^1.0"
+ },
+ "suggest": {
+ "yajra/laravel-datatables-buttons": "Plugin for server-side exporting of dataTables.",
+ "yajra/laravel-datatables-editor": "Plugin to use DataTables Editor (requires a license).",
+ "yajra/laravel-datatables-export": "Plugin for server-side exporting using livewire and queue worker.",
+ "yajra/laravel-datatables-fractal": "Plugin for server-side response using Fractal.",
+ "yajra/laravel-datatables-html": "Plugin for server-side HTML builder of dataTables."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "DataTables": "Yajra\\DataTables\\Facades\\DataTables"
+ },
+ "providers": [
+ "Yajra\\DataTables\\DataTablesServiceProvider"
+ ]
+ },
+ "branch-alias": {
+ "dev-master": "11.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helper.php"
+ ],
+ "psr-4": {
+ "Yajra\\DataTables\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arjay Angeles",
+ "email": "aqangeles@gmail.com"
+ }
+ ],
+ "description": "jQuery DataTables API for Laravel",
+ "keywords": [
+ "datatables",
+ "jquery",
+ "laravel",
+ "yajra"
+ ],
+ "support": {
+ "issues": "https://github.com/yajra/laravel-datatables/issues",
+ "source": "https://github.com/yajra/laravel-datatables/tree/v11.1.6"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/yajra",
+ "type": "github"
+ }
+ ],
+ "time": "2025-01-21T03:15:46+00:00"
}
],
"packages-dev": [
@@ -6069,16 +7624,16 @@
},
{
"name": "laravel/pail",
- "version": "v1.2.3",
+ "version": "v1.2.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/pail.git",
- "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a"
+ "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a",
- "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a",
+ "url": "https://api.github.com/repos/laravel/pail/zipball/49f92285ff5d6fc09816e976a004f8dec6a0ea30",
+ "reference": "49f92285ff5d6fc09816e976a004f8dec6a0ea30",
"shasum": ""
},
"require": {
@@ -6095,9 +7650,9 @@
"require-dev": {
"laravel/framework": "^10.24|^11.0|^12.0",
"laravel/pint": "^1.13",
- "orchestra/testbench-core": "^8.13|^9.0|^10.0",
- "pestphp/pest": "^2.20|^3.0",
- "pestphp/pest-plugin-type-coverage": "^2.3|^3.0",
+ "orchestra/testbench-core": "^8.13|^9.17|^10.8",
+ "pestphp/pest": "^2.20|^3.0|^4.0",
+ "pestphp/pest-plugin-type-coverage": "^2.3|^3.0|^4.0",
"phpstan/phpstan": "^1.12.27",
"symfony/var-dumper": "^6.3|^7.0"
},
@@ -6144,20 +7699,20 @@
"issues": "https://github.com/laravel/pail/issues",
"source": "https://github.com/laravel/pail"
},
- "time": "2025-06-05T13:55:57+00:00"
+ "time": "2025-11-20T16:29:35+00:00"
},
{
"name": "laravel/pint",
- "version": "v1.25.1",
+ "version": "v1.26.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9"
+ "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/5016e263f95d97670d71b9a987bd8996ade6d8d9",
- "reference": "5016e263f95d97670d71b9a987bd8996ade6d8d9",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/69dcca060ecb15e4b564af63d1f642c81a241d6f",
+ "reference": "69dcca060ecb15e4b564af63d1f642c81a241d6f",
"shasum": ""
},
"require": {
@@ -6168,13 +7723,13 @@
"php": "^8.2.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.87.2",
- "illuminate/view": "^11.46.0",
- "larastan/larastan": "^3.7.1",
- "laravel-zero/framework": "^11.45.0",
+ "friendsofphp/php-cs-fixer": "^3.90.0",
+ "illuminate/view": "^12.40.1",
+ "larastan/larastan": "^3.8.0",
+ "laravel-zero/framework": "^12.0.4",
"mockery/mockery": "^1.6.12",
- "nunomaduro/termwind": "^2.3.1",
- "pestphp/pest": "^2.36.0"
+ "nunomaduro/termwind": "^2.3.3",
+ "pestphp/pest": "^3.8.4"
},
"bin": [
"builds/pint"
@@ -6200,6 +7755,7 @@
"description": "An opinionated code formatter for PHP.",
"homepage": "https://laravel.com",
"keywords": [
+ "dev",
"format",
"formatter",
"lint",
@@ -6210,20 +7766,20 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2025-09-19T02:57:12+00:00"
+ "time": "2025-11-25T21:15:52+00:00"
},
{
"name": "laravel/sail",
- "version": "v1.48.0",
+ "version": "v1.51.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/sail.git",
- "reference": "1bf3b8870b72a258a3b6b5119435835ece522e8a"
+ "reference": "1c74357df034e869250b4365dd445c9f6ba5d068"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/sail/zipball/1bf3b8870b72a258a3b6b5119435835ece522e8a",
- "reference": "1bf3b8870b72a258a3b6b5119435835ece522e8a",
+ "url": "https://api.github.com/repos/laravel/sail/zipball/1c74357df034e869250b4365dd445c9f6ba5d068",
+ "reference": "1c74357df034e869250b4365dd445c9f6ba5d068",
"shasum": ""
},
"require": {
@@ -6273,7 +7829,7 @@
"issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail"
},
- "time": "2025-11-09T14:46:21+00:00"
+ "time": "2025-12-09T13:33:49+00:00"
},
{
"name": "mockery/mockery",
@@ -6420,16 +7976,16 @@
},
{
"name": "nunomaduro/collision",
- "version": "v8.8.2",
+ "version": "v8.8.3",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
- "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb"
+ "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb",
- "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb",
+ "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4",
+ "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4",
"shasum": ""
},
"require": {
@@ -6451,7 +8007,7 @@
"laravel/sanctum": "^4.1.1",
"laravel/tinker": "^2.10.1",
"orchestra/testbench-core": "^9.12.0 || ^10.4",
- "pestphp/pest": "^3.8.2",
+ "pestphp/pest": "^3.8.2 || ^4.0.0",
"sebastian/environment": "^7.2.1 || ^8.0"
},
"type": "library",
@@ -6515,7 +8071,7 @@
"type": "patreon"
}
],
- "time": "2025-06-25T02:12:12+00:00"
+ "time": "2025-11-20T02:55:25+00:00"
},
{
"name": "phar-io/manifest",
@@ -6637,35 +8193,35 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "11.0.11",
+ "version": "11.0.12",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4"
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4",
- "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^5.4.0",
+ "nikic/php-parser": "^5.7.0",
"php": ">=8.2",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-text-template": "^4.0.1",
"sebastian/code-unit-reverse-lookup": "^4.0.1",
"sebastian/complexity": "^4.0.1",
- "sebastian/environment": "^7.2.0",
+ "sebastian/environment": "^7.2.1",
"sebastian/lines-of-code": "^3.0.1",
"sebastian/version": "^5.0.2",
- "theseer/tokenizer": "^1.2.3"
+ "theseer/tokenizer": "^1.3.1"
},
"require-dev": {
- "phpunit/phpunit": "^11.5.2"
+ "phpunit/phpunit": "^11.5.46"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -6703,7 +8259,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.11"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12"
},
"funding": [
{
@@ -6723,7 +8279,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-27T14:37:49+00:00"
+ "time": "2025-12-24T07:01:01+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -6972,16 +8528,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.44",
+ "version": "11.5.46",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "c346885c95423eda3f65d85a194aaa24873cda82"
+ "reference": "75dfe79a2aa30085b7132bb84377c24062193f33"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c346885c95423eda3f65d85a194aaa24873cda82",
- "reference": "c346885c95423eda3f65d85a194aaa24873cda82",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/75dfe79a2aa30085b7132bb84377c24062193f33",
+ "reference": "75dfe79a2aa30085b7132bb84377c24062193f33",
"shasum": ""
},
"require": {
@@ -7053,7 +8609,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.44"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.46"
},
"funding": [
{
@@ -7077,7 +8633,7 @@
"type": "tidelift"
}
],
- "time": "2025-11-13T07:17:35+00:00"
+ "time": "2025-12-06T08:01:15+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -8119,28 +9675,28 @@
},
{
"name": "symfony/yaml",
- "version": "v7.3.5",
+ "version": "v7.4.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc"
+ "reference": "24dd4de28d2e3988b311751ac49e684d783e2345"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/90208e2fc6f68f613eae7ca25a2458a931b1bacc",
- "reference": "90208e2fc6f68f613eae7ca25a2458a931b1bacc",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345",
+ "reference": "24dd4de28d2e3988b311751ac49e684d783e2345",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"symfony/console": "<6.4"
},
"require-dev": {
- "symfony/console": "^6.4|^7.0"
+ "symfony/console": "^6.4|^7.0|^8.0"
},
"bin": [
"Resources/bin/yaml-lint"
@@ -8171,7 +9727,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v7.3.5"
+ "source": "https://github.com/symfony/yaml/tree/v7.4.1"
},
"funding": [
{
@@ -8191,20 +9747,20 @@
"type": "tidelift"
}
],
- "time": "2025-09-27T09:00:46+00:00"
+ "time": "2025-12-04T18:11:45+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.3.0",
+ "version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb"
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
- "reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
"shasum": ""
},
"require": {
@@ -8233,7 +9789,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.3.0"
+ "source": "https://github.com/theseer/tokenizer/tree/1.3.1"
},
"funding": [
{
@@ -8241,7 +9797,7 @@
"type": "github"
}
],
- "time": "2025-11-13T13:44:09+00:00"
+ "time": "2025-11-17T20:03:58+00:00"
}
],
"aliases": [],
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.css
new file mode 100644
index 0000000..e245831
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.css
@@ -0,0 +1,167 @@
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+ul.dt-button-collection.dropdown-menu {
+ display: block;
+ z-index: 2002;
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+ul.dt-button-collection.dropdown-menu.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+ul.dt-button-collection.dropdown-menu.fixed.two-column {
+ margin-left: -150px;
+}
+ul.dt-button-collection.dropdown-menu.fixed.three-column {
+ margin-left: -225px;
+}
+ul.dt-button-collection.dropdown-menu.fixed.four-column {
+ margin-left: -300px;
+}
+ul.dt-button-collection.dropdown-menu > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+ul.dt-button-collection.dropdown-menu.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+ul.dt-button-collection.dropdown-menu.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+ul.dt-button-collection.dropdown-menu.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+ul.dt-button-collection.dropdown-menu .dt-button {
+ border-radius: 0;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 2001;
+}
+
+@media screen and (max-width: 767px) {
+ div.dt-buttons {
+ float: none;
+ width: 100%;
+ text-align: center;
+ margin-bottom: 0.5em;
+ }
+ div.dt-buttons a.btn {
+ float: none;
+ }
+}
+div.dt-buttons button.btn.processing,
+div.dt-buttons div.btn.processing,
+div.dt-buttons a.btn.processing {
+ color: rgba(0, 0, 0, 0.2);
+}
+div.dt-buttons button.btn.processing:after,
+div.dt-buttons div.btn.processing:after,
+div.dt-buttons a.btn.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.min.css
new file mode 100644
index 0000000..a2f7fe0
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}ul.dt-button-collection.dropdown-menu{display:block;z-index:2002;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.dropdown-menu.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.dropdown-menu.fixed.two-column{margin-left:-150px}ul.dt-button-collection.dropdown-menu.fixed.three-column{margin-left:-225px}ul.dt-button-collection.dropdown-menu.fixed.four-column{margin-left:-300px}ul.dt-button-collection.dropdown-menu>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.dropdown-menu.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.dropdown-menu.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.dropdown-menu.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection.dropdown-menu .dt-button{border-radius:0}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;z-index:2001}@media screen and (max-width: 767px){div.dt-buttons{float:none;width:100%;text-align:center;margin-bottom:0.5em}div.dt-buttons a.btn{float:none}}div.dt-buttons button.btn.processing,div.dt-buttons div.btn.processing,div.dt-buttons a.btn.processing{color:rgba(0,0,0,0.2)}div.dt-buttons button.btn.processing:after,div.dt-buttons div.btn.processing:after,div.dt-buttons a.btn.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.css
new file mode 100644
index 0000000..214b270
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.css
@@ -0,0 +1,231 @@
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+ul.dt-button-collection.dropdown-menu {
+ display: block;
+ z-index: 2002;
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+ul.dt-button-collection.dropdown-menu.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+ul.dt-button-collection.dropdown-menu.fixed.two-column {
+ margin-left: -150px;
+}
+ul.dt-button-collection.dropdown-menu.fixed.three-column {
+ margin-left: -225px;
+}
+ul.dt-button-collection.dropdown-menu.fixed.four-column {
+ margin-left: -300px;
+}
+ul.dt-button-collection.dropdown-menu > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+ul.dt-button-collection.dropdown-menu.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+ul.dt-button-collection.dropdown-menu.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+ul.dt-button-collection.dropdown-menu.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+ul.dt-button-collection.dropdown-menu .dt-button {
+ border-radius: 0;
+}
+
+ul.dt-button-collection {
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+ul.dt-button-collection.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+ul.dt-button-collection.fixed.two-column {
+ margin-left: -150px;
+}
+ul.dt-button-collection.fixed.three-column {
+ margin-left: -225px;
+}
+ul.dt-button-collection.fixed.four-column {
+ margin-left: -300px;
+}
+ul.dt-button-collection > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+ul.dt-button-collection.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+ul.dt-button-collection.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+ul.dt-button-collection.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+ul.dt-button-collection .dt-button {
+ border-radius: 0;
+}
+ul.dt-button-collection.fixed {
+ max-width: none;
+}
+ul.dt-button-collection.fixed:before, ul.dt-button-collection.fixed:after {
+ display: none;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 999;
+}
+
+@media screen and (max-width: 767px) {
+ div.dt-buttons {
+ float: none;
+ width: 100%;
+ text-align: center;
+ margin-bottom: 0.5em;
+ }
+ div.dt-buttons a.btn {
+ float: none;
+ }
+}
+div.dt-buttons button.btn.processing,
+div.dt-buttons div.btn.processing,
+div.dt-buttons a.btn.processing {
+ color: rgba(0, 0, 0, 0.2);
+}
+div.dt-buttons button.btn.processing:after,
+div.dt-buttons div.btn.processing:after,
+div.dt-buttons a.btn.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.min.css
new file mode 100644
index 0000000..df33424
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.bootstrap4.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}ul.dt-button-collection.dropdown-menu{display:block;z-index:2002;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.dropdown-menu.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.dropdown-menu.fixed.two-column{margin-left:-150px}ul.dt-button-collection.dropdown-menu.fixed.three-column{margin-left:-225px}ul.dt-button-collection.dropdown-menu.fixed.four-column{margin-left:-300px}ul.dt-button-collection.dropdown-menu>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.dropdown-menu.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.dropdown-menu.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.dropdown-menu.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection.dropdown-menu .dt-button{border-radius:0}ul.dt-button-collection{-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.fixed.two-column{margin-left:-150px}ul.dt-button-collection.fixed.three-column{margin-left:-225px}ul.dt-button-collection.fixed.four-column{margin-left:-300px}ul.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection .dt-button{border-radius:0}ul.dt-button-collection.fixed{max-width:none}ul.dt-button-collection.fixed:before,ul.dt-button-collection.fixed:after{display:none}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999}@media screen and (max-width: 767px){div.dt-buttons{float:none;width:100%;text-align:center;margin-bottom:0.5em}div.dt-buttons a.btn{float:none}}div.dt-buttons button.btn.processing,div.dt-buttons div.btn.processing,div.dt-buttons a.btn.processing{color:rgba(0,0,0,0.2)}div.dt-buttons button.btn.processing:after,div.dt-buttons div.btn.processing:after,div.dt-buttons a.btn.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.css
new file mode 100644
index 0000000..c9f3b25
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.css
@@ -0,0 +1,365 @@
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+button.dt-button,
+div.dt-button,
+a.dt-button {
+ position: relative;
+ display: inline-block;
+ box-sizing: border-box;
+ margin-right: 0.333em;
+ margin-bottom: 0.333em;
+ padding: 0.5em 1em;
+ border: 1px solid #999;
+ border-radius: 2px;
+ cursor: pointer;
+ font-size: 0.88em;
+ line-height: 1.6em;
+ color: black;
+ white-space: nowrap;
+ overflow: hidden;
+ background-color: #e9e9e9;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, white 0%, #e9e9e9 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, white 0%, #e9e9e9 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, white 0%, #e9e9e9 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, white 0%, #e9e9e9 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, white 0%, #e9e9e9 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='white', EndColorStr='#e9e9e9');
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ text-decoration: none;
+ outline: none;
+}
+button.dt-button.disabled,
+div.dt-button.disabled,
+a.dt-button.disabled {
+ color: #999;
+ border: 1px solid #d0d0d0;
+ cursor: default;
+ background-color: #f9f9f9;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #ffffff 0%, #f9f9f9 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#ffffff', EndColorStr='#f9f9f9');
+}
+button.dt-button:active:not(.disabled), button.dt-button.active:not(.disabled),
+div.dt-button:active:not(.disabled),
+div.dt-button.active:not(.disabled),
+a.dt-button:active:not(.disabled),
+a.dt-button.active:not(.disabled) {
+ background-color: #e2e2e2;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #f3f3f3 0%, #e2e2e2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f3f3f3', EndColorStr='#e2e2e2');
+ box-shadow: inset 1px 1px 3px #999999;
+}
+button.dt-button:active:not(.disabled):hover:not(.disabled), button.dt-button.active:not(.disabled):hover:not(.disabled),
+div.dt-button:active:not(.disabled):hover:not(.disabled),
+div.dt-button.active:not(.disabled):hover:not(.disabled),
+a.dt-button:active:not(.disabled):hover:not(.disabled),
+a.dt-button.active:not(.disabled):hover:not(.disabled) {
+ box-shadow: inset 1px 1px 3px #999999;
+ background-color: #cccccc;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #eaeaea 0%, #cccccc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#eaeaea', EndColorStr='#cccccc');
+}
+button.dt-button:hover,
+div.dt-button:hover,
+a.dt-button:hover {
+ text-decoration: none;
+}
+button.dt-button:hover:not(.disabled),
+div.dt-button:hover:not(.disabled),
+a.dt-button:hover:not(.disabled) {
+ border: 1px solid #666;
+ background-color: #e0e0e0;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #f9f9f9 0%, #e0e0e0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f9f9f9', EndColorStr='#e0e0e0');
+}
+button.dt-button:focus:not(.disabled),
+div.dt-button:focus:not(.disabled),
+a.dt-button:focus:not(.disabled) {
+ border: 1px solid #426c9e;
+ text-shadow: 0 1px 0 #c4def1;
+ outline: none;
+ background-color: #79ace9;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #bddef4 0%, #79ace9 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #bddef4 0%, #79ace9 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #bddef4 0%, #79ace9 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #bddef4 0%, #79ace9 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #bddef4 0%, #79ace9 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#bddef4', EndColorStr='#79ace9');
+}
+
+.dt-button embed {
+ outline: none;
+}
+
+div.dt-buttons {
+ position: relative;
+ float: left;
+}
+div.dt-buttons.buttons-right {
+ float: right;
+}
+
+div.dt-button-collection {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 150px;
+ margin-top: 3px;
+ padding: 8px 8px 4px 8px;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.4);
+ background-color: white;
+ overflow: hidden;
+ z-index: 2002;
+ border-radius: 5px;
+ box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+div.dt-button-collection button.dt-button,
+div.dt-button-collection div.dt-button,
+div.dt-button-collection a.dt-button {
+ position: relative;
+ left: 0;
+ right: 0;
+ width: 100%;
+ display: block;
+ float: none;
+ margin-bottom: 4px;
+ margin-right: 0;
+}
+div.dt-button-collection button.dt-button:active:not(.disabled), div.dt-button-collection button.dt-button.active:not(.disabled),
+div.dt-button-collection div.dt-button:active:not(.disabled),
+div.dt-button-collection div.dt-button.active:not(.disabled),
+div.dt-button-collection a.dt-button:active:not(.disabled),
+div.dt-button-collection a.dt-button.active:not(.disabled) {
+ background-color: #dadada;
+ /* Fallback */
+ background-image: -webkit-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
+ /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
+ /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
+ /* IE10 */
+ background-image: -o-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
+ /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, #f0f0f0 0%, #dadada 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f0f0f0', EndColorStr='#dadada');
+ box-shadow: inset 1px 1px 3px #666;
+}
+div.dt-button-collection.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+div.dt-button-collection.fixed.two-column {
+ margin-left: -150px;
+}
+div.dt-button-collection.fixed.three-column {
+ margin-left: -225px;
+}
+div.dt-button-collection.fixed.four-column {
+ margin-left: -300px;
+}
+div.dt-button-collection > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+div.dt-button-collection.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+div.dt-button-collection.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+div.dt-button-collection.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+div.dt-button-collection .dt-button {
+ border-radius: 0;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.7);
+ /* Fallback */
+ background: -ms-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* IE10 Consumer Preview */
+ background: -moz-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Firefox */
+ background: -o-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Opera */
+ background: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0, 0, 0, 0.3)), color-stop(1, rgba(0, 0, 0, 0.7)));
+ /* Webkit (Safari/Chrome 10) */
+ background: -webkit-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Webkit (Chrome 11+) */
+ background: radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* W3C Markup, IE10 Release Preview */
+ z-index: 2001;
+}
+
+@media screen and (max-width: 640px) {
+ div.dt-buttons {
+ float: none !important;
+ text-align: center;
+ }
+}
+button.dt-button.processing,
+div.dt-button.processing,
+a.dt-button.processing {
+ color: rgba(0, 0, 0, 0.2);
+}
+button.dt-button.processing:after,
+div.dt-button.processing:after,
+a.dt-button.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.min.css
new file mode 100644
index 0000000..f23849d
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.dataTables.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}button.dt-button,div.dt-button,a.dt-button{position:relative;display:inline-block;box-sizing:border-box;margin-right:0.333em;margin-bottom:0.333em;padding:0.5em 1em;border:1px solid #999;border-radius:2px;cursor:pointer;font-size:0.88em;line-height:1.6em;color:black;white-space:nowrap;overflow:hidden;background-color:#e9e9e9;background-image:-webkit-linear-gradient(top, #fff 0%, #e9e9e9 100%);background-image:-moz-linear-gradient(top, #fff 0%, #e9e9e9 100%);background-image:-ms-linear-gradient(top, #fff 0%, #e9e9e9 100%);background-image:-o-linear-gradient(top, #fff 0%, #e9e9e9 100%);background-image:linear-gradient(to bottom, #fff 0%, #e9e9e9 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='white', EndColorStr='#e9e9e9');-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;outline:none}button.dt-button.disabled,div.dt-button.disabled,a.dt-button.disabled{color:#999;border:1px solid #d0d0d0;cursor:default;background-color:#f9f9f9;background-image:-webkit-linear-gradient(top, #fff 0%, #f9f9f9 100%);background-image:-moz-linear-gradient(top, #fff 0%, #f9f9f9 100%);background-image:-ms-linear-gradient(top, #fff 0%, #f9f9f9 100%);background-image:-o-linear-gradient(top, #fff 0%, #f9f9f9 100%);background-image:linear-gradient(to bottom, #fff 0%, #f9f9f9 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#ffffff', EndColorStr='#f9f9f9')}button.dt-button:active:not(.disabled),button.dt-button.active:not(.disabled),div.dt-button:active:not(.disabled),div.dt-button.active:not(.disabled),a.dt-button:active:not(.disabled),a.dt-button.active:not(.disabled){background-color:#e2e2e2;background-image:-webkit-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);background-image:-moz-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);background-image:-ms-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);background-image:-o-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);background-image:linear-gradient(to bottom, #f3f3f3 0%, #e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f3f3f3', EndColorStr='#e2e2e2');box-shadow:inset 1px 1px 3px #999999}button.dt-button:active:not(.disabled):hover:not(.disabled),button.dt-button.active:not(.disabled):hover:not(.disabled),div.dt-button:active:not(.disabled):hover:not(.disabled),div.dt-button.active:not(.disabled):hover:not(.disabled),a.dt-button:active:not(.disabled):hover:not(.disabled),a.dt-button.active:not(.disabled):hover:not(.disabled){box-shadow:inset 1px 1px 3px #999999;background-color:#cccccc;background-image:-webkit-linear-gradient(top, #eaeaea 0%, #ccc 100%);background-image:-moz-linear-gradient(top, #eaeaea 0%, #ccc 100%);background-image:-ms-linear-gradient(top, #eaeaea 0%, #ccc 100%);background-image:-o-linear-gradient(top, #eaeaea 0%, #ccc 100%);background-image:linear-gradient(to bottom, #eaeaea 0%, #ccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#eaeaea', EndColorStr='#cccccc')}button.dt-button:hover,div.dt-button:hover,a.dt-button:hover{text-decoration:none}button.dt-button:hover:not(.disabled),div.dt-button:hover:not(.disabled),a.dt-button:hover:not(.disabled){border:1px solid #666;background-color:#e0e0e0;background-image:-webkit-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);background-image:-moz-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);background-image:-ms-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);background-image:-o-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);background-image:linear-gradient(to bottom, #f9f9f9 0%, #e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f9f9f9', EndColorStr='#e0e0e0')}button.dt-button:focus:not(.disabled),div.dt-button:focus:not(.disabled),a.dt-button:focus:not(.disabled){border:1px solid #426c9e;text-shadow:0 1px 0 #c4def1;outline:none;background-color:#79ace9;background-image:-webkit-linear-gradient(top, #bddef4 0%, #79ace9 100%);background-image:-moz-linear-gradient(top, #bddef4 0%, #79ace9 100%);background-image:-ms-linear-gradient(top, #bddef4 0%, #79ace9 100%);background-image:-o-linear-gradient(top, #bddef4 0%, #79ace9 100%);background-image:linear-gradient(to bottom, #bddef4 0%, #79ace9 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#bddef4', EndColorStr='#79ace9')}.dt-button embed{outline:none}div.dt-buttons{position:relative;float:left}div.dt-buttons.buttons-right{float:right}div.dt-button-collection{position:absolute;top:0;left:0;width:150px;margin-top:3px;padding:8px 8px 4px 8px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.4);background-color:white;overflow:hidden;z-index:2002;border-radius:5px;box-shadow:3px 3px 5px rgba(0,0,0,0.3);-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}div.dt-button-collection button.dt-button,div.dt-button-collection div.dt-button,div.dt-button-collection a.dt-button{position:relative;left:0;right:0;width:100%;display:block;float:none;margin-bottom:4px;margin-right:0}div.dt-button-collection button.dt-button:active:not(.disabled),div.dt-button-collection button.dt-button.active:not(.disabled),div.dt-button-collection div.dt-button:active:not(.disabled),div.dt-button-collection div.dt-button.active:not(.disabled),div.dt-button-collection a.dt-button:active:not(.disabled),div.dt-button-collection a.dt-button.active:not(.disabled){background-color:#dadada;background-image:-webkit-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background-image:-moz-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background-image:-ms-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background-image:-o-linear-gradient(top, #f0f0f0 0%, #dadada 100%);background-image:linear-gradient(to bottom, #f0f0f0 0%, #dadada 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f0f0f0', EndColorStr='#dadada');box-shadow:inset 1px 1px 3px #666}div.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}div.dt-button-collection.fixed.two-column{margin-left:-150px}div.dt-button-collection.fixed.three-column{margin-left:-225px}div.dt-button-collection.fixed.four-column{margin-left:-300px}div.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}div.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}div.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}div.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}div.dt-button-collection .dt-button{border-radius:0}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);background:-ms-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-moz-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-o-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0,0,0,0.3)), color-stop(1, rgba(0,0,0,0.7)));background:-webkit-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:radial-gradient(ellipse farthest-corner at center, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);z-index:2001}@media screen and (max-width: 640px){div.dt-buttons{float:none !important;text-align:center}}button.dt-button.processing,div.dt-button.processing,a.dt-button.processing{color:rgba(0,0,0,0.2)}button.dt-button.processing:after,div.dt-button.processing:after,a.dt-button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.css
new file mode 100644
index 0000000..606e81e
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.css
@@ -0,0 +1,200 @@
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+ul.dt-buttons li {
+ margin: 0;
+}
+ul.dt-buttons li.active a {
+ box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.6);
+}
+
+ul.dt-buttons.button-group a {
+ margin-bottom: 0;
+}
+
+ul.dt-button-collection.f-dropdown {
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+ul.dt-button-collection.f-dropdown.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+ul.dt-button-collection.f-dropdown.fixed.two-column {
+ margin-left: -150px;
+}
+ul.dt-button-collection.f-dropdown.fixed.three-column {
+ margin-left: -225px;
+}
+ul.dt-button-collection.f-dropdown.fixed.four-column {
+ margin-left: -300px;
+}
+ul.dt-button-collection.f-dropdown > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+ul.dt-button-collection.f-dropdown.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+ul.dt-button-collection.f-dropdown.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+ul.dt-button-collection.f-dropdown.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+ul.dt-button-collection.f-dropdown .dt-button {
+ border-radius: 0;
+}
+ul.dt-button-collection.f-dropdown.fixed {
+ max-width: none;
+}
+ul.dt-button-collection.f-dropdown.fixed:before, ul.dt-button-collection.f-dropdown.fixed:after {
+ display: none;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 88;
+}
+
+@media screen and (max-width: 767px) {
+ ul.dt-buttons {
+ float: none;
+ width: 100%;
+ text-align: center;
+ margin-bottom: 0.5rem;
+ }
+ ul.dt-buttons li {
+ float: none;
+ }
+}
+div.button-group.stacked.dropdown-pane {
+ margin-top: 2px;
+ padding: 1px;
+ z-index: 89;
+}
+div.button-group.stacked.dropdown-pane a.button {
+ display: block;
+ margin-bottom: 1px;
+ border-right: none;
+}
+div.button-group.stacked.dropdown-pane a.button:last-child {
+ margin-bottom: 0;
+ margin-right: 1px;
+}
+
+div.dt-buttons button.button.processing,
+div.dt-buttons div.button.processing,
+div.dt-buttons a.button.processing {
+ color: rgba(0, 0, 0, 0.2);
+ color: rgba(255, 255, 255, 0.2);
+ border-top-color: white;
+ border-bottom-color: white;
+}
+div.dt-buttons button.button.processing:after,
+div.dt-buttons div.button.processing:after,
+div.dt-buttons a.button.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.min.css
new file mode 100644
index 0000000..3fb5cb3
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.foundation.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}ul.dt-buttons li{margin:0}ul.dt-buttons li.active a{box-shadow:inset 0 0 10px rgba(0,0,0,0.6)}ul.dt-buttons.button-group a{margin-bottom:0}ul.dt-button-collection.f-dropdown{-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.f-dropdown.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.f-dropdown.fixed.two-column{margin-left:-150px}ul.dt-button-collection.f-dropdown.fixed.three-column{margin-left:-225px}ul.dt-button-collection.f-dropdown.fixed.four-column{margin-left:-300px}ul.dt-button-collection.f-dropdown>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.f-dropdown.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.f-dropdown.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.f-dropdown.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection.f-dropdown .dt-button{border-radius:0}ul.dt-button-collection.f-dropdown.fixed{max-width:none}ul.dt-button-collection.f-dropdown.fixed:before,ul.dt-button-collection.f-dropdown.fixed:after{display:none}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;z-index:88}@media screen and (max-width: 767px){ul.dt-buttons{float:none;width:100%;text-align:center;margin-bottom:0.5rem}ul.dt-buttons li{float:none}}div.button-group.stacked.dropdown-pane{margin-top:2px;padding:1px;z-index:89}div.button-group.stacked.dropdown-pane a.button{display:block;margin-bottom:1px;border-right:none}div.button-group.stacked.dropdown-pane a.button:last-child{margin-bottom:0;margin-right:1px}div.dt-buttons button.button.processing,div.dt-buttons div.button.processing,div.dt-buttons a.button.processing{color:rgba(0,0,0,0.2);color:rgba(255,255,255,0.2);border-top-color:white;border-bottom-color:white}div.dt-buttons button.button.processing:after,div.dt-buttons div.button.processing:after,div.dt-buttons a.button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.css
new file mode 100644
index 0000000..933239a
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.css
@@ -0,0 +1,226 @@
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+div.dt-buttons {
+ position: relative;
+ float: left;
+}
+div.dt-buttons .dt-button {
+ margin-right: 0;
+}
+div.dt-buttons .dt-button span.ui-icon {
+ display: inline-block;
+ vertical-align: middle;
+ margin-top: -2px;
+}
+div.dt-buttons .dt-button:active {
+ outline: none;
+}
+div.dt-buttons .dt-button:hover > span {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+div.dt-button-collection {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 150px;
+ margin-top: 3px;
+ padding: 8px 8px 4px 8px;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.4);
+ background-color: #f3f3f3;
+ background-color: rgba(255, 255, 255, 0.3);
+ overflow: hidden;
+ z-index: 2002;
+ border-radius: 5px;
+ box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
+ z-index: 2002;
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+ -webkit-column-gap: 0;
+ -moz-column-gap: 0;
+ -ms-column-gap: 0;
+ -o-column-gap: 0;
+ column-gap: 0;
+}
+div.dt-button-collection .dt-button {
+ position: relative;
+ left: 0;
+ right: 0;
+ width: 100%;
+ display: block;
+ float: none;
+ margin-right: 0;
+ margin-bottom: 4px;
+}
+div.dt-button-collection .dt-button:hover > span {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+div.dt-button-collection.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+div.dt-button-collection.fixed.two-column {
+ margin-left: -150px;
+}
+div.dt-button-collection.fixed.three-column {
+ margin-left: -225px;
+}
+div.dt-button-collection.fixed.four-column {
+ margin-left: -300px;
+}
+div.dt-button-collection > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+div.dt-button-collection.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+div.dt-button-collection.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+div.dt-button-collection.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+div.dt-button-collection .dt-button {
+ border-radius: 0;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.7);
+ /* Fallback */
+ background: -ms-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* IE10 Consumer Preview */
+ background: -moz-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Firefox */
+ background: -o-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Opera */
+ background: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0, 0, 0, 0.3)), color-stop(1, rgba(0, 0, 0, 0.7)));
+ /* Webkit (Safari/Chrome 10) */
+ background: -webkit-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* Webkit (Chrome 11+) */
+ background: radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
+ /* W3C Markup, IE10 Release Preview */
+ z-index: 2001;
+}
+
+@media screen and (max-width: 640px) {
+ div.dt-buttons {
+ float: none !important;
+ text-align: center;
+ }
+}
+button.dt-button.processing,
+div.dt-button.processing,
+a.dt-button.processing {
+ color: rgba(0, 0, 0, 0.2);
+}
+button.dt-button.processing:after,
+div.dt-button.processing:after,
+a.dt-button.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.min.css
new file mode 100644
index 0000000..afb1b37
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.jqueryui.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}div.dt-buttons{position:relative;float:left}div.dt-buttons .dt-button{margin-right:0}div.dt-buttons .dt-button span.ui-icon{display:inline-block;vertical-align:middle;margin-top:-2px}div.dt-buttons .dt-button:active{outline:none}div.dt-buttons .dt-button:hover>span{background-color:rgba(0,0,0,0.05)}div.dt-button-collection{position:absolute;top:0;left:0;width:150px;margin-top:3px;padding:8px 8px 4px 8px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.4);background-color:#f3f3f3;background-color:rgba(255,255,255,0.3);overflow:hidden;z-index:2002;border-radius:5px;box-shadow:3px 3px 5px rgba(0,0,0,0.3);z-index:2002;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px;-webkit-column-gap:0;-moz-column-gap:0;-ms-column-gap:0;-o-column-gap:0;column-gap:0}div.dt-button-collection .dt-button{position:relative;left:0;right:0;width:100%;display:block;float:none;margin-right:0;margin-bottom:4px}div.dt-button-collection .dt-button:hover>span{background-color:rgba(0,0,0,0.05)}div.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}div.dt-button-collection.fixed.two-column{margin-left:-150px}div.dt-button-collection.fixed.three-column{margin-left:-225px}div.dt-button-collection.fixed.four-column{margin-left:-300px}div.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}div.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}div.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}div.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}div.dt-button-collection .dt-button{border-radius:0}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);background:-ms-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-moz-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-o-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:-webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0,0,0,0.3)), color-stop(1, rgba(0,0,0,0.7)));background:-webkit-radial-gradient(center, ellipse farthest-corner, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);background:radial-gradient(ellipse farthest-corner at center, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);z-index:2001}@media screen and (max-width: 640px){div.dt-buttons{float:none !important;text-align:center}}button.dt-button.processing,div.dt-button.processing,a.dt-button.processing{color:rgba(0,0,0,0.2)}button.dt-button.processing:after,div.dt-button.processing:after,a.dt-button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.css
new file mode 100644
index 0000000..56dd99c
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.css
@@ -0,0 +1,180 @@
+@charset "UTF-8";
+@keyframes dtb-spinner {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+@-o-keyframes dtb-spinner {
+ 100% {
+ -o-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-ms-keyframes dtb-spinner {
+ 100% {
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-webkit-keyframes dtb-spinner {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@-moz-keyframes dtb-spinner {
+ 100% {
+ -moz-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+}
+div.dt-button-info h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+}
+div.dt-button-info > div {
+ padding: 1em;
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
+
+div.dt-button-collection {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 150px;
+ margin-top: 3px !important;
+ z-index: 2002;
+ background: white;
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+}
+div.dt-button-collection.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+}
+div.dt-button-collection.fixed.two-column {
+ margin-left: -150px;
+}
+div.dt-button-collection.fixed.three-column {
+ margin-left: -225px;
+}
+div.dt-button-collection.fixed.four-column {
+ margin-left: -300px;
+}
+div.dt-button-collection > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+}
+div.dt-button-collection.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+}
+div.dt-button-collection.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+}
+div.dt-button-collection.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+}
+div.dt-button-collection .dt-button {
+ border-radius: 0;
+}
+
+button.buttons-collection.ui.button span:after {
+ display: inline-block;
+ content: "▾";
+ padding-left: 0.5em;
+}
+
+div.dt-button-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 2001;
+}
+
+@media screen and (max-width: 767px) {
+ div.dt-buttons {
+ float: none;
+ width: 100%;
+ text-align: center;
+ margin-bottom: 0.5em;
+ }
+ div.dt-buttons a.btn {
+ float: none;
+ }
+}
+div.dt-buttons button.button.processing,
+div.dt-buttons div.button.processing,
+div.dt-buttons a.button.processing {
+ position: relative;
+ color: rgba(0, 0, 0, 0.2);
+}
+div.dt-buttons button.button.processing:after,
+div.dt-buttons div.button.processing:after,
+div.dt-buttons a.button.processing:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+ display: block;
+ content: ' ';
+ border: 2px solid #282828;
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.min.css b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.min.css
new file mode 100644
index 0000000..e2b44ed
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/buttons.semanticui.min.css
@@ -0,0 +1 @@
+@keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}div.dt-button-collection-title{text-align:center;padding:0.3em 0 0.5em;font-size:0.9em}div.dt-button-collection{position:absolute;top:0;left:0;width:150px;margin-top:3px !important;z-index:2002;background:white;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}div.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}div.dt-button-collection.fixed.two-column{margin-left:-150px}div.dt-button-collection.fixed.three-column{margin-left:-225px}div.dt-button-collection.fixed.four-column{margin-left:-300px}div.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}div.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}div.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}div.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}div.dt-button-collection .dt-button{border-radius:0}button.buttons-collection.ui.button span:after{display:inline-block;content:"▾";padding-left:0.5em}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;z-index:2001}@media screen and (max-width: 767px){div.dt-buttons{float:none;width:100%;text-align:center;margin-bottom:0.5em}div.dt-buttons a.btn{float:none}}div.dt-buttons button.button.processing,div.dt-buttons div.button.processing,div.dt-buttons a.button.processing{position:relative;color:rgba(0,0,0,0.2)}div.dt-buttons button.button.processing:after,div.dt-buttons div.button.processing:after,div.dt-buttons a.button.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/common.scss b/public/assets/plugins/DataTables/Buttons-1.5.4/css/common.scss
new file mode 100644
index 0000000..2b5384d
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/common.scss
@@ -0,0 +1,33 @@
+
+div.dt-button-info {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 400px;
+ margin-top: -100px;
+ margin-left: -200px;
+ background-color: white;
+ border: 2px solid #111;
+ box-shadow: 3px 3px 8px rgba( 0, 0, 0, 0.3);
+ border-radius: 3px;
+ text-align: center;
+ z-index: 21;
+
+ h2 {
+ padding: 0.5em;
+ margin: 0;
+ font-weight: normal;
+ border-bottom: 1px solid #ddd;
+ background-color: #f3f3f3;
+ }
+
+ > div {
+ padding: 1em;
+ }
+}
+
+div.dt-button-collection-title {
+ text-align: center;
+ padding: 0.3em 0 0.5em;
+ font-size: 0.9em;
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/css/mixins.scss b/public/assets/plugins/DataTables/Buttons-1.5.4/css/mixins.scss
new file mode 100644
index 0000000..6328942
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/css/mixins.scss
@@ -0,0 +1,141 @@
+
+@mixin dtb-two-stop-gradient($fromColor, $toColor) {
+ background-color: $toColor; /* Fallback */
+ background-image: -webkit-linear-gradient(top, $fromColor 0%, $toColor 100%); /* Chrome 10+, Saf5.1+, iOS 5+ */
+ background-image: -moz-linear-gradient(top, $fromColor 0%, $toColor 100%); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, $fromColor 0%, $toColor 100%); /* IE10 */
+ background-image: -o-linear-gradient(top, $fromColor 0%, $toColor 100%); /* Opera 11.10+ */
+ background-image: linear-gradient(to bottom, $fromColor 0%, $toColor 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#{nth( $fromColor, 1 )}', EndColorStr='#{nth( $toColor, 1 )}');
+}
+
+@mixin dtb-radial-gradient ($fromColor, $toColor ) {
+ background: $toColor; /* Fallback */
+ background: -ms-radial-gradient(center, ellipse farthest-corner, $fromColor 0%, $toColor 100%); /* IE10 Consumer Preview */
+ background: -moz-radial-gradient(center, ellipse farthest-corner, $fromColor 0%, $toColor 100%); /* Firefox */
+ background: -o-radial-gradient(center, ellipse farthest-corner, $fromColor 0%, $toColor 100%); /* Opera */
+ background: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, $fromColor), color-stop(1, $toColor)); /* Webkit (Safari/Chrome 10) */
+ background: -webkit-radial-gradient(center, ellipse farthest-corner, $fromColor 0%, $toColor 100%); /* Webkit (Chrome 11+) */
+ background: radial-gradient(ellipse farthest-corner at center, $fromColor 0%, $toColor 100%); /* W3C Markup, IE10 Release Preview */
+}
+
+
+@mixin dtb-fixed-collection {
+ // Fixed positioning feature
+ &.fixed {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-left: -75px;
+ border-radius: 0;
+
+ &.two-column {
+ margin-left: -150px;
+ }
+
+ &.three-column {
+ margin-left: -225px;
+ }
+
+ &.four-column {
+ margin-left: -300px;
+ }
+ }
+
+ // Multi-column layout feature
+ -webkit-column-gap: 8px;
+ -moz-column-gap: 8px;
+ -ms-column-gap: 8px;
+ -o-column-gap: 8px;
+ column-gap: 8px;
+
+ > * {
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid;
+ }
+
+ &.two-column {
+ width: 300px;
+ padding-bottom: 1px;
+
+ -webkit-column-count: 2;
+ -moz-column-count: 2;
+ -ms-column-count: 2;
+ -o-column-count: 2;
+ column-count: 2;
+ }
+
+ &.three-column {
+ width: 450px;
+ padding-bottom: 1px;
+
+ -webkit-column-count: 3;
+ -moz-column-count: 3;
+ -ms-column-count: 3;
+ -o-column-count: 3;
+ column-count: 3;
+ }
+
+ &.four-column {
+ width: 600px;
+ padding-bottom: 1px;
+
+ -webkit-column-count: 4;
+ -moz-column-count: 4;
+ -ms-column-count: 4;
+ -o-column-count: 4;
+ column-count: 4;
+ }
+
+ // Chrome fix - 531528
+ .dt-button {
+ border-radius: 0;
+ }
+}
+
+
+@mixin dtb-processing {
+ color: rgba(0, 0, 0, 0.2);
+
+ &:after {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 16px;
+ height: 16px;
+ margin: -8px 0 0 -8px;
+ box-sizing: border-box;
+
+ display: block;
+ content: ' ';
+ border: 2px solid rgb(40,40,40);
+ border-radius: 50%;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ animation: dtb-spinner 1500ms infinite linear;
+ -o-animation: dtb-spinner 1500ms infinite linear;
+ -ms-animation: dtb-spinner 1500ms infinite linear;
+ -webkit-animation: dtb-spinner 1500ms infinite linear;
+ -moz-animation: dtb-spinner 1500ms infinite linear;
+ }
+}
+
+@keyframes dtb-spinner {
+ 100%{ transform: rotate(360deg); }
+}
+
+@-o-keyframes dtb-spinner {
+ 100%{ -o-transform: rotate(360deg); transform: rotate(360deg); }
+}
+
+@-ms-keyframes dtb-spinner {
+ 100%{ -ms-transform: rotate(360deg); transform: rotate(360deg); }
+}
+
+@-webkit-keyframes dtb-spinner {
+ 100%{ -webkit-transform: rotate(360deg); transform: rotate(360deg); }
+}
+
+@-moz-keyframes dtb-spinner {
+ 100%{ -moz-transform: rotate(360deg); transform: rotate(360deg); }
+}
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.js b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.js
new file mode 100644
index 0000000..994ab89
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.js
@@ -0,0 +1,70 @@
+/*! Bootstrap integration for DataTables' Buttons
+ * ©2016 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD
+ define( ['jquery', 'datatables.net-bs', 'datatables.net-buttons'], function ( $ ) {
+ return factory( $, window, document );
+ } );
+ }
+ else if ( typeof exports === 'object' ) {
+ // CommonJS
+ module.exports = function (root, $) {
+ if ( ! root ) {
+ root = window;
+ }
+
+ if ( ! $ || ! $.fn.dataTable ) {
+ $ = require('datatables.net-bs')(root, $).$;
+ }
+
+ if ( ! $.fn.dataTable.Buttons ) {
+ require('datatables.net-buttons')(root, $);
+ }
+
+ return factory( $, root, root.document );
+ };
+ }
+ else {
+ // Browser
+ factory( jQuery, window, document );
+ }
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+$.extend( true, DataTable.Buttons.defaults, {
+ dom: {
+ container: {
+ className: 'dt-buttons btn-group'
+ },
+ button: {
+ className: 'btn btn-default'
+ },
+ collection: {
+ tag: 'ul',
+ className: 'dt-button-collection dropdown-menu',
+ button: {
+ tag: 'li',
+ className: 'dt-button',
+ active: 'active',
+ disabled: 'disabled'
+ },
+ buttonLiner: {
+ tag: 'a',
+ className: ''
+ }
+ }
+ }
+} );
+
+DataTable.ext.buttons.collection.text = function ( dt ) {
+ return dt.i18n('buttons.collection', 'Collection ');
+};
+
+
+return DataTable.Buttons;
+}));
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.min.js b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.min.js
new file mode 100644
index 0000000..90a6e89
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ Bootstrap integration for DataTables' Buttons
+ ©2016 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs","datatables.net-buttons"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);b&&b.fn.dataTable||(b=require("datatables.net-bs")(a,b).$);b.fn.dataTable.Buttons||require("datatables.net-buttons")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c,a,b,d){a=c.fn.dataTable;c.extend(!0,a.Buttons.defaults,{dom:{container:{className:"dt-buttons btn-group"},
+button:{className:"btn btn-default"},collection:{tag:"ul",className:"dt-button-collection dropdown-menu",button:{tag:"li",className:"dt-button",active:"active",disabled:"disabled"},buttonLiner:{tag:"a",className:""}}}});a.ext.buttons.collection.text=function(a){return a.i18n("buttons.collection",'Collection ')};return a.Buttons});
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.js b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.js
new file mode 100644
index 0000000..f2dedd9
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.js
@@ -0,0 +1,63 @@
+/*! Bootstrap integration for DataTables' Buttons
+ * ©2016 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD
+ define( ['jquery', 'datatables.net-bs4', 'datatables.net-buttons'], function ( $ ) {
+ return factory( $, window, document );
+ } );
+ }
+ else if ( typeof exports === 'object' ) {
+ // CommonJS
+ module.exports = function (root, $) {
+ if ( ! root ) {
+ root = window;
+ }
+
+ if ( ! $ || ! $.fn.dataTable ) {
+ $ = require('datatables.net-bs4')(root, $).$;
+ }
+
+ if ( ! $.fn.dataTable.Buttons ) {
+ require('datatables.net-buttons')(root, $);
+ }
+
+ return factory( $, root, root.document );
+ };
+ }
+ else {
+ // Browser
+ factory( jQuery, window, document );
+ }
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+$.extend( true, DataTable.Buttons.defaults, {
+ dom: {
+ container: {
+ className: 'dt-buttons btn-group'
+ },
+ button: {
+ className: 'btn btn-secondary'
+ },
+ collection: {
+ tag: 'div',
+ className: 'dt-button-collection dropdown-menu',
+ button: {
+ tag: 'a',
+ className: 'dt-button dropdown-item',
+ active: 'active',
+ disabled: 'disabled'
+ }
+ }
+ }
+} );
+
+DataTable.ext.buttons.collection.className += ' dropdown-toggle';
+DataTable.ext.buttons.collection.rightAlignClassName = 'dropdown-menu-right';
+
+return DataTable.Buttons;
+}));
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.min.js b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.min.js
new file mode 100644
index 0000000..56c5e2a
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.bootstrap4.min.js
@@ -0,0 +1,6 @@
+/*!
+ Bootstrap integration for DataTables' Buttons
+ ©2016 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-buttons"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);b&&b.fn.dataTable||(b=require("datatables.net-bs4")(a,b).$);b.fn.dataTable.Buttons||require("datatables.net-buttons")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c,a,b,d){a=c.fn.dataTable;c.extend(!0,a.Buttons.defaults,{dom:{container:{className:"dt-buttons btn-group"},
+button:{className:"btn btn-secondary"},collection:{tag:"div",className:"dt-button-collection dropdown-menu",button:{tag:"a",className:"dt-button dropdown-item",active:"active",disabled:"disabled"}}}});a.ext.buttons.collection.className+=" dropdown-toggle";a.ext.buttons.collection.rightAlignClassName="dropdown-menu-right";return a.Buttons});
diff --git a/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.colVis.js b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.colVis.js
new file mode 100644
index 0000000..d5ec8de
--- /dev/null
+++ b/public/assets/plugins/DataTables/Buttons-1.5.4/js/buttons.colVis.js
@@ -0,0 +1,213 @@
+/*!
+ * Column visibility buttons for Buttons and DataTables.
+ * 2016 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+ if ( typeof define === 'function' && define.amd ) {
+ // AMD
+ define( ['jquery', 'datatables.net', 'datatables.net-buttons'], function ( $ ) {
+ return factory( $, window, document );
+ } );
+ }
+ else if ( typeof exports === 'object' ) {
+ // CommonJS
+ module.exports = function (root, $) {
+ if ( ! root ) {
+ root = window;
+ }
+
+ if ( ! $ || ! $.fn.dataTable ) {
+ $ = require('datatables.net')(root, $).$;
+ }
+
+ if ( ! $.fn.dataTable.Buttons ) {
+ require('datatables.net-buttons')(root, $);
+ }
+
+ return factory( $, root, root.document );
+ };
+ }
+ else {
+ // Browser
+ factory( jQuery, window, document );
+ }
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+$.extend( DataTable.ext.buttons, {
+ // A collection of column visibility buttons
+ colvis: function ( dt, conf ) {
+ return {
+ extend: 'collection',
+ text: function ( dt ) {
+ return dt.i18n( 'buttons.colvis', 'Column visibility' );
+ },
+ className: 'buttons-colvis',
+ buttons: [ {
+ extend: 'columnsToggle',
+ columns: conf.columns,
+ columnText: conf.columnText
+ } ]
+ };
+ },
+
+ // Selected columns with individual buttons - toggle column visibility
+ columnsToggle: function ( dt, conf ) {
+ var columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {
+ return {
+ extend: 'columnToggle',
+ columns: idx,
+ columnText: conf.columnText
+ };
+ } ).toArray();
+
+ return columns;
+ },
+
+ // Single button to toggle column visibility
+ columnToggle: function ( dt, conf ) {
+ return {
+ extend: 'columnVisibility',
+ columns: conf.columns,
+ columnText: conf.columnText
+ };
+ },
+
+ // Selected columns with individual buttons - set column visibility
+ columnsVisibility: function ( dt, conf ) {
+ var columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {
+ return {
+ extend: 'columnVisibility',
+ columns: idx,
+ visibility: conf.visibility,
+ columnText: conf.columnText
+ };
+ } ).toArray();
+
+ return columns;
+ },
+
+ // Single button to set column visibility
+ columnVisibility: {
+ columns: undefined, // column selector
+ text: function ( dt, button, conf ) {
+ return conf._columnText( dt, conf );
+ },
+ className: 'buttons-columnVisibility',
+ action: function ( e, dt, button, conf ) {
+ var col = dt.columns( conf.columns );
+ var curr = col.visible();
+
+ col.visible( conf.visibility !== undefined ?
+ conf.visibility :
+ ! (curr.length ? curr[0] : false )
+ );
+ },
+ init: function ( dt, button, conf ) {
+ var that = this;
+ button.attr( 'data-cv-idx', conf.columns );
+
+ dt
+ .on( 'column-visibility.dt'+conf.namespace, function (e, settings) {
+ if ( ! settings.bDestroying && settings.nTable == dt.settings()[0].nTable ) {
+ that.active( dt.column( conf.columns ).visible() );
+ }
+ } )
+ .on( 'column-reorder.dt'+conf.namespace, function (e, settings, details) {
+ // Don't rename buttons based on column name if the button
+ // controls more than one column!
+ if ( dt.columns( conf.columns ).count() !== 1 ) {
+ return;
+ }
+
+ conf.columns = $.inArray( conf.columns, details.mapping );
+ button.attr( 'data-cv-idx', conf.columns );
+
+ // Reorder buttons for new table order
+ button
+ .parent()
+ .children('[data-cv-idx]')
+ .sort( function (a, b) {
+ return (a.getAttribute('data-cv-idx')*1) - (b.getAttribute('data-cv-idx')*1);
+ } )
+ .appendTo(button.parent());
+ } );
+
+ this.active( dt.column( conf.columns ).visible() );
+ },
+ destroy: function ( dt, button, conf ) {
+ dt
+ .off( 'column-visibility.dt'+conf.namespace )
+ .off( 'column-reorder.dt'+conf.namespace );
+ },
+
+ _columnText: function ( dt, conf ) {
+ // Use DataTables' internal data structure until this is presented
+ // is a public API. The other option is to use
+ // `$( column(col).node() ).text()` but the node might not have been
+ // populated when Buttons is constructed.
+ var idx = dt.column( conf.columns ).index();
+ var title = dt.settings()[0].aoColumns[ idx ].sTitle
+ .replace(/\n/g," ") // remove new lines
+ .replace(/
/gi, " ") // replace line breaks with spaces
+ .replace(/