diff --git a/app/Classes/General/Eloquent/Filters/AnswerLikeWithUserId.php b/app/Classes/General/Eloquent/Filters/AnswerLikeWithUserId.php new file mode 100644 index 00000000..041f2f5e --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/AnswerLikeWithUserId.php @@ -0,0 +1,45 @@ +where(function ($query) use ($searchText) { + $query->where('answer', 'like', '%' . $searchText . '%') + ->orWhereHas('answer', function ($subquery) use ($searchText) { + $subquery->where('display_text', 'like', '%' . $searchText . '%'); + }); + }) + ->where('user_id', $userId); + } + else if($searchText){ + return $builder->where(function ($query) use ($searchText) { + $query->where('answer', 'like', '%' . $searchText . '%') + ->orWhereHas('answer', function ($subquery) use ($searchText) { + $subquery->where('display_text', 'like', '%' . $searchText . '%'); + }); + }); + } + else{ + return $builder->where('user_id', $userId); + } + + // return $builder->where('answer', 'like', '%' . $value . '%') + // ->orWhereHas('answer', function ($subquery) use($value){ + // $subquery->where('display_text', 'like', '%' . $value . '%'); + // }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/EndDate.php b/app/Classes/General/Eloquent/Filters/EndDate.php new file mode 100644 index 00000000..b6fb0d43 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/EndDate.php @@ -0,0 +1,20 @@ +whereDate('created_at', '<=', Carbon::parse($value)->format('Y-m-d')); + } +} diff --git a/app/Classes/General/Eloquent/Filters/HasQuestionnaire.php b/app/Classes/General/Eloquent/Filters/HasQuestionnaire.php new file mode 100644 index 00000000..ae4e6787 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasQuestionnaire.php @@ -0,0 +1,24 @@ +whereHas('question', function ($subquery) use($value){ + $subquery->whereHas('questionnaire', function ($subsubquery) use($value){ + $subsubquery->where('id', $value); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/IdAfter.php b/app/Classes/General/Eloquent/Filters/IdAfter.php new file mode 100644 index 00000000..3273a1a3 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IdAfter.php @@ -0,0 +1,37 @@ +', $id) + ->where('reference', $reference) + ->whereIn('answer', $questionGroups) + ->orderBy('id', 'asc') + ->limit(1) + ->value('id'); + + if ($nextId) { + return $builder->where('id', '>', $id) + ->where('id', '<', $nextId)->withTrashed(); + } + + return $builder->where('id', '>', $id)->withTrashed(); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/IsAdminFilter.php b/app/Classes/General/Eloquent/Filters/IsAdminFilter.php new file mode 100644 index 00000000..2cc18c03 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsAdminFilter.php @@ -0,0 +1,20 @@ +where('is_admin_filter', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/IsPrevious.php b/app/Classes/General/Eloquent/Filters/IsPrevious.php new file mode 100644 index 00000000..feeb8a0a --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsPrevious.php @@ -0,0 +1,21 @@ +where('is_previous', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/QuestionGroupIn.php b/app/Classes/General/Eloquent/Filters/QuestionGroupIn.php new file mode 100644 index 00000000..bc955ad8 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/QuestionGroupIn.php @@ -0,0 +1,21 @@ +whereHas('question', function ($query) use ($value) { + $query->whereIn('group', $value); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/QuestionId.php b/app/Classes/General/Eloquent/Filters/QuestionId.php new file mode 100644 index 00000000..9c78f51a --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/QuestionId.php @@ -0,0 +1,20 @@ +where('question_id', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/QuestionIn.php b/app/Classes/General/Eloquent/Filters/QuestionIn.php new file mode 100644 index 00000000..ad1911fb --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/QuestionIn.php @@ -0,0 +1,21 @@ +whereHas('question', function ($query) use ($value) { + $query->whereIn('question_number', $value); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/QuestionNumber.php b/app/Classes/General/Eloquent/Filters/QuestionNumber.php new file mode 100644 index 00000000..02d67343 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/QuestionNumber.php @@ -0,0 +1,20 @@ +where('question_number', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/QuestionnaireSetId.php b/app/Classes/General/Eloquent/Filters/QuestionnaireSetId.php new file mode 100644 index 00000000..aa9efe19 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/QuestionnaireSetId.php @@ -0,0 +1,20 @@ +where('questionnaire_set_id', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/StartDate.php b/app/Classes/General/Eloquent/Filters/StartDate.php new file mode 100644 index 00000000..ce2281b8 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/StartDate.php @@ -0,0 +1,20 @@ +whereDate('created_at', '>=', Carbon::parse($value)->format('Y-m-d')); + } +} diff --git a/app/Classes/General/Eloquent/Filters/WithAnswers.php b/app/Classes/General/Eloquent/Filters/WithAnswers.php new file mode 100644 index 00000000..1cce3d2a --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/WithAnswers.php @@ -0,0 +1,21 @@ +where(function ($query) use($value){ + $query->whereIn('answer', $value); + }); + } +} diff --git a/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php index d102a763..9033c594 100644 --- a/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php +++ b/app/Classes/Modules/Banks/Standards/Rules/CanUpdateBankMetadata.php @@ -30,13 +30,10 @@ class CanUpdateBankMetadata extends AbstractRule */ protected function authorized($object): bool { - //cief todo: 66 - temporary workaround // if (!Auth::user()->can('update bank_metadata')) { // return false; // } - // return true; - if (in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)) { return true; } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php index f7d1d775..57406e1f 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php @@ -4,15 +4,8 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Classes\Modules\Bookings\Processors\ApprovePurchaseOrderProcessor; use App\Classes\Modules\Bookings\Services\FetchesBooking; -use App\Classes\Modules\Documents\Services\ApprovesDocument; -use App\Classes\Modules\Documents\Services\FetchesDocument; -use App\Classes\Modules\Documents\Services\RejectsDocument; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; -use App\Classes\Modules\Transactions\Services\FetchesTransaction; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\TransactionType; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -32,23 +25,18 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic /** @var FetchesBooking */ private $fetchesBooking; - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - - /** @var CreateInvoiceTransactionProcessor */ - private $createInvoiceTransactionProcessor; + /** @var ApprovePurchaseOrderProcessor */ + private $approvePurchaseOrderProcessor; /** * ApprovePurchaseOrderLogic constructor. * @param FetchesBooking $fetchesBooking - * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param ApprovePurchaseOrderProcessor $approvePurchaseOrderProcessor */ - public function __construct(FetchesBooking $fetchesBooking, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor) + public function __construct(ApprovePurchaseOrderProcessor $approvePurchaseOrderProcessor, FetchesBooking $fetchesBooking) { + $this->approvePurchaseOrderProcessor = $approvePurchaseOrderProcessor; $this->fetchesBooking = $fetchesBooking; - $this->updatesTransactionStatus = $updatesTransactionStatus; - $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; } /** @@ -58,18 +46,10 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); - $purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); - - $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->where('id', '!=', $purchaseOrder->id)->delete(); - - $this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED); - - $this->createInvoiceTransactionProcessor->execute($booking); + $this->approvePurchaseOrderProcessor->execute($booking); return $this->response([]); } - -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index 478c71a4..48f1fd21 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -5,31 +5,11 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding; -use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; -use App\Classes\Modules\Companies\Services\FetchesCompanyPaymentAttemptLimit; -use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\Services\CreatesTransaction; -use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; -use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance; -use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; -use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; -use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; -use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor; -use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\PaymentMethodType; -use App\Classes\ValueObjects\Constants\TransactionType; use App\Http\Resources\TransactionResource; use App\Models\Booking; -use App\Models\Transaction; -use App\Models\Wallet; -use Carbon\Carbon; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Log; +use App\Classes\Modules\Bookings\Processors\CreateBookingPaymentProcessor; class CreateBookingPaymentLogic extends AbstractControllerLogic { @@ -44,71 +24,18 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic ]; } - /** @var FetchesBookingQuotation */ - private $fetchBookingQuotation; + /** @var CreateBookingPaymentProcessor */ + private $createBookingPaymentProcessor; - /** @var FetchesCompanyPaymentAttemptLimit */ - private $fetchesCompanyPaymentAttemptLimit; - /** @var GeneratesTransactionBillNumber */ - private $generatesTransactionBillNumber; - - /** @var CreatesTransaction */ - private $createsTransaction; - - /** @var CalculatesBookingOutstanding */ - private $calculatesBookingOutstanding; - - /** @var CreatesBillplzBill */ - private $createsBillplzBill; - - /** @var UpdatesWalletBalance */ - private $updatesWalletBalance; - - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - - /** @var CreateCashBackTransactionProcessor */ - private $createCashBackTransactionProcessor; - - /** @var RecalculatesWalletBalance */ - private $recalculatesWalletBalance; - - /** @var BookingToVoucherifyProcessor */ - private $bookingToVoucherifyProcessor; - - /** @var CalculatesBookingRefundAmount */ - private $calculatesBookingRefundAmount; /** * CreateBookingPaymentLogic constructor. - * @param FetchesBookingQuotation $fetchBookingQuotation - * @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit - * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber - * @param CreatesTransaction $createsTransaction - * @param CalculatesBookingOutstanding $calculatesBookingOutstanding - * @param CreatesBillplzBill $createsBillplzBill - * @param UpdatesWalletBalance $updatesWalletBalance - * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor - * @param RecalculatesWalletBalance $recalculatesWalletBalance - * @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor - * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount + * @param CreateBookingPaymentProcessor $createBookingPaymentProcessor */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) + public function __construct(CreateBookingPaymentProcessor $createBookingPaymentProcessor) { - $this->fetchBookingQuotation = $fetchBookingQuotation; - $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; - $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; - $this->createsTransaction = $createsTransaction; - $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; - $this->createsBillplzBill = $createsBillplzBill; - $this->updatesWalletBalance = $updatesWalletBalance; - $this->updatesTransactionStatus = $updatesTransactionStatus; - $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; - $this->recalculatesWalletBalance = $recalculatesWalletBalance; - $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; - $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->createBookingPaymentProcessor = $createBookingPaymentProcessor; } /** @@ -122,61 +49,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $booking = Booking::find($request->route('id')); - $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); - - $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); - - if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); - - $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject, $voucherCode, null, $booking); - - $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); - - $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); - - $paymentReference = null; - - $amount = $configurations->getTotal(); - - if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){ - $billPlzBill = $this->createsBillplzBill->execute($booking->company->name, $request->user()->email, 'This payment is made for transfer ref. '.$booking->marking, $configurations->getTotal(), $billNumber, $request->input('bank_code')); - $paymentReference = $billPlzBill->id; - } - - if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ - /** @var Wallet $wallet */ - $wallet = $booking->company->wallets()->first(); - - if((float) number_format(($wallet->amount - $amount),2) < 0){ - throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.'); - } - - $transaction_object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], ''); - $transaction = $this->createsTransaction->execute($wallet, $transaction_object); - - $paymentReference = $billNumber; - - $walletBalance = $this->recalculatesWalletBalance->execute($wallet); - $this->updatesWalletBalance->execute($wallet, $walletBalance); - } - - $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); - - $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, - $configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(), - $configurations->getTotal(), $configurations->getForeignTotal(), 1, - $configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(), - $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], $paymentReference); - - /** @var Transaction $transaction */ - $transaction = $this->createsTransaction->execute($booking, $object); -// $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction); - - $this->bookingToVoucherifyProcessor->execute($booking->company->employees()->first(), $transaction, $booking->company->id, $configurations->getSubTotal(), $configurations->getServiceCharge(), $configurations->getVoucherDiscountAmount(), $voucherCode); - - if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ - $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); - } + $transaction = $this->createBookingPaymentProcessor->execute($booking, $request->input('amount'), $request->input('payment_method'), $voucherCode, $request->input('bank_code'), $request->user()->email); return $this->resourceResponse(new TransactionResource($transaction)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php index d1f2286e..711ae1cb 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php @@ -19,7 +19,7 @@ class FetchBookingLogic extends AbstractControllerLogic protected function notification():array { return [ 'title' => 'Retrieved Booking', - 'message' => 'You have successfully retrieved a Address' + 'message' => 'You have successfully retrieved a Booking' ]; } @@ -58,4 +58,4 @@ class FetchBookingLogic extends AbstractControllerLogic } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php index e40a947d..b75b0d11 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php @@ -1,31 +1,20 @@ canUpdateBooking = $canUpdateBooking; - $this->updatesBookingFixedAmount = $updatesBookingFixedAmount; $this->fetchesBooking = $fetchesBooking; - $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; - $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->updateBookingAmountProcessor = $updateBookingAmountProcessor; } /** @@ -76,25 +55,11 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic public function logic(Request $request) : JsonResponse { $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + $fixAmount = floatval(str_replace(',', '', $request->input('fix_amount', $booking->fix_amount))); - $input_amount = number_format( floatval(str_replace(',', '', $request->input('fix_amount', $booking->fix_amount))), 5, '.', ''); - - $minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking); - - if (((float)$input_amount + 0.01) < (float)$minimum_amount) { - throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.'); - } - - $poTransaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); - $booking->transactions()->where('type', TransactionType::PROFORMA)->delete(); - - if($poTransaction) { - $this->updatesTransactionStatus->execute($poTransaction, ApprovalStatus::PENDING_SUBMISSION); - } - - $booking = $this->updatesBookingFixedAmount->execute($booking, $input_amount); + $this->updateBookingAmountProcessor->execute($booking, $fixAmount); return $this->resourceResponse(new BookingResource($booking)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php index ef6124cf..ab183a1f 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php @@ -4,25 +4,8 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Bookings\Processors\CreatePurchaseOrderFor1688OrderProcessor; +use App\Classes\Modules\Bookings\Processors\UploadPurchaseOrderProcessor; use App\Classes\Modules\Bookings\Services\FetchesBooking; -use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; -use App\Classes\Modules\Documents\Services\ApprovesDocument; -use App\Classes\Modules\Documents\Services\CreatesDocument; -use App\Classes\Modules\Documents\Services\CreatesFiles; -use App\Classes\Modules\Documents\Services\FetchesDocument; -use App\Classes\Modules\Documents\Services\RejectsDocument; -use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; -use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor; -use App\Classes\Modules\Transactions\Services\FetchesTransaction; -use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\DocumentType; -use App\Classes\ValueObjects\Constants\PaymentMethodType; -use App\Classes\ValueObjects\Constants\TransactionType; -use App\Models\Document; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -42,29 +25,19 @@ class UploadPurchaseOrderLogic extends AbstractControllerLogic /** @var FetchesBooking */ private $fetchesBooking; - /** @var CreatesDocument */ - private $createsDocument; - - /** @var CreatesFiles */ - private $createsFile; - - /** @var CreatePurchaseOrderFor1688OrderProcessor */ - private $createPurchaseOrderFor1688OrderProcessor; + /** @var UploadPurchaseOrderProcessor */ + private $uploadPurchaseOrderProcessor; /** * UploadPurchaseOrderLogic constructor. * @param FetchesBooking $fetchesBooking - * @param CreatesDocument $createsDocument - * @param CreatesFiles $createsFile - * @param CreatePurchaseOrderFor1688OrderProcessor $createPurchaseOrderFor1688OrderProcessor + * @param UploadPurchaseOrderProcessor $uploadPurchaseOrderProcessor */ - public function __construct(FetchesBooking $fetchesBooking, CreatesDocument $createsDocument, CreatesFiles $createsFile, CreatePurchaseOrderFor1688OrderProcessor $createPurchaseOrderFor1688OrderProcessor) + public function __construct(FetchesBooking $fetchesBooking, UploadPurchaseOrderProcessor $uploadPurchaseOrderProcessor) { $this->fetchesBooking = $fetchesBooking; - $this->createsDocument = $createsDocument; - $this->createsFile = $createsFile; - $this->createPurchaseOrderFor1688OrderProcessor = $createPurchaseOrderFor1688OrderProcessor; + $this->uploadPurchaseOrderProcessor = $uploadPurchaseOrderProcessor; } /** @@ -74,19 +47,8 @@ class UploadPurchaseOrderLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); - - $object = new DocumentObject(DocumentType::ECOMMERCE_PURCHASE_ORDER, $request->input('files'), '', ApprovalStatus::APPROVED, '1688_purchase_orders'); - - /** @var Document $document */ - $document = $this->createsDocument->execute($booking, $object); - - $this->createsFile->execute($document, $object); - - if(!in_array($booking->company->id, [199, 510])){ - $this->createPurchaseOrderFor1688OrderProcessor->execute($booking); - } + $this->uploadPurchaseOrderProcessor->execute($booking, $request->input('files')); return $this->response([]); } diff --git a/app/Classes/Modules/Bookings/Processors/ApprovePurchaseOrderProcessor.php b/app/Classes/Modules/Bookings/Processors/ApprovePurchaseOrderProcessor.php new file mode 100644 index 00000000..e5021c06 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/ApprovePurchaseOrderProcessor.php @@ -0,0 +1,53 @@ +fetchesBooking = $fetchesBooking; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; + } + + /** + * @param Booking $booking + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking) { + + $purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->where('id', '!=', $purchaseOrder->id)->delete(); + + $this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED); + + $this->createInvoiceTransactionProcessor->execute($booking); + } +} diff --git a/app/Classes/Modules/Bookings/Processors/CreateBookingPaymentProcessor.php b/app/Classes/Modules/Bookings/Processors/CreateBookingPaymentProcessor.php new file mode 100644 index 00000000..ec1233ee --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/CreateBookingPaymentProcessor.php @@ -0,0 +1,174 @@ +fetchBookingQuotation = $fetchBookingQuotation; + $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->createsBillplzBill = $createsBillplzBill; + $this->updatesWalletBalance = $updatesWalletBalance; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; + $this->recalculatesWalletBalance = $recalculatesWalletBalance; + $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + } + + /** + * Process booking payment. + * + * @param Booking $booking + * @param float $amount + * @param string $paymentMethod + * @param string|null $voucherCode + * @param string|null $bankCode + * @param string $email + * @return Transaction + * @throws MalformedRequestException + */ + public function execute(Booking $booking, string $amount, string $paymentMethod, ?string $voucherCode, ?string $bankCode, string $email, bool $checkSysRecordedOutstanding = true) + { + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $amount)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$paymentMethod]); + + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); + + if($checkSysRecordedOutstanding){ + if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); + } + + $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject, $voucherCode); + + $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + $paymentReference = null; + + $amount = $configurations->getTotal(); + + if(PaymentMethodType::PAYMENT_METHODS[$paymentMethod] == PaymentMethodType::PAYMENT_GATEWAY){ + $billPlzBill = $this->createsBillplzBill->execute($booking->company->name, $email, 'This payment is made for transfer ref. '.$booking->marking, $configurations->getTotal(), $billNumber, $bankCode); + $paymentReference = $billPlzBill->id; + } + + if(PaymentMethodType::PAYMENT_METHODS[$paymentMethod] == PaymentMethodType::WALLET){ + /** @var Wallet $wallet */ + $wallet = $booking->company->wallets()->first(); + + if((float) number_format(($wallet->amount - $amount), 2) < 0){ + throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.'); + } + + $transaction_object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], ''); + $transaction = $this->createsTransaction->execute($wallet, $transaction_object); + + $paymentReference = $billNumber; + + $walletBalance = $this->recalculatesWalletBalance->execute($wallet); + $this->updatesWalletBalance->execute($wallet, $walletBalance); + } + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, + $configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(), + $configurations->getTotal(), $configurations->getForeignTotal(), 1, + $configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(), + $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], $paymentReference); + + /** @var Transaction $transaction */ + $transaction = $this->createsTransaction->execute($booking, $object); +// $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction); + + $this->bookingToVoucherifyProcessor->execute($booking->company->employees()->first(), $transaction, $booking->company->id, $configurations->getSubTotal(), $configurations->getVoucherDiscountAmount(), $voucherCode); + + if(PaymentMethodType::PAYMENT_METHODS[$paymentMethod] == PaymentMethodType::WALLET){ + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); + } + + return $transaction; + } +} diff --git a/app/Classes/Modules/Bookings/Processors/UpdateBookingAmountProcessor.php b/app/Classes/Modules/Bookings/Processors/UpdateBookingAmountProcessor.php new file mode 100644 index 00000000..57b2531d --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/UpdateBookingAmountProcessor.php @@ -0,0 +1,65 @@ +updatesBookingFixedAmount = $updatesBookingFixedAmount; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Booking $booking + * @return Booking $booking + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking, float $fixAmount) + { + $input_amount = number_format($fixAmount, 5, '.', ''); + + $minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking); + + if (((float)$input_amount + 0.01) < (float)$minimum_amount) { + throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.'); + } + + $poTransaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + $booking->transactions()->where('type', TransactionType::PROFORMA)->delete(); + + if($poTransaction) { + $this->updatesTransactionStatus->execute($poTransaction, ApprovalStatus::PENDING_SUBMISSION); + } + + $booking = $this->updatesBookingFixedAmount->execute($booking, $input_amount); + + return $booking; + } + +} diff --git a/app/Classes/Modules/Bookings/Processors/UploadPurchaseOrderProcessor.php b/app/Classes/Modules/Bookings/Processors/UploadPurchaseOrderProcessor.php new file mode 100644 index 00000000..85203e86 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/UploadPurchaseOrderProcessor.php @@ -0,0 +1,60 @@ +createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->createPurchaseOrderFor1688OrderProcessor = $createPurchaseOrderFor1688OrderProcessor; + } + + /** + * @param Booking $booking + * @param array $files + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking, array $files) + { + $object = new DocumentObject(DocumentType::ECOMMERCE_PURCHASE_ORDER, $files, '', ApprovalStatus::APPROVED, '1688_purchase_orders'); + + /** @var Document $document */ + $document = $this->createsDocument->execute($booking, $object); + + $this->createsFile->execute($document, $object); + + if(!in_array($booking->company->id, [199, 510])){ + $this->createPurchaseOrderFor1688OrderProcessor->execute($booking); + } + } + +} diff --git a/app/Classes/Modules/Documents/Processors/UploadDocumentProcessor.php b/app/Classes/Modules/Documents/Processors/UploadDocumentProcessor.php new file mode 100644 index 00000000..d6cd77e7 --- /dev/null +++ b/app/Classes/Modules/Documents/Processors/UploadDocumentProcessor.php @@ -0,0 +1,51 @@ +createsDocument = $createsDocument; + $this->createsFiles = $createsFiles; + } + + + /** + * @param QAUserAnswerSelected qaUserAnswerSelected + * @param array $filesUpload + * @param string $path + * @param string $documentType + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(QAUserAnswerSelected $qaUserAnswerSelected, $filesUpload, string $path, string $documentType = DocumentType::ADMIN_WORK_FLOW) { + $object = new DocumentObject($documentType, $filesUpload, '', ApprovalStatus::PENDING_VERIFICATION, $path); + + /** @var Document $document */ + $document = $this->createsDocument->execute($qaUserAnswerSelected, $object); + + $result = $this->createsFiles->execute($document, $object); + return $result; + } +} diff --git a/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php new file mode 100644 index 00000000..1f8d0ffb --- /dev/null +++ b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithGroupsLogic.php @@ -0,0 +1,64 @@ + 'Export Questions & Answers', + 'message' => 'You have successfully exported data' + ]; + } + + /** @var ExportsQAWithGroups */ + private $exportsQAWithGroups; + + /** @var CanExportQuestionsAnswers */ + private $canExport; + + /** + * ExportQAWithGroupsLogic constructor. + * @param ExportsQAWithGroups $exportsQAWithGroups + * @param CanExportQuestionsAnswers $canExport + */ + public function __construct(ExportsQAWithGroups $exportsQAWithGroups, CanExportQuestionsAnswers $canExport) + { + $this->exportsQAWithGroups = $exportsQAWithGroups; + $this->canExport = $canExport; + } + + + /** + * @param Request $request + * @return Response + */ + public function logic(Request $request) : JsonResponse + { + $this->canExport->passes(); + + $this->exportsQAWithGroups->setFilters(Helper::deserializeFilters($request->input('filters'))); + + $exportFileName = 'qas.xls'; + $filesystemDriver = Storage::getDefaultDriver(); + if($filesystemDriver === 's3'){ + return $this->response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $this->exportsQAWithGroups) ]); + } + + return $this->response([ 'src' => null ]); + } + +} diff --git a/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php new file mode 100644 index 00000000..b67f1098 --- /dev/null +++ b/app/Classes/Modules/Exports/ControllersLogic/ExportQAWithoutGroupsLogic.php @@ -0,0 +1,64 @@ + 'Export Questions & Answers', + 'message' => 'You have successfully exported data' + ]; + } + + /** @var ExportsQAWithoutGroups */ + private $exportsQAWithoutGroups; + + /** @var CanExportQuestionsAnswers */ + private $canExport; + + /** + * ExportQAWithoutGroupsLogic constructor. + * @param ExportsQAWithoutGroups $exportsQAWithoutGroups + * @param CanExportQuestionsAnswers $canExport + */ + public function __construct(ExportsQAWithoutGroups $exportsQAWithoutGroups, CanExportQuestionsAnswers $canExport) + { + $this->exportsQAWithoutGroups = $exportsQAWithoutGroups; + $this->canExport = $canExport; + } + + + /** + * @param Request $request + * @return Response + */ + public function logic(Request $request) : JsonResponse + { + $this->canExport->passes(); + + $this->exportsQAWithoutGroups->setFilters(Helper::deserializeFilters($request->input('filters'))); + + $exportFileName = 'qas.xls'; + $filesystemDriver = Storage::getDefaultDriver(); + if($filesystemDriver === 's3'){ + return $this->response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $this->exportsQAWithoutGroups) ]); + } + + return $this->response([ 'src' => null ]); + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php b/app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php new file mode 100644 index 00000000..90efd5b8 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsQAWithGroups.php @@ -0,0 +1,137 @@ +filters = $filters; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $data = (new ApplyFiltersToQuery())->execute(QAUserAnswerSelected::query(), $this->filters, true); + + return $data; + } + + /** + * @param QAUserAnswerSelected $userAnswer + * + * @return array + */ + public function map($userAnswer): array + { + $source = $userAnswer->userSource; + $user = $userAnswer->source_id === 0 ? $userAnswer->user : null; + $answer = $userAnswer->answer()->first(); + $answerValue = $answer ? $answer->value : null; + if($userAnswer->is_previous === 1){ + $answerValue ='go_back'; + } + $questionGroups = explode(',', $userAnswer->question->questionnaire->group); + $metadata = json_decode($userAnswer->question_metadata); + $rows = [[ + $userAnswer->id, + $userAnswer->question->questionnaire->version, + $userAnswer->question->questionnaire->description, + $userAnswer->question->question_title, + $answer ? $answer->display_text : null, + $answerValue, + $user ? $user->email : $source->email, + $userAnswer->time_used_seconds, + $metadata->marking ?? null, + isset($metadata->company) ? $metadata->company->reference: null, + isset($metadata->payment_history[0]) ? $metadata->payment_history[0]->currency_rate : null, + isset($metadata->payment_history[0]) ? $metadata->payment_history[0]->currency->short_code . " " . round($metadata->payment_history[0]->amount, 2): null, + Carbon::parse($userAnswer->created_at)->format('d-m-Y h:i:s A'), + "YES" + ]]; + + $nextId = QAUserAnswerSelected::where('id', '>', $userAnswer->id) + ->where('reference', $userAnswer->reference) + ->whereIn('answer', $questionGroups) + ->orderBy('id', 'asc') + ->limit(1) + ->value('id'); + + if ($nextId) { + $temp = QAUserAnswerSelected::where('reference', '=', $userAnswer->reference)->where('id', '>', $userAnswer->id) + ->where('id', '<', $nextId)->withTrashed()->get(); + } + else{ + $temp = QAUserAnswerSelected::where('reference', '=', $userAnswer->reference)->where('id', '>', $userAnswer->id)->withTrashed()->get(); + } + + foreach ($temp as $relatedAnswer) { + $source = $relatedAnswer->userSource; + $user = $relatedAnswer->source_id === 0 ? $relatedAnswer->user : null; + $answer = $relatedAnswer->answer()->first(); + $answerValue = $answer ? $answer->value : null; + if($relatedAnswer->is_previous === 1){ + $answerValue ='go_back'; + } + $md = json_decode($relatedAnswer->question_metadata); + + $rows[] = [ + $relatedAnswer->id, + $relatedAnswer->question->questionnaire->version, + $relatedAnswer->question->questionnaire->description, + $relatedAnswer->question->question_title, + $answer ? $answer->display_text : null, + $answerValue, + $user ? $user->email : $source->email, + $relatedAnswer->time_used_seconds, + $md->marking ?? null, + isset($md->company) ? $md->company->reference: null, + isset($md->payment_history[0]) ? $md->payment_history[0]->currency_rate : null, + isset($md->payment_history[0]) ? $md->payment_history[0]->currency->short_code . " " . round($md->payment_history[0]->amount, 2): null, + Carbon::parse($userAnswer->created_at)->format('d-m-Y h:i:s A'), + ]; + } + + return $rows; + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php b/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php new file mode 100644 index 00000000..a35845cc --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsQAWithoutGroups.php @@ -0,0 +1,93 @@ +filters = $filters; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $data = (new ApplyFiltersToQuery())->execute(QAUserAnswerSelected::query()->withTrashed(), $this->filters, true); + + return $data; + } + + /** + * @param QAUserAnswerSelected $userAnswer + * + * @return array + */ + public function map($userAnswer): array + { + $source = $userAnswer->userSource; + $user = $userAnswer->source_id === 0 ? $userAnswer->user : null; + $answer = $userAnswer->answer()->first(); + $answerValue = $answer ? $answer->value : null; + if($userAnswer->is_previous === 1){ + $answerValue ='go_back'; + } + $questionGroups = explode(',', $userAnswer->question->questionnaire->group); + $metadata = json_decode($userAnswer->question_metadata); + $rows = [[ + $userAnswer->id, + $userAnswer->question->questionnaire->version, + $userAnswer->question->questionnaire->description, + $userAnswer->question->question_title, + $answer ? $answer->display_text : null, + $answerValue, + $user ? $user->email : $source->email, + $userAnswer->time_used_seconds, + $metadata->marking ?? null, + isset($metadata->company) ? $metadata->company->reference: null, + isset($metadata->payment_history[0]) ? $metadata->payment_history[0]->currency_rate : null, + isset($metadata->payment_history[0]) ? $metadata->payment_history[0]->currency->short_code . " " . round($metadata->payment_history[0]->amount, 2): null, + Carbon::parse($userAnswer->created_at)->format('d-m-Y h:i:s A'), + $answer ? in_array($answer->value, $questionGroups) : false, + ]]; + + return $rows; + } +} diff --git a/app/Classes/Modules/Exports/Standards/Rules/CanExportQuestionsAnswers.php b/app/Classes/Modules/Exports/Standards/Rules/CanExportQuestionsAnswers.php new file mode 100644 index 00000000..5072a6b3 --- /dev/null +++ b/app/Classes/Modules/Exports/Standards/Rules/CanExportQuestionsAnswers.php @@ -0,0 +1,48 @@ +user()){ + $roleToCheck = Auth()->user()->type; + if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) { + return true; + } + else { + return false; + } + } + return false; + } + + /** + * @param $object + * @return bool + */ + protected function validators($object): bool + { + return true; + } + + + /** + * @param $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWF1688BookingLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWF1688BookingLogic.php new file mode 100644 index 00000000..205b6dbe --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWF1688BookingLogic.php @@ -0,0 +1,111 @@ + 'Retrieved Booking for Admin Workflow ', + 'message' => 'You have successfully retrieved a Booking for Admin Workflow' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** + * FetchAdminWFBookingLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param FetchesBooking $fetchesBooking + */ + public function __construct(CanFetchQuestion $canFetchQuestion, FetchesBooking $fetchesBooking) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->fetchesBooking = $fetchesBooking; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchQuestion->passes(); + + $excludedBookingIds = KeyValuePair::where('owner_type', 'App\Models\Booking') + ->where(function ($query) { + $query->where('key', '1688_admin_workflow_processed') + ->orWhere(function ($query) { + $query->where('key', '1688_admin_workflow_processing') + ->where('updated_at', '>', Carbon::now()->subHour()); + }); + }) + ->pluck('owner_id') + ->filter(function ($value) { + return is_numeric($value); + }) + ->toArray(); + + + $timeAgo = Carbon::now()->subMonths(6); + $serviceId = 4; + $booking = Booking::where('service_id', $serviceId) + ->where('status', ApprovalStatus::APPROVED) + ->whereNotIn('id', $excludedBookingIds) + ->whereHas('bills', function ($query) { + $query->whereHas('groupTransaction', function ($query) { + $query->whereHas('group', function ($query) { + $query->whereDoesntHave('billGroup')->whereIn('issuer', [2]); + }); + }); + }) + ->where('created_at', '>=', $timeAgo) + ->latest() + ->first(); + + if(!$booking){ + return responseJson(null, 'No booking found', 404); + } + + $booking = $this->fetchesBooking->execute(['id' => $booking->id, 'with_transactions' => true, 'order_by_id_desc' => true]); + + markedProcessing($booking, '1688_admin_workflow_processing'); + + // return responseJson([ + // 'passwords' => $booking->bank->holder_name ?? null, + // 'account_no' => $booking->bank->account_no ?? null, + // 'pin' => $booking->bank->bank_branch ?? null, + // 'holder_name' => $booking->bank->holder_name ?? null, + // 'booking' => $booking + // ]); + + // return responseJson([ + // 'booking' => new BookingBaseResource($booking) + // ]); + + return $this->resourceResponse(new BookingBaseResource($booking)); + } +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFModelAttributesLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFModelAttributesLogic.php new file mode 100644 index 00000000..ed7151e0 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFModelAttributesLogic.php @@ -0,0 +1,82 @@ + 'Retrieved Model Attributes for Admin Workflow ', + 'message' => 'You have successfully retrieved Model Attributes for Admin Workflow' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** + * FetchAdminWFModelAttributesLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param FetchesBooking $fetchesBooking + */ + public function __construct(CanFetchQuestion $canFetchQuestion, FetchesBooking $fetchesBooking) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->fetchesBooking = $fetchesBooking; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchQuestion->passes(); + + // $booking = Booking::find($request->route('booking_id')); + $booking = $this->fetchesBooking->execute(['id' => $request->route('booking_id'), 'with_transactions' => true, 'order_by_id_desc' => true]); + + if (!$booking) { + return responseJson(null, 'No booking found', 404); + } + + $attributes = $booking->modelAttributes() + ->where('name', BookingAttributeNames::ORDER_REFERENCE_NO) + ->get(['id', 'value']) + ->map(fn ($attr) => $attr->only(['id', 'value'])); + + $transaction = $booking->bills()->first(); //cief todo: 74 - more than 1 record? + // return responseJson([ + // 'booking' => $booking, + // 'booking_attributes' => $attributes, + // 'reference' =>$transaction->owner->owner->marking, + // 'marking' => $transaction->owner->owner->company->reference, + // 'currency_rate' => $transaction->currency_rate, + // 'total_amount' =>$transaction->currency->short_code . ' ' . number_format((float)$transaction->amount, 2, '.', '') + // ]); + + return $this->resourceResponse(new BookingBaseResource($booking)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingApprovalPOLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingApprovalPOLogic.php new file mode 100644 index 00000000..7006bdc0 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingApprovalPOLogic.php @@ -0,0 +1,99 @@ + 'Retrieved Pending Approval PO for Admin Workflow ', + 'message' => 'You have successfully retrieved Pending Approval PO for Admin Workflow' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** + * FetchAdminWFPendingApprovalPOLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param FetchesBooking $fetchesBooking + */ + public function __construct(CanFetchQuestion $canFetchQuestion, FetchesBooking $fetchesBooking) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->fetchesBooking = $fetchesBooking; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchQuestion->passes(); + + $excludedBookingIds = KeyValuePair::where('owner_type', 'App\Models\Booking') + ->where(function ($query) { + $query->where('key', 'approve_po_admin_workflow_processed') + ->orWhere(function ($query) { + $query->where('key', 'approve_po_admin_workflow_processing') + ->where('updated_at', '>', Carbon::now()->subMinutes(30)); + }); + }) + ->pluck('owner_id') + ->filter(function ($value) { + return is_numeric($value); + }) + ->toArray(); + + // $booking = Booking::with('transactions') + // ->where('service_id', 4) + // ->where('status', ApprovalStatus::APPROVED) + // ->whereNotIn('id', $excludedBookingIds) + // ->whereHas('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER)->where('status', '<', ApprovalStatus::APPROVED)) + // ->first(); + + $booking = $this->fetchesBooking->execute(['purchase_order_approval' => true, 'status_in' => [2], 'id_not_in' => $excludedBookingIds, 'with_transactions' => true, 'order_by_id_desc' => true]); + + if(!$booking){ + return responseJson(null, 'No booking found', 404); + } + + markedProcessing($booking, 'approve_po_admin_workflow_processing'); + + // $result = new BookingBaseResource($booking); + // return responseJson([ + // 'booking' => $result, + // ]); + // return $booking ? responseJson(new BookingBaseResource($booking)) : responseJson(null, 'No booking found', 404); + + return $this->resourceResponse(new BookingBaseResource($booking)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingFillPOLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingFillPOLogic.php new file mode 100644 index 00000000..001838ce --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchAdminWFPendingFillPOLogic.php @@ -0,0 +1,96 @@ + 'Retrieved Pending Fill PO for Admin Workflow ', + 'message' => 'You have successfully retrieved Pending Fill PO for Admin Workflow' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** + * FetchAdminWFPendingFillPOLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param FetchesBooking $fetchesBooking + */ + public function __construct(CanFetchQuestion $canFetchQuestion, FetchesBooking $fetchesBooking) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->fetchesBooking = $fetchesBooking; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchQuestion->passes(); + + $excludedBookingIds = KeyValuePair::where('owner_type', 'App\Models\Booking') + ->where(function ($query) { + $query->where('key', 'fill_po_admin_workflow_processed') + ->orWhere(function ($query) { + $query->where('key', 'fill_po_admin_workflow_processing') + ->where('updated_at', '>', Carbon::now()->subHour()); + }); + }) + ->pluck('owner_id') + ->filter(function ($value) { + return is_numeric($value); + }) + ->toArray(); + + // $booking = Booking::with('transactions') + // ->where('service_id', 4) + // ->where('status', ApprovalStatus::APPROVED) + // ->whereNotIn('id', $excludedBookingIds) + // ->whereDoesntHave('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER)) + // ->first(); + + $booking = $this->fetchesBooking->execute(['pending_purchase_order' => true, 'has_payment_status_in' => [2, 3], 'id_not_in' => $excludedBookingIds, 'with_transactions' => true, 'order_by_id_desc' => true]); + + if(!$booking){ + return responseJson(null, 'No booking found', 404); + } + + markedProcessing($booking, 'fill_po_admin_workflow_processing'); + + // $result = new BookingBaseResource($booking); + // return responseJson([ + // 'booking' => $result, + // ]); + // return $booking ? responseJson(new BookingResource($booking)) : responseJson(null, 'No booking found', 404); + + return $this->resourceResponse(new BookingBaseResource($booking)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/FetchQuestionV1AdminWFLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchQuestionV1AdminWFLogic.php new file mode 100644 index 00000000..0b6bfdd8 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/FetchQuestionV1AdminWFLogic.php @@ -0,0 +1,62 @@ + 'Retrieved Admin Workflow First Question', + 'message' => 'You have successfully retrieved a Admin Workflow First Question' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var FetchFirstQuestionV1AdminWFProcessor */ + private $fetchFirstQuestionQAProcessor; + + /** + * FetchQuestionV1AdminWFLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param FetchFirstQuestionV1AdminWFProcessor $fetchFirstQuestionQAProcessor + */ + public function __construct(CanFetchQuestion $canFetchQuestion, FetchFirstQuestionV1AdminWFProcessor $fetchFirstQuestionQAProcessor) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->fetchFirstQuestionQAProcessor = $fetchFirstQuestionQAProcessor; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchQuestion->passes(); + + $userId = Auth::user()->id; + + $query = $this->fetchFirstQuestionQAProcessor->execute($request); + + return $this->resourceResponse(new QuestionResource($query, $userId)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionnaireSetLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionnaireSetLogic.php new file mode 100644 index 00000000..d8fe5667 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionnaireSetLogic.php @@ -0,0 +1,60 @@ + 'Retrieved Questionnaire Sets', + 'message' => 'You have successfully retrieved a list of questionnaire sets' + ]; + } + + /** @var CanListQuestions */ + private $canListQuestions; + + /** @var ListsQuestionnaireSet */ + private $listsQuestionnaireSet; + + /** + * ListQuestionnaireSetLogic constructor. + * @param CanListQuestions $canListQuestions + * @param ListsQuestionnaireSet $listsQuestionnaires + */ + public function __construct(CanListQuestions $canListQuestions, ListsQuestionnaireSet $listsQuestionnaireSet) + { + $this->canListQuestions = $canListQuestions; + $this->listsQuestionnaireSet = $listsQuestionnaireSet; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + // $this->canListQuestions->passes(); //cief todo: 74 + + $query = $this->listsQuestionnaireSet->execute($this->listsQuestionnaireSet->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(QuestionnaireSetsResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsAnswersLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsAnswersLogic.php new file mode 100644 index 00000000..d1912b1a --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsAnswersLogic.php @@ -0,0 +1,60 @@ + 'Retrieved Questions Answers', + 'message' => 'You have successfully retrieved a list of questions and answers' + ]; + } + + /** @var CanListQuestions */ + private $canListQuestions; + + /** @var ListsQuestionUserAnswerSelected */ + private $listsQuestionUserAnswerSelected; + + /** + * ListQuestionsAnswersLogic constructor. + * @param CanListQuestions $canListQuestions + * @param ListsQuestionUserAnswerSelected $listsQuestionUserAnswerSelected + */ + public function __construct(CanListQuestions $canListQuestions, ListsQuestionUserAnswerSelected $listsQuestionUserAnswerSelected) + { + $this->canListQuestions = $canListQuestions; + $this->listsQuestionUserAnswerSelected = $listsQuestionUserAnswerSelected; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $this->canListQuestions->passes(); + + $query = $this->listsQuestionUserAnswerSelected->execute($this->listsQuestionUserAnswerSelected->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(QuestionsAnswersResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsLogic.php new file mode 100644 index 00000000..a3d7ffa1 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/ListQuestionsLogic.php @@ -0,0 +1,70 @@ + 'Retrieved Questions', + 'message' => 'You have successfully retrieved a list of questions' + ]; + } + + /** @var CanListQuestions */ + private $canListQuestions; + + /** @var ListsQuestions */ + private $listsQuestions; + + /** + * ListQuestionsLogic constructor. + * @param CanListQuestions $canListQuestions + * @param ListsQuestions $listsQuestions + */ + public function __construct(CanListQuestions $canListQuestions, ListsQuestions $listsQuestions) + { + $this->canListQuestions = $canListQuestions; + $this->listsQuestions = $listsQuestions; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $this->canListQuestions->passes(); + $setId = 0; + if ($request->route('set_id')) { + $setId = $request->route('set_id'); + } + + if($setId === 0){ + $set = QAQuestionnaireSet::where('group', '1688,approve_po,fill_po')->latest('id')->first(); + $setId = $set->id; + } + + $query = $this->listsQuestions->execute(array_merge($this->listsQuestions->deserializeFilters($request->input('filters')), ['questionnaire_set_id' => $setId])); + + return $this->collectionResponse(QuestionResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Questionnaires/ControllersLogic/UpdateNextQuestionV1AdminWFLogic.php b/app/Classes/Modules/Questionnaires/ControllersLogic/UpdateNextQuestionV1AdminWFLogic.php new file mode 100644 index 00000000..5395a898 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/ControllersLogic/UpdateNextQuestionV1AdminWFLogic.php @@ -0,0 +1,185 @@ + 'Retrieved Admin Workflow Next Question', + 'message' => 'You have successfully retrieved a Admin Workflow Next Question' + ]; + } + + /** @var CanFetchQuestion */ + private $canFetchQuestion; + + /** @var SaveAnswerV1AdminWFProcessor */ + private $saveAnswerProcessor; + + /** @var SaveAnswerActionV1AdminWFProcessor */ + private $saveAnswerActionProcessor; + + /** @var FetchNextQuestionV1AdminWFProcessor */ + private $fetchNextQuestionV1AdminWFProcessor; + + /** @var FetchNextQuestionMetadataV1AdminWFProcessor */ + private $fetchNextQuestionMetadataProcessor; + + /** @var FetchFirstQuestionV1AdminWFProcessor */ + private $fetchFirstQuestionQAProcessor; + + /** @var ListsQuestionUserAnswerSelected */ + private $listsUserAnswerSelected; + + /** @var CreatesKeyValuePair */ + private $createsKeyValuePair; + + /** + * UpdateNextQuestionV1AdminWFLogic constructor. + * @param CanFetchQuestion $canFetchQuestion + * @param SaveAnswerV1AdminWFProcessor $saveAnswerProcessor + * @param FetchNextQuestionV1AdminWFProcessor $fetchNextQuestionV1AdminWFProcessor + * @param FetchFirstQuestionV1AdminWFProcessor $fetchFirstQuestionQAProcessor + * @param ListsQuestionUserAnswerSelected $listsUserAnswerSelected + * @param CreatesKeyValuePair $createsKeyValuePair + * @param SaveAnswerActionV1AdminWFProcessor $saveAnswerActionProcessor + * @param FetchNextQuestionMetadataV1AdminWFProcessor $fetchNextQuestionMetadataProcessor + */ + public function __construct(CanFetchQuestion $canFetchQuestion, SaveAnswerV1AdminWFProcessor $saveAnswerProcessor, FetchNextQuestionV1AdminWFProcessor $fetchNextQuestionV1AdminWFProcessor, FetchFirstQuestionV1AdminWFProcessor $fetchFirstQuestionQAProcessor, ListsQuestionUserAnswerSelected $listsUserAnswerSelected, CreatesKeyValuePair $createsKeyValuePair, SaveAnswerActionV1AdminWFProcessor $saveAnswerActionProcessor, FetchNextQuestionMetadataV1AdminWFProcessor $fetchNextQuestionMetadataProcessor) + { + $this->canFetchQuestion = $canFetchQuestion; + $this->saveAnswerProcessor = $saveAnswerProcessor; + $this->fetchNextQuestionV1AdminWFProcessor = $fetchNextQuestionV1AdminWFProcessor; + $this->fetchFirstQuestionQAProcessor = $fetchFirstQuestionQAProcessor; + $this->listsUserAnswerSelected = $listsUserAnswerSelected; + $this->createsKeyValuePair = $createsKeyValuePair; + $this->saveAnswerActionProcessor = $saveAnswerActionProcessor; + $this->fetchNextQuestionMetadataProcessor = $fetchNextQuestionMetadataProcessor; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws MalformedRequestException + * @throws ResourceNotFoundException + */ + public function logic(Request $request) : JsonResponse + { + $userId = Auth::user()->id; + $timeUsedSeconds = 0; + $reference = null; + $questionMetadata = null; + $booking = null; + $previousAnswer = null; + + $this->canFetchQuestion->passes(); + + $currentQuestion = $request->question; + $filesUpload = $request->only(['files', 'filesA', 'filesB', 'filesC']); + if ($request->has('questionContext')) { + $questionMetadata = $request->questionContext['questionMetadata'] ?? null; + $timeUsedSeconds = intval($request->questionContext['timeUsedSeconds']) ?? 0; + $reference = $request->questionContext['session_id']; + $booking = $questionMetadata ? Booking::where('id', $questionMetadata['id'])->first() : null; + } + + //Save answer given by user (both next and previous) + $answerOptionId = 0; + if ($request->has('answerObj')) { + $answerOptionId = intval($request->answerObj['id']); + } + + $this->saveAnswerProcessor->execute($userId, 0, $currentQuestion, $questionMetadata, $request->answer, $answerOptionId, $filesUpload, $timeUsedSeconds, $request->has('isPrevious'), $reference); + if(!$request->has('isPrevious')){ + $this->saveAnswerActionProcessor->execute($booking, $questionMetadata, $answerOptionId, $currentQuestion, $filesUpload); + } + + if ($request->has('questionContext')) { + $previousAnswer = $this->listsUserAnswerSelected->execute(['user_id' => $userId, 'reference' => $reference, 'is_previous' => 0, 'order_by' => (object)['column' => 'id','DESC' => true]])[0]; + } + + if($booking){ + $this->markBookingAsProcessed($booking, $request->has('isPrevious'), $currentQuestion); + } + + //Get returned question (previous or next) and additional metadata if applicable + $returnQuestion = $this->fetchNextQuestionV1AdminWFProcessor->execute($currentQuestion, $request->answerObj, $request->questionContext, $previousAnswer, $booking, $request->has('isPrevious')); + $questionMetadata = $this->fetchNextQuestionMetadataProcessor->execute($returnQuestion, $questionMetadata); + + //When a questionnaire ended, return back the first question + if(is_null($returnQuestion)){ + $returnQuestion = $this->fetchFirstQuestionQAProcessor->execute($request); + } + + return $this->resourceResponse(new QuestionResource($returnQuestion, $userId, $request->has('isPrevious'), $this->isNoGoingBack($returnQuestion), $previousAnswer, $questionMetadata)); + } + + private function markBookingAsProcessed(Booking $booking, bool $isPrevious, array $currentQuestion){ + //Marked data that has already been processed so that it does not appear again + if($currentQuestion && $currentQuestion['is_end'] === 1 && !$isPrevious){ + $key1 = "admin_workflow_processed"; + $key2 = "admin_workflow_processing"; + if (strpos($currentQuestion['question_number'], '1688') === 0) { + $key1 = '1688_'.$key1; + $key2 = '1688_'.$key2; + } + if (strpos($currentQuestion['question_number'], 'fill_po') === 0) { + $key1 = 'xfill_po_'.$key1; + $key2 = 'xfill_po_'.$key2; + } + if (strpos($currentQuestion['question_number'], 'approve_po') === 0) { + $key1 = 'xapprove_po_'.$key1; + $key2 = 'xapprove_po_'.$key2; + } + + $processingRecord = $booking->attributesKVP()->where('key', $key2)->first(); + if ($processingRecord) { + $processingRecord->delete(); + } + + $kvp = $booking->attributesKVP()->where('key', $key1)->first(); + + if(!$kvp){ + $keyValuePairObject = new KeyValuePairObject($key1, true); + $this->createsKeyValuePair->execute($booking, $keyValuePairObject); + } + } + } + + private function isNoGoingBack(QAQuestions $returnQuestion){ + + if($returnQuestion && ($returnQuestion->is_start || $returnQuestion->is_end)){ + return 1; + } + else if($returnQuestion && $returnQuestion->is_start === 0 && $returnQuestion && $returnQuestion->is_end === 0){ + return 0; + } + + return 0; + } +} diff --git a/app/Classes/Modules/Questionnaires/DataTransferObjects/QAUserSourceObject.php b/app/Classes/Modules/Questionnaires/DataTransferObjects/QAUserSourceObject.php new file mode 100644 index 00000000..510a945c --- /dev/null +++ b/app/Classes/Modules/Questionnaires/DataTransferObjects/QAUserSourceObject.php @@ -0,0 +1,56 @@ +system = $system; + $this->marking = $marking; + $this->email = $email; + } + + /** + * @return string + */ + public function getSystem(): string + { + return $this->system; + } + + /** + * @return string + */ + public function getMarking(): string + { + return $this->marking; + } + + /** + * @return string + */ + public function getEmail(): string + { + return $this->email; + } + +} diff --git a/app/Classes/Modules/Questionnaires/Processors/FetchFirstQuestionV1AdminWFProcessor.php b/app/Classes/Modules/Questionnaires/Processors/FetchFirstQuestionV1AdminWFProcessor.php new file mode 100644 index 00000000..2bebe260 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Processors/FetchFirstQuestionV1AdminWFProcessor.php @@ -0,0 +1,39 @@ +fetchesQuestion = $fetchesQuestion; + } + + public function execute(Request $request){ + try { + $setId = $request->route('set_id'); + if($setId === '0'){ + $set = QAQuestionnaireSet::where('group', '1688,approve_po,fill_po')->latest('id')->first(); + $setId = $set->id; + } + $query = $this->fetchesQuestion->execute(['questionnaire_set_id' => $setId]); + return $query; + } catch (\Exception $exception){ + throw new ErrorException($exception->getMessage(), $exception->getCode()); + } + } +} diff --git a/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionMetadataV1AdminWFProcessor.php b/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionMetadataV1AdminWFProcessor.php new file mode 100644 index 00000000..0c57b6d1 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionMetadataV1AdminWFProcessor.php @@ -0,0 +1,19 @@ +question_number === '1688_underpaid_order_1'){ + $amountProcessed = $questionMetadata['amount_processed']; + $amountPaid = $questionMetadata['paid_amount']; + $questionMetadata['amount_to_be_deducted'] = $amountProcessed - $amountPaid; + } + + return $questionMetadata; + } +} diff --git a/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionV1AdminWFProcessor.php b/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionV1AdminWFProcessor.php new file mode 100644 index 00000000..bb9454e3 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Processors/FetchNextQuestionV1AdminWFProcessor.php @@ -0,0 +1,148 @@ +fetchesQuestion = $fetchesQuestion; + $this->listsQuestions = $listsQuestions; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->fetchBookingQuotation = $fetchBookingQuotation; + } + + public function execute(array $currentQuestion, ?array $currentQuestionAnswer, array $questionContext, QAUserAnswerSelected $previousAnswer, ?Booking $booking, bool $isPrevious){ + $isEnd = 0; + $questionId = 0; + $nextQuestionNumber = ""; + $nextNestedQuestion = ""; + $nextMainQuestion= ""; + $questionnaireSetId = 0; + $questionType = QAType::DEFAULT; + $returnQuestion = null; + + if ($currentQuestion && array_key_exists('id', $currentQuestion)) { + $questionId = $currentQuestion['id']; + $isEnd = $currentQuestion['is_end']; + $questionType = $currentQuestion['question_type']; + $nextNestedQuestion = $currentQuestion['next_nested_question']; + $nextMainQuestion = $currentQuestion['next_main_question']; + $questionnaireSetId = $currentQuestion['questionnaire_set_id']; + } + + if ($currentQuestionAnswer && $currentQuestionAnswer['next_question_number']) { + $nextQuestionNumber = $currentQuestionAnswer['next_question_number']; + } + + if ($isPrevious) { + if($previousAnswer) + { + $previousAnswer->delete(); + } + else{ + return null; + } + + //Get previous question + $previousQuestion = $this->fetchesQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'id' => $previousAnswer['question_id']]); + $returnQuestion = $previousQuestion; + } + else{ + //Get next question + $nextQuestion = null; + $question_number = ""; + if($nextQuestionNumber !== ""){ + $question_number = $nextQuestionNumber; + } + else if($nextNestedQuestion !== ""){ + $question_number = $nextNestedQuestion; + } + else { + $question_number = $nextMainQuestion; + } + + if($question_number !== ""){ + //Check if question exists + $questions = $this->listsQuestions->execute(['questionnaire_set_id' => $questionnaireSetId, 'question_number' => $question_number]); + if($previousAnswer['answer'] === '1688_order_verified' && count($questions) == 0){ + $questionMetadata = $questionContext['questionMetadata'] ?? null; + $amountProcessed = $questionMetadata['amount_processed']; + $amountPaid = $questionMetadata['paid_amount']; + $wallet = $booking->company->wallets()->first(); + $walletAmount = $wallet->amount; + + if ($amountProcessed === $amountPaid) { + $question_number = '1688_proceed_order'; + } + else if ($amountProcessed > $amountPaid) { + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); + + $differenceUnderPayinCNY = $amountProcessed - $amountPaid; + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $differenceUnderPayinCNY)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS['wallet']); + $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject); + $amountUnderpay = $configurations->getTotal(); + + // if($amountUnderpay > round($outstanding, 2)) { + // $question_number = '1688_underpaid_order_3'; + // } + + if($walletAmount > $amountUnderpay) { + $question_number = '1688_underpaid_order_1'; + } + else { + $question_number = '1688_underpaid_order_2'; + } + } + else { + $question_number = '1688_overpaid_order'; + } + } + + $nextQuestion = $this->fetchesQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'question_number' => $question_number]); + $returnQuestion = $nextQuestion; + } + } + + return $returnQuestion; + } +} diff --git a/app/Classes/Modules/Questionnaires/Processors/SaveAnswerActionV1AdminWFProcessor.php b/app/Classes/Modules/Questionnaires/Processors/SaveAnswerActionV1AdminWFProcessor.php new file mode 100644 index 00000000..822e7dd8 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Processors/SaveAnswerActionV1AdminWFProcessor.php @@ -0,0 +1,113 @@ +approvePurchaseOrderProcessor = $approvePurchaseOrderProcessor; + $this->uploadPurchaseOrderProcessor = $uploadPurchaseOrderProcessor; + $this->createPaymentProofDocumentProcessor = $createPaymentProofDocumentProcessor; + $this->fetchesTransaction = $fetchesTransaction; + $this->fetchBookingQuotation = $fetchBookingQuotation; + $this->createBookingPaymentProcessor = $createBookingPaymentProcessor; + $this->updateBookingAmountProcessor = $updateBookingAmountProcessor; + } + + /** + * @return + */ + public function execute($booking, $questionMetadata, $answerOptionId, $currentQuestion, $filesUpload){ + $answerOption = QAAnswerOptions::where('id', $answerOptionId)->first(); + if($currentQuestion['question_number'] === 'approve_po' && $answerOption && $answerOption->value === "approve_po_approved"){ + $this->approvePurchaseOrderProcessor->execute($booking); + } + else if($currentQuestion['question_number'] === '1688_submit' || $currentQuestion['question_number'] === '1688_underpaid_documents_submission' || $currentQuestion['question_number'] === '1688_overpaid_documents_submission') + { + if($filesUpload){ + if ($booking && isset($filesUpload['filesA']) && isset($filesUpload['filesB'])) + { + $mergedFilesUpload = array_merge( + $filesUpload['filesA'] ?? [], + $filesUpload['filesB'] ?? [] + ); + $this->uploadPurchaseOrderProcessor->execute($booking, $mergedFilesUpload); + } + + if (isset($filesUpload['filesC']) && isset($questionMetadata['payment_history'][0]['transaction_bill']['id'])) + { + $transaction = $this->fetchesTransaction->execute(['id' =>$questionMetadata['payment_history'][0]['transaction_bill']['id']]); + $this->createPaymentProofDocumentProcessor->execute($transaction, $filesUpload['filesC']); + } + } + } + else if($currentQuestion['question_number'] === '1688_underpaid_order_1') + { + $wallet = $booking->company->wallets()->first(); + $amountProcessed = $questionMetadata['amount_processed']; + $amountPaid = $questionMetadata['paid_amount']; + if ($amountProcessed > $amountPaid) { + $differenceUnderInCNY = $amountProcessed - $amountPaid; + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $differenceUnderInCNY)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS['wallet']); + $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject); + $amountUnderpay = $configurations->getTotal(); + + if($amountUnderpay != $differenceUnderInCNY){ + $this->updateBookingAmountProcessor->execute($booking, $amountProcessed); + } + + if($wallet->amount > $amountUnderpay){ + $company = $booking->company()->first(); + $employee = $company->employees()->first(); + $transaction = $this->createBookingPaymentProcessor->execute($booking, (string) $differenceUnderInCNY, 'wallet', "", "", $employee->email, false); + } + } + + } + } +} diff --git a/app/Classes/Modules/Questionnaires/Processors/SaveAnswerV1AdminWFProcessor.php b/app/Classes/Modules/Questionnaires/Processors/SaveAnswerV1AdminWFProcessor.php new file mode 100644 index 00000000..70ee3c36 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Processors/SaveAnswerV1AdminWFProcessor.php @@ -0,0 +1,130 @@ +uploadDocumentForProcessor = $uploadDocumentForProcessor; + } + + /** + * @return QAUserAnswerSelected|\Illuminate\Database\Eloquent\Model + */ + public function execute($userId, $sourceId, $currentQuestion, $questionMetadata, $answerInText, $answerOptionId, $filesUpload, $timeUsedSeconds, $isPrevious, $reference = null){ + + $answer = null; + $attachments = []; + $questionId = $currentQuestion['id']; + $questionType = $currentQuestion['question_type']; + $questionNumber = $currentQuestion['question_number']; + if ($isPrevious){ + $answerInText = "go_back"; + } + + if(is_null($answer)) + { + $answer = new QAUserAnswerSelected; + } + $answer->user_id = $userId; + $answer->source_id = $sourceId; + $answer->question_id = $questionId; + $answer->question_metadata = json_encode($questionMetadata); + $answer->answer_option_id = $answerOptionId; + $answer->time_used_seconds = $timeUsedSeconds; + $answer->is_previous = $isPrevious; + if($reference){ + $answer->reference = $reference; + } + $answer->save(); //cief todo: why 2 save() in this file, this is wrong + + if($filesUpload){ + if (isset($filesUpload['filesA'])) + { + foreach ($filesUpload as $key => $files) { + if($key === 'filesA'){ + $attachments[$key] = $this->saveFile($answer, $files, 'questionnaires', DocumentType::ADMIN_WORK_FLOW.'/'.DocumentType::ECOMMERCE_PURCHASE_ORDER_EN); + } + else if($key === "filesB"){ + $attachments[$key] = $this->saveFile($answer, $files, 'questionnaires', DocumentType::ADMIN_WORK_FLOW.'/'.DocumentType::ECOMMERCE_PURCHASE_ORDER_CH); + } + else if($key === "filesC"){ + $attachments[$key] = $this->saveFile($answer, $files, 'questionnaires', DocumentType::ADMIN_WORK_FLOW.'/'.DocumentType::CURRENCY_VENDOR_PAYMENT_PROOF); + } + } + } + else if (isset($filesUpload['files']) && $filesUpload['files']) + { + $attachments = $this->saveFile($answer, $filesUpload['files']); + } + } + + if(!$isPrevious) { + if($questionType === QAType::SUBMIT_1688_3_TYPES_DOCUMENTS){ + $structuredAnswer = [ + 'text' => "3_DOCUMENTS_UPLOADED", + 'files' => $attachments, + ]; + $answer->answer = json_encode($structuredAnswer); + } + else if($questionType === QAType::REMARKS_WITH_DOCUMENT_UPLOAD){ + $structuredAnswer = [ + 'text' => $answerInText, + 'files' => $attachments, + ]; + $answer->answer = json_encode($structuredAnswer); + } + else if($questionType === QAType::DOCUMENT_UPLOAD){ + $structuredAnswer = [ + 'files' => $attachments, + ]; + $answer->answer = json_encode($structuredAnswer); + } + else if($questionType === QAType::FLOAT_MONEY){ + $answer->answer = floatval(str_replace(',', '', $answerInText)); + } + else { + $answer->answer = $answerInText; + + if($questionNumber === '1688_underpaid_order_1_proceed' || $questionNumber === '1688_underpaid_order_1'){ + $answer->answer = $questionMetadata['amount_to_be_deducted']; + } + } + } + else { + $answer->answer = $answerInText; + } + + $answer->save(); + + return $answer; + } + + private function saveFile(QAUserAnswerSelected $answer, array $files, string $path = 'questionnaires', string $documentType = DocumentType::ADMIN_WORK_FLOW){ + $result = $this->uploadDocumentForProcessor->execute($answer, $files, $path, $documentType); + $attachment = array_map(function ($item) use($documentType) { + return [ + 'name' => $item->document_id, + 'file_id' => $item->id, + 'document_type'=> $documentType, + ]; + }, $result); + + return $attachment; + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/CreatesQAUserSource.php b/app/Classes/Modules/Questionnaires/Services/CreatesQAUserSource.php new file mode 100644 index 00000000..2268cf7f --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/CreatesQAUserSource.php @@ -0,0 +1,26 @@ +system = $object->getSystem(); + $model->marking = $object->getMarking(); + $model->email = $object->getEmail(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/FetchesQAUserSource.php b/app/Classes/Modules/Questionnaires/Services/FetchesQAUserSource.php new file mode 100644 index 00000000..c8b467c1 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/FetchesQAUserSource.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/FetchesQuestion.php b/app/Classes/Modules/Questionnaires/Services/FetchesQuestion.php new file mode 100644 index 00000000..5fe948e5 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/FetchesQuestion.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/FetchesUserAnswerSelected.php b/app/Classes/Modules/Questionnaires/Services/FetchesUserAnswerSelected.php new file mode 100644 index 00000000..34007879 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/FetchesUserAnswerSelected.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/ListsQuestionUserAnswerSelected.php b/app/Classes/Modules/Questionnaires/Services/ListsQuestionUserAnswerSelected.php new file mode 100644 index 00000000..358ab612 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/ListsQuestionUserAnswerSelected.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/ListsQuestionnaireSet.php b/app/Classes/Modules/Questionnaires/Services/ListsQuestionnaireSet.php new file mode 100644 index 00000000..fb58304b --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/ListsQuestionnaireSet.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Services/ListsQuestions.php b/app/Classes/Modules/Questionnaires/Services/ListsQuestions.php new file mode 100644 index 00000000..b736f454 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Services/ListsQuestions.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Questionnaires/Standards/Rules/CanFetchQuestion.php b/app/Classes/Modules/Questionnaires/Standards/Rules/CanFetchQuestion.php new file mode 100644 index 00000000..65e46e26 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Standards/Rules/CanFetchQuestion.php @@ -0,0 +1,43 @@ +user()->type; + if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) { + return true; + } else { + return false; + } + } + + /** + * @param $object + * @return bool + */ + protected function validators($object): bool + { + return true; + } + + /** + * @param $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Questionnaires/Standards/Rules/CanListQuestions.php b/app/Classes/Modules/Questionnaires/Standards/Rules/CanListQuestions.php new file mode 100644 index 00000000..7ff92774 --- /dev/null +++ b/app/Classes/Modules/Questionnaires/Standards/Rules/CanListQuestions.php @@ -0,0 +1,45 @@ +user()->type; + if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) { + return true; + } else { + return false; + } + } + + /** + * @param $object + * @return bool + */ + protected function validators($object): bool + { + return true; + + } + + + /** + * @param $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php index 46534d77..9e619ee1 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php @@ -4,24 +4,10 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Companies\Services\FetchesCompany; -use App\Classes\Modules\Companies\Services\UpdatesCompanyStatus; -use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; -use App\Classes\Modules\Documents\Services\CreatesDocument; -use App\Classes\Modules\Documents\Services\CreatesFiles; -use App\Classes\Modules\Transactions\Services\FetchesTransaction; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\CompanyType; -use App\Classes\ValueObjects\Constants\DocumentType; -use App\Classes\Jobs\SendUserPaymentProofUploadedEmail; -use App\Models\Company; -use App\Models\Document; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; - -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; - +use App\Classes\Modules\Transactions\Services\FetchesTransaction; +use App\Classes\Modules\Transactions\Processors\CreatePaymentProofDocumentProcessor; class CreatePaymentProofDocumentLogic extends AbstractControllerLogic { @@ -39,37 +25,18 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic /** @var FetchesTransaction */ private $fetchesTransaction; - /** @var CreatesDocument */ - private $createsDocument; - - /** @var CreatesFiles */ - private $createsFile; - - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - - /** @var CreateInvoiceTransactionProcessor */ - private $createInvoiceTransactionProcessor; - - /** @var SendUserPaymentProofUploadedEmail */ - private $sendUserPaymentProofUploadedEmail; + /** @var CreatePaymentProofDocumentProcessor */ + private $createPaymentProofDocumentProcessor; /** * CreatePaymentProofDocumentLogic constructor. + * @param CreatePaymentProofDocumentProcessor $createPaymentProofDocumentProcessor * @param FetchesTransaction $fetchesTransaction - * @param CreatesDocument $createsDocument - * @param CreatesFiles $createsFile - * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor */ - public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor, SendUserPaymentProofUploadedEmail $sendUserPaymentProofUploadedEmail) + public function __construct(CreatePaymentProofDocumentProcessor $createPaymentProofDocumentProcessor, FetchesTransaction $fetchesTransaction) { + $this->createPaymentProofDocumentProcessor = $createPaymentProofDocumentProcessor; $this->fetchesTransaction = $fetchesTransaction; - $this->createsDocument = $createsDocument; - $this->createsFile = $createsFile; - $this->updatesTransactionStatus = $updatesTransactionStatus; - $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; - $this->sendUserPaymentProofUploadedEmail = $sendUserPaymentProofUploadedEmail; } /** @@ -79,30 +46,10 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); - - $object = new DocumentObject(DocumentType::CURRENCY_VENDOR_PAYMENT_PROOF, $request->input('files'), '', ApprovalStatus::APPROVED, 'china_bank_slip'); - - /** @var Document $document */ - $document = $this->createsDocument->execute($transaction, $object); - - $file = $this->createsFile->execute($document, $object); - - $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); - - $this->createInvoiceTransactionProcessor->execute($transaction->owner->booking); - - // send email to customer - // todo: a function to send a proof to the receipiant, they have to give us a email of the receipiant and also need to submiited purchase order - $companyEmployee = $transaction->owner->booking->company->employees; - foreach ($companyEmployee as $employee) { - if (app()->environment('production') || in_array($employee->email, ['cief.enquirycntr@gmail.com', 'tech.ciefmalaysia@gmail.com'])) { - $this->sendUserPaymentProofUploadedEmail::dispatch($employee, $transaction->owner->booking, $file[0]); - } - } + $this->createPaymentProofDocumentProcessor->execute($transaction, $request->input('files')); return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DownloadMockUpWhiteFormPdfLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DownloadMockUpWhiteFormPdfLogic.php index 4d80785f..7c68536d 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/DownloadMockUpWhiteFormPdfLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/DownloadMockUpWhiteFormPdfLogic.php @@ -48,7 +48,7 @@ class DownloadMockUpWhiteFormPdfLogic return ['id' => $value]; }, json_decode($request->input('payments'))); - DB::beginTransaction(); + DB::beginTransaction(); //cief todo: 74 $this->createSupplierTransactionProcessor->execute($supplier, $rate, $payments); @@ -56,7 +56,7 @@ class DownloadMockUpWhiteFormPdfLogic $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $this->createSupplierTransactionProcessor->getBills(), 'transferFeeTransactions' => $this->createSupplierTransactionProcessor->getTransferTransactions(), 'supplier' => $supplier]); - DB::rollBack(); + DB::rollBack(); //cief todo: 74 $exportFileName = 'MockUpWhiteForm.pdf'; $filesystemDriver = Storage::getDefaultDriver(); diff --git a/app/Classes/Modules/Transactions/Processors/CreatePaymentProofDocumentProcessor.php b/app/Classes/Modules/Transactions/Processors/CreatePaymentProofDocumentProcessor.php new file mode 100644 index 00000000..29dc8e5d --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreatePaymentProofDocumentProcessor.php @@ -0,0 +1,81 @@ +createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; + $this->sendUserPaymentProofUploadedEmail = $sendUserPaymentProofUploadedEmail; + } + + /** + * @param Transaction $transaction + * @param array $files + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Transaction $transaction, array $files) + { + $object = new DocumentObject(DocumentType::CURRENCY_VENDOR_PAYMENT_PROOF, $files, '', ApprovalStatus::APPROVED, 'china_bank_slip'); + + /** @var Document $document */ + $document = $this->createsDocument->execute($transaction, $object); + + $file = $this->createsFile->execute($document, $object); + + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); + + $this->createInvoiceTransactionProcessor->execute($transaction->owner->booking); + + // send email to customer + // todo: a function to send a proof to the receipiant, they have to give us a email of the receipiant and also need to submiited purchase order + $companyEmployee = $transaction->owner->booking->company->employees; + foreach ($companyEmployee as $employee) { + if (app()->environment('production') || in_array($employee->email, ['cief.enquirycntr@gmail.com', 'tech.ciefmalaysia@gmail.com'])) { + $this->sendUserPaymentProofUploadedEmail::dispatch($employee, $transaction->owner->booking, $file[0]); + } + } + } + +} diff --git a/app/Classes/ValueObjects/Constants/DocumentType.php b/app/Classes/ValueObjects/Constants/DocumentType.php index 42f8222b..f2fe0b09 100644 --- a/app/Classes/ValueObjects/Constants/DocumentType.php +++ b/app/Classes/ValueObjects/Constants/DocumentType.php @@ -2,6 +2,7 @@ namespace App\Classes\ValueObjects\Constants; + final class DocumentType { public const PROFILE_PICTURE = 'PROFILE_PICTURE'; @@ -27,4 +28,8 @@ final class DocumentType { public const BULK_PURCHASE_ORDER = 'BULK_PURCHASE_ORDER'; public const BILL_GROUP_PAYMENT_PROOF = 'BILL_GROUP_PAYMENT_PROOF'; + + public const ADMIN_WORK_FLOW = 'ADMIN_WORK_FLOW'; + public const ECOMMERCE_PURCHASE_ORDER_EN = 'ECOMMERCE_PURCHASE_ORDER_EN'; + public const ECOMMERCE_PURCHASE_ORDER_CH = 'ECOMMERCE_PURCHASE_ORDER_CH'; } diff --git a/app/Classes/ValueObjects/Constants/QAType.php b/app/Classes/ValueObjects/Constants/QAType.php new file mode 100644 index 00000000..43f5b7c5 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/QAType.php @@ -0,0 +1,27 @@ + '1688', 'id' => QuestionGroup::_1688], + // ['text' => 'approve_po', 'id' => QuestionGroup::APPROVE_PO], + // ['text' => 'fill_po', 'id' => QuestionGroup::FILL_PO], + // ]; + + // const QUESTION_GROUPS = [ + // QuestionGroup::_1688, + // QuestionGroup::APPROVE_PO, + // QuestionGroup::FILL_PO, + // ]; +} diff --git a/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php b/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php new file mode 100644 index 00000000..92262915 --- /dev/null +++ b/app/Http/Controllers/Exports/ExportQuestionsAnswersController.php @@ -0,0 +1,33 @@ +execute($request); + } + + /** + * @param Request $request + * @param ExportQAWithoutGroupsLogic $logic + * @return BinaryFileResponse + * @return JsonResponse + */ + public function exportWithoutGroups(Request $request, ExportQAWithoutGroupsLogic $logic) { + return $logic->execute($request); + } +} diff --git a/app/Http/Controllers/Questionnaires/AdminWorkflowBaseController.php b/app/Http/Controllers/Questionnaires/AdminWorkflowBaseController.php new file mode 100644 index 00000000..c94cbe6b --- /dev/null +++ b/app/Http/Controllers/Questionnaires/AdminWorkflowBaseController.php @@ -0,0 +1,50 @@ +execute($request); + } + + /** + * @param Request $request + * @param FetchAdminWFModelAttributesLogic $logic + * @return JsonResponse + */ + public function fetchModelAttributes(Request $request, FetchAdminWFModelAttributesLogic $logic): JsonResponse { + return $logic->execute($request); + } + + /** + * @param Request $request + * @param FetchAdminWFPendingApprovalPOLogic $logic + * @return JsonResponse + */ + public function fetchPendingApprovalPO(Request $request, FetchAdminWFPendingApprovalPOLogic $logic): JsonResponse { + return $logic->execute($request); + } + + /** + * @param Request $request + * @param FetchAdminWFPendingFillPOLogic $logic + * @return JsonResponse + */ + public function fetchPendingFillPO(Request $request, FetchAdminWFPendingFillPOLogic $logic): JsonResponse { + return $logic->execute($request); + } +} diff --git a/app/Http/Controllers/Questionnaires/FetchQuestionV1AdminWFController.php b/app/Http/Controllers/Questionnaires/FetchQuestionV1AdminWFController.php new file mode 100644 index 00000000..2e047aca --- /dev/null +++ b/app/Http/Controllers/Questionnaires/FetchQuestionV1AdminWFController.php @@ -0,0 +1,21 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Questionnaires/ListQuestionnaireSetController.php b/app/Http/Controllers/Questionnaires/ListQuestionnaireSetController.php new file mode 100644 index 00000000..8fac21a0 --- /dev/null +++ b/app/Http/Controllers/Questionnaires/ListQuestionnaireSetController.php @@ -0,0 +1,21 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Questionnaires/ListQuestionsAnswersController.php b/app/Http/Controllers/Questionnaires/ListQuestionsAnswersController.php new file mode 100644 index 00000000..091eba5e --- /dev/null +++ b/app/Http/Controllers/Questionnaires/ListQuestionsAnswersController.php @@ -0,0 +1,21 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Questionnaires/ListQuestionsController.php b/app/Http/Controllers/Questionnaires/ListQuestionsController.php new file mode 100644 index 00000000..3fc4d75f --- /dev/null +++ b/app/Http/Controllers/Questionnaires/ListQuestionsController.php @@ -0,0 +1,21 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Questionnaires/UpdateNextQuestionV1AdminWFController.php b/app/Http/Controllers/Questionnaires/UpdateNextQuestionV1AdminWFController.php new file mode 100644 index 00000000..87ed672b --- /dev/null +++ b/app/Http/Controllers/Questionnaires/UpdateNextQuestionV1AdminWFController.php @@ -0,0 +1,31 @@ +question; + // $questionnaireSetId = $currentQuestion['questionnaire_set_id']; + // $questionnaireSet = QAQuestionnaireSet::where('id', $questionnaireSetId)->first(); + // $group = ''; + // $version = 0; + // if($questionnaireSet){ + // $group = $questionnaireSet->group; + // $version = $questionnaireSet->version; + // } + return $logic->execute($request); + } +} diff --git a/app/Http/Resources/AnswerOptionsResource.php b/app/Http/Resources/AnswerOptionsResource.php new file mode 100644 index 00000000..6c168847 --- /dev/null +++ b/app/Http/Resources/AnswerOptionsResource.php @@ -0,0 +1,27 @@ + $this->id, + 'display_text' => $this->display_text, + 'value' => $this->value, + 'order' => $this->order, + 'question_number' => $this->question_number, + 'next_question_number' => $this->next_question_number, + ]; + } +} diff --git a/app/Http/Resources/BookingBaseResource.php b/app/Http/Resources/BookingBaseResource.php new file mode 100644 index 00000000..960be05e --- /dev/null +++ b/app/Http/Resources/BookingBaseResource.php @@ -0,0 +1,61 @@ + $this->id, + 'company' => new CompanyResource($this->company), + 'bank' => new BankResource($this->bank), + 'service' => new ServiceTypeResource($this->service), + 'marking' => $this->marking, + // 'amount' => $this->fix_amount, + // 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + // 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)), + 'fixed_currency' => new CurrencyResource($this->fixedCurrency), + 'order_reference_no' => $this->modelAttributes()->where('name', BookingAttributeNames::ORDER_REFERENCE_NO)->get()->map(function ($attr) { + return [ + 'id' => $attr->id, + 'value' => $attr->value + ]; + }), + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED, ApprovalStatus::REFUNDED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/QuestionResource.php b/app/Http/Resources/QuestionResource.php new file mode 100644 index 00000000..e2ad946c --- /dev/null +++ b/app/Http/Resources/QuestionResource.php @@ -0,0 +1,77 @@ +question = $question; + $this->userId = $userId; + $this->isPrevious = $isPrevious; + $this->isNoGoingBack = $isNoGoingBack; + $this->previousAnswer = $previousAnswer; + $this->questionMetadata = $questionMetadata; + } + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function toArray($request) + { + if($this->question){ + $q = (object)$this->question; + return [ + 'id' => $q->id, + 'question_number' => $q->question_number, + 'question_title' => $q->question_title, + 'question_description' => $q->question_description, + 'question_type' => $q->question_type, + 'question_answers' => AnswerOptionsResource::collection(QAAnswerOptions::where('question_number', $q->question_number)->where('questionnaire_set_id', $q->questionnaire_set_id)->orderBy('order', 'ASC')->get()), + 'questionnaire_set_id' => $q->questionnaire_set_id, + 'question_metadata'=> $this->questionMetadata, + // 'questionnaire' => new QuestionnaireSetsResource($q->questionnaire), + // 'questionnaire_answers' => $q->is_end ? QuestionnaireAnswersResource::collection(QAUserAnswerSelected::where('user_id', $this->userId)->get()) : null, + 'next_nested_question' => $q->next_nested_question, + 'next_main_question' => $q->next_main_question, + 'is_start' => $q->is_start, + 'is_end' => $q->is_end, + 'end_text' => $q->end_text, + 'order' => $q->order, + 'answer' => $this->previousAnswer, + 'url' => $q->url, + 'is_no_going_back' => $this->isNoGoingBack, + 'is_previous' => $this->isPrevious, + ]; + } + else{ + return []; + } + } +} diff --git a/app/Http/Resources/QuestionnaireAnswersResource.php b/app/Http/Resources/QuestionnaireAnswersResource.php new file mode 100644 index 00000000..1deda19d --- /dev/null +++ b/app/Http/Resources/QuestionnaireAnswersResource.php @@ -0,0 +1,25 @@ +question_id)->first(); + return [ + 'question_title' => $question ? $question->question_title : null, + 'answer' => $this->answer + ]; + } +} diff --git a/app/Http/Resources/QuestionnaireSetsResource.php b/app/Http/Resources/QuestionnaireSetsResource.php new file mode 100644 index 00000000..0865de6d --- /dev/null +++ b/app/Http/Resources/QuestionnaireSetsResource.php @@ -0,0 +1,26 @@ + $this->id, + 'name' => $this->name, + 'description' => $this->description, + 'group' => explode(',', $this->group), + 'version' => $this->version, + ]; + } +} diff --git a/app/Http/Resources/QuestionsAnswersResource.php b/app/Http/Resources/QuestionsAnswersResource.php new file mode 100644 index 00000000..b3ff2974 --- /dev/null +++ b/app/Http/Resources/QuestionsAnswersResource.php @@ -0,0 +1,50 @@ +question_id)->first(); + $source = new UserSourceResource($this->userSource); + $user = $this->source_id === 0 ? new UserResource($this->user) : null; + $answerOption = QAAnswerOptions::where('id', $this->answer_option_id)->first(); + $questionGroups = explode(',', $this->question->questionnaire->group); + $user_marking = ''; + + return [ + 'id' => $this->id, + 'question_id' => $this->question_id, + 'question_groups' => $questionGroups, + 'questionnaire' => new QuestionnaireSetsResource($this->question->questionnaire), + 'question_title' => $question ? $question->question_title : null, + 'question_type' => $question ? $question->question_type : 0, + 'question_metadata' => $this->question_metadata, + 'answer' => $answerOption ? $answerOption->display_text : null, + 'answer_value' => $this->answer, + 'documentsList' => DocumentResource::collection($this->documents), + 'documents' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::ADMIN_WORK_FLOW)->first()), + 'reference' => $this->reference, + 'source_system' => null, + 'source_marking' => $user ? $user_marking : $source->marking, + 'source_email' => $user ? $user->email : $source->email, + 'time' => $this->time_used_seconds, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + ]; + } +} diff --git a/app/Http/Resources/UserSourceResource.php b/app/Http/Resources/UserSourceResource.php new file mode 100644 index 00000000..f39fbdfe --- /dev/null +++ b/app/Http/Resources/UserSourceResource.php @@ -0,0 +1,24 @@ + $this->system, + 'email' => $this->email, + 'marking' => $this->marking, + ]; + } +} diff --git a/app/Models/Booking.php b/app/Models/Booking.php index 259ca01e..83b724a6 100644 --- a/app/Models/Booking.php +++ b/app/Models/Booking.php @@ -2,11 +2,13 @@ namespace App\Models; + use App\Classes\General\Interfaces\Documentable; use App\Classes\General\Interfaces\Transactionable; use App\Classes\General\Interfaces\Voucherifiable; use App\Classes\General\Traits\LogData; use App\Classes\ValueObjects\Constants\RoleTypes; +use App\Classes\General\Interfaces\KeyValueInterface; use App\Scopes\CustomerBookingsScope; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphMany; @@ -26,7 +28,7 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships; * @property int convertible_currency_id * @property int conversion_currency_id */ -class Booking extends AbstractModel implements Documentable, Transactionable, Voucherifiable +class Booking extends AbstractModel implements Documentable, Transactionable, Voucherifiable, KeyValueInterface { use HasRelationships; use SoftDeletes; @@ -130,4 +132,11 @@ class Booking extends AbstractModel implements Documentable, Transactionable, Vo return $this->morphMany(VoucherEntityMapping::class, 'owner'); } + /** + * @return MorphMany + */ + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } } diff --git a/app/Models/QAAnswerOptions.php b/app/Models/QAAnswerOptions.php new file mode 100644 index 00000000..cd2eca79 --- /dev/null +++ b/app/Models/QAAnswerOptions.php @@ -0,0 +1,9 @@ +BelongsTo(QAQuestionnaireSet::class, 'questionnaire_set_id', 'id'); + } + + /** + * @return HasMany + */ + public function userAnswers() + { + return $this->hasMany(QAUserAnswerSelected::class, 'question_id', 'id'); + } +} diff --git a/app/Models/QAUserAnswerSelected.php b/app/Models/QAUserAnswerSelected.php new file mode 100644 index 00000000..56515d31 --- /dev/null +++ b/app/Models/QAUserAnswerSelected.php @@ -0,0 +1,71 @@ +morphMany(Document::class, 'owner'); + } + + /** + * @return BelongsTo + */ + public function userSource(): BelongsTo + { + return $this->BelongsTo(QAUserSource::class, 'source_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->BelongsTo(User::class, 'user_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function question(): BelongsTo + { + return $this->BelongsTo(QAQuestions::class, 'question_id', 'id'); + } + + + /** + * @return BelongsTo + */ + public function answer(): BelongsTo + { + return $this->BelongsTo(QAAnswerOptions::class, 'answer_option_id', 'id'); + } + + /** + * @return MorphMany + */ + public function attributesKVP(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } + +} diff --git a/app/Models/QAUserSource.php b/app/Models/QAUserSource.php new file mode 100644 index 00000000..21401df5 --- /dev/null +++ b/app/Models/QAUserSource.php @@ -0,0 +1,9 @@ +id(); + $table->string('name'); + $table->string('description')->nullable(); + $table->string('group')->nullable(); + $table->unsignedBigInteger('order')->default(0); + $table->unsignedBigInteger('next_set')->nullable(); + $table->unsignedBigInteger('version')->default(1); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qa_questionnaire_sets'); + } +} diff --git a/database/migrations/2024_11_26_015531_create_qa_questions_table.php b/database/migrations/2024_11_26_015531_create_qa_questions_table.php new file mode 100644 index 00000000..c6811f4e --- /dev/null +++ b/database/migrations/2024_11_26_015531_create_qa_questions_table.php @@ -0,0 +1,47 @@ +id(); + $table->string('question_number'); + $table->text('question_title'); + $table->text('question_description')->nullable(); + $table->unsignedBigInteger('questionnaire_set_id'); + $table->string('next_nested_question')->nullable(); + $table->string('next_main_question')->nullable(); + $table->unsignedBigInteger('question_type'); + $table->tinyInteger('is_start'); + $table->tinyInteger('is_end'); + $table->string('end_text')->nullable(); + $table->unsignedBigInteger('order')->default(0); + $table->string('url')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->foreign('questionnaire_set_id')->references('id')->on('qa_questionnaire_sets'); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qa_questions'); + } +} diff --git a/database/migrations/2024_11_26_025531_change_value_column_to_text_in_key_value_pairs_table.php b/database/migrations/2024_11_26_025531_change_value_column_to_text_in_key_value_pairs_table.php new file mode 100644 index 00000000..b7fe759e --- /dev/null +++ b/database/migrations/2024_11_26_025531_change_value_column_to_text_in_key_value_pairs_table.php @@ -0,0 +1,32 @@ +text('value')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('key_value_pairs', function (Blueprint $table) { + $table->string('value', 191)->change(); + }); + } +} diff --git a/database/migrations/2024_11_26_025531_create_qa_answer_options_table.php b/database/migrations/2024_11_26_025531_create_qa_answer_options_table.php new file mode 100644 index 00000000..9198768a --- /dev/null +++ b/database/migrations/2024_11_26_025531_create_qa_answer_options_table.php @@ -0,0 +1,41 @@ +id(); + $table->text('display_text'); + $table->string('value'); + $table->unsignedBigInteger('order')->default(0); + $table->string('question_number'); + $table->string('next_question_number')->nullable(); + $table->unsignedBigInteger('questionnaire_set_id'); + $table->timestamps(); + $table->softDeletes(); + + $table->foreign('questionnaire_set_id')->references('id')->on('qa_questionnaire_sets'); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qa_answer_options'); + } +} diff --git a/database/migrations/2024_11_26_025531_create_qa_user_answer_selected_table.php b/database/migrations/2024_11_26_025531_create_qa_user_answer_selected_table.php new file mode 100644 index 00000000..a7ce3977 --- /dev/null +++ b/database/migrations/2024_11_26_025531_create_qa_user_answer_selected_table.php @@ -0,0 +1,46 @@ +id(); + $table->unsignedBigInteger('user_id')->default(0); + $table->unsignedBigInteger('source_id')->default(0); + $table->unsignedBigInteger('question_id'); + $table->longText('question_metadata')->nullable(); + $table->unsignedBigInteger('answer_option_id'); + $table->text('answer')->nullable(); + $table->string('reference')->nullable(); + $table->integer('time_used_seconds')->nullable(); + $table->tinyInteger('is_previous')->default(0); + $table->timestamps(); + $table->softDeletes(); + + $table->foreign('question_id')->references('id')->on('qa_questions'); + // $table->foreign('answer_option_id')->references('id')->on('qa_answer_options'); + // $table->foreign('user_id')->references('id')->on('users'); + // $table->foreign('source_id')->references('id')->on('qa_user_source'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qa_user_answer_selected'); + } +} diff --git a/database/migrations/2024_11_26_025531_create_qa_user_source_table.php b/database/migrations/2024_11_26_025531_create_qa_user_source_table.php new file mode 100644 index 00000000..638a8d44 --- /dev/null +++ b/database/migrations/2024_11_26_025531_create_qa_user_source_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('system'); + $table->string('email'); + $table->string('marking'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qa_user_source'); + } +} diff --git a/database/migrations/2024_12_28_142918_add_group_to_qa_questions_table.php b/database/migrations/2024_12_28_142918_add_group_to_qa_questions_table.php new file mode 100644 index 00000000..372874ab --- /dev/null +++ b/database/migrations/2024_12_28_142918_add_group_to_qa_questions_table.php @@ -0,0 +1,32 @@ +string('group')->after('questionnaire_set_id')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('qa_questions', function (Blueprint $table) { + $table->dropColumn('group'); + }); + } +} diff --git a/database/migrations/2025_02_17_105441_add_is_admin_filter_to_qa_questions_table.php b/database/migrations/2025_02_17_105441_add_is_admin_filter_to_qa_questions_table.php new file mode 100644 index 00000000..b16fb12c --- /dev/null +++ b/database/migrations/2025_02_17_105441_add_is_admin_filter_to_qa_questions_table.php @@ -0,0 +1,32 @@ +boolean('is_admin_filter')->after('url')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('qa_questions', function (Blueprint $table) { + $table->dropColumn('is_admin_filter'); + }); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index eb94b74f..a12bc52d 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -5,6 +5,7 @@ use Database\Seeders\CompaniesTableDevelopmentSeeder; use Database\Seeders\CurrenciesTableDevelopmentSeeder; use Database\Seeders\CurrencyRatesTableDevelopmentSeeder; use Database\Seeders\DummyDataSeeder; +use Database\Seeders\QAWorkFlowSeeder; use Database\Seeders\SegmentConstantsTableDevelopmentSeeder; use Database\Seeders\SegmentsTableDevelopmentSeeder; use Database\Seeders\ServiceTypesTableDevelopmentSeeder; @@ -20,7 +21,7 @@ class DatabaseSeeder extends Seeder */ public function run() { - DB::beginTransaction(); + DB::beginTransaction(); //General $this->call(CountriesTableSeeder::class); @@ -48,6 +49,9 @@ class DatabaseSeeder extends Seeder $this->call(DummyDataSeeder::class); } + // Admin Work Flow + $this->call(QAWorkFlowSeeder::class); + // DB::commit(); } } diff --git a/database/seeds/QAWorkFlowSeeder.php b/database/seeds/QAWorkFlowSeeder.php new file mode 100644 index 00000000..bc875b5a --- /dev/null +++ b/database/seeds/QAWorkFlowSeeder.php @@ -0,0 +1,776 @@ + 'Admin Work Flow', + 'description' => 'Admin Work Flow', + 'group' => '1688,approve_po,fill_po', + 'version' => 1, + 'questions' => [ + [ + 'question_number' => 'node_0', + 'question_title' => 'Are you ready to work today?', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => true, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Yes', 'value' => 'start_work', 'next_question_number' => 'start_work'], + ['display_text' => 'No', 'value' => 'no_work', 'next_question_number' => 'no_work'], + ], + 'group' => '', + ], + [ + 'question_number' => 'start_work', + 'question_title' => 'What will you work on?', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => '1688', 'value' => '1688', 'next_question_number' => '1688'], + ['display_text' => 'Approve PO', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ['display_text' => 'Fill PO', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ], + 'group' => '', + ], + [ + 'question_number' => 'no_work', + 'question_title' => 'Come back when you are ready to work', + 'question_type' => QAType::DEFAULT, + 'is_start' => false, + 'is_end' => true, + 'group' => '', + ], + [ + 'question_number' => '1688', + 'question_title' => '1688', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'url' => 'api.admin_work_flow.fetch_oldest_order', //'http://localhost:8082/api/v1/admin-work-flow/fetch-oldest-order', //this.route("api.admin_work_flow.fetch_oldest_order"), + 'is_start' => true, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Login Issue', 'value' => '1688_login_issue', 'btn_color' => 'warning', 'next_question_number' => '1688_login_issue'], + ['display_text' => 'Login Successful', 'value' => '1688_login_successful', 'next_question_number' => '1688_login_successful'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_login_issue', + 'question_title' => '1688_login_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Need TAC', 'value' => '1688_login_issue_need_tac', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Wrong login details', 'value' => '1688_login_issue_wrong_login_details', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Others', 'value' => '1688_login_issue_others', 'next_question_number' => '1688_login_issue_others'], + ['display_text' => 'Order Cancelled', 'value' => '1688_login_issue_refund_request', 'next_question_number' => '1688_login_issue_refund_request'], + ], + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_login_successful', + 'question_title' => '1688_login_successful', + 'question_type' => QAType::MULTIPLE_CHOICES, + //'url' => 'api.admin_work_flow.fetch_model_attributes', //'http://localhost:8082/api/v1/admin-work-flow/{booking_id}/fetch-model-attributes', + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => "Can't verify order?", 'value' => '1688_login_successful_cannot_verify', 'next_question_number' => '1688_login_successful_cannot_verify'], + ['display_text' => 'Order Verified', 'value' => '1688_order_verify', 'next_question_number' => '1688_order_verify'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_login_successful_cannot_verify', + 'question_title' => '1688_login_successful_cannot_verify', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Amount not found', 'value' => '1688_login_successful_cannot_verify_amount_not_found', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Plus Member', 'value' => '1688_login_successful_cannot_verify_plus_member', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Others', 'value' => '1688_login_successful_cannot_verify_others', 'next_question_number' => '1688_login_successful_cannot_verify_others'], + ['display_text' => 'Customer did not verify 1688 account', 'value' => '1688_login_successful_cannot_verify_customer_did_not_verify_account', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'WorldFirst account linked another account', 'value' => '1688_login_successful_cannot_verify_worldfirst_account_linked_another_account', 'next_question_number' => '1688_issue_submit'], + ], + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_login_successful_cannot_verify_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => '1688_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_order_verify', + 'question_title' => 'Order Amount (CNY)', + 'question_description' => 'Please key in the order amount', + 'question_' => 'Order Amount', + 'question_type' => QAType::FLOAT_MONEY, + 'next_nested_question' => '1688_order_verification', + //'url' => 'api.admin_work_flow.fetch_model_attributes', + 'is_start' => false, + 'is_end' => false, + // 'answer_options' => [ + // ['display_text' => 'Yes', 'value' => '1688_order_verification', 'next_question_number' => '1688_order_verification'], + // ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_order_verification', + 'question_title' => 'Are You Sure this is the correct amount?', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Yes', 'value' => '1688_order_verified', 'next_question_number' => '1688_order_verified'], + ['display_text' => 'No', 'value' => '1688_order_verified', 'next_question_number' => '1688_order_verified'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_proceed_order', + 'question_title' => 'Proceed the order on 1688?', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Yes', 'value' => '1688_submit', 'next_question_number' => '1688_submit'], + ['display_text' => 'Got Issue', 'value' => '1688_proceed_order_issue', 'next_question_number' => '1688_proceed_order_issue'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_proceed_order_issue', + 'question_title' => '1688_proceed_order_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Wrong Pin Number', 'value' => '1688_proceed_order_issue_wrong_pin_number', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Not Enough Stock', 'value' => '1688_proceed_order_issue_not_enough_stock', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'Others', 'value' => '1688_proceed_order_issue_others', 'next_question_number' => '1688_proceed_order_issue_others'], + ['display_text' => 'No CrossBoarder', 'value' => '1688_proceed_order_issue_no_crossborder', 'next_question_number' => '1688_issue_submit'], + ['display_text' => 'AngPau', 'value' => '1688_proceed_order_issue_angpau', 'next_question_number' => '1688_issue_submit'], + ], + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_proceed_order_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => '1688_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_login_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => '1688_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_submit', + 'question_title' => '1688_submit', + 'question_type' => QAType::SUBMIT_1688_3_TYPES_DOCUMENTS, + 'next_nested_question' => '1688_documents_submitted', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + ], + [ + 'question_number' => '1688_documents_submitted', + 'question_title' => 'Thank you for the hard work', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_login_issue_refund_request', + 'question_title' => 'Refund Request sent', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + // [ + // 'question_number' => '1688_insufficient_order', + // 'question_title' => 'Are You Sure this is the correct amount?', + // 'question_type' => QAType::MULTIPLE_CHOICES, + // 'is_start' => false, + // 'is_end' => false, + // 'answer_options' => [ + // ['display_text' => 'Underpaid Order', 'value' => 'underpaid_order_1', 'next_question_number' => '1688_issue_submit'], + // ['display_text' => 'Underpaid Order', 'value' => 'underpaid_order_2', 'next_question_number' => '1688_issue_submit'], + // ['display_text' => 'Overpaid Order', 'value' => 'underpaid_order_2', 'next_question_number' => '1688_issue_submit'], + // ], + // 'group' => '1688', + // ], + // [ + // 'question_number' => '1688_order_paid_precisely', + // 'question_title' => 'Amount paid is same as recorded in system', + // 'question_type' => QAType::MULTIPLE_CHOICES, + // 'is_start' => false, + // 'is_end' => false, + // 'answer_options' => [ + // ['display_text' => 'Done', 'value' => '1688_issue_submit', 'next_question_number' => '1688_issue_submit'], + // ], + // 'group' => '1688', + // ], + [ + 'question_number' => '1688_underpaid_order_1', + 'question_title' => "This order is underpaid. Clicking 'Next' will deduct the amount short from wallet automatically. ", + 'question_type' => QAType::DEFAULT, + 'is_start' => false, + 'is_end' => false, + 'next_nested_question' => '1688_underpaid_order_1_proceed', + // 'answer_options' => [ + // ['display_text' => 'Proceed', 'value' => '1688_underpaid_order_1_proceed', 'next_question_number' => '1688_underpaid_order_1_proceed'], + // ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_order_1_proceed', + 'question_title' => "The missing amount has successfully been deducted from the customer’s wallet", + 'question_type' => QAType::DEFAULT, + 'is_start' => false, + 'is_end' => true, + 'next_nested_question' => '1688_underpaid_proceed_order', + // 'answer_options' => [ + // ['display_text' => 'Done', 'value' => '1688_issue_submit', 'next_question_number' => '1688_issue_submit'], + // ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_order_2', + 'question_title' => 'Underpaid Order', + 'question_description' => 'Insufficient wallet balance. Refund request to be sent', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Done', 'value' => '1688_underpaid_order_2_submitted', 'next_question_number' => '1688_underpaid_order_2_submitted'], + ], + 'group' => '1688', + ], + // [ + // 'question_number' => '1688_underpaid_order_3', + // 'question_title' => 'Underpaid Order?', + // 'question_description' => 'There is no outstanding on record, please go back and check if the amount processed is entered correctly.', + // 'question_type' => QAType::MULTIPLE_CHOICES, + // 'is_start' => false, + // 'is_end' => false, + // 'answer_options' => [ + // ['display_text' => 'Done', 'value' => '1688_issue_submit', 'next_question_number' => '1688_issue_submit'], + // ], + // 'group' => '1688', + // ], + [ + 'question_number' => '1688_overpaid_order', + 'question_title' => 'Overpaid Order', + 'question_description' => 'Exceeded amount to be refunded to customer’s wallet', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Next', 'value' => '1688_overpaid_proceed_order', 'next_question_number' => '1688_overpaid_proceed_order'], + ], + 'group' => '1688', + ], + + // 1688 underpaid - starts + [ + 'question_number' => '1688_underpaid_proceed_order', + 'question_title' => 'Please process the order on 1688', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Yes', 'value' => '1688_underpaid_documents_submission', 'next_question_number' => '1688_underpaid_documents_submission'], + ['display_text' => 'Got Issue', 'value' => '1688_underpaid_proceed_order_issue', 'next_question_number' => '1688_underpaid_proceed_order_issue'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_proceed_order_issue', + 'question_title' => '1688_underpaid_proceed_order_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Wrong Pin Number', 'value' => '1688_underpaid_proceed_order_issue_wrong_pin_number', 'next_question_number' => '1688_underpaid_issue_submit'], + ['display_text' => 'Not Enough Stock', 'value' => '1688_underpaid_proceed_order_issue_not_enough_stock', 'next_question_number' => '1688_underpaid_issue_submit'], + ['display_text' => 'Others', 'value' => '1688_underpaid_proceed_order_issue_others', 'next_question_number' => '1688_underpaid_proceed_order_issue_others'], + ['display_text' => 'No CrossBoarder', 'value' => '1688_underpaid_proceed_order_issue_no_crossborder', 'next_question_number' => '1688_underpaid_issue_submit'], + ['display_text' => 'AngPau', 'value' => '1688_underpaid_proceed_order_issue_angpau', 'next_question_number' => '1688_underpaid_issue_submit'], + ], + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_underpaid_proceed_order_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => '1688_underpaid_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_underpaid_documents_submission', + 'question_title' => '1688_underpaid_documents_submission', + 'question_type' => QAType::SUBMIT_1688_3_TYPES_DOCUMENTS, + 'next_nested_question' => '1688_underpaid_documents_submitted', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_documents_submitted', + 'question_title' => 'Thank you for your hard work', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_underpaid_order_2_submitted', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + // 1688 underpaid - ends + // 1688 overpaid - starts + [ + 'question_number' => '1688_overpaid_proceed_order', + 'question_title' => 'Please process the order on 1688', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Yes', 'value' => '1688_overpaid_documents_submission', 'next_question_number' => '1688_overpaid_documents_submission'], + ['display_text' => 'Got Issue', 'value' => '1688_overpaid_proceed_order_issue', 'next_question_number' => '1688_overpaid_proceed_order_issue'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_overpaid_proceed_order_issue', + 'question_title' => '1688_overpaid_proceed_order_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Wrong Pin Number', 'value' => '1688_overpaid_proceed_order_issue_wrong_pin_number', 'next_question_number' => '1688_overpaid_issue_submit'], + ['display_text' => 'Not Enough Stock', 'value' => '1688_overpaid_proceed_order_issue_not_enough_stock', 'next_question_number' => '1688_overpaid_issue_submit'], + ['display_text' => 'Others', 'value' => '1688_overpaid_proceed_order_issue_others', 'next_question_number' => '1688_overpaid_proceed_order_issue_others'], + ['display_text' => 'No CrossBoarder', 'value' => '1688_overpaid_proceed_order_issue_no_crossborder', 'next_question_number' => '1688_overpaid_issue_submit'], + ['display_text' => 'AngPau', 'value' => '1688_overpaid_proceed_order_issue_angpau', 'next_question_number' => '1688_overpaid_issue_submit'], + ], + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_overpaid_proceed_order_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => '1688_overpaid_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + 'is_admin_filter' => true + ], + [ + 'question_number' => '1688_overpaid_documents_submission', + 'question_title' => '1688_overpaid_documents_submission', + 'question_type' => QAType::SUBMIT_1688_3_TYPES_DOCUMENTS, + 'next_nested_question' => '1688_overpaid_documents_submitted', + 'is_start' => false, + 'is_end' => false, + 'group' => '1688', + ], + [ + 'question_number' => '1688_overpaid_documents_submitted', + 'question_title' => 'Thank you for your hard work', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + [ + 'question_number' => '1688_overpaid_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next Order', 'value' => '1688', 'next_question_number' => '1688'], + ], + 'group' => '1688', + ], + // 1688 overpaid - ends + + [ + 'question_number' => 'approve_po', + 'question_title' => 'approve_po', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'url' => "api.admin_work_flow.fetch_pending_approve_po", + 'is_start' => true, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Approve', 'value' => 'approve_po_approved', 'next_question_number' => 'approve_po_approved'], + ['display_text' => 'Edit PO', 'value' => 'approve_po_edit', 'next_question_number' => 'approve_po_edit'], + ['display_text' => 'Reject', 'value' => 'approve_po_reject', 'next_question_number' => 'approve_po_reject'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'fill_po', + 'question_title' => 'fill_po', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'url' => "api.admin_work_flow.fetch_pending_fill_po", + 'is_start' => true, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Edit PO', 'value' => 'fill_po_edit', 'next_question_number' => 'fill_po_edit'], + ], + 'group' => 'fill_po', + ], + [ + 'question_number' => 'approve_po_filled', + 'question_title' => 'PO Filled', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'approve_po_approved', + 'question_title' => 'PO Approved', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'approve_po_edit', + 'question_title' => 'approve_po_edit', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'url' => "api.booking.show", + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Issue?', 'value' => 'approve_po_edit_po_issue', 'next_question_number' => 'approve_po_edit_po_issue'], + ['display_text' => 'Done', 'value' => 'approve_po_filled', 'next_question_number' => 'approve_po_filled'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'approve_po_reject', + 'question_title' => 'PO Rejected', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Sensitive Goods', 'value' => 'Sensitive Goods', 'next_question_number' => 'approve_po_reject_others_complete'], + ['display_text' => 'Others', 'value' => 'approve_po_reject_others', 'next_question_number' => 'approve_po_reject_others'], + // ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + // ['display_text' => 'Next Order', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'approve_po_reject_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => 'approve_po_reject_others_complete', + 'is_start' => false, + 'is_end' => false, + 'group' => 'approve_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'approve_po_reject_others_complete', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'approve_po_edit_po_issue', + 'question_title' => 'approve_po_edit_po_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Sensitive Goods', 'value' => 'Sensitive Goods', 'next_question_number' => 'approve_po_edit_po_issue_submit'], + ['display_text' => 'Others', 'value' => 'approve_po_edit_po_issue_others', 'next_question_number' => 'approve_po_edit_po_issue_others'], + ], + 'group' => 'approve_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'approve_po_edit_po_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'approve_po_edit_po_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => 'approve_po_edit_po_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => 'approve_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'approve_po_edit_po_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'approve_po', + ], + [ + 'question_number' => 'fill_po_issue_others', + 'question_title' => 'What other issues did you encounter? Upload documents if needed', + 'question_type' => QAType::REMARKS_WITH_DOCUMENT_UPLOAD, + 'next_nested_question' => 'fill_po_issue_submit', + 'is_start' => false, + 'is_end' => false, + 'group' => 'fill_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'fill_po_issue_submit', + 'question_title' => 'Issue has been submitted', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'fill_po', + ], + [ + 'question_number' => 'fill_po_edit', + 'question_title' => 'fill_po_edit', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'url' => "api.booking.show", + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Issue?', 'value' => 'fill_po_edit_issue', 'next_question_number' => 'fill_po_edit_issue'], + ['display_text' => 'Done', 'value' => 'fill_po_edit_filled', 'next_question_number' => 'fill_po_edit_filled'], + ], + 'group' => 'fill_po', + ], + [ + 'question_number' => 'fill_po_edit_issue', + 'question_title' => 'fill_po_edit_issue', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => false, + 'answer_options' => [ + ['display_text' => 'Sensitive Goods', 'value' => 'Sensitive Goods', 'next_question_number' => 'fill_po_issue_submit'], + ['display_text' => 'Others', 'value' => 'fill_po_issue_others', 'next_question_number' => 'fill_po_issue_others'], + ], + 'group' => 'fill_po', + 'is_admin_filter' => true + ], + [ + 'question_number' => 'fill_po_edit_filled', + 'question_title' => 'PO Filled', + 'question_type' => QAType::MULTIPLE_CHOICES, + 'is_start' => false, + 'is_end' => true, + 'answer_options' => [ + ['display_text' => 'Stop Working', 'value' => 'stop_working', 'next_question_number' => 'stop_working'], + ['display_text' => 'Next PO (Fill)', 'value' => 'fill_po', 'next_question_number' => 'fill_po'], + ['display_text' => 'Next PO (Approve)', 'value' => 'approve_po', 'next_question_number' => 'approve_po'], + ], + 'group' => 'fill_po', + ], + [ + 'question_number' => 'stop_working', + 'question_title' => 'Thank you. Reload page to restart.', + 'question_type' => QAType::DEFAULT, + 'is_start' => false, + 'is_end' => true, + 'group' => '', + ], + ] + ], + ]; + + foreach ($questionnaireSets as $set) { + $questionnaireSet = QAQuestionnaireSet::create([ + 'name' => $set['name'], + 'description' => $set['description'], + 'group' => $set['group'], + ]); + + foreach ($set['questions'] as $key => $questionData) { + $question = new QAQuestions; + $question->question_number = $questionData['question_number']; + $question->question_title = $questionData['question_title']; + if (isset($questionData['question_description'])) { + $question->question_description = $questionData['question_description']; + } + $question->question_type = $questionData['question_type']; + $question->questionnaire_set_id = $questionnaireSet->id; + if (isset($questionData['group']) && $questionData['group'] != '') { + $question->group = $questionData['group']; + } + + if (isset($questionData['next_nested_question'])) { + $question->next_nested_question = $questionData['next_nested_question']; + } + if (isset($questionData['next_main_question'])) { + $question->next_main_question = $questionData['next_main_question']; + } + + $question->is_start = $questionData['is_start']; + $question->is_end = $questionData['is_end']; + if (isset($questionData['end_text'])) { + $question->end_text = $questionData['end_text']; + } + + if (isset($questionData['url'])) { + $question->url = $questionData['url']; + } + + if (isset($questionData['is_admin_filter'])) { + $question->is_admin_filter = $questionData['is_admin_filter']; + } + + $question->order = $key + 1; + $question->save(); + + if (isset($questionData['answer_options'])) { + foreach ($questionData['answer_options'] as $optionData) { + $answerOption = new QAAnswerOptions; + $answerOption->display_text = $optionData['display_text']; + $answerOption->value = $optionData['value']; + $answerOption->question_number = $questionData['question_number']; + $answerOption->next_question_number = $optionData['next_question_number'] ?? null; + $answerOption->questionnaire_set_id = $questionnaireSet->id; + $answerOption->save(); + } + } + } + } + } +} diff --git a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue new file mode 100644 index 00000000..9a25f5af --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswer2Component.vue @@ -0,0 +1,202 @@ + + + diff --git a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue new file mode 100644 index 00000000..f0f215f7 --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerComponent.vue @@ -0,0 +1,146 @@ + + + diff --git a/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerInnerComponent.vue b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerInnerComponent.vue new file mode 100644 index 00000000..298960e5 --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/elements/QuestionAnswerInnerComponent.vue @@ -0,0 +1,86 @@ + + diff --git a/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSection2Component.vue b/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSection2Component.vue new file mode 100644 index 00000000..fa106a22 --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSection2Component.vue @@ -0,0 +1,194 @@ + + + + diff --git a/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSectionComponent.vue b/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSectionComponent.vue new file mode 100644 index 00000000..cd474f76 --- /dev/null +++ b/resources/assets/vue/components/admin-workflow/sections/QuestionAnswerSectionComponent.vue @@ -0,0 +1,167 @@ + + + + diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index de4e496b..c6b1aa76 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -283,7 +283,9 @@ this.parameters = { products: this.products }; - + this.$emit('update-parameters', { + parameters: this.parameters, + }); this.submit(route('api.transaction.po.create', this.data.id), 'post', this.section, true, true); }, uploadProducts() { @@ -291,13 +293,18 @@ this.parameters = { files: this.files }; - + this.$emit('update-parameters', { + parameters: this.parameters, + }); this.submit(route('api.transaction.po.import', this.data.id), 'post', this.section, true, true); }, successHandler(){ if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ this.submitted = true; } + this.$emit('amount-tally-poTotal', { + isDone: this.submitted, + }); this.updateList() }, addProduct(){ diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormReadOnlyComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormReadOnlyComponent.vue new file mode 100644 index 00000000..8d3b22cb --- /dev/null +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormReadOnlyComponent.vue @@ -0,0 +1,86 @@ + + diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderItemFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderItemFormComponent.vue index d91d2661..518dfda1 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderItemFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderItemFormComponent.vue @@ -35,7 +35,7 @@

