diff --git a/app/Classes/Jobs/Commands/V2/AutoFillPurchaseOrderV2CommandJob.php b/app/Classes/Jobs/Commands/V2/AutoFillPurchaseOrderV2CommandJob.php new file mode 100644 index 00000000..1d1b86f9 --- /dev/null +++ b/app/Classes/Jobs/Commands/V2/AutoFillPurchaseOrderV2CommandJob.php @@ -0,0 +1,89 @@ +where('created_at', '<', now()->subDays(60)->endOfDay()) + ->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }) + ->whereDoesntHave('transactions', function($transaction){ + $transaction->where('type', TransactionType::PURCHASE_ORDER); + $transaction->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]); + })->get(); + Log::info('Bookings count: '.count($bookings)); + + foreach ($bookings as $booking) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->where('issuer', $booking->company_id) + ->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + + + if (!$po) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + } + + $products = (App()->make(GeneratesPurchaseOrderProducts::class))->execute($po, $booking->fix_amount); + + $deference = $booking->fix_amount - $products->sum('total'); + + if($deference > -150 && $deference < 150 && $deference != 0) { + + $products->push([ + 'description' => $deference < 0 ? 'Discount':'Shipping Fee', + 'quantity' => 1, + 'stockCode' => '', + 'total' => $deference, + 'unit_price' => $deference + ]); + } + + $billNumber = (App()->make(GeneratesTransactionBillNumber::class))->execute('XPO-'); + + Log::info('Single booking billNumber: '.$billNumber); + + $total = $products->sum('total'); + + $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1, + 1, PaymentMethodType::CASH, + $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, + 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products->toArray()); + + (App()->make(CreatePurchaseOrderTransactionProcessor::class))->execute($booking, $object); + } + + $end = new Carbon(); + $elapsedTime = $start->diff($end)->format('%H:%I:%S'); + Log::info(Carbon::now() . ': End job - Auto fill up the purchase order for booking that have payment. ElapsedTime: ' . $elapsedTime . '.'); + } +} diff --git a/app/Classes/Jobs/Commands/V2/ExpiredBookingV2CommandJob.php b/app/Classes/Jobs/Commands/V2/ExpiredBookingV2CommandJob.php new file mode 100644 index 00000000..22f91ba6 --- /dev/null +++ b/app/Classes/Jobs/Commands/V2/ExpiredBookingV2CommandJob.php @@ -0,0 +1,81 @@ +where('created_at', '<', now()->subDays(30)->endOfDay()) + ->where(function ($query) { + $query->whereDoesntHave('transactions') + ->orWhereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PURCHASE_ORDER)->orWhere(function ($q) { + $q->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->get(); + + foreach ($bookings as $booking) { + (App()->make(UpdatesBookingStatus::class))->execute($booking, ApprovalStatus::EXPIRED); + Log::info(Carbon::now() . " : Expired Booking without payment & purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + Log::info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + } + } + + // 2. Cancel booking without payment but with purchase order (2 month) + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(60)->endOfDay()) + ->where(function ($query) { + $query->whereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PURCHASE_ORDER); + }); + })->get(); + + foreach ($bookings as $booking) { + (App()->make(UpdatesBookingStatus::class))->execute($booking, ApprovalStatus::EXPIRED); + Log::info(Carbon::now() . " : Expired Booking without payment but with purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + Log::info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + } + } + + $end = new Carbon(); + $elapsedTime = $start->diff($end)->format('%H:%I:%S'); + Log::info(Carbon::now() . ': End job - Expiring booking that do not have further action by user. ElapsedTime: ' . $elapsedTime . '.'); + } +} diff --git a/app/Classes/Jobs/Commands/V2/ExpiredRefundedBookingV2CommandJob.php b/app/Classes/Jobs/Commands/V2/ExpiredRefundedBookingV2CommandJob.php new file mode 100644 index 00000000..4d5ad89e --- /dev/null +++ b/app/Classes/Jobs/Commands/V2/ExpiredRefundedBookingV2CommandJob.php @@ -0,0 +1,137 @@ +where('payment_reference', 'LIKE', "%refund%")->get(); + + foreach ($transactions as $transaction) { + // get the booking marking + $payment_reference = explode(" ", trim($transaction->payment_reference)); + // $marking = substr($transaction->payment_reference, -5); + $marking = trim(end($payment_reference)); + + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(".", trim($transaction->payment_reference)); + $marking = trim(end($payment_reference)); + } + + // for a special payment reference on transaction id: 140231 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode("No", trim($transaction->payment_reference)); + $marking = end($payment_reference); + } + + // for a special payment reference on transaction id: 152013 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(" ", trim($transaction->payment_reference)); + $marking = end($payment_reference); + $marking = prev($payment_reference); + } + + if (preg_match('/^[0-9]+$/', $marking)) { + $booking = Booking::where('marking', $marking)->first(); + + if ($booking) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + if (!$bookingPayment) { + $bookingPaymentCount = $booking->transactions()->payments()->count(); + if ($bookingPaymentCount > 1) { + Log::info("Credit note transaction id: {$transaction->id}, there are {$bookingPaymentCount} payment for the booking."); + foreach ($booking->transactions()->payments()->get() as $bp) { + if ($transaction->amount - $bp->amount < 0.01) { + $bookingPayment = $bp; + break; + } + } + } + + if (!$bookingPayment) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->orderBy('id', 'DESC')->first(); + } + $status = ApprovalStatus::APPROVAL_STATUS_ID[$bookingPayment->status]; + Log::info("Credit note transaction id: {$transaction->id}, the payment for the booking is in status {$status}"); + } + $bookingPaymentAmount = $bookingPayment->amount; + // check if the booking is fully refund + $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); + + if (abs($amountDifference) < 0.01) { + // rejecting booking payment transaction + // $bookingPayment->status = ApprovalStatus::REJECTED; + // $bookingPayment->save(); + + //expired booking + // $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + Log::info("Credit note transaction id: {$transaction->id} is fully refunded, the refunded amount was {$transaction->amount} the payment reference is: {$transaction->payment_reference}"); + // Log::info("Credit note transaction id: {$transaction->id}, Rejected Booking Transaction Payment id: {$bookingPayment->id}, the payment amount was {$bookingPayment->amount}"); + // Log::info("Credit note transaction id: {$transaction->id}, Expired Booking id: {$booking->id}"); + } else { + Log::info("Credit note transaction id: {$transaction->id} is not fully refunded, the refunded amount was {$transaction->amount}, the payment amount was {$bookingPayment->amount}, the payment reference is: {$transaction->payment_reference}"); + } + + $refund = $bookingPayment->transactions()->refunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); + + $bookingInWhiteForm = $bookingPayment->transactions()->bills()->first(); + + if ($refund) { + Log::info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction"); + } + + if ($bookingInWhiteForm) { + Log::info("Credit note transaction id: {$transaction->id}, booking is in white form"); + } + + if (!$refund && !$bookingInWhiteForm) { + $billNumber = (App()->make(GeneratesTransactionBillNumber::class))->execute('RFD-'); + + $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, + 1, PaymentMethodType::CASH, + $transaction->amount, $transaction->amount * $bookingPayment->currency_rate, 1, + $bookingPayment->original_currency_id, $bookingPayment->currency_rate, + 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + + $transaction =(App()->make(CreatesTransaction::class))->execute($bookingPayment, $object); + } + } else { + Log::info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}"); + } + } else { + Log::info("Credit note transaction id: {$transaction->id} does not have booking marking, the payment reference is: {$transaction->payment_reference}"); + } + } + + + + $end = new Carbon(); + $elapsedTime = $start->diff($end)->format('%H:%I:%S'); + Log::info(Carbon::now() . ': End job - Expiring refunded booking. ElapsedTime: ' . $elapsedTime . '.'); + } +} diff --git a/app/Console/Commands/V2/AutoFillPurchaseOrderV2Command.php b/app/Console/Commands/V2/AutoFillPurchaseOrderV2Command.php new file mode 100644 index 00000000..a6f83a32 --- /dev/null +++ b/app/Console/Commands/V2/AutoFillPurchaseOrderV2Command.php @@ -0,0 +1,34 @@ +command('new-user-registration-expire-check-command') ->dailyAt('23:55') ->withoutOverlapping(); + + $schedule->command('booking-expired-command') + ->dailyAt('02:00') + ->withoutOverlapping(); + + // $schedule->command('purchase-order-autofill-command') + // ->dailyAt('03:00') + // ->withoutOverlapping(); } //Commands Version 1: Before Laravel Vapor/AWS else{ @@ -68,13 +76,11 @@ class Kernel extends ConsoleKernel ->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log') ->withoutOverlapping(); - //cief todo: command version 2 $schedule->command('booking:expired') ->dailyAt('02:00') ->appendOutputTo(storage_path().'/logs/expire-booking.log') ->withoutOverlapping(); - //cief todo: command version 2 // $schedule->command('purchaseOrder:autoFill') // ->dailyAt('03:00') // ->withoutOverlapping(); diff --git a/resources/assets/vue/vuex/modules/crudRequest.js b/resources/assets/vue/vuex/modules/crudRequest.js index cea9f12d..6f1b6ee0 100644 --- a/resources/assets/vue/vuex/modules/crudRequest.js +++ b/resources/assets/vue/vuex/modules/crudRequest.js @@ -1,8 +1,8 @@ export default { actions: { crudRequest({getters, dispatch}, {endpoint, method, parameters}){ - console.log(endpoint); - console.log(window.LARAVEL_VAPOR_ENABLED); + // console.log(endpoint); + // console.log(window.LARAVEL_VAPOR_ENABLED); return dispatch('ensureReCaptchaIsSet').then(function () { let combinedAbsoluteUrl = endpoint; if(window.LARAVEL_VAPOR_ENABLED){ diff --git a/routes/api.php b/routes/api.php index 460bd772..9d67e62c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -60,15 +60,13 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/wallet.php'; require __DIR__ . '/voucher.php'; - + require __DIR__ . '/accounting.php'; require __DIR__ . '/reward.php'; require __DIR__ . '/milestone.php'; - // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed - require __DIR__ . '/job.php'; // require __DIR__ . '/rate.php';