diff --git a/TODO.md b/TODO.md index c5adff5..0a16861 100644 --- a/TODO.md +++ b/TODO.md @@ -39,6 +39,6 @@ - [x] menu mitra wbb ada tombol tambah mitra untuk registrasi dengan full form - [x] menu pembayaran hutang [admin dapat melakukan pembayaran hutang dari customer, atau mengkonfirmasi pembayaran yang dilakukan custoemr] - [x] ubah filter di mitra list dan customer list menjadi seperti di sale index -- [ ] untuk detail mitra nanti akan ada button untuk (transaksi mitra dengan cakupan: pembelian voucher, pembayaran hutang, +- [x] untuk detail mitra nanti akan ada button untuk (transaksi mitra dengan cakupan: pembelian voucher, pembayaran hutang, topuplimit, penambahan batas bayar, history deposit) - [ ] tambah floating button untuk notifikasi deposit (angka saja), di dashboard tambahkan list deposit terbaru diff --git a/app/Http/Controllers/Admin/CustomerHistoryController.php b/app/Http/Controllers/Admin/CustomerHistoryController.php index f1a1a2d..e74dc54 100644 --- a/app/Http/Controllers/Admin/CustomerHistoryController.php +++ b/app/Http/Controllers/Admin/CustomerHistoryController.php @@ -35,8 +35,17 @@ class CustomerHistoryController extends Controller ]); } - public function paylater() + public function paylater(Customer $customer) { + $query = PaylaterHistory::with(['editor']) + ->where('customer_id', $customer->id) + // ->where('type', PaylaterHistory::TYPE_REPAYMENT) + ->orderBy('created_at', 'desc'); + + return inertia('CustomerHistory/PaylaterHistory', [ + 'query' => $query->paginate(), + 'customer' => $customer, + ]); } public function paylater_limit(Customer $customer) diff --git a/app/Http/Controllers/Admin/DepositController.php b/app/Http/Controllers/Admin/DepositController.php index 22211ec..0af9337 100644 --- a/app/Http/Controllers/Admin/DepositController.php +++ b/app/Http/Controllers/Admin/DepositController.php @@ -42,10 +42,6 @@ class DepositController extends Controller $deposits->where('is_valid', $request->status); } - if ($request->customer_id != '') { - $deposits->where('is_valid', $request->customer_id); - } - $customers = Customer::with(['paylater'])->orderBy('deposit_balance', 'desc'); $stats = [ @@ -96,7 +92,7 @@ class DepositController extends Controller 'debit' => 'required|numeric', ]); - if ($request->status == DepositHistory::STATUS_REJECT) { + if ($request->is_valid == DepositHistory::STATUS_REJECT) { $request->validate(['reject_reason' => 'required|string']); } @@ -107,12 +103,13 @@ class DepositController extends Controller 'note' => $request->reject_reason, ]); - if ($request->status == DepositHistory::STATUS_VALID) { + if ($request->is_valid == DepositHistory::STATUS_VALID) { $deposit->update_customer_balance(); $deposit->create_notification_user(); } DB::commit(); - session()->flash('message', ['type' => 'success', 'message' => 'Item has beed updated']); + return redirect()->route('deposit.index') + ->with('message', ['type' => 'success', 'message' => 'Item has beed updated']); } } diff --git a/app/Http/Controllers/Admin/PaylaterController.php b/app/Http/Controllers/Admin/PaylaterController.php index 9012568..a7c8731 100644 --- a/app/Http/Controllers/Admin/PaylaterController.php +++ b/app/Http/Controllers/Admin/PaylaterController.php @@ -4,27 +4,105 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use App\Models\Customer; +use App\Models\DepositHistory; use App\Models\PaylaterHistory; use App\Services\GeneralService; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; +use Illuminate\Validation\Rule; class PaylaterController extends Controller { - public function index() + public function index(Request $request) { - // TODO show list of paylater repaymeny + $deposits = DepositHistory::with(['customer', 'account', 'depositLocation', 'editor']) + ->where('credit', 0) + ->where('type', DepositHistory::TYPE_REPAYMENT); + + if ($request->q != '') { + $deposits->where(function ($query) use ($request) { + $query->where('description', 'ilike', "%$request->q%") + ->orWhereHas('customer', function ($query) use ($request) { + $query->where('fullname', 'ilike', "%$request->q%") + ->orWhere('email', 'ilike', "%$request->q%") + ->orWhere('phone', 'ilike', "%$request->q%"); + }); + }); + } + + $sortBy = 'updated_at'; + $sortRule = 'desc'; + if ($request->sortBy != '' && $request->sortRule != '') { + $sortBy = $request->sortBy; + $sortRule = $request->sortRule; + } + + $deposits->orderBy($sortBy, $sortRule); + + if ($request->status != '') { + $deposits->where('is_valid', $request->status); + } + + return inertia('Paylater/Index', [ + 'deposits' => $deposits->paginate(), + '_q' => $request->q, + '_sortBy' => $sortBy, + '_sortRule' => $sortRule, + ]); } - public function edit() + public function show(PaylaterHistory $paylater) { - // TODO show detail repayment and confirmation + return inertia('Paylater/Detail', [ + 'paylater' => $paylater->load(['customer']) + ]); } - public function update() + public function edit(DepositHistory $deposit) { - // TODO store update detail of repayment + return inertia('Paylater/Form', [ + 'deposit' => $deposit->load(['customer', 'account', 'depositLocation', 'editor']), + ]); + } + + public function update(Request $request, DepositHistory $deposit) + { + $request->validate([ + 'is_valid' => [ + 'required', + Rule::in([DepositHistory::STATUS_VALID, DepositHistory::STATUS_REJECT]), + ], + 'debit' => 'required|numeric', + ]); + + if ($request->is_valid == DepositHistory::STATUS_REJECT) { + $request->validate(['reject_reason' => 'required|string']); + } + + DB::beginTransaction(); + $deposit->update([ + 'debit' => $request->debit, + 'is_valid' => $request->is_valid, + 'note' => $request->reject_reason, + ]); + + $paylater = $deposit->paylater; + $paylater->update([ + 'credit' => $request->debit, + 'is_valid' => $request->is_valid, + 'note' => $request->reject_reason, + ]); + + if ($request->is_valid == DepositHistory::STATUS_VALID) { + $paylater->update_customer_paylater(); + $paylater->create_notification_user(); + } + + DB::commit(); + + return redirect()->route('paylater.index') + ->with('message', ['type' => 'success', 'message' => 'Item has beed updated']); } public function limit() diff --git a/app/Http/Controllers/Customer/DepositController.php b/app/Http/Controllers/Customer/DepositController.php index e26c6a3..4b38a6f 100644 --- a/app/Http/Controllers/Customer/DepositController.php +++ b/app/Http/Controllers/Customer/DepositController.php @@ -102,6 +102,7 @@ class DepositController extends Controller 'direct' => $request->direct, 'bank_admin_fee' => Setting::getByKey('ADMINFEE_MANUAL_TRANSFER'), 'cash_admin_fee' => Setting::getByKey('ADMINFEE_CASH_DEPOSIT'), + 'back' => $request->back ?? 'transactions.deposit.index' ]); } @@ -156,6 +157,7 @@ class DepositController extends Controller if ($is_valid == DepositHistory::STATUS_VALID) { $deposit->update_customer_balance(); } + // TODO: update for paylater DB::commit(); @@ -188,6 +190,7 @@ class DepositController extends Controller $deposit->save(); } + // TODO: update for paylater DB::commit(); diff --git a/app/Http/Controllers/Customer/PaylaterController.php b/app/Http/Controllers/Customer/PaylaterController.php index 67b670c..8f22bc3 100644 --- a/app/Http/Controllers/Customer/PaylaterController.php +++ b/app/Http/Controllers/Customer/PaylaterController.php @@ -3,8 +3,10 @@ namespace App\Http\Controllers\Customer; use App\Http\Controllers\Controller; +use App\Models\Account; use App\Models\Customer; use App\Models\DepositHistory; +use App\Models\DepositLocation; use App\Models\PaylaterHistory; use App\Models\Setting; use App\Services\GeneralService; @@ -27,6 +29,17 @@ class PaylaterController extends Controller public function show(Request $request, PaylaterHistory $paylater) { + if ($paylater->type == PaylaterHistory::TYPE_REPAYMENT) { + $deposit = DepositHistory::where('related_id', $paylater->id)->first(); + + if (!in_array($deposit->is_valid, [DepositHistory::STATUS_VALID])) { + return redirect()->route('transactions.deposit.show', [ + 'deposit' => $deposit, + 'back' => 'customer.paylater.index' + ]); + } + } + return inertia('Paylater/Detail', [ 'paylater' => $paylater, ]); @@ -52,6 +65,27 @@ class PaylaterController extends Controller $customer = $request->user('customer'); + // validate amount + if ($customer->paylater->usage < $request->amount) { + return redirect()->back() + ->with('message', ['type' => 'error', 'message' => 'Nominal Tagihan tidak boleh lebih dari tagihan']); + } + + // only 1 repayment at a time + $repayment = DepositHistory::query() + ->where([ + ['customer_id', '=', $customer->id], + ['type', '=', DepositHistory::TYPE_REPAYMENT] + ])->where(function ($query) { + $query->where('is_valid', '!=', DepositHistory::STATUS_VALID) + ->where('is_valid', '!=', DepositHistory::STATUS_REJECT) + ->where('is_valid', '!=', DepositHistory::STATUS_EXPIRED); + })->first(); + if ($repayment != null) { + return redirect()->back() + ->with('message', ['type' => 'error', 'message' => 'Selesaikan pembayaran tagihan sebelumnya']); + } + DB::beginTransaction(); $code = GeneralService::generateDepositRepayCode(); @@ -93,6 +127,10 @@ class PaylaterController extends Controller DB::commit(); - return redirect()->route('transactions.deposit.show', ['deposit' => $deposit->id, 'direct' => 'true']); + return redirect()->route('transactions.deposit.show', [ + 'deposit' => $deposit->id, + 'direct' => 'true', + 'back' => 'customer.paylater.index' + ]); } } diff --git a/app/Jobs/ExpiredDepositHistoryJob.php b/app/Jobs/ExpiredDepositHistoryJob.php index 821a1fe..4528dba 100644 --- a/app/Jobs/ExpiredDepositHistoryJob.php +++ b/app/Jobs/ExpiredDepositHistoryJob.php @@ -3,6 +3,7 @@ namespace App\Jobs; use App\Models\DepositHistory; +use App\Models\PaylaterHistory; use App\Models\Setting; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -41,6 +42,8 @@ class ExpiredDepositHistoryJob implements ShouldQueue ]) ->get(); + $paylaterIds = []; + info(self::class, ['deposit' => $deposits->count()]); foreach ($deposits as $deposit) { $lastUpdated = Carbon::parse($deposit->updated_at); @@ -51,14 +54,22 @@ class ExpiredDepositHistoryJob implements ShouldQueue // Check if the time difference is more than 2 hours if ($timeDifference > $maxTimeout) { $expiredIds[] = $deposit->id; + if ($deposit->related_id != null && $deposit->type == DepositHistory::TYPE_REPAYMENT) { + $paylaterIds[] = $deposit->related_id; + } } } - info(self::class, ['deposit_to_expired' => count($expiredIds)]); + info(self::class, ['deposit_to_expired' => count($expiredIds)]); if (count($expiredIds) > 0) { DepositHistory::whereIn('id', $expiredIds)->update(['is_valid' => DepositHistory::STATUS_EXPIRED]); } + info(self::class, ['paylater_to_expired' => count($paylaterIds)]); + if (count($paylaterIds) > 0) { + PaylaterHistory::whereIn('id', $paylaterIds)->update(['is_valid' => PaylaterHistory::STATUS_EXPIRED]); + } + DB::commit(); info(self::class, ['done']); } diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 7354340..735930c 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -52,6 +52,7 @@ class DepositHistory extends Model 'format_created_at', 'amount', 'image_prove_url', + 'admin_fee' ]; protected static function booted(): void @@ -112,6 +113,23 @@ class DepositHistory extends Model }); } + public function adminFee(): Attribute + { + return Attribute::make(get: function () { + if ($this->account_id != null) { + return Setting::getByKey('ADMINFEE_MANUAL_TRANSFER'); + } + + if ($this->deposit_location_id != null) { + return Setting::getByKey('ADMINFEE_CASH_DEPOSIT'); + } + + if ($this->payment_token != null) { + return Setting::getByKey('MIDTRANS_ADMIN_FEE'); + } + }); + } + public function customer() { return $this->belongsTo(Customer::class); @@ -127,6 +145,11 @@ class DepositHistory extends Model return $this->belongsTo(DepositLocation::class, 'deposit_location_id'); } + public function paylater() + { + return $this->hasOne(PaylaterHistory::class, 'id', 'related_id'); + } + public function update_customer_balance() { $customer = Customer::find($this->customer_id); diff --git a/app/Models/PaylaterHistory.php b/app/Models/PaylaterHistory.php index 2f5d4fb..ecfbe48 100644 --- a/app/Models/PaylaterHistory.php +++ b/app/Models/PaylaterHistory.php @@ -44,21 +44,13 @@ class PaylaterHistory extends Model 'format_human_created_at', 'format_created_at', 'amount', + 'status', + 'status_text', ]; - public function update_customer_paylater() + public function customer() { - $customer = Customer::find($this->customer_id); - $paylater = $customer->paylater; - - if ($paylater->day_deadline_at == null) { - $paylater->day_deadline_at = now()->addDays($paylater->day_deadline); - } - - $paylater->update([ - 'usage' => $paylater->usage + $this->debit - $this->credit, - 'day_deadline_at' => $paylater->day_deadline_at, - ]); + return $this->belongsTo(Customer::class); } public function formatHumanCreatedAt(): Attribute @@ -85,4 +77,67 @@ class PaylaterHistory extends Model return '-Rp ' . number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.'); }); } + + public function status(): Attribute + { + return Attribute::make(get: function () { + if ($this->type == self::TYPE_REPAYMENT && $this->is_valid == self::STATUS_REJECT) { + return 'Reject'; + } + + if ($this->type == self::TYPE_REPAYMENT && $this->is_valid == self::STATUS_EXPIRED) { + return 'Expired'; + } + + if ($this->type == self::TYPE_REPAYMENT && $this->is_valid != self::STATUS_VALID) { + return 'Menunggu pembayaran'; + } + + return ''; + }); + } + + public function statusText(): Attribute + { + return Attribute::make(get: function () { + return [ + self::STATUS_VALID => ['text' => 'Success', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_WAIT_UPLOAD => ['text' => 'Upload bukti bayar', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + self::STATUS_WAIT_APPROVE => ['text' => 'Menunggu Approve', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_WAIT_PAYMENT => ['text' => 'Menunggu Pembayaran', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_INVALID => ['text' => 'Error', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + self::STATUS_REJECT => ['text' => 'Reject', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + self::STATUS_EXPIRED => ['text' => 'Expired', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + ][$this->is_valid]; + }); + } + + public function create_notification_user() + { + Notification::create([ + 'entity_id' => $this->customer_id, + 'description' => 'Pembayaran ' . $this->description . ' sebesar ' . $this->amount . ' sudah sukses diterima', + ]); + } + + public function update_customer_paylater() + { + $customer = Customer::find($this->customer_id); + $paylater = $customer->paylater; + + if ($paylater->day_deadline_at == null) { + $paylater->day_deadline_at = now()->addDays($paylater->day_deadline); + } + + $usage = $paylater->usage + $this->debit - $this->credit; + + if ($usage == 0) { + $paylater->day_deadline_at = null; + } + + $paylater->update([ + 'usage' => $usage, + 'day_deadline_at' => $paylater->day_deadline_at, + ]); + } } diff --git a/composer.json b/composer.json index 30e8442..32899fd 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "dyrynda/laravel-cascade-soft-deletes": "^4.3", "guzzlehttp/guzzle": "^7.7.0", "inertiajs/inertia-laravel": "^0.6.9", - "laravel/framework": "^10.13.5", + "laravel/framework": "^10.14.1", "laravel/sanctum": "^3.2.5", "laravel/socialite": "^5.6.3", "laravel/tinker": "^2.8.1", @@ -28,7 +28,7 @@ "mockery/mockery": "^1.6.2", "nunomaduro/collision": "^6.4", "phpunit/phpunit": "^9.6.9", - "spatie/laravel-ignition": "^2.1.3" + "spatie/laravel-ignition": "^2.2.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index cb7c812..dd8d30d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9a5a4aa44ec60adc8aa5223f1cdf6e32", + "content-hash": "db8739a9b80108312e32b7bcb4417196", "packages": [ { "name": "brick/math", @@ -1094,16 +1094,16 @@ }, { "name": "laravel/framework", - "version": "v10.13.5", + "version": "v10.14.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "03106ae9ba2ec4b36dc973b7bdca6fad81e032b4" + "reference": "6f89a2b74b232d8bf2e1d9ed87e311841263dfcb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/03106ae9ba2ec4b36dc973b7bdca6fad81e032b4", - "reference": "03106ae9ba2ec4b36dc973b7bdca6fad81e032b4", + "url": "https://api.github.com/repos/laravel/framework/zipball/6f89a2b74b232d8bf2e1d9ed87e311841263dfcb", + "reference": "6f89a2b74b232d8bf2e1d9ed87e311841263dfcb", "shasum": "" }, "require": { @@ -1290,7 +1290,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-06-08T20:25:36+00:00" + "time": "2023-06-28T14:25:16+00:00" }, { "name": "laravel/sanctum", @@ -2182,16 +2182,16 @@ }, { "name": "nesbot/carbon", - "version": "2.67.0", + "version": "2.68.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8" + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/c1001b3bc75039b07f38a79db5237c4c529e04c8", - "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da", + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da", "shasum": "" }, "require": { @@ -2280,7 +2280,7 @@ "type": "tidelift" } ], - "time": "2023-05-25T22:09:47+00:00" + "time": "2023-06-20T18:29:04+00:00" }, { "name": "nette/schema", @@ -8538,16 +8538,16 @@ }, { "name": "spatie/backtrace", - "version": "1.4.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "47794d19e3215ace9e005a8f200cd7cc7be52572" + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/47794d19e3215ace9e005a8f200cd7cc7be52572", - "reference": "47794d19e3215ace9e005a8f200cd7cc7be52572", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", "shasum": "" }, "require": { @@ -8584,7 +8584,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.4.1" + "source": "https://github.com/spatie/backtrace/tree/1.5.3" }, "funding": [ { @@ -8596,26 +8596,27 @@ "type": "other" } ], - "time": "2023-06-13T14:35:04+00:00" + "time": "2023-06-28T12:59:17+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.3.6", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "530ac81255af79f114344286e4275f8869c671e2" + "reference": "82138174d5fe2829a7f085a6bdb2a06f6def9f7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/530ac81255af79f114344286e4275f8869c671e2", - "reference": "530ac81255af79f114344286e4275f8869c671e2", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/82138174d5fe2829a7f085a6bdb2a06f6def9f7a", + "reference": "82138174d5fe2829a7f085a6bdb2a06f6def9f7a", "shasum": "" }, "require": { "illuminate/pipeline": "^8.0|^9.0|^10.0", + "nesbot/carbon": "^2.62.1", "php": "^8.0", - "spatie/backtrace": "^1.2", + "spatie/backtrace": "^1.5.2", "symfony/http-foundation": "^5.0|^6.0", "symfony/mime": "^5.2|^6.0", "symfony/process": "^5.2|^6.0", @@ -8632,7 +8633,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1.x-dev" + "dev-main": "1.3.x-dev" } }, "autoload": { @@ -8657,7 +8658,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.3.6" + "source": "https://github.com/spatie/flare-client-php/tree/1.4.0" }, "funding": [ { @@ -8665,28 +8666,28 @@ "type": "github" } ], - "time": "2023-04-12T07:57:12+00:00" + "time": "2023-06-28T11:08:09+00:00" }, { "name": "spatie/ignition", - "version": "1.8.1", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "d8eb8ea1ed27f48a694405cff363746ffd37f13e" + "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/d8eb8ea1ed27f48a694405cff363746ffd37f13e", - "reference": "d8eb8ea1ed27f48a694405cff363746ffd37f13e", + "url": "https://api.github.com/repos/spatie/ignition/zipball/de24ff1e01814d5043bd6eb4ab36a5a852a04973", + "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "php": "^8.0", - "spatie/backtrace": "^1.4", - "spatie/flare-client-php": "^1.1", + "spatie/backtrace": "^1.5.3", + "spatie/flare-client-php": "^1.4.0", "symfony/console": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, @@ -8698,7 +8699,7 @@ "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "psr/simple-cache-implementation": "*", - "symfony/cache": "^6.2", + "symfony/cache": "^6.0", "symfony/process": "^5.4|^6.0", "vlucas/phpdotenv": "^5.5" }, @@ -8748,20 +8749,20 @@ "type": "github" } ], - "time": "2023-06-06T14:14:58+00:00" + "time": "2023-06-28T13:24:59+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.1.3", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25" + "reference": "dd15fbe82ef5392798941efae93c49395a87d943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/35711943d4725aa80f8033e4f1cb3a6775530b25", - "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/dd15fbe82ef5392798941efae93c49395a87d943", + "reference": "dd15fbe82ef5392798941efae93c49395a87d943", "shasum": "" }, "require": { @@ -8771,7 +8772,7 @@ "illuminate/support": "^10.0", "php": "^8.1", "spatie/flare-client-php": "^1.3.5", - "spatie/ignition": "^1.5.0", + "spatie/ignition": "^1.9", "symfony/console": "^6.2.3", "symfony/var-dumper": "^6.2.3" }, @@ -8840,7 +8841,7 @@ "type": "github" } ], - "time": "2023-05-25T11:30:27+00:00" + "time": "2023-06-28T13:51:52+00:00" }, { "name": "symfony/yaml", diff --git a/resources/js/Customer/Deposit/Detail.jsx b/resources/js/Customer/Deposit/Detail.jsx index a6a0f3e..c23c5c2 100644 --- a/resources/js/Customer/Deposit/Detail.jsx +++ b/resources/js/Customer/Deposit/Detail.jsx @@ -51,7 +51,7 @@ const ActionSection = ({ deposit }) => { ) } -export default function Detail({ deposit }) { +export default function Detail({ deposit, back }) { return ( @@ -59,7 +59,7 @@ export default function Detail({ deposit }) {
{ - router.get(route('transactions.deposit.index')) + router.get(route(back)) }} > diff --git a/resources/js/Customer/Paylater/Detail.jsx b/resources/js/Customer/Paylater/Detail.jsx index 61547ce..035e6b6 100644 --- a/resources/js/Customer/Paylater/Detail.jsx +++ b/resources/js/Customer/Paylater/Detail.jsx @@ -8,7 +8,7 @@ import CustomerLayout from '@/Layouts/CustomerLayout' export default function Detail({ paylater }) { return ( - +
)} + {isEmpty(paylater.status) === false && ( +
+ {paylater.status} +
+ )}
diff --git a/resources/js/Customer/Paylater/Index.jsx b/resources/js/Customer/Paylater/Index.jsx index 1ad3020..40f04c0 100644 --- a/resources/js/Customer/Paylater/Index.jsx +++ b/resources/js/Customer/Paylater/Index.jsx @@ -26,7 +26,7 @@ export default function Index({ return ( - +
{user.fullname}
@@ -47,14 +47,18 @@ export default function Index({
-
- router.get(route('customer.paylater.repay')) - } - > - Bayar Tagihan -
+ {+user.paylater.usage !== 0 && ( +
+ router.get( + route('customer.paylater.repay') + ) + } + > + Bayar Tagihan +
+ )}
{history.amount}
+ {history.status !== '' && ( +
+ {history.status} +
+ )} ))} diff --git a/resources/js/Layouts/Partials/routes.js b/resources/js/Layouts/Partials/routes.js index 9a8e013..da8e600 100644 --- a/resources/js/Layouts/Partials/routes.js +++ b/resources/js/Layouts/Partials/routes.js @@ -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('setting.affilate'), - active: 'setting.affilate', + route: route('paylater.index'), + active: 'paylater.*', permission: 'view-paylater-repayment', }, { diff --git a/resources/js/Pages/CustomerHistory/PaylaterHistory.jsx b/resources/js/Pages/CustomerHistory/PaylaterHistory.jsx new file mode 100644 index 0000000..3ebf8d8 --- /dev/null +++ b/resources/js/Pages/CustomerHistory/PaylaterHistory.jsx @@ -0,0 +1,172 @@ +import React from 'react' +import { Link, router } from '@inertiajs/react' +import { Head } from '@inertiajs/react' +import { HiEye } from 'react-icons/hi2' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import { formatIDR } from '@/utils' +import Button from '@/Components/Button' +import { HiRefresh } from 'react-icons/hi' + +export default function PaylaterHistory(props) { + const { + query: { links, data }, + customer, + } = props + + return ( + + + +
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + {data.map((paylater) => ( + + + + + + + + + + + + ))} + +
+ # + + Customer + + Debit + + Credit + + Tanggal + + Note + + Status + + Approver + +
+ {paylater.description} + + + {customer.name} + + + {`Rp ${formatIDR( + paylater.credit + )}`} + + {`Rp ${formatIDR( + paylater.debit + )}`} + + {paylater.format_created_at} + + {paylater.note} + + {paylater.status_text.text} + + {paylater.editor?.name} + + + +
Lihat
+ +
+
+
+ +
+
+
+
+
+
+ ) +} diff --git a/resources/js/Pages/CustomerMitra/Form.jsx b/resources/js/Pages/CustomerMitra/Form.jsx index e205a69..42717f1 100644 --- a/resources/js/Pages/CustomerMitra/Form.jsx +++ b/resources/js/Pages/CustomerMitra/Form.jsx @@ -229,7 +229,12 @@ export default function Form(props) { Riwayat Pembelian - + @@ -64,7 +65,9 @@ export default function Form(props) {
-
Deposit
+
+ {deposit.description} +
@@ -81,11 +84,6 @@ export default function Form(props) { - - - - - + + + + + @@ -138,6 +141,11 @@ export default function Form(props) { )} + + + + +
Deskripsi:{deposit.description}
Metode Pembayaran @@ -117,6 +115,11 @@ export default function Form(props) { : {deposit.amount}
Admin Fee:Rp {formatIDR(deposit.admin_fee)}
Status :{deposit.editor.name}
Tanggal:{deposit.format_created_at}
@@ -170,7 +178,7 @@ export default function Form(props) { - {errors.status && ( + {errors.is_valid && ( +
+ {errors.is_valid} +
+ )} + {errors.reject_reason && (
- {errors.status} + {errors.reject_reason}
)}
diff --git a/resources/js/Pages/Paylater/Detail.jsx b/resources/js/Pages/Paylater/Detail.jsx new file mode 100644 index 0000000..5b55b49 --- /dev/null +++ b/resources/js/Pages/Paylater/Detail.jsx @@ -0,0 +1,67 @@ +import React from 'react' +import { Head, Link } from '@inertiajs/react' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' + +export default function Detail(props) { + const { paylater } = props + + return ( + + + +
+
+
+
+ {paylater.description} +
+ + + + + + + + + + + + + + + + + + + + + + + +
Customer: + + {paylater.customer.name} + +
Jumlah:{paylater.amount}
Status: + {paylater.status_text.text} +
Tanggal:{paylater.format_created_at}
+
+
+
+
+ ) +} diff --git a/resources/js/Pages/Paylater/Form.jsx b/resources/js/Pages/Paylater/Form.jsx new file mode 100644 index 0000000..c7e5bd3 --- /dev/null +++ b/resources/js/Pages/Paylater/Form.jsx @@ -0,0 +1,230 @@ +import React, { useEffect } from 'react' +import { Head, Link, useForm } from '@inertiajs/react' +import { isEmpty } from 'lodash' + +import { + STATUS_APPROVE, + STATUS_REJECT, + STATUS_WAIT_APPROVE, + STATUS_WAIT_UPLOAD, +} from '@/constant' +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import FormInput from '@/Components/FormInput' +import Button from '@/Components/Button' +import FormInputNumeric from '@/Components/FormInputNumeric' +import { formatIDR } from '@/utils' + +export default function Form(props) { + const { deposit } = props + + const { data, setData, post, processing, errors } = useForm({ + debit: 0, + is_valid: 0, + reject_reason: '', + }) + + const handleOnChange = (event) => { + setData( + event.target.name, + event.target.type === 'checkbox' + ? event.target.checked + ? 1 + : 0 + : event.target.value + ) + } + + const showForm = + +deposit.is_valid === STATUS_WAIT_APPROVE || + +deposit.is_valid === STATUS_WAIT_UPLOAD + + const handleSubmit = () => { + post(route('paylater.update', deposit)) + } + + useEffect(() => { + if (isEmpty(deposit) === false) { + setData({ + debit: deposit.debit, + is_valid: deposit.is_valid, + reject_reason: deposit.reject_reason, + }) + return + } + }, [deposit]) + + return ( + + + +
+
+
+
+ {deposit.description} +
+ + + + + + + + + + + + + {deposit.account !== null && ( + + + + + + )} + {deposit.deposit_location !== null && ( + + + + + + )} + + + + + + + + + + + + + + + + + + + + + {isEmpty(deposit.editor) === false && ( + + + + + + )} + + + + + + +
Customer: + + {deposit.customer.name} + +
+ Metode Pembayaran + :{deposit.payment_channel}
Bank Akun: + {deposit.account.name} ( + {deposit.account.bank_name}) +
+ Lokasi Cash / Setor Tunai + :{deposit.deposit_location.name}
Jumlah:{deposit.amount}
Admin Fee:Rp {formatIDR(+deposit.admin_fee)}
Status: + {deposit.status.text} +
+ Alasan Penolakan + :{deposit.reject_reason}
Approver:{deposit.editor.name}
Tanggal:{deposit.format_created_at}
+ + {isEmpty(deposit.image_prove_url) === false && ( +
+ + + +
+ )} + {showForm && ( + <> +
+ +
Status
+ + {errors.status && ( +
+ {errors.status} +
+ )} + {errors.reject_reason && ( +
+ {errors.reject_reason} +
+ )} +
+ {+data.is_valid === STATUS_REJECT && ( + + )} + +
+ +
+ + )} +
+
+
+
+ ) +} diff --git a/resources/js/Pages/Paylater/Index.jsx b/resources/js/Pages/Paylater/Index.jsx new file mode 100644 index 0000000..2264855 --- /dev/null +++ b/resources/js/Pages/Paylater/Index.jsx @@ -0,0 +1,218 @@ +import React, { useEffect, useState } from 'react' +import { Head, Link, router } from '@inertiajs/react' +import { usePrevious } from 'react-use' +import { HiEye } from 'react-icons/hi2' + +import { formatIDR, hasPermission } from '@/utils' +import { DEPOSIT_STATUSES } from '@/constant' +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import SearchInput from '@/Components/SearchInput' +import ThSort from '@/Components/ThSortComponent' + +export default function Index(props) { + const { + deposits: { links, data }, + auth, + _search, + _sortBy, + _sortRule, + } = props + + const [search, setSearch] = useState({ + q: _search, + sortBy: _sortBy, + sortRule: _sortRule, + }) + const [status, setStatus] = useState('') + const preValue = usePrevious(`${search}${status}`) + + const handleChangeSearch = (e) => { + setSearch({ + ...search, + q: e.target.value, + }) + } + + const sort = (key, sort = null) => { + if (sort !== null) { + setSearch({ + ...search, + sortBy: key, + sortRule: sort, + }) + return + } + setSearch({ + ...search, + sortBy: key, + sortRule: search.sortRule == 'asc' ? 'desc' : 'asc', + }) + } + + const params = { ...search, status: status } + useEffect(() => { + if (preValue) { + router.get( + route(route().current()), + { ...search, status: status }, + { + replace: true, + preserveState: true, + } + ) + } + }, [search, status]) + + const canUpdate = hasPermission(auth, 'update-paylater-repayment') + + return ( + + + +
+
+
+
+
+ +
+
+ +
+
+
+
+ + + + + # + + + Customer + + + Deposit + + + Tanggal + + + Status + + + Approver + + + + + {data.map((deposit) => ( + + + + + + + + + + ))} + +
+
+ {deposit.description} + + + {deposit.customer.name} + + + {deposit.amount} + + {deposit.format_created_at} + + {deposit.status.text} + + {deposit.editor?.name} + + {canUpdate && ( + + +
Lihat
+ + )} +
+
+
+ +
+
+
+
+
+
+ ) +} diff --git a/resources/js/Pages/Sale/Detail.jsx b/resources/js/Pages/Sale/Detail.jsx index 8a74271..d76d9db 100644 --- a/resources/js/Pages/Sale/Detail.jsx +++ b/resources/js/Pages/Sale/Detail.jsx @@ -41,7 +41,11 @@ export default function Detail(props) { const { sale } = props return ( - +
@@ -69,7 +73,7 @@ export default function Detail(props) { Metode Pembayaran : - {sale.payed_with} + {sale.payment_with} Total diff --git a/routes/admin.php b/routes/admin.php index 8226eeb..8423f1f 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -139,6 +139,7 @@ Route::middleware(['http_secure_aware', 'inertia.admin']) // mitra history Route::get('/mitra/{customer}/deposit', [CustomerHistoryController::class, 'deposit'])->name('mitra.history.deposit'); Route::get('/mitra/{customer}/sale', [CustomerHistoryController::class, 'sale'])->name('mitra.history.sale'); + Route::get('/mitra/{customer}/paylater', [CustomerHistoryController::class, 'paylater'])->name('mitra.history.paylater'); Route::get('/mitra/{customer}/paylater_deadline', [CustomerHistoryController::class, 'paylater_deadline'])->name('mitra.history.paylater_deadline'); Route::get('/mitra/{customer}/paylater_limit', [CustomerHistoryController::class, 'paylater_limit'])->name('mitra.history.paylater_limit'); @@ -168,6 +169,12 @@ Route::middleware(['http_secure_aware', 'inertia.admin']) Route::get('/deposites/{deposit}', [DepositController::class, 'edit'])->name('deposit.edit'); 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'); + // poin rewared Route::get('/bonus-poin', [PoinRewardController::class, 'index'])->name('poin-reward.index'); Route::post('/bonus-poin', [PoinRewardController::class, 'store'])->name('poin-reward.store'); diff --git a/routes/web.php b/routes/web.php index 4d1dff5..fb09722 100644 --- a/routes/web.php +++ b/routes/web.php @@ -53,7 +53,7 @@ Route::middleware(['http_secure_aware', 'guard_should_customer', 'inertia.custom Route::get('paylater/repay', [PaylaterController::class, 'create'])->name('customer.paylater.repay'); Route::post('paylater/repay', [PaylaterController::class, 'store']); - // deposite + // deposit Route::get('trx/deposit', [DepositController::class, 'index'])->name('transactions.deposit.index'); Route::get('trx/deposit/topup', [DepositController::class, 'create'])->name('transactions.deposit.topup'); Route::post('trx/deposit/topup', [DepositController::class, 'store']);