From 3f12da970af0e14bafbe3e2b0009d84d132cbd37 Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Sun, 25 Jun 2023 01:37:35 +0700 Subject: [PATCH] upgrade deposit --- TODO.md | 8 +- .../{ => Admin}/AccountController.php | 5 +- .../{ => Admin}/BannerController.php | 3 +- .../{ => Admin}/CustomerController.php | 3 +- .../{ => Admin}/CustomerLevelController.php | 3 +- .../{ => Admin}/DepositController.php | 10 +- .../{ => Admin}/DepositLocationController.php | 12 +- .../{ => Admin}/GeneralController.php | 3 +- .../{ => Admin}/InfoController.php | 3 +- .../{ => Admin}/LocationController.php | 3 +- .../{ => Admin}/LocationProfileController.php | 3 +- .../{ => Admin}/NotificationController.php | 3 +- .../{ => Admin}/PoinRewardController.php | 3 +- .../{ => Admin}/ProfileController.php | 3 +- .../{ => Admin}/RoleController.php | 3 +- .../{ => Admin}/SaleController.php | 3 +- .../{ => Admin}/SettingController.php | 18 +- .../{ => Admin}/UserController.php | 5 +- .../{ => Admin}/VerificationController.php | 3 +- .../{ => Admin}/VoucherController.php | 3 +- .../Controllers/Customer/CartController.php | 2 +- .../Customer/DepositController.php | 16 +- .../Customer/DepositLocationController.php | 17 ++ .../Controllers/Customer/PoinController.php | 4 +- .../Customer/PoinExchangeController.php | 2 +- app/Models/DepositHistory.php | 29 +++ app/Models/DepositLocation.php | 17 +- app/Models/Setting.php | 2 + app/Models/Voucher.php | 2 +- app/Services/GeneralService.php | 86 ++++++- app/Services/MidtransService.php | 29 ++- ..._130646_create_deposit_histories_table.php | 4 +- database/seeders/DummySeeder.php | 8 +- database/seeders/InstallationSeed.php | 9 +- public/sample/logo-bni.png | Bin 0 -> 42096 bytes resources/js/Components/Checkbox.jsx | 23 +- resources/js/Customer/Cart/Index.jsx | 2 +- .../js/Customer/Components/HeaderTrx.jsx | 75 +++++++ resources/js/Customer/Deposit/Detail.jsx | 211 +++++++++++++++--- resources/js/Customer/Deposit/Index.jsx | 33 +-- resources/js/Customer/Deposit/Topup.jsx | 101 +++++++-- .../js/Customer/DepositLocation/Index.jsx | 104 +++++++++ .../Customer/Index/Partials/BalanceBanner.jsx | 4 +- resources/js/Customer/Paylater/Index.jsx | 4 +- resources/js/Customer/Poin/Detail.jsx | 2 +- resources/js/Customer/Poin/Index.jsx | 30 +-- resources/js/Customer/Profile/Form.jsx | 7 + resources/js/Customer/Profile/Index.jsx | 16 +- resources/js/Customer/Trx/Detail.jsx | 2 +- resources/js/Customer/Trx/Index.jsx | 9 +- resources/js/Customer/utils.jsx | 2 + resources/js/Layouts/CustomerLayout.jsx | 2 +- .../js/Pages/DepositHistory/FormModal.jsx | 78 ++++--- resources/js/Pages/DepositHistory/Index.jsx | 32 ++- resources/js/Pages/Setting/Index.jsx | 86 ++++++- resources/js/constant.js | 4 + routes/admin.php | 38 ++-- routes/web.php | 28 ++- 58 files changed, 940 insertions(+), 280 deletions(-) rename app/Http/Controllers/{ => Admin}/AccountController.php (97%) rename app/Http/Controllers/{ => Admin}/BannerController.php (96%) rename app/Http/Controllers/{ => Admin}/CustomerController.php (98%) rename app/Http/Controllers/{ => Admin}/CustomerLevelController.php (95%) rename app/Http/Controllers/{ => Admin}/DepositController.php (85%) rename app/Http/Controllers/{ => Admin}/DepositLocationController.php (88%) rename app/Http/Controllers/{ => Admin}/GeneralController.php (98%) rename app/Http/Controllers/{ => Admin}/InfoController.php (95%) rename app/Http/Controllers/{ => Admin}/LocationController.php (96%) rename app/Http/Controllers/{ => Admin}/LocationProfileController.php (98%) rename app/Http/Controllers/{ => Admin}/NotificationController.php (84%) rename app/Http/Controllers/{ => Admin}/PoinRewardController.php (95%) rename app/Http/Controllers/{ => Admin}/ProfileController.php (95%) rename app/Http/Controllers/{ => Admin}/RoleController.php (97%) rename app/Http/Controllers/{ => Admin}/SaleController.php (92%) rename app/Http/Controllers/{ => Admin}/SettingController.php (79%) rename app/Http/Controllers/{ => Admin}/UserController.php (95%) rename app/Http/Controllers/{ => Admin}/VerificationController.php (95%) rename app/Http/Controllers/{ => Admin}/VoucherController.php (99%) create mode 100644 app/Http/Controllers/Customer/DepositLocationController.php create mode 100644 public/sample/logo-bni.png create mode 100644 resources/js/Customer/Components/HeaderTrx.jsx create mode 100644 resources/js/Customer/DepositLocation/Index.jsx diff --git a/TODO.md b/TODO.md index 829af7f..d27214a 100644 --- a/TODO.md +++ b/TODO.md @@ -2,12 +2,12 @@ ## Front +- [x] mengubah metode pembayaran deposit dengan daftar bank seperti deposit dan tampil logo bank - [ ] tampilan keranjang jadi lebih seperti tokped dengan metode pembayaran deposit atau hutang jika tersedia -- [ ] tampilan transaksi deposit, hutang (mitra wbb), dan poin jadi satu tampilan -- [ ] mengubah metode pembayaran deposit dengan daftar bank seperti deposit dan tampil logo bank +- [x] tampilan transaksi deposit, hutang (mitra wbb), dan poin jadi satu tampilan - [ ] tambah metode topup deposit dengan setor tunai kantor wbb -- [ ] tambah screen untuk daftar setor tunai kantor wbb -- [ ] halaman untuk menampilkan level customer +- [x] tambah screen untuk daftar setor tunai kantor wbb +- [x] halaman untuk menampilkan level customer - [ ] expired time 2jam di deposit manual maupun kantor wbb - [ ] ubah username dan password di detail transaksi dengan kode voucher saja - [ ] [BUG] pembelian voucher lebih dari 1 mendapat kode yang sama diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/Admin/AccountController.php similarity index 97% rename from app/Http/Controllers/AccountController.php rename to app/Http/Controllers/Admin/AccountController.php index 821c100..ffe293c 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/Admin/AccountController.php @@ -1,7 +1,8 @@ file('logo'); $file->store('uploads', 'public'); - + Account::create([ 'name' => $request->name, 'bank_name' => $request->bank_name, diff --git a/app/Http/Controllers/BannerController.php b/app/Http/Controllers/Admin/BannerController.php similarity index 96% rename from app/Http/Controllers/BannerController.php rename to app/Http/Controllers/Admin/BannerController.php index afb3471..632fe3f 100644 --- a/app/Http/Controllers/BannerController.php +++ b/app/Http/Controllers/Admin/BannerController.php @@ -1,7 +1,8 @@ where('credit', 0) ->orderBy('is_valid', 'desc') ->orderBy('updated_at', 'desc'); @@ -50,9 +51,14 @@ class DepositController extends Controller ], ]); + if ($request->status == DepositHistory::STATUS_REJECT) { + $request->validate(['reject_reason' => 'required|string']); + } + DB::beginTransaction(); $deposit->update([ 'is_valid' => $request->status, + 'note' => $request->reject_reason ]); if ($request->status == DepositHistory::STATUS_VALID) { $deposit->update_customer_balance(); diff --git a/app/Http/Controllers/DepositLocationController.php b/app/Http/Controllers/Admin/DepositLocationController.php similarity index 88% rename from app/Http/Controllers/DepositLocationController.php rename to app/Http/Controllers/Admin/DepositLocationController.php index 6bb952b..9ebde67 100644 --- a/app/Http/Controllers/DepositLocationController.php +++ b/app/Http/Controllers/Admin/DepositLocationController.php @@ -1,8 +1,10 @@ $request->gmap_url, 'image' => $file->hashName('uploads'), 'description' => $request->description, - 'open_hour' => $request->open_hour, - 'close_hour' => $request->close_hour, + 'open_hour' => GeneralService::parserToHour($request->open_hour), + 'close_hour' => GeneralService::parserToHour($request->close_hour), 'is_active' => $request->is_active, ]); @@ -88,8 +90,8 @@ class DepositLocationController extends Controller 'gmap_url' => $request->gmap_url, 'image' => $location->image, 'description' => $request->description, - 'open_hour' => $request->open_hour, - 'close_hour' => $request->close_hour, + 'open_hour' => GeneralService::parserToHour($request->open_hour), + 'close_hour' => GeneralService::parserToHour($request->close_hour), 'is_active' => $request->is_active, ]); diff --git a/app/Http/Controllers/GeneralController.php b/app/Http/Controllers/Admin/GeneralController.php similarity index 98% rename from app/Http/Controllers/GeneralController.php rename to app/Http/Controllers/Admin/GeneralController.php index 6017890..44eeff1 100644 --- a/app/Http/Controllers/GeneralController.php +++ b/app/Http/Controllers/Admin/GeneralController.php @@ -1,7 +1,8 @@ validate([ 'OPEN_WEBSITE_NAME' => 'required|string', 'SHARE_TEXT' => 'required|string', + 'ENABLE_CASH_DEPOSIT' => 'required|in:0,1', + 'ENABLE_MANUAL_TRANSFER' => 'required|in:0,1', + 'MAX_MANUAL_TRANSFER_TIMEOUT' => 'required|numeric', + 'MANUAL_TRANSFER_OPEN_HOUR' => 'required|string', + 'MANUAL_TRANSFER_CLOSE_HOUR' => 'required|string', + 'MAX_POINT_EXPIRED' => 'required|numeric', ]); DB::beginTransaction(); - foreach ($request->input() as $key => $value) { + $inputs = $request->except(['MANUAL_TRANSFER_OPEN_HOUR', 'MANUAL_TRANSFER_CLOSE_HOUR']); + foreach ($inputs as $key => $value) { Setting::where('key', $key)->update(['value' => $value]); } + $hours = $request->only(['MANUAL_TRANSFER_OPEN_HOUR', 'MANUAL_TRANSFER_CLOSE_HOUR']); + foreach ($hours as $key => $value) { + Setting::where('key', $key)->update(['value' => GeneralService::parserToHour($value)]); + } + Cache::flush(); DB::commit(); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/Admin/UserController.php similarity index 95% rename from app/Http/Controllers/UserController.php rename to app/Http/Controllers/Admin/UserController.php index be274ba..ce85b01 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -1,7 +1,8 @@ validate([ 'name' => 'required|string|max:255', - 'email' => 'required|email|unique:users,email,'.$user->id, + 'email' => 'required|email|unique:users,email,' . $user->id, 'password' => 'nullable|string|max:255', 'username' => 'required|alpha_dash|unique:users,username,' . $user->id, 'phone_wa' => 'required|string', diff --git a/app/Http/Controllers/VerificationController.php b/app/Http/Controllers/Admin/VerificationController.php similarity index 95% rename from app/Http/Controllers/VerificationController.php rename to app/Http/Controllers/Admin/VerificationController.php index ec41881..4a5959b 100644 --- a/app/Http/Controllers/VerificationController.php +++ b/app/Http/Controllers/Admin/VerificationController.php @@ -1,7 +1,8 @@ remove('carts'); - return redirect()->route('transactions.show', $sale) + return redirect()->route('transactions.sale.show', $sale) ->with('message', ['type' => 'success', 'message' => 'pembelian berhasil']); } } diff --git a/app/Http/Controllers/Customer/DepositController.php b/app/Http/Controllers/Customer/DepositController.php index 512dd52..cc51f1d 100644 --- a/app/Http/Controllers/Customer/DepositController.php +++ b/app/Http/Controllers/Customer/DepositController.php @@ -20,7 +20,8 @@ class DepositController extends Controller { $histories = DepositHistory::where('customer_id', auth()->id()) ->orderBy('updated_at', 'desc') - ->orderBy('is_valid', 'desc'); + ->orderBy('is_valid', 'desc') + ->where('type', DepositHistory::TYPE_DEPOSIT); return inertia('Deposit/Index', [ 'histories' => $histories->paginate(20), @@ -40,7 +41,7 @@ class DepositController extends Controller 'amount' => 'required|numeric|min:10000', 'payment' => [ 'required', - Rule::in([Setting::PAYMENT_MANUAL, Setting::PAYMENT_MIDTRANS]), + Rule::in([Setting::PAYMENT_MANUAL, Setting::PAYMENT_MIDTRANS, Setting::PAYMENT_CASH_DEPOSIT]), ], ]); @@ -48,11 +49,11 @@ class DepositController extends Controller $deposit = DepositHistory::make([ 'customer_id' => auth()->id(), 'debit' => $request->amount, - 'description' => 'Top Up #'.Str::random(5), 'payment_channel' => $request->payment, + 'type' => DepositHistory::TYPE_DEPOSIT, ]); - if ($request->payment == Setting::PAYMENT_MANUAL) { + if (in_array($request->payment, [Setting::PAYMENT_MANUAL, Setting::PAYMENT_CASH_DEPOSIT])) { $deposit->is_valid = DepositHistory::STATUS_WAIT_UPLOAD; $deposit->save(); } @@ -65,17 +66,18 @@ class DepositController extends Controller $deposit->update(['payment_token' => $token]); } + $deposit->create_notification(); DB::commit(); - return redirect()->route('customer.deposit.show', ['deposit' => $deposit->id, 'direct' => 'true']); + return redirect()->route('transactions.deposit.show', ['deposit' => $deposit->id, 'direct' => 'true']); } public function show(Request $request, DepositHistory $deposit) { return inertia('Deposit/Detail', [ - 'deposit' => $deposit, + 'deposit' => $deposit->load(['account']), 'accounts' => Account::get(), 'midtrans_client_key' => Setting::getByKey('MIDTRANS_CLIENT_KEY'), 'is_production' => app()->isProduction(), @@ -131,7 +133,7 @@ class DepositController extends Controller DB::commit(); - return redirect()->route('customer.deposit.show', ['deposit' => $deposit->id]); + return redirect()->route('transactions.deposit.show', ['deposit' => $deposit->id]); } public function mindtrans_notification(Request $request) diff --git a/app/Http/Controllers/Customer/DepositLocationController.php b/app/Http/Controllers/Customer/DepositLocationController.php new file mode 100644 index 0000000..a200a3b --- /dev/null +++ b/app/Http/Controllers/Customer/DepositLocationController.php @@ -0,0 +1,17 @@ + DepositLocation::orderBy('updated_at', 'desc')->paginate(20), + ]); + } +} diff --git a/app/Http/Controllers/Customer/PoinController.php b/app/Http/Controllers/Customer/PoinController.php index 060fdff..f0a4820 100644 --- a/app/Http/Controllers/Customer/PoinController.php +++ b/app/Http/Controllers/Customer/PoinController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers\Customer; use App\Http\Controllers\Controller; -use App\Models\poinHistory; +use App\Models\PoinHistory; class PoinController extends Controller { @@ -17,7 +17,7 @@ class PoinController extends Controller ]); } - public function show(poinHistory $poin) + public function show(PoinHistory $poin) { return inertia('Poin/Detail', [ 'poin' => $poin, diff --git a/app/Http/Controllers/Customer/PoinExchangeController.php b/app/Http/Controllers/Customer/PoinExchangeController.php index a342c99..26c7895 100644 --- a/app/Http/Controllers/Customer/PoinExchangeController.php +++ b/app/Http/Controllers/Customer/PoinExchangeController.php @@ -84,7 +84,7 @@ class PoinExchangeController extends Controller $poin->update_customer_balance(); DB::commit(); - return redirect()->route('transactions.show', $sale) + return redirect()->route('transactions.sale.show', $sale) ->with('message', ['type' => 'success', 'message' => 'penukaran berhasil']); } } diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 738bdba..081a466 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Services\GeneralService; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Support\Carbon; @@ -19,10 +20,15 @@ class DepositHistory extends Model const STATUS_REJECT = 5; + const TYPE_DEPOSIT = 0; + + const TYPE_REPAYMENT = 1; + protected $fillable = [ 'debit', 'credit', 'description', + 'note', 'customer_id', 'related_type', 'related_id', @@ -34,6 +40,7 @@ class DepositHistory extends Model 'payment_response', 'payment_channel', 'payment_type', + 'type', ]; protected $appends = [ @@ -44,6 +51,17 @@ class DepositHistory extends Model 'image_prove_url', ]; + protected static function booted(): void + { + static::creating(function (DepositHistory $model) { + if ($model->description == null) { + if ($model->type == DepositHistory::TYPE_DEPOSIT) { + $model->description = GeneralService::generateDepositCode(); + } + } + }); + } + public function status(): Attribute { return Attribute::make(get: function () { @@ -109,6 +127,17 @@ class DepositHistory extends Model public function create_notification() { if ($this->payment_channel == Setting::PAYMENT_MANUAL) { + $status = ''; + if ($this->is_valid == self::STATUS_WAIT_APPROVE) { + $status = ' (bukti bayar di upload, membutuhkan konfirmasi)'; + } + Notification::create([ + 'entity_type' => User::class, + 'description' => $this->customer->fullname . ' melakukan deposit transfer manual sebesar : ' . $this->amount . $status, + ]); + } + + if ($this->payment_channel == Setting::PAYMENT_CASH_DEPOSIT) { $status = ''; if ($this->is_valid == self::STATUS_WAIT_APPROVE) { $status = ' (bukti bayar di upload, membutuhkan konfirmasi)'; diff --git a/app/Models/DepositLocation.php b/app/Models/DepositLocation.php index 126a2c9..46957d6 100644 --- a/app/Models/DepositLocation.php +++ b/app/Models/DepositLocation.php @@ -33,22 +33,7 @@ class DepositLocation extends Model protected function operationalHour(): Attribute { return Attribute::make(get: function () { - return $this->parser($this->open_hour) . ' - ' . $this->parser($this->close_hour); + return $this->open_hour . ' - ' . $this->close_hour; }); } - - private function parser($time) - { - $r = ''; - $time = explode(':', $time); - foreach ($time as $t) { - if ($t == 0) { - $r .= '00:'; - } else { - $r .= $t . ':'; - } - } - - return substr($r, 0, -1); - } } diff --git a/app/Models/Setting.php b/app/Models/Setting.php index e7a021a..b65c5d2 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -19,6 +19,8 @@ class Setting extends Model const PAYMENT_PAYLATER = 'PAYLATER'; + const PAYMENT_CASH_DEPOSIT = 'CASH_DEPOSIT'; + protected $fillable = [ 'key', 'value', diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index 7801412..71b33bf 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -37,7 +37,7 @@ class Voucher extends Model { if (count(self::$instance) == 0) { self::$instance = [ - 'customer' => Customer::find(auth()->id()) + 'customer' => Customer::find(auth()->guard('customer')->id()) ]; } diff --git a/app/Services/GeneralService.php b/app/Services/GeneralService.php index c176a1f..fcac01d 100644 --- a/app/Services/GeneralService.php +++ b/app/Services/GeneralService.php @@ -2,7 +2,11 @@ namespace App\Services; +use App\Models\DepositHistory; +use App\Models\DepositLocation; use App\Models\Setting; +use Illuminate\Support\Carbon; +use Illuminate\Support\Str; class GeneralService { @@ -55,13 +59,51 @@ class GeneralService public static function getEnablePayment() { - $payment = [ - ['name' => Setting::PAYMENT_MANUAL, 'logo' => null, 'display_name' => 'Transfer Manual'], - ]; + $payment = []; $midtrans_enable = Setting::getByKey('MIDTRANS_ENABLED'); if ($midtrans_enable == 1) { - $payment[] = ['name' => Setting::PAYMENT_MIDTRANS, 'logo' => asset(Setting::getByKey('MIDTRANS_LOGO'))]; + $payment[] = [ + 'name' => Setting::PAYMENT_MIDTRANS, + 'logo' => asset(Setting::getByKey('MIDTRANS_LOGO')), + 'display_name' => 'Midtrans', + 'admin_fee' => Setting::getByKey('MIDTRANS_ADMIN_FEE'), + ]; + } + + $enable = Setting::getByKey('ENABLE_MANUAL_TRANSFER'); + if ($enable == 1) { + $openHour = Carbon::createFromFormat('H:i', Setting::getByKey('MANUAL_TRANSFER_OPEN_HOUR')); + $closeHour = Carbon::createFromFormat('H:i', Setting::getByKey('MANUAL_TRANSFER_CLOSE_HOUR')); + if (now()->between($openHour, $closeHour)) { + $payment[] = [ + 'name' => Setting::PAYMENT_MANUAL, + 'logo' => null, + 'display_name' => 'Transfer Manual', + 'admin_fee' => 0 + ]; + } + } + + $enable = Setting::getByKey('ENABLE_CASH_DEPOSIT'); + if ($enable == 1) { + $locations = DepositLocation::all(); // 30 partner + $enables = []; + + foreach ($locations as $location) { + $openHour = Carbon::createFromFormat('H:i', $location->open_hour); + $closeHour = Carbon::createFromFormat('H:i', $location->close_hour); + $enables[] = now()->between($openHour, $closeHour); + } + + if (in_array(true, $enables)) { + $payment[] = [ + 'name' => Setting::PAYMENT_CASH_DEPOSIT, + 'logo' => null, + 'display_name' => 'Setor Tunai di Kantor WBB', + 'admin_fee' => 0 + ]; + } } return $payment; @@ -73,4 +115,40 @@ class GeneralService // poin // paylater } + + public static function parserToHour($time) + { + $r = ''; + $time = explode(':', $time); + foreach ($time as $t) { //00 : 00 + if ($t < 10) { + $r .= '0' . (int) $t . ':'; + } else { + $r .= $t . ':'; + } + } + + return substr($r, 0, -1); + } + + public static function generateDepositCode() + { + $code = DepositHistory::where('type', DepositHistory::TYPE_DEPOSIT)->count() + 1; + + return 'Invoice #DSR' . now()->format('dmy') . GeneralService::formatNumberCode($code); + } + + public static function formatNumberCode($number) + { + if ($number < 10) { + return '000' . $number; + } + if ($number < 100) { + return '00' . $number; + } + if ($number < 1000) { + return '0' . $number; + } + return $number; + } } diff --git a/app/Services/MidtransService.php b/app/Services/MidtransService.php index 4f5df54..849a2e1 100644 --- a/app/Services/MidtransService.php +++ b/app/Services/MidtransService.php @@ -3,6 +3,7 @@ namespace App\Services; use App\Models\DepositHistory; +use App\Models\Setting; use Midtrans\Config; use Midtrans\Snap; @@ -22,17 +23,31 @@ class MidtransService public function getSnapToken() { + $items = [ + [ + 'id' => $this->deposit->id, + 'price' => $this->deposit->debit, + 'quantity' => 1, + 'name' => $this->deposit->description, + ] + ]; + + $adminFee = Setting::getByKey('MIDTRANS_ADMIN_FEE'); + if ($adminFee > 0) { + $items[] = [ + 'id' => 'tambahan_biaya_admin', + 'price' => $adminFee, + 'quantity' => 1, + 'name' => 'tambahan_biaya_admin', + ]; + } + $params = [ 'transaction_details' => [ 'order_id' => $this->deposit->id, 'gross_amount' => $this->deposit->debit, ], - 'item_details' => [[ - 'id' => $this->deposit->id, - 'price' => $this->deposit->debit, - 'quantity' => 1, - 'name' => $this->deposit->description, - ]], + 'item_details' => $items, 'customer_details' => [ 'name' => $this->deposit->customer->fullname, 'email' => $this->deposit->customer->email, @@ -40,7 +55,7 @@ class MidtransService 'address' => $this->deposit->customer->address, ], 'callbacks' => [ - 'finish' => route('customer.deposit.show', ['deposit' => $this->deposit->id]), + 'finish' => route('transactions.deposit.show', ['deposit' => $this->deposit->id]), ], ]; diff --git a/database/migrations/2023_05_24_130646_create_deposit_histories_table.php b/database/migrations/2023_05_24_130646_create_deposit_histories_table.php index 2deb771..0bf3cd3 100644 --- a/database/migrations/2023_05_24_130646_create_deposit_histories_table.php +++ b/database/migrations/2023_05_24_130646_create_deposit_histories_table.php @@ -16,12 +16,14 @@ return new class extends Migration $table->decimal('debit', 20, 2)->default(0); $table->decimal('credit', 20, 2)->default(0); - $table->text('description')->nullable(); + $table->string('description')->nullable(); + $table->text('note')->nullable(); $table->ulid('customer_id')->nullable(); $table->ulid('account_id')->nullable(); $table->string('related_type')->nullable(); $table->string('related_id')->nullable(); $table->smallInteger('is_valid')->default(0); + $table->smallInteger('type')->default(0); $table->string('image_prove')->nullable(); $table->string('payment_channel')->nullable(); $table->string('payment_token')->nullable(); diff --git a/database/seeders/DummySeeder.php b/database/seeders/DummySeeder.php index 9c6f1cd..82b1e6c 100644 --- a/database/seeders/DummySeeder.php +++ b/database/seeders/DummySeeder.php @@ -60,8 +60,9 @@ class DummySeeder extends Seeder public function account() { $banks = [ - ['name' => 'BTPN', 'bank_name' => 'BTPN', 'holder_name' => 'Aji Kamaludin', 'account_number' => '187391738129', 'logo' => 'sample/logo-jenius.png'], - ['name' => 'Jago', 'bank_name' => 'Bank Jago', 'holder_name' => 'Aji Kamaludin', 'account_number' => '718297389172', 'logo' => 'sample/logo-jago.png'], + ['name' => 'BTPN', 'bank_name' => 'BTPN', 'holder_name' => 'Aji Kamaludin', 'account_number' => '187391738129', 'logo' => 'sample/logo-jenius.png', 'admin_fee' => 0], + ['name' => 'Jago', 'bank_name' => 'Bank Jago', 'holder_name' => 'Aji Kamaludin', 'account_number' => '718297389172', 'logo' => 'sample/logo-jago.png', 'admin_fee' => 2500], + ['name' => 'BNI', 'bank_name' => 'Bank Negara Indoneisa', 'holder_name' => 'Aji Kamaludin', 'account_number' => '718297389172', 'logo' => 'sample/logo-bni.png', 'admin_fee' => 6500], ]; foreach ($banks as $bank) { @@ -70,7 +71,8 @@ class DummySeeder extends Seeder 'bank_name' => $bank['bank_name'], 'holder_name' => $bank['holder_name'], 'account_number' => $bank['account_number'], - 'logo' => $bank['logo'] + 'logo' => $bank['logo'], + 'admin_fee' => $bank['admin_fee'] ]); } } diff --git a/database/seeders/InstallationSeed.php b/database/seeders/InstallationSeed.php index f3773c7..46d0a82 100644 --- a/database/seeders/InstallationSeed.php +++ b/database/seeders/InstallationSeed.php @@ -22,8 +22,7 @@ class InstallationSeed extends Seeder $settings = [ // general ['key' => 'OPEN_WEBSITE_NAME', 'value' => 'Welcome to Voucher App', 'type' => 'text'], - ['key' => 'SHARE_TEXT', 'value' => '', 'type' => 'text'], - + ['key' => 'SHARE_TEXT', 'value' => '

