Merged in afiqhamzah/feat/add-report-keseluruhan-stokaudit-admin (pull request #39)

Add report keseluruhan stok audit admin
This commit is contained in:
Afiq Hamzah
2024-04-15 08:43:01 +00:00
7 changed files with 529 additions and 0 deletions
@@ -0,0 +1,89 @@
<?php
namespace App\Exports\LaporanKeseluruhan;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class StokAuditExport extends DefaultValueBinder implements FromArray, WithStrictNullComparison, WithMapping, WithHeadings, ShouldAutoSize, WithCustomValueBinder
{
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function headings(): array
{
return [
'Cawangan',
'Jumlah Pinjaman',
'Total Pinjaman',
'Total Berat',
'Total Nilai Marhun',
'Total Baki Pinjaman',
'Total Upah Belum Bayar',
'Total Untung 1%',
'Total Ujrah',
];
}
public function array(): array
{
return $this->data;
}
public function startCell(): string
{
return 'B2';
}
public function map($data): array
{
return [
$data['cawangan'],
$data['jumlah_pinjaman'],
number_format($data['total_pinjaman'], 2),
number_format($data['total_berat'], 2),
number_format($data['total_nilai_marhun'], 2),
number_format($data['total_baki_pinjaman'], 2),
number_format($data['total_upah_belum_bayar'], 2),
number_format($data['total_utg_onepercent'], 2),
number_format($data['total_ujrah'], 2),
];
}
public function columnFormats(): array
{
return [
'C' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'D' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'E' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'F' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'G' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'H' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'I' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
];
}
public function bindValue(Cell $cell, $value)
{
if (is_numeric($value)) {
$cell->setValueExplicit($value, DataType::TYPE_NUMERIC);
return true;
}
// else return default behavior
return parent::bindValue($cell, $value);
}
}
@@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Http;
use App\Exports\LaporanKeseluruhan\StokAuditExport;
use Maatwebsite\Excel\Facades\Excel;
class StokAuditController extends Controller
{
public function index(Request $request)
{
$request->hostname = config('api.url');
$current = new Carbon();
$month = $request->filled('month') ? $request->month : $current->month;
$year = $request->filled('year') ? $request->year : $current->year;
return view('reports.stok-audit.index', compact('month', 'year'));
}
public function show(Request $request)
{
$validated = $request->validate(
['monthYear' => 'required'],
['monthYear.required' => 'Sila isi tarikh sebelum hantar',
]);
$current = Carbon::now();
$tarikh_cetak = $current->toDateString();
$tokens = explode('-', $validated['monthYear']);
$month = ltrim($tokens[0], '0');
$year = $tokens[1];
// Set the locale to Malaysian
App::setLocale('ms');
// Create a Carbon instance representing the date
$date = Carbon::createFromDate($year, $month, 1); // Set the day to 1st of the month
// Get the name of the month in Malaysian local
$monthName = $date->translatedFormat('F');
$request->hostname = config('api.url');
$stokAudit = Http::get($request->hostname . '/api/reports/stok-audit', [
'month' => $month,
'year' => $year,
])->json();
$tebus_date = $monthName . ' ' . $year;
$file_title = sprintf("Laporan-StokAudit %s (%s - %s).xlsx", 'Semua cawanangan', $monthName, $year);
if ($request->generateType === 'pdf') {
return view('reports.stok-audit.show', compact('tebus_date', 'tarikh_cetak', 'stokAudit', 'month', 'year'));
} else {
return Excel::download(new StokAuditExport($stokAudit), $file_title);
}
}
}
+14
View File
@@ -30,6 +30,8 @@ import VueFlatPickr from 'vue-flatpickr-component';
import 'flatpickr/dist/flatpickr.css';
import VueExcelXlsx from "vue-excel-xlsx";
import flatpickr from "flatpickr";
import monthSelect from "flatpickr/dist/plugins/monthSelect";
let ops = {
// global component name
@@ -271,3 +273,15 @@ const app = new Vue({
el: '#app',
store
});
//flatpickr for report keseluruhan stok audit
flatpickr( '#stock_audit_monthYear', {
maxDate: 'today',
plugins: [
new monthSelect({
shorthand: false, //defaults to false
dateFormat: "m-Y",
altFormat: "F Y", //defaults to "F Y"
})
]
});
@@ -37,6 +37,12 @@
<h2 class="mx-auto text-center font-bold text-2xl uppercase">Ringkasan Harian</h2>
</a>
</div>
<div
class="bg-white ml-2 shadow border border-solid px-6 py-4 rounded-lg hover:bg-yellow-300 hover:transition-all mb-2 cursor-pointer">
<a href="{{ route('reports.stok-audit.index', ['startDate' => now()->toDateString(), 'endDate' => now()->toDateString()]) }}" class="">
<h2 class="mx-auto text-center font-bold text-2xl uppercase">Stok Audit</h2>
</a>
</div>
</div>
</div>
</div>
@@ -0,0 +1,120 @@
@extends('layouts.app')
@section('content')
<div class="bg-gray-900 opacity-50 hidden fixed inset-0 z-10" id="sidebarBackdrop"></div>
<div id="main-content" class="h-full w-full bg-gray-50 relative overflow-y-auto">
<main>
<div class="pt-6 px-4">
<breadcrumb
:items="[{ 'title': 'Laporan Keseluruhan', 'icon': 'fas fa-users', 'url': '{{ route('reports') }}' },
{ 'title': 'Stok Audit', 'icon': 'fas fa-users' }]">
</breadcrumb>
<div class="container">
@if ($errors->any())
<div id="error-alert" class="flex justify-center">
<div id="alert-border-2" class="flex items-center p-4 text-red-800 border-t-4 border-red-300 bg-red-50 dark:text-red-400 dark:bg-gray-800 dark:border-red-800 px-10" role="alert">
<svg class="flex-shrink-0 w-4 h-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"/>
</svg>
<div class="ms-3 text-sm font-medium ml-2 ">
@foreach ($errors->all() as $error)
{{ $error }}
@endforeach
</div>
</div>
</div>
@endif
<div class="flex w-full">
<div class="xl:w-2/3 2xl:w-1/2 p-8 mx-auto">
<div class="bg-yellow-600 text-gray-200 text-lg px-6 py-4 rounded-t-lg"><a href="/reports"
class="router-link-active"><i class="fas fa-backspace text-white"></i></a> <span
class="text-center mx-auto text-white font-bold">Laporan Stok Audit</span></div>
<form method="get" id="formStokAudit" action="{{ route('reports.stok-audit.show') }}">
<div class="rounded bg-white shadow p-6">
<div class="pb-6"><label for="username"
class="font-semibold text-gray-700 block pb-1">Tarikh</label>
<div class="flex">
<span
class="text-gray-600 border border-2 rounded-l px-4 py-2 whitespace-no-wrap"
style="background-color: rgb(249, 250, 251);">Mula</span>
<input id="stock_audit_monthYear" name="monthYear" value=""
class="border border-2 border-l-0 rounded-r px-4 py-2 w-80r mr-2">
<div class="hidden">
<input type="radio" name="generateType" id="generateTypePdf"
value="pdf">
<input type="radio" name="generateType" id="generateTypeExcel"
value="excel">
</div>
<button id="generateExcel"
class="border border-yellow-600 text-yellow-600 font-montserrat py-2 px-8 font-medium rounded-xl hover:bg-yellow-600 hover:text-white transition-all duration-300 ml-5"
type="button">
<i class="fas fa-file-excel mr-2"></i>Excel
</button>
<button id="generatePdf"
class="border border-yellow-600 text-yellow-600 font-montserrat py-2 px-8 font-medium rounded-xl hover:bg-yellow-600 hover:text-white transition-all duration-300 ml-5"
type="button">
<i class="fas fa-eye mr-2"></i>View
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div kodcaw="operasi">
<div>
<!---->
<!---->
</div>
<div>
<!---->
<!---->
</div>
<div class="flex justify-between mb-2">
</div>
</div>
</div>
</main>
@include('layouts.footer')
</div>
@endsection
@push('additional_scripts')
<script>
document.addEventListener("DOMContentLoaded", function(event) {
let form = document.querySelector('#formStokAudit')
document.querySelector('button#generatePdf').addEventListener("click", function(event) {
document.querySelector('#generateTypePdf').checked = true;
form.submit();
})
document.querySelector('button#generateExcel').addEventListener("click", function(event) {
document.querySelector('#generateTypeExcel').checked = true;
form.submit();
})
const errorAlert = document.getElementById("error-alert");
if (errorAlert) {
setTimeout(function() {
errorAlert.classList.add = "opacity-0";
setTimeout(function() {
errorAlert.style.display = "none";
}, 500)
}, 5000); // 5000 milliseconds = 5 seconds
}
});
</script>
@endpush
@@ -0,0 +1,232 @@
<style>
#header {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#header td, #customers th {
padding:4px;
font-size:10px;
}
#header tr:nth-child(even){background-color: #ffffff;}
#header tr:hover {background-color: #ddd;}
#header th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
padding:4px;
color:black;
}
</style>
<style>
#scan {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#scan td, #scan th {
padding: 8px;
font-size:11px;
}
#scan tr:nth-child(even){background-color: #ffffff;}
#scan tr:hover {background-color: #ddd;}
#scan th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
padding:4px;
color:black;
}
</style>
<style>
#scan {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#scan td, #scan th {
border-collapse: collapse;
padding: 8px;
font-size:11px;
}
#scan tr:nth-child(even){background-color: #ffffff;}
#scan tr:hover {background-color: #ddd;}
#scan th {
border-collapse: collapse;
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
padding:4px;
color:black;
}
</style>
<style>
#details {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#details td, #details th {
padding: 8px;
font-size:11px;
}
#details tr:nth-child(even){background-color: #ffffff;}
#details tr:hover {background-color: #ddd;}
#details th {
padding-top: 12px;
font-style:bold;
padding-bottom: 12px;
text-align: left;
padding:4px;
color:black;
}
</style>
<style>
#sign {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#sign td, #sign th {
padding: 8px;
font-size:11px;
text-align: center;
}
#sign tr:nth-child(even){background-color: #ffffff;}
#sign tr:hover {background-color: #ddd;}
#sign th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
padding:4px;
color:black;
}
</style>
<table id="header">
<tr>
<th rowspan="4" style="width:50px"><br><img src="{{ asset('img/ARRAHN1.png') }}" style="width:70px"></img></th>
<th colspan="1">KOPERASI PERMODALAN KELANTAN BERHAD</th>
</tr>
<tr>
<td>Semua Cawangan</td>
<td></td>
</tr>
</table>
<br>
<table id="scan">
<tr>
<th colspan ="5"><b>Laporan Stok Audit</b></th>
<th> </th>
<th> </th>
<th><b> Tarikh Cetak:</b>
@php
$myDateTime = DateTime::createFromFormat('Y-m-d', $tarikh_cetak);
$formattedweddingdate = $myDateTime->format('d-m-Y');
echo($formattedweddingdate)
@endphp
</th>
<th></th>
</tr>
<tr>
<td style="width:10px"> <b>TARIKH</b></td>
<td>{{ $tebus_date }}</td>
<td style="width:50px">
</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
<br>
<table id="details">
<thead>
<th>Cawangan</th>
<th>Jumlah Pinjaman</th>
<th>Total Pinjaman</th>
<th>Total Berat</th>
<th>Total Nilai Marhun</th>
<th>Total Baki Pinjaman</th>
<th>Total Upah Belum Bayar</th>
<th>Total Untung 1% Percent</th>
<th>Total Ujrah</th>
</thead>
@foreach($stokAudit as $item)
<tr>
<td>{{$item['cawangan']}}</td>
<td>{{ $item['jumlah_pinjaman'] }}</td>
<td>{{ number_format($item['total_pinjaman'],2) }}</td>
<td>{{ number_format($item['total_berat'],2) }}</td>
<td>{{ number_format($item['total_nilai_marhun'],2) }}</td>
<td>{{ number_format($item['total_baki_pinjaman'],2) }}</td>
<td>{{ number_format($item['total_upah_belum_bayar'],2) }}</td>
<td>{{ number_format($item['total_utg_onepercent'],2) }}</td>
<td>{{ number_format($item['total_ujrah'],2) }}</td>
</tr>
@endforeach
</table>
<br>
<br>
<table id="sign">
<tr>
<td></td>
<td colspan="2"> .................................................................. </td>
<td> </td>
<td colspan="2">.................................................................. </td>
<td> </td>
</tr>
<tr>
<td></td>
<td colspan="2"><B> DI SEMAK</B> </td>
<td> </td>
<td colspan="2"><B>DI SAHKAN </B></td>
<td> </td>
</tr>
</table>
+3
View File
@@ -4,6 +4,7 @@ use App\Http\Controllers\Reports\GadaianController;
use App\Http\Controllers\Reports\PenebusanController;
use App\Http\Controllers\Reports\AnsuranController;
use App\Http\Controllers\Reports\RingkasanHarianController;
use App\Http\Controllers\Reports\StokAuditController;
use Illuminate\Support\Facades\Route;
Route::middleware(['roleChecker:admin,akaun,operasi,kpo, null'])->group(function () {
@@ -16,4 +17,6 @@ Route::middleware(['roleChecker:admin,akaun,operasi,kpo, null'])->group(function
Route::get('ansuran/{kod_cawangan}', [AnsuranController::class, 'downloadAnsuranCawanganExcel'])->name('reports.ansuran.cawangan.excel');
Route::get('ringkasan-harian', [RingkasanHarianController::class, 'index'])->name('reports.ringkasan-harian.index');
Route::get('ringkasan-harian/{kod_cawangan}', [RingkasanHarianController::class, 'downloadRingkasanHarianPdf'])->name('reports.ringkasan-harian.cawangan.pdf');
Route::get('stok-audit', [StokAuditController::class, 'index'])->name('reports.stok-audit.index');
Route::get('stok-audit/view', [StokAuditController::class, 'show'])->name('reports.stok-audit.show');
});