Merge pull request #10 from alealien666/manualPay

nambah titik
This commit is contained in:
AleAlien 2025-02-17 23:20:13 +07:00 committed by GitHub
commit 52d1c09542
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 118 additions and 10 deletions

View File

@ -7,19 +7,28 @@
use App\Models\Santri; use App\Models\Santri;
use Inertia\Inertia; use Inertia\Inertia;
use App\Services\cekDenda; use App\Services\cekDenda;
use App\Services\GenerateMonthlyBill;
class PaymentController extends Controller class PaymentController extends Controller
{ {
public function indexManualPayment() public function indexManualPayment(cekDenda $cekDenda, GenerateMonthlyBill $generateMonthlyBill)
{ {
$santri = Santri::with(['payments.detailPayments.paymentType']) $penalty = $cekDenda->applyPenalty();
->withSum(['payments.detailPayments as total_penalty' => function ($query) { $bill = $generateMonthlyBill->generateAutoBill();
$query->whereNotNull('penalty');
}], 'penalty')
->get(); $santri = Santri::with([
'payments.detailPayments.paymentType'
])->get();
// $santri = Payment::with('detailPayments')->get();
// dd($santri);
return Inertia::render('list-admin/payment/ManualPayment', [ return Inertia::render('list-admin/payment/ManualPayment', [
'santri' => $santri, 'santri' => $santri,
'penalty' => $penalty,
'bill' => $bill,
'fields' => [ 'fields' => [
'nis' => 'text', 'nis' => 'text',
'nama' => 'text', 'nama' => 'text',

View File

@ -20,7 +20,7 @@ public static function cekTunggakan($santri_id)
})->orderBy('payment_year', 'asc')->orderBy('payment_month')->get(); })->orderBy('payment_year', 'asc')->orderBy('payment_month')->get();
} }
public function payment() public function payments()
{ {
return $this->belongsTo(Payment::class, 'payment_id', 'id'); return $this->belongsTo(Payment::class, 'payment_id', 'id');
} }

View File

@ -0,0 +1,51 @@
<?php
namespace App\Services;
use App\Models\DetailPayment;
use App\Models\Payment;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class GenerateMonthlyBill
{
public function generateAutoBill()
{
$currentMonth = Carbon::now()->month;
$currentYear = Carbon::now()->year;
DB::beginTransaction();
try {
$previousPayments = Payment::with('detailPayments')
->whereHas('detailPayments', function ($query) {
$query->where('payment_month', Carbon::now()->subMonth()->month)
->where('payment_year', Carbon::now()->subMonth()->year);
})->get();
foreach ($previousPayments as $prevPay) {
$existingBill = DetailPayment::where('payment_id', $prevPay->id)
->where('payment_month', $currentMonth)
->where('payment_year', $currentYear)->exists();
}
if (!$existingBill) {
$previousDetail = $prevPay->detailPayments->last();
DetailPayment::create([
'payment_id' => $prevPay->id,
'payment_type_id' => $previousDetail->payment_type_id,
'amount' => $previousDetail->amount,
'status' => 'unpaid',
'payment_month' => $currentMonth,
'payment_year' => $currentYear,
'penalty' => null,
]);
}
DB::commit();
return ['message' => 'berhasil menambah data'];
} catch (\Exception $e) {
DB::rollBack();
return ['error' => 'gagal menambah data' . $e->getMessage()];
}
}
}

View File

@ -19,7 +19,7 @@ public function up(): void
$table->string('no_va')->nullable(); $table->string('no_va')->nullable();
$table->dateTime('expired_at')->nullable(); $table->dateTime('expired_at')->nullable();
$table->foreignId('santri_id')->constrained('santris')->onDelete('cascade'); $table->foreignId('santri_id')->constrained('santris')->onDelete('cascade');
$table->foreignId('wallet_id')->constrained('wallets')->onDelete('cascade'); $table->foreignId('wallet_id')->nullable()->constrained('wallets')->onDelete('cascade');
$table->timestamps(); $table->timestamps();
}); });
} }

View File

@ -15,7 +15,7 @@ public function up(): void
$table->id(); $table->id();
$table->foreignId('payment_id')->constrained('payments')->onDelete('cascade'); $table->foreignId('payment_id')->constrained('payments')->onDelete('cascade');
$table->enum('status', ['paid', 'unpaid']); $table->enum('status', ['paid', 'unpaid']);
$table->float('amount'); $table->float('amount')->nullable();
$table->float('penalty')->nullable(); $table->float('penalty')->nullable();
$table->integer('payment_month'); $table->integer('payment_month');
$table->integer('payment_year'); $table->integer('payment_year');

View File

@ -0,0 +1,48 @@
import React, { useState } from 'react';
import { Head } from '@inertiajs/react';
import ModalInput from '@/Components/ModalInput';
export default function ManualPayment({ santri, penalty, bill, fields }) {
const [selectedSantri, setSelectedSantri] = useState(null);
return (
<div className='text-red-500'>
<Head title="Manual Payment" />
<ModalInput fields={fields} tableName={['payments', 'detail_payments']} initialData={selectedSantri} onClose={() => setSelectedSantri(null)} />
{santri && santri.length > 0 ? santri.map((item, i) => (
<div key={i} className="p-4 border-b">
<p><strong>Santri:</strong> {item.nama}</p>
{item.payments && item.payments.length > 0 ? (
<div className="ml-4">
<p className="font-semibold">Payments:</p>
{item.payments.map((payment) => (
<div key={payment.id} className="ml-4">
{payment.detail_payments && payment.detail_payments.length > 0 ? (
<ul className="ml-6 list-disc">
{payment.detail_payments.map((detail) => (
<li key={detail.id}>
{detail.penalty ? `Denda: Rp ${detail.penalty}` : 'Tidak ada denda'}
<p>{detail.status}</p>
</li>
))}
</ul>
) : <p className="ml-4 text-gray-500">Tidak ada detail pembayaran.</p>}
</div>
))}
</div>
) : <p className="ml-4 text-gray-500">Tidak ada pembayaran.</p>}
<div>
<button className='btn btn-accent text-white mt-2' onClick={() => {
setSelectedSantri(item)
document.getElementById('modal_input').checked = true
}}>Bayar</button>
</div>
</div>
)) : <p>Tidak ada data santri.</p>}
</div>
);
}

View File

@ -41,7 +41,7 @@
Route::post('/deletepayment_types/{id}', [PaymentTypeController::class, 'destroy'])->name('deletePaymentType'); Route::post('/deletepayment_types/{id}', [PaymentTypeController::class, 'destroy'])->name('deletePaymentType');
// manual payment // manual payment
Route::get('/manualPayment', [PaymentController::class, 'index'])->name('indexManualPayment'); Route::get('index-manual-payment', [PaymentController::class, 'indexManualPayment'])->name('indexManualPayment');
Route::get('/dashboard', function () { Route::get('/dashboard', function () {
return Inertia::render('Dashboard'); return Inertia::render('Dashboard');