Baru Beli Voucher nih

', 'type' => 'text'], // affilate ['key' => 'AFFILATE_ENABLED', 'value' => '0', 'type' => 'checkbox'], @@ -41,9 +40,9 @@ class InstallationSeed extends Seeder ['key' => 'MIDTRANS_ADMIN_FEE', 'value' => '2500', 'type' => 'text'], // deposit - ['key' => 'ENABLE_CASH_DEPOSIT', 'value' => '0', 'type' => 'text'], - ['key' => 'ENABLE_MANUAL_TRANSFER', 'value' => '0', 'type' => 'text'], - ['key' => 'MAX_MANUAL_TRANSFER_TIMEOUT', 'value' => '2', 'type' => 'text'], //dalam jam + ['key' => 'ENABLE_CASH_DEPOSIT', 'value' => '0', 'type' => 'text'], // deposit by location (on/off) + ['key' => 'ENABLE_MANUAL_TRANSFER', 'value' => '0', 'type' => 'text'], // transfer manual (on/off) + ['key' => 'MAX_MANUAL_TRANSFER_TIMEOUT', 'value' => '2', 'type' => 'text'], // dalam jam ['key' => 'MANUAL_TRANSFER_OPEN_HOUR', 'value' => '06:00', 'type' => 'text'], ['key' => 'MANUAL_TRANSFER_CLOSE_HOUR', 'value' => '23:00', 'type' => 'text'], ['key' => 'MAX_POINT_EXPIRED', 'value' => '90', 'type' => 'text'], //dalam hari diff --git a/public/sample/logo-bni.png b/public/sample/logo-bni.png new file mode 100644 index 0000000000000000000000000000000000000000..1686ee7fec4ab60924020c2309ae0f75c1c16dd4 GIT binary patch literal 42096 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 g`>!_SSC#GYWM+RpM6nPH+ZS
- + className="w-4 h-4 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600" + /> {label !== '' && ( )} -
{error && ( -

{error}

+

+ {error} +

)} ) -} \ No newline at end of file +} diff --git a/resources/js/Customer/Cart/Index.jsx b/resources/js/Customer/Cart/Index.jsx index 9a2ef9b..4584cd3 100644 --- a/resources/js/Customer/Cart/Index.jsx +++ b/resources/js/Customer/Cart/Index.jsx @@ -29,7 +29,7 @@ export default function Index({ } const handleTopUp = () => { - router.get(route('customer.deposit.topup')) + router.get(route('transactions.deposit.topup')) } return ( diff --git a/resources/js/Customer/Components/HeaderTrx.jsx b/resources/js/Customer/Components/HeaderTrx.jsx new file mode 100644 index 0000000..2cf7bca --- /dev/null +++ b/resources/js/Customer/Components/HeaderTrx.jsx @@ -0,0 +1,75 @@ +import { usePage, router, Link } from '@inertiajs/react' + +export default function HeaderTrx({ enable = 'deposit' }) { + const { + props: { + auth: { user }, + }, + } = usePage() + return ( + <> +
+
{user.fullname}
+
+
+
+
+ Rp {user.display_deposit} +
+
+
+
+ router.get(route('transactions.deposit.topup')) + } + > + Top Up +
+
+
+
+
+
{user.display_poin} poin
+
+ ( kadaluarsa pada 20 juni 2023 ) +
+
+
+
+
+ + Deposit + + + Pembelian + + + Poin + +
+
+ + ) +} diff --git a/resources/js/Customer/Deposit/Detail.jsx b/resources/js/Customer/Deposit/Detail.jsx index 85368f2..16728df 100644 --- a/resources/js/Customer/Deposit/Detail.jsx +++ b/resources/js/Customer/Deposit/Detail.jsx @@ -1,17 +1,19 @@ import React, { useState, useEffect } from 'react' import { Head, router, useForm, usePage } from '@inertiajs/react' +import { isEmpty } from 'lodash' import { HiChevronLeft, - HiClipboard, HiClipboardDocumentList, + HiOutlineClipboardDocumentCheck, + HiOutlineClipboardDocumentList, } from 'react-icons/hi2' +import { toastSuccess } from '../utils' import CustomerLayout from '@/Layouts/CustomerLayout' -import { formatIDR } from '@/utils' import FormFile from '@/Components/FormFile' -import { isEmpty } from 'lodash' import Alert from '@/Components/Alert' -import { toast } from 'react-toastify' +import { formatIDR } from '@/utils' +import { STATUS_REJECT } from '@/constant' const PayButton = () => { const { @@ -106,6 +108,7 @@ const FormUpload = () => { props: { accounts, deposit, flash }, } = usePage() + const [imageUrl, setImageUrl] = useState(deposit.image_prove_url) const [account, setAccount] = useState(null) const { data, setData, errors, processing, post } = useForm({ account_id: '', @@ -117,6 +120,7 @@ const FormUpload = () => { if (id === '') { setData('account_id', '') setAccount(null) + return } const account = accounts.find((acc) => acc.id === id) setData('account_id', account.id) @@ -124,15 +128,17 @@ const FormUpload = () => { } const handleCopyToClipboard = (text) => { - toast.success('copied to clipboard') - navigator.clipboard.writeText(account.account_number) + toastSuccess('copied to clipboard') + navigator.clipboard.writeText(text) } const handleSubmit = () => { if (processing) { return } - post(route('customer.deposit.update', deposit), { + post(route('transactions.deposit.update', deposit), { + replace: true, + preserveState: true, onSuccess: () => setTimeout( () => router.get(route(route().current(), deposit)), @@ -141,6 +147,31 @@ const FormUpload = () => { }) } + useEffect(() => { + if (deposit.account !== null) { + handleSelectAccount(deposit.account.id) + } + }, [deposit]) + + if (isEmpty(imageUrl) == false) { + return ( +
+
Bukti Transfer
+ bukti transfer +
setImageUrl(null)} + > + Ubah Bukti Transfer +
+
+ ) + } + return (
@@ -149,26 +180,59 @@ const FormUpload = () => { {flash.message.message} -
Bank
- +
Bank
+ + {account !== null ? ( +
+
handleSelectAccount(account.id)} + > +
+ logo bank +
+
+ {account.name} - {account.bank_name} +
+
+
handleSelectAccount('')} + > +
Ubah
+
+
+ ) : ( +
+ {accounts.map((account) => ( +
handleSelectAccount(account.id)} + > +
+ logo bank +
+
+ {account.name} - {account.bank_name} +
+
+ ))} +
+ )}
- {data.account_id !== '' && ( + {account !== null && ( <>
-
-
Silahkan transfer nominal di atas ke
+
{account.bank_name} @@ -189,28 +253,90 @@ const FormUpload = () => { } >
Nomor Rekening :
-
+
{account.account_number}
- +
+
Rincian
+ + + + + + + + + + + + + + handleCopyToClipboard( + +account.admin_fee + + +deposit.debit + ) + } + > + + + + + + +
+ Jumlah Deposit + : + + {deposit.amount} + + +
Biaya Admin: + + {+account.admin_fee === 0 ? ( + 'Gratis' + ) : ( + <> + Rp.{' '} + {formatIDR( + +account.admin_fee + )} + + )} + + +
Total Transfer : + + Rp.{' '} + {formatIDR( + +account.admin_fee + + +deposit.debit + )} + + + +
+
+
Bukti Transfer
+ {isEmpty(data.image_url) == false && ( + bukti transfer + )} +
setData('image', e.target.files[0])} error={errors.image} - preview={ - isEmpty(data.image_url) == false && ( - bukti transfer - ) - } /> +
+ upload gambar dalam ekstensi jpg, png, jpeg +
{ } const ActionSection = ({ deposit }) => { + if (deposit.is_valid === STATUS_REJECT) { + return ( +
+
+
+ {deposit.note} +
+
+
+ ) + } return (
{deposit.payment_channel === 'MIDTRANS' ? ( @@ -244,7 +381,7 @@ export default function Detail({ deposit }) {
{ - router.get(route('customer.deposit.index')) + router.get(route('transactions.deposit.index')) }} > diff --git a/resources/js/Customer/Deposit/Index.jsx b/resources/js/Customer/Deposit/Index.jsx index e816873..4c21529 100644 --- a/resources/js/Customer/Deposit/Index.jsx +++ b/resources/js/Customer/Deposit/Index.jsx @@ -1,7 +1,8 @@ import React, { useState } from 'react' import { Head, router } from '@inertiajs/react' import CustomerLayout from '@/Layouts/CustomerLayout' -import { formatIDR } from '@/utils' +import { HiOutlineQuestionMarkCircle } from 'react-icons/hi2' +import HeaderTrx from '../Components/HeaderTrx' export default function Index({ auth: { user }, @@ -28,31 +29,9 @@ export default function Index({
-
-
{user.fullname}
-
-
-
-
- Saldo -
-
- Rp {user.display_deposit} -
-
-
-
- router.get(route('customer.deposit.topup')) - } - > - Top Up -
-
-
+
-
+
{deposites.map((history) => (
router.get( route( - 'customer.deposit.show', + 'transactions.deposit.show', history.id ) ) @@ -80,7 +59,7 @@ export default function Index({
{+history.is_valid !== 0 && (
{history.status.text}
diff --git a/resources/js/Customer/Deposit/Topup.jsx b/resources/js/Customer/Deposit/Topup.jsx index b56d903..b6a44b9 100644 --- a/resources/js/Customer/Deposit/Topup.jsx +++ b/resources/js/Customer/Deposit/Topup.jsx @@ -1,11 +1,11 @@ import React from 'react' -import { Head, router, useForm } from '@inertiajs/react' -import { HiChevronLeft } from 'react-icons/hi2' +import { Head, Link, router, useForm } from '@inertiajs/react' +import { HiCheck, HiChevronLeft, HiQuestionMarkCircle } from 'react-icons/hi2' +import { formatIDR } from '@/utils' +import { CASH_DEPOSIT } from '@/Customer/utils' import CustomerLayout from '@/Layouts/CustomerLayout' -import FormInput from '@/Components/FormInput' import Alert from '@/Components/Alert' -import { formatIDR } from '@/utils' import FormInputNumeric from '@/Components/FormInputNumeric' export default function Topup({ payments }) { @@ -33,11 +33,21 @@ export default function Topup({ payments }) { }` } + const isActivePaymentAdminFee = (payment) => { + return `text-xs ${ + payment === data.payment ? 'text-white' : 'text-gray-400' + }` + } + + const handleSetPayment = (payment) => { + setData('payment', payment.name) + } + const handleSubmit = () => { if (processing) { return } - post(route('customer.deposit.topup')) + post(route('transactions.deposit.topup')) } return ( @@ -47,7 +57,7 @@ export default function Topup({ payments }) {
{ - router.get(route('customer.deposit.index')) + router.get(route('transactions.deposit.index')) }} > @@ -86,33 +96,78 @@ export default function Topup({ payments }) { )}
+ {payments.length <= 0 && ( + + Sistem pembayaran non-aktif{' '} + + )} {payments.map((payment) => (
setData('payment', payment.name)} > - - {payment.logo === null ? ( -

{payment.display_name}

- ) : ( - +
handleSetPayment(payment)} + > + {payment.name === data.payment ? ( +
+ +
+ ) : ( +
+ )} +
+ {payment.logo === null ? ( +

{payment.display_name}

+ ) : ( + + )} + {+payment.admin_fee !== 0 && ( +

+ biaya admin:{' '} + {formatIDR(payment.admin_fee)} +

+ )} +
+
+ {payment.name === CASH_DEPOSIT && ( + +
Daftar lokasi setor tunai
+
+ ada disini +
+
+ +
+ )}
))}
-
-
- Bayar -
+
+ {payments.length > 0 && ( +
+ Bayar +
+ )}
) diff --git a/resources/js/Customer/DepositLocation/Index.jsx b/resources/js/Customer/DepositLocation/Index.jsx new file mode 100644 index 0000000..85425db --- /dev/null +++ b/resources/js/Customer/DepositLocation/Index.jsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react' +import { Head, router } from '@inertiajs/react' +import CustomerLayout from '@/Layouts/CustomerLayout' +import { HiChevronLeft } from 'react-icons/hi2' +import { BsWhatsapp } from 'react-icons/bs' +import { GrMap } from 'react-icons/gr' + +export default function Index({ locations: { data, next_page_url } }) { + const [locations, setLocations] = useState(data) + + const handleNextPage = () => { + router.get( + next_page_url, + {}, + { + replace: true, + preserveState: true, + only: ['locations'], + onSuccess: (res) => { + setLocations(locations.concat(res.props.locations.data)) + }, + } + ) + } + return ( + + +
+
{ + router.get(route('transactions.deposit.topup')) + }} + > +
+ +
+
+ Lokasi Setor Tunai +
+
+
+ {locations.map((location) => ( +
+ +
+
{location.name}
+ +
+ Alamat : {location.address} +
+
+ Jam Buka :{' '} + + {location.operational_hour} + +
+ +
+
+ ))} + {next_page_url !== null && ( +
+ Load more +
+ )} +
+
+
+ ) +} diff --git a/resources/js/Customer/Index/Partials/BalanceBanner.jsx b/resources/js/Customer/Index/Partials/BalanceBanner.jsx index 7a60dc9..d5a7493 100644 --- a/resources/js/Customer/Index/Partials/BalanceBanner.jsx +++ b/resources/js/Customer/Index/Partials/BalanceBanner.jsx @@ -9,7 +9,9 @@ export default function BalanceBanner({ user }) {
router.get(route('customer.deposit.index'))} + onClick={() => + router.get(route('transactions.deposit.index')) + } >
diff --git a/resources/js/Customer/Paylater/Index.jsx b/resources/js/Customer/Paylater/Index.jsx index 05ac5e0..5dff9fd 100644 --- a/resources/js/Customer/Paylater/Index.jsx +++ b/resources/js/Customer/Paylater/Index.jsx @@ -50,7 +50,9 @@ export default function Index({
- router.get(route('customer.deposit.topup')) + router.get( + route('transactions.deposit.topup') + ) } > Bayar Tagihan diff --git a/resources/js/Customer/Poin/Detail.jsx b/resources/js/Customer/Poin/Detail.jsx index 115e469..361ece9 100644 --- a/resources/js/Customer/Poin/Detail.jsx +++ b/resources/js/Customer/Poin/Detail.jsx @@ -12,7 +12,7 @@ export default function Detail({ poin }) {
{ - router.get(route('customer.poin.index')) + router.get(route('transactions.poin.index')) }} > diff --git a/resources/js/Customer/Poin/Index.jsx b/resources/js/Customer/Poin/Index.jsx index 269f14b..4289b46 100644 --- a/resources/js/Customer/Poin/Index.jsx +++ b/resources/js/Customer/Poin/Index.jsx @@ -1,6 +1,19 @@ import React, { useState } from 'react' import { Head, router } from '@inertiajs/react' import CustomerLayout from '@/Layouts/CustomerLayout' +import HeaderTrx from '../Components/HeaderTrx' + +const EmptyHere = () => { + return ( +
+
Transaksi kosong
+
+ Yuk kumpulkan poin sebanyak banyaknya dengan share link refferal + kamu +
+
+ ) +} export default function Index({ auth: { user }, @@ -27,19 +40,8 @@ export default function Index({
-
-
{user.fullname}
-
-
-
-
- poin -
-
- {user.display_poin} -
-
-
+ + {_poins.length <= 0 && }
{_poins.map((poin) => ( @@ -48,7 +50,7 @@ export default function Index({ className="flex flex-row pb-2 items-center justify-between border-b" onClick={() => router.get( - route('customer.poin.show', poin.id) + route('transactions.poin.show', poin.id) ) } > diff --git a/resources/js/Customer/Profile/Form.jsx b/resources/js/Customer/Profile/Form.jsx index 55e6ffc..388d37c 100644 --- a/resources/js/Customer/Profile/Form.jsx +++ b/resources/js/Customer/Profile/Form.jsx @@ -138,6 +138,12 @@ export default function Index({ auth: { user }, flash }) { label="password confirm" />
+
+
email
+
+ {user.email} +
+
+
- -
- - )} + {+data.is_valid !== STATUS_APPROVE && + +data.is_valid !== STATUS_REJECT && ( + <> +
+
Status
+ + {errors.status && ( +
+ {errors.status} +
+ )} +
+ {+data.status === STATUS_REJECT && ( + + )} +
+ + +
+ + )} ) } diff --git a/resources/js/Pages/DepositHistory/Index.jsx b/resources/js/Pages/DepositHistory/Index.jsx index cf154e4..c78caf8 100644 --- a/resources/js/Pages/DepositHistory/Index.jsx +++ b/resources/js/Pages/DepositHistory/Index.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react' -import { router } from '@inertiajs/react' +import { Link, router } from '@inertiajs/react' import { usePrevious } from 'react-use' import { Head } from '@inertiajs/react' import { HiEye } from 'react-icons/hi2' @@ -63,6 +63,12 @@ export default function Index(props) { + + +
+ # + Tanggal - Deskripsi + Status - Status + Approver - {deposit.customer.name} + {deposit.description} - {deposit.amount} + + {deposit.customer.name} + - {deposit.format_created_at} + {deposit.amount} - {deposit.description} + {deposit.format_created_at} {deposit.status.text} + {deposit.editor?.name} + {canUpdate && (
{ @@ -27,11 +45,7 @@ export default function General(props) { } const handleSubmit = () => { - post(route('setting.update'), { - onSuccess: () => { - setTimeout(() => router.get(route(route().current())), 3000) - }, - }) + post(route('setting.update')) } return ( @@ -55,6 +69,7 @@ export default function General(props) { label="Nama Website" error={errors.OPEN_WEBSITE_NAME} /> +
+
+ + + +
+
+ + setData( + 'MANUAL_TRANSFER_OPEN_HOUR', + h + ) + } + label="Jam Buka" + error={errors.MANUAL_TRANSFER_OPEN_HOUR} + /> +
+
-
+
+ + setData( + 'MANUAL_TRANSFER_CLOSE_HOUR', + h + ) + } + label="Jam Tutup" + error={ + errors.MANUAL_TRANSFER_CLOSE_HOUR + } + /> +
+
+ +