Compare commits

...

56 Commits

Author SHA1 Message Date
Dillon 0e79bbfd6a Quick undo experimental security check 2023-10-16 13:24:30 +08:00
Dillon Ngo 3a411e8b9a Merge branch 'dillon/44-customer-satisfaction-feedback-project-b' into 'master'
Preparation for help menu

See merge request CIEFWorldwideSdnBhd/shipping-portal!175
2023-10-15 17:16:57 +00:00
Dillon bffe438455 Disable help menu 2023-10-16 01:09:24 +08:00
Dillon Ngo d17beda04b Merge branch 'dillon/44-customer-satisfaction-feedback-project' into 'master'
New Feedback Form for gathering feedback from customer

See merge request CIEFWorldwideSdnBhd/shipping-portal!174
2023-10-15 10:19:13 +00:00
Dillon 7acc6932b5 Merge branch 'master' into dillon/44-customer-satisfaction-feedback-project 2023-10-15 18:07:26 +08:00
edmondlang 31905e56be enable top up for superadmin 2023-10-13 15:00:30 +08:00
edmondlang 6508155aea fix group payment not showing in wallet transaction history 2023-10-12 13:17:24 +08:00
edmondlang 760f8684ea fix group payment not showing in wallet transaction history 2023-10-12 13:12:50 +08:00
edmondlang 979b8b2ef9 show accident-approve-invoice 2023-10-12 13:06:51 +08:00
edmondlang 9a0073e906 add company active wallet web 2023-10-12 12:43:35 +08:00
edmondlang 976e54bb4c temporary disable wallet top up 2023-10-11 17:33:22 +08:00
edmondlang 87226377be update packinglist measurement template 2023-10-09 20:38:53 +08:00
edmondlang 674fd84fa0 update packinglist measurement template 2023-10-09 20:31:02 +08:00
edmondlang da1ed10740 update packinglist measurement template 2023-10-09 20:30:36 +08:00
edmondlang eb73d20b00 update packinglist measurement 2023-10-09 20:27:42 +08:00
edmondlang 158fa2eefe Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into add-delivery-order-to-invoice 2023-10-09 00:26:24 +08:00
edmondlang fa4cfc0d75 debug billplz 2023-10-08 23:53:39 +08:00
edmondlang f87bcff930 update packinglist measurement 2023-10-08 21:48:47 +08:00
Dillon e774962c44 Backend validation for generating feedback url 2023-10-08 18:58:43 +08:00
Dillon f5482a29e4 New exception handling for all PerfexCRM services 2023-10-08 17:23:55 +08:00
Dillon 0a14a64fbb Security Patch - Retrieving list of packing list 2023-10-08 16:56:15 +08:00
Dillon ee5051fc26 Merge branch 'dillon/44-customer-satisfaction-feedback-project-e' into dillon/44-customer-satisfaction-feedback-project 2023-10-08 05:25:57 +08:00
Dillon 034c93091a Security Patch - Exporting packinglist data to excel file 2023-10-08 05:25:38 +08:00
Dillon 8b184313cb Error 500 fix 2023-10-08 05:14:03 +08:00
Dillon c2b097e6d1 Merge branch 'dillon/44-customer-satisfaction-feedback-project-e' into dillon/44-customer-satisfaction-feedback-project 2023-10-08 05:12:58 +08:00
Dillon b0195a9640 Merge branch 'dillon/44-customer-satisfaction-feedback-project-d' into dillon/44-customer-satisfaction-feedback-project 2023-10-08 04:55:39 +08:00
Dillon 38d69434fa Security Patch - Exporting packinglist data to excel file 2023-10-08 04:54:38 +08:00
Dillon 1b559f91a2 Security Patch - Exporting feedback data to excel file 2023-10-08 03:50:19 +08:00
edmondlang 05a21af5a6 add line break on top of the file 2023-10-07 18:58:47 +08:00
edmondlang 3e7fbdbafc update packinglist mearuement in invoice 2023-10-07 17:56:47 +08:00
Dillon 527eca50fe Minor UI Fix 2023-10-07 08:42:53 +08:00
Dillon d010a8f8c7 Function for admin to export feedback data 2023-10-07 08:12:52 +08:00
Dillon 7bc2ca512a Function for admin to export feedback data 2023-10-07 07:33:51 +08:00
Dillon b76e0ebeef Merge branch 'dillon/44-customer-satisfaction-feedback-project-a' into dillon/44-customer-satisfaction-feedback-project 2023-10-07 07:33:07 +08:00
Dillon f595c43f2c Function for admin to export feedback data 2023-10-07 07:24:06 +08:00
Dillon 5584d22376 Improvement to log capture thrown by custom exception (ConnectionErrorException), to evaluate if need to extend to other custom exception as well 2023-10-05 19:58:07 +08:00
Dillon 42b6140df7 UX update when system failed to open a support ticket via help menu 2023-10-05 17:30:29 +08:00
Dillon 619fc25605 Merge branch 'dillon/44-customer-satisfaction-feedback-project' into dillon/44-customer-satisfaction-feedback-project-b 2023-10-05 17:04:41 +08:00
Dillon 8c24c86c77 Extra log to capture when ticket not created from Help Menu 2023-10-05 17:02:34 +08:00
Dillon 822046cc69 Updated comments in code 2023-10-05 16:52:42 +08:00
Dillon d708b8b540 404 page when feedback form not found 2023-10-05 16:41:21 +08:00
Jia Sheng Lee 553d2c44aa add delivery order to shipping invoice 2023-10-04 16:53:11 +08:00
Dillon 0f7f5f7ab9 Shorten feedback url 2023-10-04 01:34:45 +08:00
Dillon a5c1ae14b7 Shorten feedback url 2023-10-04 01:02:19 +08:00
Omair Saleh 8f5aa0a861 change ui for feedback answers to use columns instead of rows 2023-10-03 16:11:46 +08:00
Omair Saleh 1bed7f1cc9 change ui for feedback answers to use columns instead of rows 2023-10-03 14:09:46 +08:00
Omair Saleh 0a16e40a23 change ui for feedback answers to use columns instead of rows 2023-10-03 13:53:21 +08:00
Dillon 5c24b6f81e Relocate help menu and make dynamic questionnaire set generation 2023-10-01 00:32:40 +08:00
Dillon b81f3e50ad Filter out help menu questions and answers from been listed in admin feedback q&a list + disabled help menu 2023-09-30 18:45:35 +08:00
edmondlang c493b3786c update credit_note pdf 2023-09-25 22:34:13 +08:00
edmondlang 99f4699260 update wallet credit note 2023-09-15 18:42:14 +08:00
edmondlang 0ea52048e1 update wallet credit note 2023-09-15 18:37:04 +08:00
edmondlang a47bb95e50 update wallet credit note 2023-09-15 18:32:36 +08:00
edmondlang 431aed18d3 update wallet credit note 2023-09-15 18:03:39 +08:00
edmondlang 6ab289057b wallet credit note 2023-09-15 17:34:16 +08:00
JiaSheng c55a8e7af9 fix account statement mapping issue 2023-09-14 14:59:02 +08:00
81 changed files with 1572 additions and 144 deletions
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
use Illuminate\Support\Facades\Log;
final class ConnectionErrorException extends ServiceApiException {
public function __construct(?string $message = null, ?string $exceptionMessage = null, ?string $payload = null, ?string $exceptionTrace = null) {
Log::error($message. ": ". $exceptionMessage);
if($payload){
Log::error('Payload: '.$payload);
}
if($exceptionTrace){
Log::error($exceptionTrace);
}
parent::__construct($message ?? 'A connection error has occurred. Please check application logs for more information.',
HttpStatus::SERVER_ERROR);
}
}
@@ -0,0 +1,97 @@
<?php
namespace App\Classes\General\Abstracts;
use App\Classes\Exceptions\ErrorException;
use App\Classes\Exceptions\InternalServerErrorException;
use App\Classes\ValueObjects\Constants\Notifications;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use ErrorException as GeneralExceptions;
use TypeError;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Facades\DB;
abstract class Abstract2ControllerLogic
{
/**
* @return array
*/
abstract protected function notification(): array;
/**
* @return string
*/
private function getNotificationTitle():string {
return $this->notification()['title'] ? $this->notification()['title']: Notifications::UNDEFINED['title'];
}
/**
* @return string
*/
private function getNotificationMessage():string {
return $this->notification()['message'] ? $this->notification()['message']: Notifications::UNDEFINED['message'];
}
/**
* @param Request $request
* @return BinaryFileResponse
* @throws ErrorException
*/
abstract protected function logic(Request $request) : BinaryFileResponse;
/**
* @param Request $request
* @return BinaryFileResponse
*/
public function execute(Request $request) : BinaryFileResponse {
try {
DB::beginTransaction();
$response = $this->logic($request);
DB::commit();
return $response;
} catch (ErrorException|GeneralExceptions|TypeError $exception){
abort(404, $exception->getMessage());
}
}
/**
* @param array|null $data
* @return JsonResponse
*/
public function response(?array $data = []) : JsonResponse {
return (new ApiResponseObject($this->getNotificationTitle().' Successful',
$this->getNotificationMessage(),
HttpStatus::OK_WITH_MESSAGE, $data))->handler();
}
/**
* @param JsonResource $resource
* @return JsonResponse
*/
public function resourceResponse(JsonResource $resource){
return $this->response(['data' => $resource]);
}
/**
* @param ResourceCollection $collection
* @return JsonResponse
*/
public function collectionResponse(ResourceCollection $collection){
return $this->response(json_decode($collection->response()->getContent(), true));
}
}
@@ -27,7 +27,7 @@ abstract class AbstractRule
public function passes(?DataTransferObject $object = null): bool {
try {
if(!$this->authorized($object)){
throw new AccessForbiddenException('You don\'t have permission to preform this action');
throw new AccessForbiddenException('You don\'t have permission to perform this action');
}
$this->validators($object);
@@ -36,7 +36,7 @@ abstract class AbstractRule
return true;
} catch(AccessForbiddenException $exception){
throw new AccessForbiddenException('You don\'t have permission to preform this action');
throw new AccessForbiddenException('You don\'t have permission to perform this action');
} catch(\Exception $exception){
throw new RequestValidationException($exception->getMessage());
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class HasQuestionnaireGroupIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('question.questionnaire', function (Builder $query) use ($value) {
$query->whereIn('group', $value);
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class PaymentMethodNotIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereNotIn('payment_method', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class ShortUrl implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('short_url', $value);
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\Exports\ControllersLogic;
use App\Classes\General\Abstracts\Abstract2ControllerLogic;
use App\Classes\Modules\Exports\Services\ExportsFeedback;
use App\Classes\Modules\Exports\Standards\Rules\CanExportFeedback;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Maatwebsite\Excel\Excel;
class ExportFeedbackDataLogic extends Abstract2ControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Feedback',
'message' => 'You have successfully exported feedback data'
];
}
/** @var ExportsFeedback */
private $exportsFeedback;
/** @var CanExportFeedback */
private $canExportFeedback;
/**
* ExportFeedbackDataLogic constructor.
* @param ExportsFeedback $exportsFeedback
* @param CanExportFeedback $canExportFeedback
*/
public function __construct(ExportsFeedback $exportsFeedback, CanExportFeedback $canExportFeedback)
{
$this->exportsFeedback = $exportsFeedback;
$this->canExportFeedback = $canExportFeedback;
}
/**
* @param Request $request
* @return Response
*/
public function logic(Request $request) : BinaryFileResponse
{
$this->canExportFeedback->passes();
$response = $this->exportsFeedback->download('feedback.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\Modules\Exports\ControllersLogic;
use App\Classes\General\Abstracts\Abstract2ControllerLogic;
use App\Classes\Modules\Exports\Standards\Rules\CanExportPackingList;
use App\Classes\Modules\Exports\Services\ExportsOnHoldPackingList;
use App\Classes\Modules\Exports\Services\ExportsPendingArrangementDeliveryList;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Maatwebsite\Excel\Excel;
class ExportPackingListLogic extends Abstract2ControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved PackingList',
'message' => 'You have successfully exported PackingList'
];
}
/** @var ExportsOnHoldPackingList */
private $exportsOnHoldPackingList;
/** @var ExportsPendingArrangementDeliveryList */
private $exportsPendingArrangementDeliveryList;
/** @var CanExportPackingList */
private $canExportPackingList;
/**
* ExportPackingListLogic constructor.
* @param ExportsPendingArrangementDeliveryList $exportsPendingArrangementDeliveryList
* @param ExportsOnHoldPackingList $exportsOnHoldPackingList
* @param CanExportPackingList $canExportPackingList
*/
public function __construct(ExportsPendingArrangementDeliveryList $exportsPendingArrangementDeliveryList, ExportsOnHoldPackingList $exportsOnHoldPackingList, CanExportPackingList $canExportPackingList)
{
$this->exportsPendingArrangementDeliveryList = $exportsPendingArrangementDeliveryList;
$this->exportsOnHoldPackingList = $exportsOnHoldPackingList;
$this->canExportPackingList = $canExportPackingList;
}
/**
* @param Request $request
* @return Response
*/
public function logic(Request $request) : BinaryFileResponse
{
$this->canExportPackingList->passes();
$isSetPendingArrangement = $request->header('PendingArrangement');
if($isSetPendingArrangement){
$response = $this->exportsPendingArrangementDeliveryList->download('packing-list-delivery.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
}
else {
$response = $this->exportsOnHoldPackingList->download('packing-list-on-hold.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
}
ob_end_clean();
return $response;
}
}
@@ -0,0 +1,70 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Models\QAUserAnswerSelected;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use App\Classes\ValueObjects\Constants\QASystemSourceType;
use Carbon\Carbon;
class ExportsFeedback implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
public function headings(): array
{
return [
'Question Set',
'Question Text',
'Answer',
'Source System',
'Source Marking',
'Source Email',
'Created Date'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
return QAUserAnswerSelected::whereHas('question', function ($query) {
$query->whereHas('questionnaire', function ($innerQuery) {
$innerQuery->where('group', 'feedback');
})->where('created_at', '>', Carbon::now()->subMonths(1));
})->orderBy('created_at', 'desc');
}
/**
* @param QAUserAnswerSelected $userAnswer
*
* @return array
*/
public function map($userAnswer): array
{
$source = $userAnswer->userSource;
$user = $userAnswer->source_id === 0 ? $userAnswer->user : null;
$user_marking = '';
if($user){
$companyModule = $user->companyModule()->first();
$user_marking = $companyModule ? $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference : "";
}
return [
$userAnswer->question->questionnaire->description,
$userAnswer->question->question_text,
$userAnswer->free_text_answer,
$user ? QASystemSourceType::getText(QASystemSourceType::IZYIM) : QASystemSourceType::getText($source->system),
$user ? $user_marking : $source->marking,
$user ? $user->email : $source->email,
Carbon::parse($userAnswer->created_at)->format('d-m-Y'),
];
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\Exports\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\ValueObjects\Constants\RoleTypes;
class CanExportFeedback extends AbstractRule
{
/**
* @return bool
*/
protected function authorized($object): bool
{
if(Auth()->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;
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Classes\Modules\Exports\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\ValueObjects\Constants\RoleTypes;
class CanExportPackingList extends AbstractRule
{
/**
* @return bool
*/
protected function authorized($object): bool
{
if(Auth()->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;
}
}
@@ -4,12 +4,15 @@ namespace App\Classes\Modules\HelpMenu\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\HelpMenu\DataTransferObjects\UrlObject;
use App\Classes\Modules\HelpMenu\Standards\Rules\CanGenerateFeedbackUrl;
use App\Classes\Modules\HelpMenu\Services\CreatesUrl;
use App\Classes\Modules\HelpMenu\DataTransferObjects\GenerateFeedbackUrlObject;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Log;
class GenerateFeedbackUrlLogic extends AbstractControllerLogic
@@ -28,14 +31,18 @@ class GenerateFeedbackUrlLogic extends AbstractControllerLogic
/** @var CanGenerateFeedbackUrl */
private $canGenerateFeedbackUrl;
/** @var CreatesUrl */
private $createsUrl;
/**
* GenerateFeedbackUrlLogic constructor.
* @param CanGenerateFeedbackUrl $canGenerateFeedbackUrl
* @param CreatesUrl $createsUrl
*/
public function __construct(CanGenerateFeedbackUrl $canGenerateFeedbackUrl)
public function __construct(CanGenerateFeedbackUrl $canGenerateFeedbackUrl, CreatesUrl $createsUrl)
{
$this->canGenerateFeedbackUrl = $canGenerateFeedbackUrl;
$this->createsUrl = $createsUrl;
}
@@ -46,15 +53,22 @@ class GenerateFeedbackUrlLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$object = new GenerateFeedbackUrlObject();
$apiKey = "";
if($request->get('apiKeyExist'))
{
$object = new GenerateFeedbackUrlObject($request->get('apiKeyExist'));
$apiKey = $request->get('apiKeyExist');
}
$object = new GenerateFeedbackUrlObject($apiKey, $request->input('system'), $request->input('customer_marking'), $request->input('email'), $request->input('question_set'));
$this->canGenerateFeedbackUrl->passes($object);
$originalText = $request->input('system') . '|' . $request->input('customer_marking'). '|' . $request->input('email'). '|' . $request->input('question_set');
$resource = ['token' => Crypt::encryptString($originalText)];
$shortUrl = Str::random(20);
$originalText = $object->getSystem() . '|' . $object->getCustomerMarking(). '|' . $object->getEmail(). '|' . $object->getQuestionSet() . '|' . $shortUrl;
$originalUrl = Crypt::encryptString($originalText);
$url = $this->createsUrl->execute(new UrlObject('feedback', $shortUrl, $originalUrl));
$resource = ['token' => $url->short_url];
return $this->response(['data' => $resource]);
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\HelpMenu\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\HelpMenu\Services\ListsHelpMenuQuestions;
use App\Classes\Modules\HelpMenu\Services\FetchesUrl;
use App\Http\Resources\HelpMenuQuestionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -27,13 +28,18 @@ class ListQuestionsQALogic extends AbstractControllerLogic
/** @var ListsHelpMenuQuestions */
private $listsHelpMenuQuestions;
/** @var FetchesUrl */
private $fetchesUrl;
/**
* ListQuestionsQALogic constructor.
* @param ListsHelpMenuQuestions $listsHelpMenuQuestions
* @param FetchesUrl $fetchesUrl
*/
public function __construct(ListsHelpMenuQuestions $listsHelpMenuQuestions)
public function __construct(ListsHelpMenuQuestions $listsHelpMenuQuestions, FetchesUrl $fetchesUrl)
{
$this->listsHelpMenuQuestions = $listsHelpMenuQuestions;
$this->fetchesUrl = $fetchesUrl;
}
@@ -47,17 +53,14 @@ class ListQuestionsQALogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
try{
$token = $request->input('token');
$decriptedToken = Crypt::decryptString($token);
$delimiter = "|";
$parts = explode($delimiter, $decriptedToken);
$questionSet = $parts[3];
$query = $this->listsHelpMenuQuestions->execute(['questionnaire_set_id' => $questionSet]);
return $this->collectionResponse(HelpMenuQuestionResource::collection($query));
} catch(\Exception $exception){
throw new ResourceNotFoundException($exception->getMessage());
}
$url = $this->fetchesUrl->execute(['short_url' => $request->input('token')]);
$token = $url->original_url;
$decriptedToken = Crypt::decryptString($token);
$delimiter = "|";
$parts = explode($delimiter, $decriptedToken);
$questionSet = $parts[3];
$query = $this->listsHelpMenuQuestions->execute(['questionnaire_set_id' => $questionSet]);
return $this->collectionResponse(HelpMenuQuestionResource::collection($query));
}
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\HelpMenu\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\HelpMenu\Processors\SaveAnswerProcessor;
use App\Classes\Modules\HelpMenu\Processors\UserSourceForQAProcessor;
use App\Classes\Modules\HelpMenu\Services\FetchesUrl;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -30,15 +31,20 @@ class SubmitQAQuestionsLogic extends AbstractControllerLogic
/** @var UserSourceForQAProcessor */
private $userSourceForQAProcessor;
/** @var FetchesUrl */
private $fetchesUrl;
/**
* SubmitQAQuestionsLogic constructor.
* @param SaveAnswerProcessor $saveAnswerProcessor
* @param UserSourceForQAProcessor $userSourceForQAProcessor
* @param FetchesUrl $fetchesUrl
*/
public function __construct(SaveAnswerProcessor $saveAnswerProcessor, UserSourceForQAProcessor $userSourceForQAProcessor)
public function __construct(SaveAnswerProcessor $saveAnswerProcessor, UserSourceForQAProcessor $userSourceForQAProcessor, FetchesUrl $fetchesUrl)
{
$this->saveAnswerProcessor = $saveAnswerProcessor;
$this->userSourceForQAProcessor = $userSourceForQAProcessor;
$this->fetchesUrl = $fetchesUrl;
}
@@ -49,11 +55,14 @@ class SubmitQAQuestionsLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$token = $request->input('token');
$originalToken = '';
$shortToken = $request->input('token');
$userId = 0;
$sourceId = 0;
try {
$decriptedToken = Crypt::decryptString($token);
$url = $this->fetchesUrl->execute(['short_url' => $shortToken]);
$originalToken = $url->original_url;
$decriptedToken = Crypt::decryptString($originalToken);
$delimiter = "|";
$parts = explode($delimiter, $decriptedToken);
$system = $parts[0];
@@ -71,7 +80,7 @@ class SubmitQAQuestionsLogic extends AbstractControllerLogic
$answers = $request->input('answers');
foreach ($answers as $answer) {
$filesUpload = $request->input('files');
$this->saveAnswerProcessor->execute($userId, $sourceId, $answer['questionId'], $answer['answer'], $answer['answerId'], $filesUpload);
$this->saveAnswerProcessor->execute($userId, $sourceId, $answer['questionId'], $answer['answer'], $answer['answerId'], $filesUpload, $shortToken);
}
$response = ['message' => 'Thank you for your feedback.'];
@@ -75,7 +75,8 @@ class UpdateNextQuestionQALogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
* @throws MalformedRequestException
* @throws ResourceNotFoundException
*/
public function logic(Request $request) : JsonResponse
{
@@ -11,13 +11,29 @@ class GenerateFeedbackUrlObject implements DataTransferObject
/** @var string */
private $apiKey;
/** @var string */
private $system;
/** @var string */
private $customerMarking;
/** @var string */
private $email;
/** @var string */
private $questionSet;
/**
* GenerateFeedbackUrlObject constructor.
* @param string $apiKey
*/
public function __construct(string $apiKey = "")
public function __construct(string $apiKey = "", ?string $system, ?string $customerMarking, ?string $email, ?string $questionSet)
{
$this->apiKey = $apiKey;
$this->system = $system;
$this->customerMarking = $customerMarking;
$this->email = $email;
$this->questionSet = $questionSet;
}
/**
@@ -28,4 +44,36 @@ class GenerateFeedbackUrlObject implements DataTransferObject
return $this->apiKey;
}
}
/**
* @return string
*/
public function getSystem(): ?string
{
return $this->system;
}
/**
* @return string
*/
public function getCustomerMarking(): ?string
{
return $this->customerMarking;
}
/**
* @return string
*/
public function getEmail(): ?string
{
return $this->email;
}
/**
* @return string
*/
public function getQuestionSet(): ?string
{
return $this->questionSet;
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\Modules\HelpMenu\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UrlObject implements DataTransferObject
{
/** @var string */
private $type;
/** @var string */
private $shortUrl;
/** @var string */
private $originalUrl;
/**
* UrlObject constructor.
* @param string $type
* @param string $shortUrl
* @param string $originalUrl
*/
public function __construct(string $type, string $shortUrl, string $originalUrl)
{
$this->type = $type;
$this->shortUrl = $shortUrl;
$this->originalUrl = $originalUrl;
}
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* @return string
*/
public function getShortUrl(): string
{
return $this->shortUrl;
}
/**
* @return string
*/
public function getOriginalUrl(): string
{
return $this->originalUrl;
}
}
@@ -25,6 +25,14 @@ class DeleteAnswerQAProcessor
$this->listsHelpMenuUserAnswerSelected = $listsHelpMenuUserAnswerSelected;
}
/**
* @param int $userId
* @param int $questionId
* @param Request $request
* @return void
* @throws ResourceNotFoundException
*/
public function execute($userId, $questionId, $request){
if ($request->has('isPrevious')) {
//Get current and previous question's answer
@@ -23,7 +23,7 @@ class FetchFirstQuestionQAProcessor
public function execute(Request $request){
try {
$query = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1]);
$query = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $request->route('set_id')]);
return $query;
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
@@ -38,6 +38,7 @@ class FetchNextQuestionQAProcessor
$nextQuestionNumber = 0;
$nextNestedQuestion = 0;
$nextMainQuestion= 0;
$questionnaireSetId = 0;
$currentQuestion = $request->question;
$questionType = QAType::DEFAULT;
$returnQuestion = null;
@@ -48,7 +49,9 @@ class FetchNextQuestionQAProcessor
$questionType = $currentQuestion['question_type'];
$nextNestedQuestion = $currentQuestion['next_nested_question'];
$nextMainQuestion = $currentQuestion['next_main_question'];
$questionnaireSetId = $currentQuestion['questionnaire_set_id'];
}
if ($request->has('answerObj')) {
$nextQuestionNumber = $request->answerObj['next_question_number'];
}
@@ -58,7 +61,7 @@ class FetchNextQuestionQAProcessor
$previousAnswer = $this->listsHelpMenuUserAnswerSelected->execute(['user_id' => $userId, 'order_by' => (object)['column' => 'id','DESC' => true]])[0];
//Get previous question
$previousQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'id' => $previousAnswer['question_id']]);
$previousQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'id' => $previousAnswer['question_id']]);
$returnQuestion = $previousQuestion;
}
else{
@@ -79,11 +82,11 @@ class FetchNextQuestionQAProcessor
$returnQuestion = null;
}
else if($question_number != 0){
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'question_number' => $question_number]);
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'question_number' => $question_number]);
$returnQuestion = $nextQuestion;
}
else if (array_key_exists('id', $request->input('question'))) {
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'id_next' => $questionId, 'next_main_question' => null]);
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'id_next' => $questionId, 'next_main_question' => null]);
$returnQuestion = $nextQuestion;
}
}
@@ -26,7 +26,7 @@ class SaveAnswerProcessor
$this->uploadDocumentForHelpMenuProcessor = $uploadDocumentForHelpMenuProcessor;
}
public function execute($userId, $sourceId, $questionId, $answerInText, $answerOptionId, $filesUpload){
public function execute($userId, $sourceId, $questionId, $answerInText, $answerOptionId, $filesUpload, $reference = null){
$answer = null;
// try{
@@ -45,6 +45,9 @@ class SaveAnswerProcessor
$answer->question_id = $questionId;
$answer->answer_option_id = intval($answerOptionId);
$answer->free_text_answer = $answerInText;
if($reference){
$answer->reference = $reference;
}
$answer->save();
if($filesUpload){
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\HelpMenu\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\HelpMenu\DataTransferObjects\UrlObject;
use App\Models\Url;
class CreatesUrl extends AbstractUpdateRecord
{
/**
* @param UrlObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(UrlObject $object) {
$model = new Url();
$model->type = $object->getType();
$model->short_url = $object->getShortUrl();
$model->original_url = $object->getOriginalUrl();
return $this->handler($model);
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Modules\HelpMenu\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use App\Models\Url;
use Illuminate\Database\Eloquent\Builder;
class FetchesUrl extends AbstractFetchRecord
{
/** @var Url */
private $repository;
/**
* FetchesUrl constructor.
* @param Url $repository
*/
public function __construct(Url $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -5,11 +5,25 @@ namespace App\Classes\Modules\HelpMenu\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Modules\HelpMenu\Standards\Validators\FeedbackUrlValidation;
use App\Classes\Modules\HelpMenu\DataTransferObjects\GenerateFeedbackUrlObject;
use Illuminate\Support\Facades\Log;
class CanGenerateFeedbackUrl extends AbstractRule
{
/** @var FeedbackUrlValidation */
private $feedbackUrlValidation;
/**
* CanGenerateFeedbackUrl constructor.
* @param FeedbackUrlValidation $feedbackUrlValidation
*/
public function __construct(FeedbackUrlValidation $feedbackUrlValidation)
{
$this->feedbackUrlValidation = $feedbackUrlValidation;
}
/**
* @return bool
*/
@@ -20,7 +34,7 @@ class CanGenerateFeedbackUrl extends AbstractRule
$roleToCheck = Auth()->user()->type;
if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
return true;
}
}
}
else if($object->getApiKey()){
return true;
@@ -30,12 +44,13 @@ class CanGenerateFeedbackUrl extends AbstractRule
}
/**
* @param $object
* @param GenerateFeedbackUrlObject $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return true;
return $this->feedbackUrlValidation->validate($object);
}
/**
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\HelpMenu\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\HelpMenu\DataTransferObjects\GenerateFeedbackUrlObject;
class FeedbackUrlValidation extends AbstractValidation
{
/**
* @param GenerateFeedbackUrlObject $object
* @return array
*/
protected function data($object): array {
return [
'system' => $object->getSystem(),
'email' => $object->getEmail(),
'question_set' => $object->getQuestionSet()
// 'customer_marking' => $object->getCustomerMarking(),
];
}
/**
* @return array
*/
protected function rules(): array {
return [
'system' => 'required',
'email' => 'required',
'question_set' => 'required',
// 'customer_marking' => 'required',
];
}
/**
* @return array
*/
protected function messages(): array {
return [];
}
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\PackingLists\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\ValueObjects\Constants\RoleTypes;
class CanListPackingLists extends AbstractRule
{
@@ -15,9 +16,17 @@ class CanListPackingLists extends AbstractRule
*/
protected function authorized($object): bool
{
// TODO Set Authorization rules
// if(Auth()->user()){
// $roleToCheck = Auth()->user()->type;
// if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
// return true;
// }
// else {
// return false;
// }
// }
// return false;
return true;
}
/**
@@ -119,13 +119,13 @@ class TransactionToPerfexCRMV2Processor
}
private function definePaymentTasks(Transaction $model): array //cief todo: to comfirm what tasks need to be created
private function definePaymentTasks(Transaction $model): array //cief todo: to comfirm what tasks need to be created at crm
{
$tasks = [];
return $tasks;
}
private function defineTasks_handleApprovedStatus_handlePaymentApprovedStatus(): array //cief todo: to comfirm what tasks need to be created
private function defineTasks_handleApprovedStatus_handlePaymentApprovedStatus(): array //cief todo: to comfirm what tasks need to be created at crm
{
$tasks = [];
// $tasks = [
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class ConvertsPerfexCRMLeadToCustomer
@@ -27,8 +28,13 @@ class ConvertsPerfexCRMLeadToCustomer
Log::error('ConvertsPerfexCRMLeadToCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomer
@@ -30,8 +31,13 @@ class CreatesPerfexCRMCustomer
Log::error('CreatesPerfexCRMCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $companyName, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerContact
@@ -37,8 +38,13 @@ class CreatesPerfexCRMCustomerContact
Log::error('CreatesPerfexCRMCustomerContact: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerProject
@@ -36,8 +37,13 @@ class CreatesPerfexCRMCustomerProject
Log::error('CreatesPerfexCRMCustomerProject: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
@@ -56,8 +57,13 @@ class CreatesPerfexCRMInvoice
Log::error('CreatesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
@@ -36,8 +37,13 @@ class CreatesPerfexCRMInvoicePayment
Log::error('CreatesPerfexCRMInvoicePayment: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
@@ -43,8 +44,13 @@ class CreatesPerfexCRMLead
Log::error('CreatesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server ' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMMilestone
@@ -39,8 +40,13 @@ class CreatesPerfexCRMMilestone
Log::error('CreatesPerfexCRMMilestone: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMSupportTicket
@@ -36,8 +37,16 @@ class CreatesPerfexCRMSupportTicket
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
$error = 'Support Ticket creation failed';
Log::error($error. ": ". $exception->getMessage());
Log::error('Payload: '.json_encode($data));
throw new MalformedRequestException($error);
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
@@ -60,8 +61,13 @@ class CreatesPerfexCRMTask
Log::error('CreatesPerfexCRMTask: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMCustomer
@@ -27,8 +28,15 @@ class FetchesPerfexCRMCustomer
Log::error('FetchesPerfexCRMCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
$error = 'Unable to get correct response from Perfex CRM server: ' . $exception->getMessage();
Log::error($error);
throw new MalformedRequestException($error);
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMInvoice
@@ -29,7 +30,12 @@ class FetchesPerfexCRMInvoice
Log::error('FetchesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMLead
@@ -27,7 +28,12 @@ class FetchesPerfexCRMLead
Log::error('FetchesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMMilestone
@@ -33,8 +34,13 @@ class FetchesPerfexCRMMilestone
Log::error('FetchesPerfexCRMMilestone: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMProject
@@ -33,8 +34,13 @@ class FetchesPerfexCRMProject
Log::error('FetchesPerfexCRMProject: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
@@ -47,8 +48,13 @@ class FetchesPerfexCRMTask
Helper::debugLogger($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
use App\Classes\General\Helper;
@@ -41,8 +42,13 @@ class UpdatesPerfexCRMCustomer
// Helper::debugLogger($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMInvoice
@@ -63,7 +64,12 @@ class UpdatesPerfexCRMInvoice
Log::error('UpdatesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
@@ -44,7 +45,12 @@ class UpdatesPerfexCRMLead
Log::error('UpdatesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMProject
@@ -36,7 +37,12 @@ class UpdatesPerfexCRMProject
Log::error('UpdatesPerfexCRMProject: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMTask
@@ -41,8 +42,13 @@ class UpdatesPerfexCRMTask
Log::error('UpdatesPerfexCRMTask: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -47,7 +47,7 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'));
//cief todo: at exchange there is a transition step
//cief todo: at exchange there is a transition step - starts
// if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
// $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION);
// }
@@ -59,7 +59,7 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
//To use
//ApprovalStatus::PENDING_VERIFICATION;
//use this to trigger $this->transactionToPerfexCRMV2Processor->execute > defineTasks > defineTasks_handlePendingVerificationStatus > definePaymentTasks
//cief todo: at exchange there is a transition step - ends
return $this->resourceResponse(new TransactionResource($payment_transaction));
}
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\ValueObjects\Constants\TransactionType;
class GenerateCreditNotePdfLogic
{
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/**
* GenerateCreditNotePdfLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param FetchesCompany $fetchesCompany
*/
public function __construct(FetchesTransaction $fetchesTransaction, FetchesCompanyModule $fetchesCompanyModule)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->fetchesCompanyModule = $fetchesCompanyModule;
}
/**
* @param Request $request
* @return string|\Symfony\Component\HttpFoundation\Response
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Request $request)
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$supplier = $this->fetchesCompanyModule->execute(['id' => $transaction->receiver]);
$pdf = LaravelMpdf::loadView('pages.pdfs.credit_note', ['transaction' => $transaction, 'supplier' => $supplier]);
return $pdf->stream('CreditNote.pdf');
}
}
@@ -10,6 +10,7 @@ use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Wallets\Services\GeneratesWalletCode;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
@@ -29,6 +30,9 @@ class CreditWalletLogic extends AbstractControllerLogic
}
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var FetchesCompany */
private $fetchesCompany;
@@ -62,6 +66,7 @@ class CreditWalletLogic extends AbstractControllerLogic
*/
public function __construct(
FetchesCompany $fetchesCompany,
FetchesCompanyModule $fetchesCompanyModule,
GeneratesWalletCode $generatesWalletCode,
CreatesWallet $createsWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
@@ -71,6 +76,7 @@ class CreditWalletLogic extends AbstractControllerLogic
)
{
$this->fetchesCompany = $fetchesCompany;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->generatesWalletCode = $generatesWalletCode;
$this->createsWallet = $createsWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
@@ -88,13 +94,13 @@ class CreditWalletLogic extends AbstractControllerLogic
{
$amount = floatval(str_replace(',', '', $request->input('amount')));
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]);
$reference = $request->input('reference');
$type = $request->input('transaction_type');
$wallet = $this->creditWalletProcessor->execute($company, $type, $amount, $reference);
$wallet = $this->creditWalletProcessor->execute($companyModule, $type, $amount, $reference);
return $this->resourceResponse(new WalletResource($wallet));
}
@@ -11,9 +11,11 @@ use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Wallets\Services\GeneratesWalletCode;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionableTransaction;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Models\CompanyModule;
class CreditWalletProcessor
{
@@ -29,6 +31,9 @@ class CreditWalletProcessor
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesTransactionableTransaction */
private $createsTransactionableTransaction;
/** @var UpdatesWallet */
private $updatesWallet;
@@ -38,6 +43,7 @@ class CreditWalletProcessor
* @param CreatesWallet $createsWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionableTransaction $createsTransactionableTransaction
* @param UpdatesWallet $updatesWallet
*/
public function __construct(
@@ -45,6 +51,7 @@ class CreditWalletProcessor
CreatesWallet $createsWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
CreatesTransactionableTransaction $createsTransactionableTransaction,
UpdatesWallet $updatesWallet
)
{
@@ -52,32 +59,33 @@ class CreditWalletProcessor
$this->createsWallet = $createsWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionableTransaction = $createsTransactionableTransaction;
$this->updatesWallet = $updatesWallet;
}
/**
* @param Company $company
* @param CompanyModule $companyModule
* @param int $transactionType
* @param float $amount
* @param string $reference
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $company, int $transactionType, float $amount, string $reference)
public function execute(CompanyModule $companyModule, int $transactionType, float $amount, string $reference)
{
if (!$company->wallets()->first()) {
$object = new WalletObject($company->id, 1, $this->generatesWalletCode->execute());
$this->createsWallet->execute($object, $company);
if (!$companyModule->wallets()->first()) {
$object = new WalletObject($companyModule->id, 1, $this->generatesWalletCode->execute());
$this->createsWallet->execute($object, $companyModule);
}
/** @var Wallet $wallet */
$wallet = $company->wallets()->first();
$wallet = $companyModule->wallets()->first();
$billNumber = $this->generatesTransactionBillNumber->execute($transactionType === 2 ? 'DEBIT-NOTE-' : 'CREDIT-NOTE-');
$transaction_object = new TransactionObject($billNumber, $transactionType === 2 ? TransactionType::DEBIT_NOTE : TransactionType::CREDIT_NOTE, 1, $wallet->owner->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference);
$transaction = $this->createsTransaction->execute($wallet, $transaction_object);
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
$updateWalletAmount = $transactionType === 2 ? ($wallet->amount - $transaction->amount) : ($wallet->amount + $transaction->amount);
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\ControllersLogic\ExportFeedbackDataLogic;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class ExportFeedbackDataController
{
/**
* @param Request $request
* @param ExportFeedbackDataLogic $logic
* @return BinaryFileResponse
*/
public function export(Request $request, ExportFeedbackDataLogic $logic) {
return $logic->execute($request);
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\ControllersLogic\ExportPackingListLogic;
use Illuminate\Http\Request;
class ExportPendingArrangementPackingListV2Controller
{
/**
* @param Request $request
* @param ExportPackingListLogic $logic
* @return BinaryFileResponse
*/
public function export(Request $request, ExportPackingListLogic $logic) {
$request->headers->set('PendingArrangement', true);
return $logic->execute($request);
}
/**
* @param Request $request
* @param ExportPackingListLogic $logic
* @return BinaryFileResponse
*/
public function onHold(Request $request, ExportPackingListLogic $logic) {
$request->headers->set('OnHold', true);
return $logic->execute($request);
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\GenerateCreditNotePdfLogic;
use Illuminate\Http\JsonResponse;
class GenerateCreditNotePdfController
{
public function download(Request $request, GenerateCreditNotePdfLogic $logic) {
return $logic->execute($request);
}
}
@@ -26,7 +26,7 @@ class MappableTransactionResource extends JsonResource
$reference = $this->owner->owner->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
}
if($this->type === TransactionType::PAYMENT && $this->owner !== Wallet::class){
if($this->type === TransactionType::PAYMENT && $this->owner_type !== Wallet::class){
$reference = $this->owner->owner->owner->reference;
}
@@ -34,7 +34,7 @@ class MappableTransactionResource extends JsonResource
'status' => 'success',
'system' => 'SHIPPING_PORTAL',
'type' => $this->type,
'owner_type' => $this->owner_type,
'owner_type' => Transaction::class,
'owner_id'=> $this->id,
'owner_reference'=> $reference,
];
@@ -41,10 +41,14 @@ class WalletTransactionResource extends JsonResource
case 11:
$description = 'Debit Voucher for '.$this->payment_reference;
break;
case 15:
$description = (double) $this->amount.' Credit Top up';
break;
}
return [
'id' => (int) $this->id,
'type' => (int) $this->type,
'marking' => $this->owner->owner->reference,
'bill_no' => $this->bill_no,
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App\Models;
class Url extends AbstractModel
{
protected $table = 'urls';
}
@@ -20,6 +20,7 @@ class CreateQAUserAnswerSelectedTable extends Migration
$table->unsignedBigInteger('question_id');
$table->unsignedBigInteger('answer_option_id')->default(0);
$table->string('free_text_answer')->nullable();
$table->string('reference')->nullable();
$table->timestamps();
$table->softDeletes();
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUrlsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('urls', function (Blueprint $table) {
$table->id();
$table->string('type');
$table->string('short_url');
$table->text('original_url');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('urls');
}
}
+3 -3
View File
@@ -15,17 +15,17 @@ class QAQuestionsSeeder extends Seeder
[
'name' => 'Set 1',
'description' => 'Customer Support Satisfaction Survey',
'group' => 'Feedback'
'group' => 'feedback'
],
[
'name' => 'Set 2',
'description' => 'First Order Experience Feedback',
'group' => 'Feedback'
'group' => 'feedback'
],
[
'name' => 'Set 3',
'description' => 'Sales Inquiry Experience',
'group' => 'Feedback'
'group' => 'feedback'
],
];
@@ -17,7 +17,7 @@
<div class="col">
<div class="row" v-if="section === 'customerPendingPaymentInvoiceComponent'">
<div class="col m-b-15">
<wallet-component :company_module_id="company_module_id" section="billingWalletSection"></wallet-component>
<wallet-component :company_module_id="company_module_id" section="billingWalletSection" :creditable=true></wallet-component>
</div>
</div>
<div class="b-a b-grey rounded padding-25 bg-white">
@@ -20,16 +20,21 @@
<div v-html="ans.display_text"></div>
</div>
</div>
<div class="row m-b-10" v-else-if="questions[index].question_type === 1" >
<div class="col" >
<validation-wrapper-component :validator="$v.answers.$each[index]" class="col">
<div class="col" v-for="ans in questions[index].question_answers">
<div :class="'col question-answers-' + index">
<div class="btn btn-xs btn-block" :answerValue="ans.value" :answerId=ans.id @click="addClass($event, 'question-answers-' + index, index)">{{ ans.display_text }}</div>
</div>
</div>
</validation-wrapper-component>
<div class="row m-b-25" v-else-if="questions[index].question_type === 1" >
<div class="col" v-for="ans in questions[index].question_answers">
<div :class="'question-answers-' + index">
<div class="btn btn-xs btn-block p-t-35 p-b-35 fs-16" :answerValue="ans.value" :answerId=ans.id @click="addClass($event, 'question-answers-' + index, index)">{{ ans.display_text }}</div>
</div>
</div>
<!-- <div class="col" >-->
<!-- <validation-wrapper-component :validator="$v.answers.$each[index]" class="row">-->
<!-- <div class="col" v-for="ans in questions[index].question_answers">-->
<!-- <div :class="'question-answers-' + index">-->
<!-- <div class="btn btn-xs btn-block p-t-35 p-b-35 fs-16" :answerValue="ans.value" :answerId=ans.id @click="addClass($event, 'question-answers-' + index, index)">{{ ans.display_text }}</div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </validation-wrapper-component>-->
<!-- </div>-->
</div>
<div class="row m-b-10" v-else-if="questions[index].question_type === 6" >
@@ -64,8 +69,8 @@
</div>
</div>
<div class="row" v-if="!$store.getters.isLoading(section)">
<div class="col">
<div class="btn btn-sm btn-primary btn-block b-rad-none" :disabled="!$v.$dirty || !$v.$valid" @click="formTouched = true; submitForm()">Submit</div>
<div class="col text-center">
<div class="btn btn-lg btn-info b-rad-none padding-25 w-50 fs-20" :disabled="!$v.$dirty || !$v.$valid" @click="formTouched = true; submitForm()">Submit Feedback</div>
</div>
</div>
</div>
@@ -125,7 +130,7 @@
this.answers[index].answer = div.getAttribute('answerValue');
this.answers[index].answerId = div.getAttribute('answerId');
this.removeClass(cls);
div.classList.add('btn-primary');
div.classList.add('btn-success');
},
setRating(value, index) {
this.answers[index].answer = value;
@@ -133,9 +138,9 @@
},
removeClass(cls) {
document.getElementsByClassName(cls).forEach(el => {
const btnPrimaryEl = el.getElementsByClassName('btn-primary')[0];
const btnPrimaryEl = el.getElementsByClassName('btn-success')[0];
if (btnPrimaryEl) {
btnPrimaryEl.classList.remove('btn-primary');
btnPrimaryEl.classList.remove('btn-success');
}
});
},
@@ -46,6 +46,11 @@
successHandler(response){
this.$store.dispatch('completeList', {'name': this.section, 'data': []});
this.questions = response.payload.data;
},
errorHandler(error, status){
if(status == 404){
window.location.href = this.route('error.404');
}
}
}
}
@@ -0,0 +1,51 @@
<template>
<a :href="href" @click="downloadFile" target="_blank">
<slot></slot>
</a>
</template>
<script>
export default {
props: {
href: {
type: String,
required: true,
},
},
methods: {
downloadFile(event) {
event.preventDefault();
fetch(this.href, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + this.$store.getters.getAccessToken,
},
})
.then((response) => {
if (response.status === 200) {
const contentDisposition = response.headers.get('Content-Disposition');
const filename = contentDisposition ? contentDisposition.split('filename=')[1] : 'downloaded_file';
return response.blob()
.then((blob) => {
const blobUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(blobUrl);
});
} else {
console.error('Request failed with status:', response.status);
}
})
.catch((error) => {
console.error('Network error:', error);
});
}
}
}
</script>
@@ -0,0 +1,68 @@
<template>
<div class="parentContainer">
<div class="floating-button">
<button class="requestModal round-button" data-type="helpMenu">
<i class="fa fa-info"></i>
<span class="beta-label">Beta</span>
</button>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="helpMenu">
<help-menu-form-component></help-menu-form-component>
</modal-component>
</div>
</div>
</template>
<script>
export default {
};
</script>
<style scoped>
.floating-button {
position: fixed;
z-index: 9999;
bottom: 95px;
right: 24px;
}
.round-button {
width: 60px;
height: 60px;
background-color: #007bff;
color: white;
border: none;
border-radius: 50%;
font-size: 24px;
cursor: pointer;
outline: none;
}
.round-button:hover {
background-color: #0056b3;
}
.beta-label {
position: absolute;
top: 44px;
left: 88%;
transform: translateX(-50%);
background-color: #ffee00;
color: black;
padding: 0px 4px;
border-radius: 5px;
font-size: 11px;
}
@media (max-height: 600px) {
.floating-button {
bottom: 85px;
right: 14px;
}
.round-button {
width: 54px;
height: 54px;
}
}
</style>
@@ -77,16 +77,6 @@
<script>
import { required } from "vuelidate/lib/validators";
export default {
props: {
data:{
type: Object,
required: true
},
module_type: {
type: String,
required: true
}
},
data(){
return {
section: 'helpMenuForm',
@@ -132,7 +122,7 @@
},
methods: {
fetchFirstQuestion(){
this.submit(route('api.helpmenu.first.question'), 'get', this.section, false, false);
this.submit(route('api.helpmenu.first.question', 4), 'get', this.section, false, false);
},
successHandler(response){
this.$store.dispatch('completeList', {'name': this.section, 'data': []});
@@ -144,7 +134,8 @@
}
},
errorHandler(error){
this.error = error.message;
// this.error = error.message;
this.error = 'We are sorry, something went wrong. Please contact us via live chat.';
},
submitForm(direction) {
this.parameters = {}
@@ -173,7 +164,7 @@
else{
if(this.question.is_end){
if(this.question.question_type === 5){
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, true, true);
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, false, false);
this.closeModal();
this.reset();
}
@@ -185,14 +176,14 @@
let payload = [];
payload.push(result);
$crisp.push(["set", "session:data", payload]);
$crisp.push(["do", "message:send", ["text", "Hello there!"]]);
$crisp.push(["do", "message:send", ["text", "Hello there!"]]); //cief todo: need to update what message to send from customer to operator
this.closeModal();
this.reset();
this.fetchFirstQuestion();
}
}
else{
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, true, true);
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, false, false);
}
}
}
@@ -200,7 +191,7 @@
this.formTouched = false;
this.parameters.question = this.question;
this.parameters.isPrevious = true;
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, true, true);
this.submit(this.route('api.helpmenu.next.question'), 'post', this.section, false, false);
}
},
reset() {
@@ -25,13 +25,13 @@
</div>
<div class="col d-flex">
<div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex" data-type="changeOrderNo" v-if="$store.getters.isSuperAdmin">Change Order Number</div>
<div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex m-l-10" data-type="helpMenu" v-if="$store.getters.isSuperAdmin">Help Menu</div>
<!-- <div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex m-l-10" data-type="helpMenu" v-if="$store.getters.isSuperAdmin">Help Menu</div> -->
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="changeOrderNo">
<change-order-number-form-component :section="section" :data="order"></change-order-number-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="helpMenu">
<help-menu-form-component module_type="Order" :data="order"></help-menu-form-component>
</modal-component>
<!-- <modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="helpMenu">
<help-menu-form-component></help-menu-form-component>
</modal-component> -->
</div>
</div>
<div class="row m-b-20">
@@ -25,13 +25,13 @@
</div>
<div class="col d-flex">
<div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex" data-type="changeOrderNo" v-if="$store.getters.isSuperAdmin">Change Order Number</div>
<div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex m-l-10" data-type="helpMenu" v-if="$store.getters.isSuperAdmin">Help Menu</div>
<!-- <div class="btn btn-xs btn-outline-danger b-rad-none pointer requestModal align-items-center d-flex m-l-10" data-type="helpMenu" v-if="$store.getters.isSuperAdmin">Help Menu</div> -->
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="changeOrderNo">
<change-order-number-form-component :section="section" :data="order"></change-order-number-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="helpMenu">
<help-menu-form-component module_type="Order" :data="order"></help-menu-form-component>
</modal-component>
<!-- <modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="helpMenu">
<help-menu-form-component></help-menu-form-component>
</modal-component> -->
</div>
</div>
<div class="row m-b-20">
@@ -69,7 +69,7 @@
this.canSubmitChanges = !this.canSubmitChanges;
this.parameters.transaction_details = this.details;
console.log(this.parameters.transaction_details);
// console.log(this.parameters.transaction_details);
this.submit(this.route('api.transaction.invoice.update', this.data.id), 'put', this.section, true, true);
}
@@ -21,8 +21,8 @@
<div class="row bg-white padding-10 m-b-10 rounded align-items-center" v-for="(item, index) in wallet.transactions" v-bind:key="item.id" :data="item">
<div class="col-3 fs-12">{{item.created_at}}</div>
<div class="col fs-12" v-html="item.description"></div>
<div class="col-2 text-success text-center">{{[5, 9].includes(parseFloat(item.type)) ? (Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col fs-12"><span v-html="item.description"></span> <a target=”_blank” v-if="[9,11].includes(item.type) " :href="route('transaction.credit_note.download', item.id)"><i class="fa fa-download fs-11 m-l-5 text-secondary hover-primary"></i></a></div>
<div class="col-2 text-success text-center">{{[5, 9, 15].includes(parseFloat(item.type)) ? (Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-danger text-center">{{[2, 11].includes(parseFloat(item.type)) ? '- ' + (Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-right">{{remainingBalance(index)}}</div>
</div>
@@ -52,7 +52,7 @@
</div>
</div>
<div class="col-4">
<wallet-component :data="wallet" :company_module_id="id" section="CompanyWalletTransactionSection"></wallet-component>
<wallet-component :data="wallet" :company_module_id="id" section="CompanyWalletTransactionSection" :creditable=true></wallet-component>
<div class="row m-t-20">
<div class="col">
<div class="row m-b-10">
@@ -15,9 +15,10 @@
</div>
</div>
<div class="row m-t-10 d-flex align-items-center">
<div class="col-auto">
<div class="col-auto" v-if="$store.getters.isSuperAdmin">
<div class="btn btn-xs p-l-15 p-r-20 b-rad-none font-heading btn-rounded bg-white" @click="reload = true"><i class="fa fa-plus fs-8 m-r-5"></i> Reload</div>
</div>
<div class="col-auto p-l-0" v-else="$store.getters.isSuperAdmin"></div>
<div class="col-auto p-l-0" v-if="!mini && wallet && section!=='CompanyWalletTransactionSection'">
<!-- <a class="text-white fs-10" :href="route('wallet.details', wallet.company_module_marking)" target="_blank">Transaction History<i class="fa fa-angle-right p-l-5"></i></a> -->
<a class="text-white fs-10" :href="route('wallet.details', wallet.company_module_marking)">Transaction History<i class="fa fa-angle-right p-l-5"></i></a>
@@ -99,6 +99,7 @@
</div>
</div>
@include('partials.footer')
<!-- @include('partials.helpmenu') -->
</div>
</div>
@@ -77,7 +77,7 @@
<div class="col">
<div class="row">
<div class="col">
<a href="{{route('packaging_list.pending_arrangement.export')}}" target="_blank">
<anchor-link-component href="{{route('packaging_list.pending_arrangement.export')}}" target="_blank">
<button type="button" class="btn btn-sm p-t-10 p-b-10 p-r-35 p-l-35 btn-primary b-rad-none">
<div class="row align-items-center">
<div class="col-auto p-r-0 p-l-0">
@@ -86,7 +86,7 @@
<div class="col p-r-5">Export To Excel</div>
</div>
</button>
</a>
</anchor-link-component>
<div class="row align-items-center m-t-10 p-t-10 p-b-10 b-t b-grey muted all-caps fs-10">
<div class="col-2">Marking</div>
<div class="col-1 text-center">Quantity</div>
@@ -156,4 +156,4 @@
</div>
</div>
</div>
@endsection
@endsection
+12 -2
View File
@@ -9,11 +9,21 @@
<div class="row d-none" :class="[{'d-flex': $store.getters.isAdmin}]" v-if="$store.getters.isAdmin">
<div class="col no-padding">
<div class="row no-margin">
<div class="col bg-master-lightest p-1 p-sm-4">
<div class="col bg-master-lightest p-1 p-sm-4 m-b-50">
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<anchor-link-component href="{{route('feedback.export')}}">
<button type="button" class="btn btn-sm p-t-10 p-b-10 p-r-35 p-l-35 btn-primary b-rad-none">
<div class="row align-items-center">
<div class="col-auto p-r-0 p-l-0">
<i class="fa fa-file-excel-o fs-16"></i>
</div>
<div class="col p-r-5">Export To Excel</div>
</div>
</button>
</anchor-link-component>
<div class="row align-items-center m-t-10 p-t-10 p-b-10 b-t b-grey muted all-caps fs-10">
<div class="col-1">Question Set</div>
<div class="col-2">Question Text</div>
@@ -25,7 +35,7 @@
</div>
</div>
</div>
<list-component section="questionsAnswersSection" :endpoint="route('api.helpmenu.list.questions.answers')" :options="{'per_page': 10, order_by: {column: 'created_at', DESC: true}}">
<list-component section="questionsAnswersSection" :endpoint="route('api.helpmenu.list.questions.answers')" :options="{'per_page': 10, 'has_questionnaire_group_in':['feedback'], order_by: {column: 'created_at', DESC: true}}">
<template slot="list" slot-scope="{data}">
<question-answer-component :data="data"></question-answer-component>
</template>
@@ -0,0 +1,114 @@
@extends('layouts.base_pdf')
@section('inner_content')
<br>
<htmlpageheader name="page-header">
<br><br>
<div class="separator"><strong><i>{{ $transaction->bill_no }}</i></strong></div>
</htmlpageheader>
<table>
<tr>
<td class="header-logo">
<img src="{{ asset('images/ri_1.png') }}" alt="logo" id="logo" class="logo">
</td>
<td class="header-cief-address">
<span class="company-name">
<strong>
CIEF WORLDWIDE SDN BHD
</strong>
</span>
<span class="company-reg">(1134596-M)</span><br>
No. 72-3, Jalan Jalil 1,<br>
The Earth Bukit Jalil,<br>
57000 Kuala Lumpur<br>
Tel: 03-8082 1252
</td>
<td class="header-details">
<div class="title">
<strong>
{{ $transaction->type == 9 ? 'Credit' : 'Debit' }} Note
</strong>
</div>
<div class="date">Date: {{ $transaction->created_at }}</div>
<div>&nbsp;</div>
</div>
</td>
<tr>
<td colspan="3" class="bill-to">
<span class="sub-title">
{{ $transaction->type == 9 ? 'Credit' : 'Debit' }} To
</span>
</td>
</tr>
<tr>
<td colspan="3" class="address">
<div class="label">
{{ $supplier->name }}
</div>
<div class="address">
@php
$addresses = $supplier->addresses()->where('type', 1)->first();
@endphp
@if($addresses)
{{ $addresses->street_one }}
{{ $addresses->street_two }} ,
{{ $addresses->district()->first()->name }},
{{ $addresses->postcode }}
{{ $addresses->state()->first()->name }},
{{ $addresses->country()->first()->name }}
@endif
</div>
<div>
@php
$contact = $supplier->contacts()->first();
@endphp
Phone: {{ $contact ? $contact->phone : '' }}
</div>
</td>
</tr>
</table>
<br>
<br>
<table class="line-table" style="overflow: wrap" autosize="1">
<thead>
<tr>
<th width="5%">No</th>
<th class="description">Description</th>
<th width="10%">Quantity</th>
<th width="15%">Unit Price (RM)</th>
<th width="10%">Total Amount<br>(RM)</th>
</tr>
</thead>
<tbody>
<tr>
<td width="5%" class="center top">1</td>
<td class="description">{{ ucfirst($transaction->payment_reference) }}</td>
<td width="10%" class="center top">1</td>
<td width="15%" class="center top">
{{ number_format($transaction->amount, 2) }}
</td>
<td width="20%" class="right top">
{{ number_format($transaction->amount, 2) }}
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3"></td>
<td class="right middle">Total</td>
<td class="total right middle">
{{ number_format($transaction->amount, 2) }}
</td>
</tr>
</tfoot>
</table>
<htmlpagefooter name="page-footer">
<table width="100%">
<tr>
<td style="text-align: right; ">This is generated by computer. No signature required.</td>
<td style="text-align: right; ">Page {PAGENO} of {nbpg}</td>
</tr>
</table>
</htmlpagefooter>
@endsection
@@ -0,0 +1,86 @@
<br>
<table>
<tr>
<td class="header-logo">
<img src="{{ asset('images/ri_1.png') }}" alt="logo" id="logo" class="logo">
</td>
<td class="header-cief-address">
<span class="company-name">
<strong>
CIEF WORLDWIDE SDN BHD
</strong>
</span>
<span class="company-reg">(1134596-M)</span><br>
No. 72-3, Jalan Jalil 1,<br>
The Earth Bukit Jalil,<br>
57000 Kuala Lumpur<br>
Tel: 03-8082 1252
</td>
<td class="header-details">
<div class="title" style="font-size: 20px; text-transform: uppercase;">
<strong>
Packing List Measurements
</strong>
</div>
<div class="date">Date: {{ $invoice_transaction->created_at }}</div>
</td>
</tr>
</table>
<br>
<br>
<table class="line-table" style="overflow: wrap" autosize="1">
<thead>
<tr>
<th width="5%">No</th>
<th class="description">Description</th>
<th width="15%">Measurement</th>
<th width="15%">CBM</th>
<th width="10%">Quantity</th>
<th width="15%">Total CBM</th>
</tr>
</thead>
<tbody>
@php
$packages = $invoice_transaction->owner->packages;
$totalCBM = 0;
$totalQty = 0;
@endphp
@foreach ($packages as $key => $package)
@php
$measurement = "{$package->length} (L) <br> {$package->width} (W) <br> {$package->height} (H)";
$itemCBM = ($package->width / 100) * ($package->height / 100) * ($package->length / 100);
$itemTotalCBM = $itemCBM * $package->quantity;
$totalCBM += $itemTotalCBM;
$totalQty += $package->quantity;
@endphp
<tr>
<td width="5%" class="center top">{{ $key + 1 }}</td>
<td class="description">{!! $package->description !!}</td>
<td width="15%" class="center top" style="text-align: center">
{!! $measurement !!}
</td>
<td width="15%" class="center top" style="text-align: center">
{{ round($itemCBM, 5) }}
</td>
<td width="10%" class="center top" style="text-align: center">{{ $package->quantity }}</td>
<td width="15%" class="right top">
{{ round($itemTotalCBM, 5) }}
</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<td colspan="3"></td>
<td class="right middle">Total</td>
<td class="total" style="text-align: center">
{{ $totalQty }}
</td>
<td class="total right middle">
{{ round($totalCBM, 5) }}
</td>
</tr>
</tfoot>
</table>
@@ -8,6 +8,9 @@
@include('pages.pdfs.shipping_invoice_inner', ['invoice_transaction' => $invoice_transaction])
<pagebreak />
@include('pages.pdfs.packing_list_measurement', ['invoice_transaction' => $invoice_transaction])
<htmlpagefooter name="page-footer">
<table width="100%">
<tr>
@@ -0,0 +1 @@
<help-menu-component></help-menu-component>
+1 -1
View File
@@ -3,7 +3,7 @@
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'helpmenu', 'as' => 'helpmenu.', 'namespace' => 'HelpMenu'], function () {
Route::get('/question', 'FetchQuestionQAController@fetch')->name('first.question');
Route::get('/question/{set_id}', 'FetchQuestionQAController@fetch')->name('first.question');
Route::post('/question', 'UpdateNextQuestionQAController@fetch')->name('next.question');
Route::post('/generate', 'GenerateFeedbackUrlController@generate')->name('feedback.url.generate');
Route::get('/list', 'ListQuestionsAnswersQAController@list')->name('list.questions.answers');
+52 -3
View File
@@ -42,6 +42,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use App\Models\Container;
use App\Models\Transaction;
use App\Models\Wallet;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
@@ -434,8 +435,8 @@ Route::get('/warehouse/{id}/show', function ($id) {
})->name('warehouse.show');
Route::get('/export/customer-latest-order-date/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@export');
Route::get('/export/packing-list/{id}', 'Exports\ExportContainerPackingListController@export')->name('container.packaging_list.export');
Route::get('/export/pending-arrangement-delivery-list', 'Exports\ExportPendingArrangementPackingListController@export')->name('packaging_list.pending_arrangement.export');
Route::get('/export/on-hold-packing-list', 'Exports\ExportPendingArrangementPackingListController@onHold')->name('packaging_list.on_hold.export');
Route::get('/export/pending-arrangement-delivery-list', 'Exports\ExportPendingArrangementPackingListV2Controller@export')->name('packaging_list.pending_arrangement.export');
Route::get('/export/on-hold-packing-list', 'Exports\ExportPendingArrangementPackingListV2Controller@onHold')->name('packaging_list.on_hold.export');
Route::get('/export/arrived-parcel', 'Exports\ExportArrivedParcelController@export')->name('packing_list.arrived_parcel.export');
Route::get('/export/parcel-summary', 'Exports\ExportArrivedParcelController@summary');
Route::get('/export/parcel-postcode', 'Exports\ExportParcelPostcodesController@export');
@@ -1078,7 +1079,8 @@ Route::get('/wallet/audit', function (Request $request) {
foreach ($wallet->transactions as $transaction){
if(!in_array((int) $transaction->status, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])) continue;
if((int) $transaction->type === TransactionType::TOP_UP) {
if((int) $transaction->type === TransactionType::TOP_UP || (int) $transaction->type === TransactionType::GROUP_PAYMENT) {
// if((int) $transaction->type === TransactionType::TOP_UP) {
$topups += (float) $transaction->amount;
}
if((int) $transaction->type === TransactionType::CREDIT_NOTE) $credit += (float) $transaction->amount;
@@ -1197,3 +1199,50 @@ Route::get('/feedback/{token}', function ($token) {
Route::get('/feedback', function () {
return view('pages.feedback');
})->name('admin.feedback');
Route::get('/export/feedback', 'Exports\ExportFeedbackDataController@export')->middleware(['api'])->middleware(['valid.token'])->name('feedback.export');
Route::get('/404', function () {
abort(404);
})->name('error.404');
Route::get('transaction/{id}/credit_note/download', 'Transactions\GenerateCreditNotePdfController@download')->name('transaction.credit_note.download');
Route::get('/check-successful-payment-or-topup', function () {
$sum = 0 ;
$transactions = Transaction::whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP, TransactionType::GROUP_PAYMENT])->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
foreach ($transactions as $transaction){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$transaction->payment_reference);
if($response->successful()){
$sum += $transaction->amount;
dump($transaction->payment_reference . 'Amount : ' . $transaction->amount);
}else{
dump("billplz error</br>");
}
}
dump("Sum is : " . $sum);
});
Route::get('/wallets/active', function(){
$wallets = Wallet::all();
echo '<table>';
foreach ($wallets as $wallet){
$companyMarking = $wallet->owner->getMarking();
echo '<tr>';
echo '<td><a href="'.route('wallet.details', $companyMarking).'" target="_blank">'.$companyMarking.'</a></td>';
echo '<td>'.$wallet->amount.'</td>';
echo '</tr>';
}
echo '</table>';
});
Route::get('/accident-approve-invoice', function(){
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->whereDate('updated_at', '2023-10-12')->get();
foreach ($invoices as $invoice) {
$orderMarking = $invoice->owner->owner->reference;
echo '<a href="'.route('order.v2.show', $orderMarking).'" target="_blank">'.$orderMarking.'</a><br>';
}
});