Unit Price

-

{{product.unit_price}}

+

{{product.unit_price.toFixed(3)}}

Quantity

@@ -144,7 +144,7 @@ }, created() { this.product = this.data; - this.product.unit_price = (Math.round((this.product.unit_price+ Number.EPSILON) * 1000) / 1000).toFixed(3) + this.product.unit_price = (Math.round((this.product.unit_price+ Number.EPSILON) * 1000) / 1000); }, computed: { productTotal(){ diff --git a/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue b/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue index f8598c69..dee98112 100644 --- a/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/AddVoucherOptionsSectionComponent.vue @@ -14,8 +14,7 @@
- - +
diff --git a/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue b/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue index 145dd0f7..b7a92111 100644 --- a/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue +++ b/resources/assets/vue/components/general/elements/OpenLinkInNewTabComponent.vue @@ -33,6 +33,10 @@ type: Boolean, default: true }, + onClick: { + type: Function, + default: null + } }, data() { return { @@ -75,6 +79,9 @@ }); }, handleClick(){ + if(this.onClick){ + this.url = this.onClick(); + } this.isDownloading = true; if(window.LARAVEL_VAPOR_ENABLED){ this.submit(this.url, 'get', this.section, false, false); diff --git a/resources/assets/vue/components/general/forms/AdminWorkFlowFormComponent.vue b/resources/assets/vue/components/general/forms/AdminWorkFlowFormComponent.vue new file mode 100644 index 00000000..785d9ecf --- /dev/null +++ b/resources/assets/vue/components/general/forms/AdminWorkFlowFormComponent.vue @@ -0,0 +1,760 @@ + + + diff --git a/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue b/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue deleted file mode 100644 index 05a4e007..00000000 --- a/resources/assets/vue/components/general/forms/SelectableHardCodedComponent.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/resources/assets/vue/components/general/sections/AdminWorkFlowSectionComponent.vue b/resources/assets/vue/components/general/sections/AdminWorkFlowSectionComponent.vue new file mode 100644 index 00000000..4770fdf8 --- /dev/null +++ b/resources/assets/vue/components/general/sections/AdminWorkFlowSectionComponent.vue @@ -0,0 +1,670 @@ + + + diff --git a/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue b/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue index 461a447b..7a8c1bac 100644 --- a/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue +++ b/resources/assets/vue/components/settings/forms/AddMilestoneFormComponent.vue @@ -20,7 +20,7 @@ - +
diff --git a/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue b/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue index b00be4b0..6d975d4f 100644 --- a/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue +++ b/resources/assets/vue/components/settings/forms/AddRewardFormComponent.vue @@ -36,7 +36,7 @@
- +
@@ -44,7 +44,7 @@
- +
diff --git a/resources/assets/vue/general/mixins/request.js b/resources/assets/vue/general/mixins/request.js index 4048415a..0b246f2a 100644 --- a/resources/assets/vue/general/mixins/request.js +++ b/resources/assets/vue/general/mixins/request.js @@ -37,11 +37,11 @@ export default { if (!success) { this.openModal(); errorNotification ? this.$store.dispatch('createNotification', { title: response.title, message: response.message, type: 'error' }) : null; - this.errorHandler(response, statusCode); return; + this.errorHandler(response, statusCode, section); return; } successNotification ? this.$store.dispatch('createNotification', { title: response.title, message: response.message, type: 'success' }) : null; - this.successHandler(response) + this.successHandler(response, section); }); diff --git a/resources/assets/vue/vuex/modules/loadRequestQueue.js b/resources/assets/vue/vuex/modules/loadRequestQueue.js index 3bb574c5..76faf8d1 100644 --- a/resources/assets/vue/vuex/modules/loadRequestQueue.js +++ b/resources/assets/vue/vuex/modules/loadRequestQueue.js @@ -15,7 +15,11 @@ export default { return state.queue.find(list => list.name === name); }, getListData: (state, getters) => (name) => { - return (!getters.isInCompleteQueue()) ? state.queue.find(list => list.name === name).data : []; + if (!getters.isInCompleteQueue(name)) { + const list = state.queue.find(list => list.name === name); + return list ? list.data : []; + } + return []; }, getSelectableList: (state, getters) => (name) => { let list = state.queue.find(list => list.name === name); @@ -68,4 +72,4 @@ export default { store.commit('SET_LIST_COMPLETE', {name: payload.name, data: payload.data}); } } -} \ No newline at end of file +} diff --git a/resources/views/pages/admin-workflow/list-workflow.blade.php b/resources/views/pages/admin-workflow/list-workflow.blade.php new file mode 100644 index 00000000..d70936ca --- /dev/null +++ b/resources/views/pages/admin-workflow/list-workflow.blade.php @@ -0,0 +1,56 @@ +@extends('layouts.base_portal') +@section('inner_content') + + +
+
+
+
+
+
+
+
+
+
+
Questions
+
+
+
+
+
+
+
+
+
+
+
Groups
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+@endsection diff --git a/resources/views/pages/dashboards/admin_work_flow.blade.php b/resources/views/pages/dashboards/admin_work_flow.blade.php new file mode 100644 index 00000000..558ab193 --- /dev/null +++ b/resources/views/pages/dashboards/admin_work_flow.blade.php @@ -0,0 +1,5 @@ +@extends('layouts.base_portal') +@section('inner_content') + + +@endsection diff --git a/routes/admin_workflow.php b/routes/admin_workflow.php new file mode 100644 index 00000000..201df14e --- /dev/null +++ b/routes/admin_workflow.php @@ -0,0 +1,162 @@ + $message]; + + if ($data !== null) { + $response['data'] = $data; + } + + return response()->json($response, $status); + } +} + +if (!function_exists('markedProcessing')) { + function markedProcessing($model, $key){ + $kvp = $model->attributesKVP()->where('key', $key)->first(); + + if($kvp){ + $kvp->delete(); + $kvp = null; + } + + if(!$kvp){ + $keyValuePairObject = new KeyValuePairObject($key, true); + (App()->make(CreatesKeyValuePair::class))->execute($model, $keyValuePairObject); + } + } +} + +Route::group(['prefix' => 'admin-work-flow', 'as' => 'admin_work_flow.', 'namespace' => 'Questionnaires'], function () { + + Route::get('/fetch-booking', [AdminWorkflowBaseController::class, 'fetchBooking'])->name('fetch_oldest_order'); + // Route::get('{booking_id}/fetch-model-attributes', [AdminWorkflowBaseController::class, 'fetchModelAttributes'])->name('fetch_model_attributes'); + Route::get('/fetch-pending-approved-po', [AdminWorkflowBaseController::class, 'fetchPendingApprovalPO'])->name('fetch_pending_approve_po'); + Route::get('/fetch-pending-fill-po', [AdminWorkflowBaseController::class, 'fetchPendingFillPO'])->name('fetch_pending_fill_po'); + + + // Route::post('/add-workflow-timestamp', function (Request $request) { + // $validator = Validator::make($request->all(), [ + // 'current_node' => 'required|string', + // 'next_node' => 'required|string', + // 'seconds' => 'required|integer', + // 'user_id' => 'required|integer|exists:users,id', + // 'session_id' => 'required|string', + // ]); + + // if ($validator->fails()) { + // throw new RequestValidationException($validator->messages()->first()); + // } + + // $workflowTimestamp = WorkflowTimestamp::create($validator->validated()); + + // return responseJson($workflowTimestamp, 'Workflow timestamp created successfully', 201); + // })->name('add_workflow_timestamp'); + + + // Route::post('/create-1688-login-issue-remark', function (Request $request) { + // $validator = Validator::make($request->all(), [ + // 'booking_id' => 'required', + // 'remark' => 'required', + // 'user_id' => 'required', + // ]); + + // if ($validator->fails()) { + // throw new RequestValidationException($validator->messages()->first()); + // } + + // $booking = Booking::find($request->booking_id); + + // if (!$booking) { + // return responseJson(null, 'Booking not found', 404); + // } + + // $remark = new Remark([ + // 'commenter_id' => $request->user_id, + // 'content' => $request->remark, + // 'owner_type' => get_class($booking), + // 'owner_id' => $booking->id, + // ]); + + // $remark->save(); + + // return responseJson($remark, 'Remark created successfully', 201); + // })->name('create_1688_login_issue_remark'); + + // Route::post('/create_issue_remark', function (Request $request) { + // $validator = Validator::make($request->all(), [ + // 'booking_id' => 'required', + // 'remark' => 'required', + // 'user_id' => 'required', + // ]); + + // if ($validator->fails()) { + // throw new RequestValidationException($validator->messages()->first()); + // } + + // $booking = Booking::find($request->booking_id); + + + // if (!$booking) { + // return responseJson(null, 'Booking not found', 404); + // } + + // $remark = new Remark([ + // 'commenter_id' => $request->user_id, + // 'content' => $request->remark, + // 'owner_type' => get_class($booking), + // 'owner_id' => $booking->id, + // ]); + + // $remark->save(); + + // return responseJson($remark, 'Remark created successfully', 201); + // })->name('create_issue_remark'); + + // Route::post('/create_po_issue_remark', function (Request $request) { + // $validator = Validator::make($request->all(), [ + // 'booking_id' => 'required', + // 'remark' => 'required', + // 'user_id' => 'required', + // ]); + + // if ($validator->fails()) { + // return response()->json(['message' => $validator->messages()->first()], 400); // Return validation error + // } + + // $booking = Booking::find($request->booking_id); + + // if (!$booking) { + // return response()->json(['message' => 'Booking not found'], 404); + // } + + // $remark = new Remark([ + // 'commenter_id' => $request->user_id, + // 'content' => $request->remark, + // 'owner_type' => get_class($booking), + // 'owner_id' => $booking->id, + // ]); + + // $remark->save(); + + // return response()->json(['data' => $remark, 'message' => 'Remark created successfully'], 201); + // })->name('create_po_issue_remark'); + +}); diff --git a/routes/api.php b/routes/api.php index ef7025a5..c9b6a9c8 100644 --- a/routes/api.php +++ b/routes/api.php @@ -71,6 +71,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/job.php'; + require __DIR__ . '/questionnaires.php'; + + require __DIR__ . '/admin_workflow.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/questionnaires.php b/routes/questionnaires.php new file mode 100644 index 00000000..df2d168c --- /dev/null +++ b/routes/questionnaires.php @@ -0,0 +1,19 @@ + 'questionnaires', 'as' => 'questionnaires.', 'namespace' => 'Questionnaires'], function () { + Route::get('/list', 'ListQuestionnaireSetController@list')->name('list'); + Route::get('/{set_id}', 'FetchQuestionV1AdminWFController@fetch')->name('first.question'); + Route::post('/question', 'UpdateNextQuestionV1AdminWFController@fetch')->name('next.question'); + + Route::group(['prefix' => 'qa', 'as' => 'qa.'], function () { + Route::get('/list', 'ListQuestionsAnswersController@list')->name('list'); + Route::get('/export1', '\\App\\Http\\Controllers\\Exports\\ExportQuestionsAnswersController@exportWithGroups')->name('export.with.groups'); + Route::get('/export2', '\\App\\Http\\Controllers\\Exports\\ExportQuestionsAnswersController@exportWithoutGroups')->name('export.without.groups'); + }); + + Route::group(['prefix' => 'q', 'as' => 'q.'], function () { + Route::get('/list/{set_id}', 'ListQuestionsController@list')->name('list'); + }); +}); diff --git a/routes/web.php b/routes/web.php index 1014aea6..f4925f1f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1202,42 +1202,42 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', const fileInput = form.querySelector("input[type=\'file\']"); const files = fileInput.files; const userToken = localStorage.getItem("user-token"); - + if (files.length === 0) { alert("Please select at least one file to upload."); return; } - + const fileReaders = []; let totalFiles = files.length; - + // Create a promise for each file to read it as Base64 Array.from(files).forEach((file) => { const reader = new FileReader(); - + // Create a promise that resolves when the file is read const fileReadPromise = new Promise((resolve, reject) => { reader.onload = (event) => { resolve(event.target.result); }; - + reader.onerror = (error) => { reject(error); }; - + reader.readAsDataURL(file); // Read the file as Data URL (Base64) }); - + fileReaders.push(fileReadPromise); }); - + // Wait for all files to be read Promise.all(fileReaders) .then((fileData) => { const payload = { files: fileData, // Array of objects with name, type, and Base64 content }; - + // Send the payload as JSON return fetch(`/api/v1/transactions/${billId}/bill/verification`, { method: "POST", @@ -1359,7 +1359,15 @@ Route::get('/site.webmanifest', function () { return response($contents, 200)->header('Content-Type', 'application/manifest+json'); }); - Route::get('/test-test', function () { dd('test-test'); }); + +Route::get('/admin-workflow', function () { + return view('pages.dashboards.admin_work_flow'); +})->name('admin-workflow'); + + +Route::get('/admin-workflow/list', function () { + return view('pages.admin-workflow.list-workflow'); +})->name('admin-workflow.list');