Admin Workflow - API code refactor to fetch information to display on workflow

This commit is contained in:
Dillon Ngo
2025-01-04 22:38:42 +08:00
parent abe1f3df2b
commit db36336484
9 changed files with 249 additions and 115 deletions
@@ -94,6 +94,11 @@ class FetchAdminWFBookingLogic extends AbstractControllerLogic
// 'booking' => $booking
// ]);
// return responseJson([
// 'booking' => new BookingBaseResource($booking)
// ]);
return $this->resourceResponse(new BookingBaseResource($booking));
}
@@ -0,0 +1,91 @@
<?php
namespace App\Classes\Modules\Questionnaires\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Questionnaires\Standards\Rules\CanFetchQuestion;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingBaseResource;
use App\Http\Resources\BookingResource;
use App\Models\KeyValuePair;
use Carbon\Carbon;
use App\Models\Booking;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchAdminWFPendingApprovalPOLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Pending Approval PO for Admin Workflow ',
'message' => 'You have successfully retrieved Pending Approval PO for Admin Workflow'
];
}
/** @var CanFetchQuestion */ //cief todo: permission update
private $canFetchQuestion;
/**
* FetchAdminWFPendingApprovalPOLogic constructor.
* @param CanFetchQuestion $canFetchQuestion
*/
public function __construct(CanFetchQuestion $canFetchQuestion)
{
$this->canFetchQuestion = $canFetchQuestion;
}
/**
* @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()->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)
->whereHas('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER)->where('status', '<', ApprovalStatus::APPROVED))
->first();
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 BookingResource($booking));
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Classes\Modules\Questionnaires\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Questionnaires\Standards\Rules\CanFetchQuestion;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingBaseResource;
use App\Models\KeyValuePair;
use Carbon\Carbon;
use App\Models\Booking;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchAdminWFPendingFillPOLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Pending Fill PO for Admin Workflow ',
'message' => 'You have successfully retrieved Pending Fill PO for Admin Workflow'
];
}
/** @var CanFetchQuestion */ //cief todo: 74 - permission update
private $canFetchQuestion;
/**
* FetchAdminWFPendingFillPOLogic constructor.
* @param CanFetchQuestion $canFetchQuestion
*/
public function __construct(CanFetchQuestion $canFetchQuestion)
{
$this->canFetchQuestion = $canFetchQuestion;
}
/**
* @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();
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));
}
}
@@ -121,7 +121,7 @@ class UpdateNextQuestionV1AdminWFLogic extends AbstractControllerLogic
//Marked data that has already been processed so that it does not appear again
$isNoGoingBack = null;
if($currentQuestion && $currentQuestion['is_end'] === 1){
$booking = Booking::where('id', $questionMetadata['booking']['id'])->first();
$booking = Booking::where('id', $questionMetadata['id'])->first();
$key1 = "admin_workflow_processed";
$key2 = "admin_workflow_processing";
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Questionnaires;
use App\Classes\Modules\Questionnaires\ControllersLogic\FetchAdminWFBookingLogic;
use App\Classes\Modules\Questionnaires\ControllersLogic\FetchAdminWFModelAttributesLogic;
use App\Classes\Modules\Questionnaires\ControllersLogic\FetchAdminWFPendingApprovalPOLogic;
use App\Classes\Modules\Questionnaires\ControllersLogic\FetchAdminWFPendingFillPOLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -12,7 +14,7 @@ class AdminWorkflowBaseController
{
/**
* @param Request $request
* @param FetchQuestionV1AdminWFLogic $logic
* @param FetchAdminWFBookingLogic $logic
* @return JsonResponse
*/
public function fetchBooking(Request $request, FetchAdminWFBookingLogic $logic): JsonResponse {
@@ -27,4 +29,22 @@ class AdminWorkflowBaseController
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);
}
}
@@ -21,6 +21,7 @@ class BookingBaseResource extends JsonResource
'company' => new CompanyResource($this->company),
'bank' => new BankResource($this->bank),
'marking' => $this->marking,
'fixed_currency' => new CurrencyResource($this->fixedCurrency),
];
}
}
@@ -3,8 +3,8 @@
<div class="col-1">{{ item.id }}</div>
<div class="col-2">{{ item.question_title }}</div>
<div class="col-1">
<a :href="route('booking.details', JSON.parse(item.question_metadata).booking.marking)"
target="_blank">{{ JSON.parse(item.question_metadata).booking.marking }}
<a :href="route('booking.details', JSON.parse(item.question_metadata).marking)"
target="_blank">{{ JSON.parse(item.question_metadata).marking }}
</a>
</div>
<div class="col-1">{{ parsedAnswer === 'go_back' ? '' : item.answer }}</div>
@@ -19,7 +19,7 @@
<h4>{{question.question_description}}</h4>
<div v-if="question.question_number === '1688'">
<h1>Login Information</h1>
<div v-if="externalApiResponse.data.booking"
<div v-if="externalApiResponse"
class="row bg-master-light m-t-15 m-b-15 rounded padding-30 justify-content-center">
<div class="col-auto text-left">
<table>
@@ -28,8 +28,8 @@
<h3><span class="bold d-inline-block m-r-15">ORDER Marking: </span></h3>
</td>
<td>
<h3><a :href="route('booking.details', externalApiResponse.data.booking.marking)"
target="_blank">{{ externalApiResponse.data.booking.marking
<h3><a :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">{{ externalApiResponse.data.marking
}}</a></h3>
</td>
</tr>
@@ -39,7 +39,7 @@
</span></h3>
</td>
<td>
<h3>{{ externalApiResponse.data.booking.bank.account_no }}</h3>
<h3>{{ externalApiResponse.data.bank.account_no }}</h3>
</td>
</tr>
<tr>
@@ -48,7 +48,7 @@
</span></h3>
</td>
<td>
<h3>{{ externalApiResponse.data.booking.bank.holder_name }}</h3>
<h3>{{ externalApiResponse.data.bank.holder_name }}</h3>
</td>
</tr>
<tr>
@@ -57,7 +57,7 @@
</span></h3>
</td>
<td>
<h3>{{ externalApiResponse.data.booking.bank.bank_branch }}</h3>
<h3>{{ externalApiResponse.data.bank.bank_branch }}</h3>
</td>
</tr>
</table>
@@ -68,9 +68,9 @@
<div v-if="question.question_number === '1688_login_successful'">
<h3>
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
<a v-if="externalApiResponse.data.booking" :href="route('booking.details', externalApiResponse.data.booking.marking)"
<a v-if="externalApiResponse" :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">
{{ externalApiResponse.data.booking.marking }}
{{ externalApiResponse.data.marking }}
</a>
</h3>
<div v-if="externalApiResponse.data.reference" class="row bg-master-light m-t-15 m-b-15 rounded padding-30 justify-content-center">
@@ -112,14 +112,14 @@
</div>
<div v-if="question.question_number === '1688_order_verify'">
<h3 v-if="externalApiResponse.data.booking">
<h3 v-if="externalApiResponse">
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
<a :href="route('booking.details', externalApiResponse.data.booking.marking)"
<a :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">
{{ externalApiResponse.data.booking.marking }}
{{ externalApiResponse.data.marking }}
</a>
</h3>
<div v-if="externalApiResponse.data.booking" class="row bg-master-light m-t-15 m-b-15 rounded padding-30 justify-content-center">
<div v-if="externalApiResponse" class="row bg-master-light m-t-15 m-b-15 rounded padding-30 justify-content-center">
<div class="col-auto text-left">
<h3>
<span class="bold d-inline-block m-r-15">ORDER Reference(s): </span>
@@ -140,16 +140,16 @@
</div>
<div v-if="question.question_number === 'approve_po'">
<div v-if="externalApiResponse.data.booking" class="row">
<div v-if="externalApiResponse && externalApiResponse.data" class="row">
<div class="col">
<h3>
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
<a :href="route('booking.details', externalApiResponse.data.booking.marking)"
target="_blank">{{ externalApiResponse.data.booking.marking }}</a>
<a :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">{{ externalApiResponse.data.marking }}</a>
</h3>
<div class="row b-a b-primary padding-30 bg-white m-t-25">
<div class="col">
<purchase-order-form-read-only-component :data="externalApiResponse.data.booking" :companySegmentIds="companySegmentIds" :section="section"></purchase-order-form-read-only-component>
<purchase-order-form-read-only-component :data="externalApiResponse.data" :companySegmentIds="companySegmentIds" :section="section"></purchase-order-form-read-only-component>
</div>
</div>
</div>
@@ -157,16 +157,16 @@
</div>
<div v-if="question.question_number === 'fill_po'">
<div v-if="externalApiResponse.data.booking" class="row">
<div v-if="externalApiResponse && externalApiResponse.data" class="row">
<div class="col">
<h3>
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
<a :href="route('booking.details', externalApiResponse.data.booking.marking)"
target="_blank">{{ externalApiResponse.data.booking.marking }}</a>
<a :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">{{ externalApiResponse.data.marking }}</a>
</h3>
<div class="row b-a b-primary padding-30 bg-white m-t-25">
<div class="col">
<purchase-order-form-read-only-component :data="externalApiResponse.data.booking" :companySegmentIds="companySegmentIds" :section="section"></purchase-order-form-read-only-component>
<purchase-order-form-read-only-component :data="externalApiResponse.data" :companySegmentIds="companySegmentIds" :section="section"></purchase-order-form-read-only-component>
</div>
</div>
</div>
@@ -174,16 +174,16 @@
</div>
<div v-if="question.question_number === 'approve_po_edit' || question.question_number === 'fill_po_edit'">
<div v-if="externalApiResponse.data.booking" class="row">
<div v-if="externalApiResponse && externalApiResponse.data" class="row">
<div class="col">
<h3>
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
<a :href="route('booking.details', externalApiResponse.data.booking.marking)"
target="_blank">{{ externalApiResponse.data.booking.marking }}</a>
<a :href="route('booking.details', externalApiResponse.data.marking)"
target="_blank">{{ externalApiResponse.data.marking }}</a>
</h3>
<div class="row b-a b-primary padding-30 bg-white m-t-25">
<div class="col">
<purchase-order-form-component :data="externalApiResponse.data.booking" :companySegmentIds="companySegmentIds" :section="section + 'GetExternalApiResponse'"
<purchase-order-form-component :data="externalApiResponse.data" :companySegmentIds="companySegmentIds" :section="section + 'GetExternalApiResponse'"
@update-parameters="handleParametersUpdate"></purchase-order-form-component>
</div>
</div>
@@ -201,7 +201,7 @@
<h2>
Upload the English PO
</h2>
<!-- <file-upload-component :data="externalApiResponse.data" section="section"></file-upload-component> -->
<!-- <file-upload-component :data="externalApiResponse" section="section"></file-upload-component> -->
<file-input-component :validator="$v.files" v-model="files">
<template slot="label">
<div class="font-heading fs-11 all-caps">Photo or File</div>
@@ -262,7 +262,7 @@
<div class="row b-a b-primary padding-30 bg-white m-t-25">
<div class="col">
<div class="m-t-25">
<!-- <remark-comment-form-component :data="externalApiResponse.data" :id="externalApiResponse.data.booking_id" :section="section" module_type="Booking"></remark-comment-form-component> -->
<!-- <remark-comment-form-component :data="externalApiResponse" :id="externalApiResponse.data.booking_id" :section="section" module_type="Booking"></remark-comment-form-component> -->
<validation-wrapper-component :validator="$v.answer">
<label>Answer</label>
<input type="text" class="form-control" v-model="answer" @input="formTouched = true">
@@ -382,7 +382,7 @@
<!-- Debug box -->
<div class="debug-box" v-if="question">
<div id="debug-meta">
{{question.question_number}}<span v-if="externalApiResponse && externalApiResponse.data && externalApiResponse.data.booking">, Booking Id: {{externalApiResponse.data.booking.id}}</span><br>
{{question.question_number}}<span v-if="externalApiResponse && externalApiResponse.data">, Booking Id: {{ externalApiResponse.data.id }}</span><br>
</div>
</div>
</div>
@@ -406,7 +406,7 @@
// From AdminWorkFlowSectionComponent
sessionId: null,
externalApiResponse: { data: null },
externalApiResponse: null,
externalApiUrl: "",
timer: null,
elapsedTime: 0,
@@ -445,7 +445,7 @@
return `${hours}:${minutes}:${seconds}`;
},
companySegmentIds() {
return this.externalApiResponse.data?.booking?.company?.segments?.map(obj => parseInt(obj.id)) ?? [];
return (this.externalApiResponse && this.externalApiResponse.data)?.booking?.company?.segments?.map(obj => parseInt(obj.id)) ?? [];
},
hidePrevious(){
// return (this.question && this.question.is_start) || (this.question && this.question.is_no_going_back && this.question.is_no_going_back === 1)
@@ -482,7 +482,7 @@
// console.log('fetchAdditionalQuestionInfo: ', JSON.stringify(this.question));
if(this.externalApiUrl){
this.isFetching = true;
this.externalApiResponse.data = {};
this.externalApiResponse = null;
this.submit(this.externalApiUrl, 'get', this.section + 'GetExternalApiResponse', false, false);
}
},
@@ -492,11 +492,11 @@
this.$store.dispatch('completeList', {'name': this.section + 'GetExternalApiResponse', 'data': []});
if(response.data)
{
this.externalApiResponse.data = response.data;
this.externalApiResponse = { data: response.data };
}
else if(response.payload.data)
{
this.externalApiResponse.data.booking = response.payload.data;
this.externalApiResponse = { data: response.payload.data } ;
}
this.isFetching = false;
}
@@ -518,17 +518,17 @@
}
if(this.question.is_previous && this.question.answer){
this.externalApiResponse.data = JSON.parse(this.question.answer.question_metadata);
this.externalApiResponse = { data: JSON.parse(this.question.answer.question_metadata) };
}
else {
if(this.question && this.question.url){
let url = this.question.url;
if(!this.isURL(this.question.url)){
if(this.question.url === 'api.admin_work_flow.fetch_model_attributes'){
url = this.route(this.question.url, this.externalApiResponse.data.booking.id);
url = this.route(this.question.url, this.externalApiResponse.data.id);
}
else if(this.question.url === 'api.booking.show'){
url = this.route(this.question.url, this.externalApiResponse.data.booking.marking);
url = this.route(this.question.url, this.externalApiResponse.data.marking);
}
else{
url = this.route(this.question.url);
@@ -579,7 +579,7 @@
}
this.parameters.extra.timeUsedSeconds = this.stepTime;
this.parameters.extra.questionMetadata = this.externalApiResponse.data;
this.parameters.extra.questionMetadata = this.externalApiResponse?.data;
this.parameters.extra.user_id = this.$store.getters.getUserId;
this.parameters.extra.session_id = this.sessionId;
+2 -75
View File
@@ -48,81 +48,8 @@ Route::group(['prefix' => 'admin-work-flow', 'as' => 'admin_work_flow.', 'namesp
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', function () {
$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()->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)
->whereHas('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER)->where('status', '<', ApprovalStatus::APPROVED))
->first();
if(!$booking){
return responseJson(null, 'No booking found', 404);
}
markedProcessing($booking, 'approve_po_admin_workflow_processing');
$result = new BookingResource($booking);
return responseJson([
'booking' => $result,
]);
// return $booking ? responseJson(new BookingResource($booking)) : responseJson(null, 'No booking found', 404);
})->name('fetch_pending_approve_po');
Route::get('/fetch-pending-fill-po', function () {
$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();
if(!$booking){
return responseJson(null, 'No booking found', 404);
}
markedProcessing($booking, 'fill_po_admin_workflow_processing');
$result = new BookingResource($booking);
return responseJson([
'booking' => $result,
]);
// return $booking ? responseJson(new BookingResource($booking)) : responseJson(null, 'No booking found', 404);
})->name('fetch_pending_fill_po');
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) {