fix pembayaran

dev
Aji Kamaludin 1 year ago
parent 53af55bf98
commit 9c78dadae2
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -39,7 +39,7 @@ class CustomerHistoryController extends Controller
{
$query = PaylaterHistory::with(['editor'])
->where('customer_id', $customer->id)
// ->where('type', PaylaterHistory::TYPE_REPAYMENT)
->where('type', PaylaterHistory::TYPE_REPAYMENT)
->orderBy('created_at', 'desc');
return inertia('CustomerHistory/PaylaterHistory', [

@ -54,15 +54,18 @@ class PaylaterController extends Controller
public function show(PaylaterHistory $paylater)
{
$deposit = DepositHistory::where('related_id', $paylater->id)->first();
return inertia('Paylater/Detail', [
'paylater' => $paylater->load(['customer']),
'deposit' => $deposit->load(['customer', 'account', 'depositLocation', 'editor', 'paylater']),
]);
}
public function edit(DepositHistory $deposit)
{
return inertia('Paylater/Form', [
'deposit' => $deposit->load(['customer', 'account', 'depositLocation', 'editor']),
'deposit' => $deposit->load(['customer', 'account', 'depositLocation', 'paylater', 'editor']),
]);
}
@ -91,7 +94,6 @@ class PaylaterController extends Controller
$paylater->update([
'credit' => $request->debit,
'is_valid' => $request->is_valid,
'note' => $request->reject_reason,
]);
if ($request->is_valid == DepositHistory::STATUS_VALID) {
@ -101,7 +103,7 @@ class PaylaterController extends Controller
DB::commit();
return redirect()->route('paylater.index')
return redirect()->route('paylater.repay.index')
->with('message', ['type' => 'success', 'message' => 'Item has beed updated']);
}

@ -42,7 +42,7 @@ class DepositController extends Controller
public function create(Request $request)
{
$customer = $request->user('customer');
if (! $customer->allow_transaction) {
if (!$customer->allow_transaction) {
return redirect()->back()
->with('message', ['type' => 'error', 'message' => 'akun anda dibekukan tidak dapat melakukan transaksi']);
}
@ -148,6 +148,10 @@ class DepositController extends Controller
$is_valid = DepositHistory::STATUS_INVALID;
}
if ($deposit->is_valid == DepositHistory::STATUS_VALID) {
return redirect()->route('transactions.deposit.show', ['deposit' => $deposit->id]);
}
$deposit->update([
'is_valid' => $is_valid,
'payment_response' => json_encode($request->result),
@ -155,9 +159,19 @@ class DepositController extends Controller
]);
if ($is_valid == DepositHistory::STATUS_VALID) {
$deposit->update_customer_balance();
if ($deposit->type == DepositHistory::TYPE_REPAYMENT) {
$paylater = $deposit->paylater;
$paylater->update([
'credit' => $deposit->debit,
'is_valid' => $deposit->is_valid,
]);
$paylater->update_customer_paylater();
}
if ($deposit->type == DepositHistory::TYPE_DEPOSIT) {
$deposit->update_customer_balance();
}
}
// TODO: update for paylater
DB::commit();
@ -178,19 +192,30 @@ class DepositController extends Controller
]);
if ($request->transaction_status == 'settlement' || $request->transaction_status == 'capture') {
$deposit->fill(['payment_status' => DepositHistory::STATUS_VALID]);
$deposit->update_customer_balance();
$deposit->create_notification();
$deposit->create_notification_user();
$deposit->fill(['is_valid' => DepositHistory::STATUS_VALID]);
if ($deposit->type == DepositHistory::TYPE_REPAYMENT) {
$paylater = $deposit->paylater;
$paylater->update([
'credit' => $deposit->debit,
'is_valid' => $deposit->is_valid,
]);
$paylater->update_customer_paylater();
}
if ($deposit->type == DepositHistory::TYPE_DEPOSIT) {
$deposit->update_customer_balance();
$deposit->create_notification();
$deposit->create_notification_user();
}
} elseif ($request->transaction_status == 'pending') {
$deposit->fill(['payment_status' => DepositHistory::STATUS_WAIT_PAYMENT]);
$deposit->fill(['is_valid' => DepositHistory::STATUS_WAIT_PAYMENT]);
} else {
$deposit->fill(['payment_status' => DepositHistory::STATUS_INVALID]);
$deposit->fill(['is_valid' => DepositHistory::STATUS_INVALID]);
}
$deposit->save();
}
// TODO: update for paylater
DB::commit();

@ -29,7 +29,7 @@ class PaylaterController extends Controller
if ($paylater->type == PaylaterHistory::TYPE_REPAYMENT) {
$deposit = DepositHistory::where('related_id', $paylater->id)->first();
if (! in_array($deposit->is_valid, [DepositHistory::STATUS_VALID])) {
if (!in_array($deposit->is_valid, [DepositHistory::STATUS_VALID])) {
return redirect()->route('transactions.deposit.show', [
'deposit' => $deposit,
'back' => 'customer.paylater.index',
@ -68,6 +68,14 @@ class PaylaterController extends Controller
->with('message', ['type' => 'error', 'message' => 'Nominal Tagihan tidak boleh lebih dari tagihan']);
}
// alasan pembayaran tidak full
if ($customer->paylater->usage != $request->amount) {
$request->validate([
'not_fullpayment_reason' => 'required|string',
'next_payment' => 'required|date',
]);
}
// only 1 repayment at a time
$repayment = DepositHistory::query()
->where([
@ -89,6 +97,8 @@ class PaylaterController extends Controller
$paylater = $customer->paylaterHistories()->create([
'credit' => $request->amount,
'description' => $code,
'not_fullpayment_reason' => $request->not_fullpayment_reason,
'next_payment' => $request->next_payment,
'type' => PaylaterHistory::TYPE_REPAYMENT,
]);

@ -38,6 +38,8 @@ class PaylaterHistory extends Model
'type',
'is_valid',
'image_prove',
'next_payment',
'not_fullpayment_reason',
];
protected $appends = [
@ -71,10 +73,10 @@ class PaylaterHistory extends Model
{
return Attribute::make(get: function () {
if ($this->credit == 0) {
return 'Rp '.number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.');
return 'Rp ' . number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.');
}
return '-Rp '.number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.');
return '-Rp ' . number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.');
});
}
@ -116,7 +118,7 @@ class PaylaterHistory extends Model
{
Notification::create([
'entity_id' => $this->customer_id,
'description' => 'Pembayaran '.$this->description.' sebesar '.$this->amount.' sudah sukses diterima',
'description' => 'Pembayaran ' . $this->description . ' sebesar ' . $this->amount . ' sudah sukses diterima',
]);
}

@ -18,6 +18,8 @@ return new class extends Migration
$table->decimal('credit', 20, 2)->default(0);
$table->string('description')->nullable();
$table->text('note')->nullable();
$table->timestamp('next_payment')->nullable();
$table->string('not_fullpayment_reason')->nullable();
$table->ulid('customer_id')->nullable();
$table->smallInteger('type')->default(0);
$table->smallInteger('is_valid')->default(0);

@ -1,28 +1,46 @@
import React from "react";
import DatePicker from "react-datepicker";
import { converToDate, dateToString } from "@/utils";
import React from 'react'
import DatePicker from 'react-datepicker'
import { converToDate, dateToString } from '@/utils'
export default function FormInputDate({ selected, onChange, label = '', error }) {
export default function FormInputDate({
selected,
onChange,
label = '',
error,
placeholder = '',
}) {
return (
<div>
{label !== '' && (
<label htmlFor="first_name" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{label}</label>
<label
htmlFor="first_name"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
>
{label}
</label>
)}
<DatePicker
selected={converToDate(selected)}
onChange={date => onChange(dateToString(date))}
onChange={(date) => onChange(dateToString(date))}
closeOnScroll={true}
shouldCloseOnSelect={true}
dateFormat="dd/MM/yyyy"
className={`mb-2 bg-gray-50 border text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:placeholder-gray-400 dark:text-white ${error ? "border-red-500 dark:border-red-500 focus:ring-red-500 focus:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500" : "border-gray-300 dark:border-gray-600 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-500 dark:focus:border-blue-500"}`}
className={`mb-2 bg-gray-50 border text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:placeholder-gray-400 dark:text-white ${
error
? 'border-red-500 dark:border-red-500 focus:ring-red-500 focus:border-red-500 dark:focus:ring-red-500 dark:focus:border-red-500'
: 'border-gray-300 dark:border-gray-600 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-500 dark:focus:border-blue-500'
}`}
nextMonthButtonLabel=">"
previousMonthButtonLabel="<"
nextYearButtonLabel=">"
previousYearButtonLabel="<"
placeholderText={placeholder}
/>
{error && (
<p className="mb-2 text-sm text-red-600 dark:text-red-500">{error}</p>
<p className="mb-2 text-sm text-red-600 dark:text-red-500">
{error}
</p>
)}
</div>
)
}
}

@ -7,11 +7,15 @@ import { CASH_DEPOSIT } from '@/Customer/utils'
import CustomerLayout from '@/Layouts/CustomerLayout'
import Alert from '@/Components/Alert'
import FormInputNumeric from '@/Components/FormInputNumeric'
import FormInput from '@/Components/FormInput'
import FormInputDate from '@/Components/FormInputDate'
export default function Repay({ payments, amount }) {
export default function Repay({ payments, amount, auth: { user } }) {
const { data, setData, post, processing, errors } = useForm({
amount: amount,
payment: '',
not_fullpayment_reason: '',
next_payment: '',
})
const amounts = [amount]
@ -42,6 +46,8 @@ export default function Repay({ payments, amount }) {
setData('payment', payment.name)
}
const isNotFullPayment = +user.paylater.usage !== +data.amount
const handleSubmit = () => {
if (processing) {
return
@ -88,6 +94,27 @@ export default function Repay({ payments, amount }) {
error={errors.amount}
/>
</div>
{isNotFullPayment && (
<div className="w-full px-5">
<FormInput
placeholder="keterangan tidak bayar penuh"
value={data.not_fullpayment_reason}
onChange={(e) =>
setData(
'not_fullpayment_reason',
e.target.value
)
}
error={errors.not_fullpayment_reason}
/>
<FormInputDate
placeholder="tanggal akan bayar penuh"
selected={data.next_payment}
onChange={(date) => setData('next_payment', date)}
error={errors.next_payment}
/>
</div>
)}
<div className="w-full px-5 mt-10 flex flex-col">
<div className="font-bold mb-2">Metode Pembayaran</div>
{errors.payment && (

@ -164,8 +164,8 @@ export default [
name: 'Pembayaran Hutang', // daftar pembayaran hutang yang perlu di konfirmasi , dan ada tombol add untuk pembayaran hutang oleh admin
show: true,
icon: HiCash,
route: route('paylater.index'),
active: 'paylater.*',
route: route('paylater.repay.index'),
active: 'paylater.repay.*',
permission: 'view-paylater-repayment',
},
{

@ -146,7 +146,7 @@ export default function PaylaterHistory(props) {
<td className="py-4 px-6 flex justify-center">
<Link
href={route(
'paylater.show',
'paylater.repay.show',
paylater
)}
className="flex space-x-1 items-center hover:underline"

@ -132,7 +132,7 @@ export default function Form(props) {
Alasan Penolakan
</td>
<td>:</td>
<td>{deposit.reject_reason}</td>
<td>{deposit.note}</td>
</tr>
{isEmpty(deposit.editor) === false && (
<tr>

@ -2,63 +2,260 @@ import React from 'react'
import { Head, Link } from '@inertiajs/react'
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import { isEmpty } from 'lodash'
import { formatIDDate, formatIDR } from '@/utils'
export default function Detail(props) {
const { paylater } = props
const { paylater, deposit } = props
return (
<AuthenticatedLayout
page={'Pembayaran Hutang'}
action={paylater.description}
parent={route('paylater.index')}
parent={route('paylater.repay.index')}
>
<Head title="Pembayaran Hutang" />
<div>
<div className="mx-auto sm:px-6 lg:px-8">
<div className="overflow-hidden p-4 shadow-sm sm:rounded-lg bg-white dark:bg-gray-800 flex flex-col ">
<div className="text-xl font-bold mb-4">
{paylater.description}
<div className="flex flex-row justify-between">
<div className="text-xl font-bold mb-4">
{paylater.description}
</div>
</div>
<table className="relative w-full overflow-x-auto p-2 rounded">
<tbody>
<tr>
<td className="font-bold">Customer</td>
<td>:</td>
<td>
<Link
href={route('customer.edit', {
customer: paylater.customer,
})}
className="hover:underline"
{isEmpty(deposit) === true && (
<table className="relative w-full overflow-x-auto p-2 rounded">
<tbody>
<tr>
<td className="font-bold">Customer</td>
<td>:</td>
<td>
<Link
href={route('mitra.edit', {
customer: paylater.customer,
})}
className="hover:underline"
>
{paylater.customer.name}
</Link>
</td>
</tr>
<tr>
<td className="font-bold">Jumlah</td>
<td>:</td>
<td>{paylater.amount}</td>
</tr>
<tr>
<td className="font-bold">Status</td>
<td>:</td>
<td
className={
paylater.status_text.text_color
}
>
{paylater.customer.name}
</Link>
</td>
</tr>
<tr>
<td className="font-bold">Jumlah</td>
<td>:</td>
<td>{paylater.amount}</td>
</tr>
<tr>
<td className="font-bold">Status</td>
<td>:</td>
<td
className={
paylater.status_text.text_color
}
>
{paylater.status_text.text}
</td>
</tr>
<tr>
<td className="font-bold">Tanggal</td>
<td>:</td>
<td>{paylater.format_created_at}</td>
</tr>
</tbody>
</table>
{paylater.status_text.text}
</td>
</tr>
<tr>
<td className="font-bold">Tanggal</td>
<td>:</td>
<td>{paylater.format_created_at}</td>
</tr>
<tr>
<td className="font-bold">
Pembayaran Hutang
</td>
<td>:</td>
<td>
{isEmpty(
paylater.not_fullpayment_reason
) === false ? (
<p>Sebagian</p>
) : (
<p>Penuh</p>
)}
</td>
</tr>
{isEmpty(paylater.next_payment) ===
false && (
<tr>
<td className="font-bold">
Tanggal Pemenuhan
</td>
<td>:</td>
<td>
{formatIDDate(
paylater.next_payment
)}
</td>
</tr>
)}
</tbody>
</table>
)}
{isEmpty(deposit) === false && (
<>
<table className="relative w-full overflow-x-auto p-2 rounded">
<tbody>
<tr>
<td className="font-bold">
Customer
</td>
<td>:</td>
<td>
<Link
href={route('mitra.edit', {
customer:
deposit.customer,
})}
className="hover:underline"
>
{deposit.customer.name}
</Link>
</td>
</tr>
<tr>
<td className="font-bold">
Metode Pembayaran
</td>
<td>:</td>
<td>{deposit.payment_channel}</td>
</tr>
{deposit.account !== null && (
<tr>
<td className="font-bold">
Bank Akun
</td>
<td>:</td>
<td>
{deposit.account.name} (
{deposit.account.bank_name})
</td>
</tr>
)}
{deposit.deposit_location !== null && (
<tr>
<td className="font-bold">
Lokasi Cash / Setor Tunai
</td>
<td>:</td>
<td>
{
deposit.deposit_location
.name
}
</td>
</tr>
)}
<tr>
<td className="font-bold">
Jumlah
</td>
<td>:</td>
<td>{deposit.amount}</td>
</tr>
<tr>
<td className="font-bold">
Admin Fee
</td>
<td>:</td>
<td>
Rp{' '}
{formatIDR(+deposit.admin_fee)}
</td>
</tr>
<tr>
<td className="font-bold">
Status
</td>
<td>:</td>
<td
className={
deposit.status.text_color
}
>
{deposit.status.text}
</td>
</tr>
<tr>
<td className="font-bold">
Alasan Penolakan
</td>
<td>:</td>
<td>{deposit.note}</td>
</tr>
{isEmpty(deposit.editor) === false && (
<tr>
<td className="font-bold">
Approver
</td>
<td>:</td>
<td>{deposit.editor.name}</td>
</tr>
)}
<tr>
<td className="font-bold">
Tanggal
</td>
<td>:</td>
<td>{deposit.format_created_at}</td>
</tr>
<tr>
<td className="font-bold">
Pembayaran Hutang
</td>
<td>:</td>
<td>
{isEmpty(
deposit.paylater
.not_fullpayment_reason
) === false ? (
<p>Sebagian</p>
) : (
<p>Penuh</p>
)}
</td>
</tr>
{isEmpty(
deposit.paylater.next_payment
) === false && (
<tr>
<td className="font-bold">
Tanggal Pemenuhan
</td>
<td>:</td>
<td>
{formatIDDate(
deposit.paylater
.next_payment
)}
</td>
</tr>
)}
</tbody>
</table>
<div>
{isEmpty(deposit.image_prove_url) ===
false && (
<div>
<a
href={deposit.image_prove_url}
target="_blank"
>
<img
src={
deposit.image_prove_url
}
className="w-full object-fill h-96"
loading="lazy"
/>
</a>
</div>
)}
</div>
</>
)}
</div>
</div>
</div>

@ -12,7 +12,7 @@ import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
import FormInput from '@/Components/FormInput'
import Button from '@/Components/Button'
import FormInputNumeric from '@/Components/FormInputNumeric'
import { formatIDR } from '@/utils'
import { formatIDDate, formatIDR } from '@/utils'
export default function Form(props) {
const { deposit } = props
@ -39,7 +39,7 @@ export default function Form(props) {
+deposit.is_valid === STATUS_WAIT_UPLOAD
const handleSubmit = () => {
post(route('paylater.update', deposit))
post(route('paylater.repay.update', deposit))
}
useEffect(() => {
@ -57,7 +57,7 @@ export default function Form(props) {
<AuthenticatedLayout
page={'Pembayaran Hutang'}
action={deposit.description}
parent={route('paylater.index')}
parent={route('paylater.repay.index')}
>
<Head title="Pembayaran Hutang" />
@ -74,7 +74,7 @@ export default function Form(props) {
<td>:</td>
<td>
<Link
href={route('customer.edit', {
href={route('mitra.edit', {
customer: deposit.customer,
})}
className="hover:underline"
@ -131,7 +131,7 @@ export default function Form(props) {
Alasan Penolakan
</td>
<td>:</td>
<td>{deposit.reject_reason}</td>
<td>{deposit.note}</td>
</tr>
{isEmpty(deposit.editor) === false && (
<tr>
@ -145,6 +145,36 @@ export default function Form(props) {
<td>:</td>
<td>{deposit.format_created_at}</td>
</tr>
<tr>
<td className="font-bold">
Pembayaran Hutang
</td>
<td>:</td>
<td>
{isEmpty(
deposit.paylater
.not_fullpayment_reason
) === false ? (
<p>Sebagian</p>
) : (
<p>Penuh</p>
)}
</td>
</tr>
{isEmpty(deposit.paylater.next_payment) ===
false && (
<tr>
<td className="font-bold">
Tanggal Pemenuhan
</td>
<td>:</td>
<td>
{formatIDDate(
deposit.paylater.next_payment
)}
</td>
</tr>
)}
</tbody>
</table>
@ -167,7 +197,7 @@ export default function Form(props) {
<div className="my-4">
<FormInputNumeric
type="number"
label="Jumlah Deposit"
label="Jumlah"
name="debit"
onChange={handleOnChange}
value={data.debit}

@ -191,7 +191,7 @@ export default function Index(props) {
{canUpdate && (
<Link
href={route(
'paylater.edit',
'paylater.repay.edit',
deposit
)}
className="flex space-x-1 items-center hover:underline"

@ -170,10 +170,10 @@ Route::middleware(['http_secure_aware', 'inertia.admin'])
Route::post('/deposites/{deposit}', [DepositController::class, 'update'])->name('deposit.update');
// repayment
Route::get('/paylater', [PaylaterController::class, 'index'])->name('paylater.index');
Route::get('/paylater/{paylater}', [PaylaterController::class, 'show'])->name('paylater.show');
Route::get('/paylater/{deposit}/edit', [PaylaterController::class, 'edit'])->name('paylater.edit');
Route::post('/paylater/{deposit}', [PaylaterController::class, 'update'])->name('paylater.update');
Route::get('/paylater', [PaylaterController::class, 'index'])->name('paylater.repay.index');
Route::get('/paylater/{paylater}', [PaylaterController::class, 'show'])->name('paylater.repay.show');
Route::get('/paylater/{deposit}/edit', [PaylaterController::class, 'edit'])->name('paylater.repay.edit');
Route::post('/paylater/{deposit}', [PaylaterController::class, 'update'])->name('paylater.repay.update');
// poin rewared
Route::get('/bonus-poin', [PoinRewardController::class, 'index'])->name('poin-reward.index');

Loading…
Cancel
Save