diff --git a/TODO.md b/TODO.md index f2f0740..91ad66d 100644 --- a/TODO.md +++ b/TODO.md @@ -2,25 +2,25 @@ ## Note -Kerjakan dulu semua yang terkait penjualan normal, deposit normal dan bonus poin transaksi dan downline -baru setelah itu yang berhubungan dengan mitrawbb dan hutang -setelah itu baru penukaran voucher +[x] Kerjakan dulu semua yang terkait penjualan normal, deposit normal dan bonus poin transaksi dan downline +[ ] baru setelah itu yang berhubungan dengan mitrawbb dan hutang +[ ] setelah itu baru penukaran voucher ## Front -- [ ] transaksi pembelian -- [ ] transaksi pembelian + dapat poin downline -- [ ] [BUG] pembelian voucher lebih dari 1 mendapat kode yang sama +- [x] transaksi pembelian +- [x] transaksi pembelian + dapat poin downline +- [x] [BUG] pembelian voucher lebih dari 1 mendapat kode yang sama - [ ] penuakaran voucher -- [ ] tambah metode topup deposit dengan setor tunai kantor wbb +- [x] tambah metode topup deposit dengan setor tunai kantor wbb - [x] mengubah metode pembayaran deposit dengan daftar bank seperti deposit dan tampil logo bank - [x] tampilan keranjang jadi lebih seperti tokped dengan metode pembayaran deposit atau hutang jika tersedia - [x] tampilan transaksi deposit, hutang (mitra wbb), dan poin jadi satu tampilan - [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 -- [ ] format nomor transaksi di deposit , transaksi dan poin +- [x] expired time 2jam di deposit manual maupun kantor wbb +- [x] ubah username dan password di detail transaksi dengan kode voucher saja +- [x] format nomor transaksi di deposit , transaksi dan poin # Back Office diff --git a/app/Http/Controllers/Admin/SettingController.php b/app/Http/Controllers/Admin/SettingController.php index 0228a53..c53fdf1 100644 --- a/app/Http/Controllers/Admin/SettingController.php +++ b/app/Http/Controllers/Admin/SettingController.php @@ -121,7 +121,15 @@ class SettingController extends Controller Setting::where('key', $key)->update(['value' => $value]); } - $allowedLevel = collect($request->AFFILATE_ALLOWED_LEVELS)->toArray(); + $allowedLevel = collect($request->AFFILATE_ALLOWED_LEVELS) + ->map(function ($item) { + return [ + 'id' => $item['id'], + 'key' => $item['key'], + 'name' => $item['name'], + ]; + }) + ->toArray(); Setting::where('key', 'AFFILATE_ALLOWED_LEVELS')->update([ 'value' => json_encode($allowedLevel) diff --git a/app/Http/Controllers/Admin/VoucherController.php b/app/Http/Controllers/Admin/VoucherController.php index adf02ee..596f571 100644 --- a/app/Http/Controllers/Admin/VoucherController.php +++ b/app/Http/Controllers/Admin/VoucherController.php @@ -109,7 +109,7 @@ class VoucherController extends Controller public function edit(Voucher $voucher) { return inertia('Voucher/Form', [ - 'voucher' => $voucher->load(['prices.level']), + 'voucher' => $voucher->load(['locationProfile']), 'levels' => CustomerLevel::all(), ]); } diff --git a/app/Http/Controllers/Api/LocationProfileController.php b/app/Http/Controllers/Api/LocationProfileController.php index 6846036..efce319 100644 --- a/app/Http/Controllers/Api/LocationProfileController.php +++ b/app/Http/Controllers/Api/LocationProfileController.php @@ -10,7 +10,8 @@ class LocationProfileController extends Controller { public function index(Request $request) { - $query = LocationProfile::with(['location'])->orderBy('updated_at', 'desc'); + $query = LocationProfile::with(['location']) + ->orderBy('updated_at', 'desc'); if ($request->q != '') { $query->where('name', 'like', "%$request->q%") diff --git a/app/Http/Controllers/Customer/AuthController.php b/app/Http/Controllers/Customer/AuthController.php index 8bc2860..6876ed8 100644 --- a/app/Http/Controllers/Customer/AuthController.php +++ b/app/Http/Controllers/Customer/AuthController.php @@ -7,6 +7,7 @@ use App\Mail\CustomerVerification; use App\Models\Customer; use App\Models\Setting; use App\Services\AsyncService; +use App\Services\GeneralService; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; @@ -133,7 +134,7 @@ class AuthController extends Controller session()->put('referral_code', $request->referral_code); $code = $request->referral_code; } else { - $code = session('referral_code', ' '); + $code = session('referral_code', ''); } return inertia('Auth/Register', [ @@ -209,17 +210,20 @@ class AuthController extends Controller session()->forget('referral_code'); return; } + $refferal->customerRefferals()->create([ 'refferal_id' => $customer->id, 'customer_code' => $refferal->referral_code, ]); $affilateEnabled = Setting::getByKey('AFFILATE_ENABLED'); - if ($affilateEnabled == 1) { - $bonuspoin = Setting::getByKey('AFFILATE_poin_AMOUNT'); + $isAllowAffilate = GeneralService::isAllowAffilate($refferal->level->key); + if ($affilateEnabled == 1 && $isAllowAffilate) { + $bonuspoin = Setting::getByKey('AFFILATE_POIN_AMOUNT'); $poin = $refferal->poins()->create([ 'debit' => $bonuspoin, - 'description' => 'Bonus Refferal #' . Str::random(5), + 'description' => GeneralService::generateBonusPoinCode(), + 'narration' => 'Bonus Poin Affilate (Register)' ]); $poin->update_customer_balance(); diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index b27e435..6525787 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -7,6 +7,7 @@ use App\Models\Customer; use App\Models\DepositHistory; use App\Models\PoinReward; use App\Models\Sale; +use App\Models\Setting; use App\Models\Voucher; use App\Services\GeneralService; use Illuminate\Http\Request; @@ -100,7 +101,6 @@ class CartController extends Controller ], ]); - DB::beginTransaction(); $customer = $request->user('customer'); $carts = $customer->carts->load(['voucher.locationProfile.location']); @@ -126,6 +126,7 @@ class CartController extends Controller return $item->quantity * $item->voucher->validate_price; }); + DB::beginTransaction(); // create sale $sale = $customer->sales()->create([ 'date_time' => now(), @@ -148,50 +149,17 @@ class CartController extends Controller ]); $voucher->update(['is_sold' => Voucher::SOLD]); + $voucher->check_stock_notification(); + + $voucher->create_bonus_poin($customer); } } - // create sale notification + $sale->create_payment(); $sale->create_notification(); - - // payed with deposit - if ($sale->payed_with == Sale::PAYED_WITH_DEPOSIT) { - $deposit = $customer->deposites()->create([ - 'credit' => $total, - 'description' => $sale->code, - 'related_type' => Sale::class, - 'related_id' => $sale->id, - 'is_valid' => DepositHistory::STATUS_VALID, - ]); - $deposit->update_customer_balance(); - } - - // payed with paylater - if ($sale->payed_with == Sale::PAYED_WITH_PAYLATER) { - $paylater = $customer->paylaterHistories()->create([ - 'debit' => $total, - 'description' => $sale->code, - ]); - $paylater->update_customer_paylater(); - } - - // bonus poin by reward - $bonus = PoinReward::where('customer_level_id', $customer->customer_level_id) - ->where('amount_buy', '<=', $total) - ->orderBy('bonus_poin', 'desc') - ->first(); - - if ($bonus != null) { - $poin = $customer->poins()->create([ - 'debit' => $bonus->bonus_poin, - 'description' => 'Bonus Pembelian #' . $sale->code, - ]); - - $poin->update_customer_balance(); - } - - // TODO : bonus poin by downline + $sale->create_poin_reward(); + $sale->create_poin_affilate(); // remove carts $customer->carts()->delete(); diff --git a/app/Http/Controllers/Customer/PoinController.php b/app/Http/Controllers/Customer/PoinController.php index 62ede3f..02fecf4 100644 --- a/app/Http/Controllers/Customer/PoinController.php +++ b/app/Http/Controllers/Customer/PoinController.php @@ -12,6 +12,7 @@ class PoinController extends Controller public function index(Request $request) { $poins = PoinHistory::where('customer_id', auth()->id()) + ->orderBy('description', 'desc') ->orderBy('updated_at', 'desc'); $start_date = now()->startOfMonth(); diff --git a/app/Http/Controllers/Customer/PoinExchangeController.php b/app/Http/Controllers/Customer/PoinExchangeController.php index 26c7895..85c2c28 100644 --- a/app/Http/Controllers/Customer/PoinExchangeController.php +++ b/app/Http/Controllers/Customer/PoinExchangeController.php @@ -15,7 +15,7 @@ class PoinExchangeController extends Controller public function index(Request $request) { $locations = Location::get(); - $vouchers = Voucher::with(['locationProfile']) + $vouchers = Voucher::with(['locationProfile.location']) ->whereHas('locationProfile', function ($q) { $q->where('price_poin', '!=', 0) ->where('price_poin', '!=', null); @@ -58,7 +58,7 @@ class PoinExchangeController extends Controller 'payed_with' => Sale::PAYED_WITH_POIN, ]); - $voucher = $voucher->shuffle_unsold(); + $voucher = $voucher->shuffle_unsold(1); $sale->items()->create([ 'entity_type' => $voucher::class, 'entity_id' => $voucher->id, diff --git a/app/Jobs/ExpiredCustomerPoinJob.php b/app/Jobs/ExpiredCustomerPoinJob.php new file mode 100644 index 0000000..5d84f09 --- /dev/null +++ b/app/Jobs/ExpiredCustomerPoinJob.php @@ -0,0 +1,31 @@ +belongsTo(Customer::class); } - public function update_customer_balance() + public function update_customer_balance($updateExpired = false) { $customer = Customer::find($this->customer_id); - $customer->update(['poin_balance' => $customer->poin_balance + $this->debit - $this->credit]); + $maxExpired = Setting::getByKey('MAX_POINT_EXPIRED'); + + if ($customer->poin_expired_at == null || $updateExpired) { + $customer->poin_expired_at = now()->addDays($maxExpired); + } + + $customer->update([ + 'poin_balance' => $customer->poin_balance + $this->debit - $this->credit, + 'poin_expired_at' => $customer->poin_expired_at + ]); } } diff --git a/app/Models/Sale.php b/app/Models/Sale.php index d0f3a8f..7cb1f4b 100644 --- a/app/Models/Sale.php +++ b/app/Models/Sale.php @@ -73,7 +73,7 @@ class Sale extends Model public function displayAmount(): Attribute { return Attribute::make(get: function () { - return 'Rp' . number_format($this->amount, is_float($this->amount) ? 2 : 0, ',', '.'); + return 'Rp ' . number_format($this->amount, is_float($this->amount) ? 2 : 0, ',', '.'); }); } @@ -103,4 +103,67 @@ class Sale extends Model 'description' => 'Transaksi pembelian anda ' . $this->code . ' sebesar ' . $this->display_amount . ' berhasil', ]); } + + public function create_payment() + { + // payed with deposit + if ($this->payed_with == Sale::PAYED_WITH_DEPOSIT) { + $deposit = $this->customer->deposites()->create([ + 'credit' => $this->amount, + 'description' => $this->code, + 'related_type' => self::class, + 'related_id' => $this->id, + 'is_valid' => DepositHistory::STATUS_VALID, + ]); + $deposit->update_customer_balance(); + } + + // payed with paylater + if ($this->payed_with == Sale::PAYED_WITH_PAYLATER) { + $paylater = $this->customer->paylaterHistories()->create([ + 'debit' => $this->amount, + 'description' => $this->code, + ]); + $paylater->update_customer_paylater(); + } + } + + public function create_poin_reward() + { + $bonus = PoinReward::where('customer_level_id', $this->customer->customer_level_id) + ->where('amount_buy', '<=', $this->amount) + ->orderBy('bonus_poin', 'desc') + ->first(); + + if ($bonus != null) { + $poin = $this->customer->poins()->create([ + 'debit' => $bonus->bonus_poin, + 'description' => GeneralService::generateBonusPoinCode(), + 'narration' => 'Bonus Poin Reward' + ]); + + $poin->update_customer_balance(); + } + } + + public function create_poin_affilate() + { + $affilateEnabled = Setting::getByKey('AFFILATE_ENABLED'); + $isAllowAffilate = GeneralService::isAllowAffilate($this->customer->level->key); + if ($affilateEnabled == 1 && $isAllowAffilate) { + $bonus = Setting::getByKey('AFFILATE_DOWNLINE_POIN_AMOUNT'); + if ($bonus > 0) { + $code = CustomerRefferal::where('refferal_id', $this->customer_id)->value('customer_code'); + $customer = Customer::where('referral_code', $code)->first(); + + $poin = $customer->poins()->create([ + 'debit' => $bonus, + 'description' => GeneralService::generateBonusPoinCode(), + 'narration' => 'Bonus Poin Affilate (Downline)' + ]); + + $poin->update_customer_balance(); + } + } + } } diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index ca870d3..6890a48 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Services\GeneralService; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Support\Facades\Auth; @@ -26,6 +27,8 @@ class Voucher extends Model protected $appends = [ 'validate_price', 'validate_display_price', + 'validate_price_poin', + 'validate_bonus_poin', 'discount', 'status', 'created_at_formated' @@ -81,6 +84,38 @@ class Voucher extends Model }); } + public function validateBonusPoin(): Attribute + { + return Attribute::make(get: function () { + if ($this->locationProfile->prices->count() > 0) { + $price = $this->locationProfile->prices; + if (auth()->guard('customer')->check()) { + $customer = self::getInstance()['customer']; + return $price->where('customer_level_id', $customer->customer_level_id) + ->value('bonus_poin'); + } + return $price->max('bonus_poin'); + } + return $this->locationProfile->bonus_poin; + }); + } + + public function validatePricePoin(): Attribute + { + return Attribute::make(get: function () { + if ($this->locationProfile->prices->count() > 0) { + $price = $this->locationProfile->prices; + if (auth()->guard('customer')->check()) { + $customer = self::getInstance()['customer']; + return $price->where('customer_level_id', $customer->customer_level_id) + ->value('price_poin'); + } + return $price->max('price_poin'); + } + return $this->locationProfile->price_poin; + }); + } + public function discount(): Attribute { return Attribute::make(get: function () { @@ -190,4 +225,20 @@ class Voucher extends Model 'sum_voucher_unsold' => $sum_voucher_unsold, ]; } + + public function create_bonus_poin(Customer $customer) + { + $bonus = $this->validate_bonus_poin; + + if ($bonus > 0) { + $customer = Customer::find($customer->id); + $poin = $customer->poins()->create([ + 'debit' => $bonus, + 'description' => GeneralService::generateBonusPoinCode(), + 'narration' => 'Bonus Poin Pembelian Voucher' + ]); + + $poin->update_customer_balance(); + } + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 7a92ae8..40fb000 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -26,17 +26,17 @@ class AppServiceProvider extends ServiceProvider public function boot() { // for optimize in development log every query - if (app()->isProduction() == false) { - DB::listen(function ($query) { - Log::info( - $query->sql, - [ - 'bindings' => $query->bindings, - 'time' => $query->time, - 'connectionName' => $query->connectionName, - ] - ); - }); - } + // if (app()->isProduction() == false) { + // DB::listen(function ($query) { + // Log::info( + // $query->sql, + // [ + // 'bindings' => $query->bindings, + // 'time' => $query->time, + // 'connectionName' => $query->connectionName, + // ] + // ); + // }); + // } } } diff --git a/app/Services/GeneralService.php b/app/Services/GeneralService.php index e50442d..d322eee 100644 --- a/app/Services/GeneralService.php +++ b/app/Services/GeneralService.php @@ -5,6 +5,7 @@ namespace App\Services; use App\Models\Customer; use App\Models\DepositHistory; use App\Models\DepositLocation; +use App\Models\PoinHistory; use App\Models\Sale; use App\Models\Setting; use Illuminate\Support\Carbon; @@ -164,6 +165,13 @@ class GeneralService return 'Invoice #VCR' . now()->format('dmy') . GeneralService::formatNumberCode($code); } + public static function generateBonusPoinCode() + { + $code = PoinHistory::whereDate('created_at', now())->count() + 1; + + return 'Invoice #BPN' . now()->format('dmy') . GeneralService::formatNumberCode($code); + } + public static function formatNumberCode($number) { if ($number < 10) { @@ -177,4 +185,16 @@ class GeneralService } return $number; } + + public static function isAllowAffilate($key) + { + $isAllow = false; + $levels = json_decode(Setting::getByKey('AFFILATE_ALLOWED_LEVELS')); + foreach($levels as $level) { + if ($key == $level->key) { + $isAllow = true; + } + } + return $isAllow; + } } diff --git a/database/migrations/2023_06_16_045835_create_poin_histories_table.php b/database/migrations/2023_06_16_045835_create_poin_histories_table.php index 9689342..a3515c8 100644 --- a/database/migrations/2023_06_16_045835_create_poin_histories_table.php +++ b/database/migrations/2023_06_16_045835_create_poin_histories_table.php @@ -16,7 +16,8 @@ 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('narration')->nullable(); $table->ulid('customer_id')->nullable(); $table->string('related_type')->nullable(); $table->string('related_id')->nullable(); diff --git a/database/seeders/DummySeeder.php b/database/seeders/DummySeeder.php index d2d33c3..fe53e80 100644 --- a/database/seeders/DummySeeder.php +++ b/database/seeders/DummySeeder.php @@ -121,7 +121,7 @@ class DummySeeder extends Seeder 'display_price' => $disply_price, 'discount' => $discount, 'price_poin' => $price, - 'bonus_poin' => 0, + 'bonus_poin' => $count == 1 ? 10 : 0, ]); if ($count == 3) { @@ -133,6 +133,7 @@ class DummySeeder extends Seeder foreach (CustomerLevel::LEVELS as $index => $level) { if ($index != 0) { $disc += 5; + $bp += 5; } $p = $dp - ($dp * ($disc / 100)); @@ -175,10 +176,10 @@ class DummySeeder extends Seeder { DepositLocation::create([ 'name' => 'Location 1', - 'address' => 'Address Lengkap Alamat', + 'address' => 'Gedung Sebaguna Kota Alele, Jl. Address Lengkap No.20 Kota Kabupaten', 'phone' => '83840745543', 'gmap_url' => 'https://goo.gl/maps/iyJ8nq32pJ2BbfUf6', - 'image' => 'sample/banner.jpg', + 'image' => 'sample/location.png', 'description' => '