Merge branch 'development' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into Add-new-service-type-for-booking

This commit is contained in:
Uwais Al-Qarni
2022-05-14 18:49:53 +08:00
21 changed files with 509 additions and 34 deletions
@@ -14,6 +14,7 @@ use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Company;
use App\Models\User;
@@ -91,7 +92,7 @@ class CreateCustomerLogic extends AbstractControllerLogic
$user = $this->createUserProcessor->execute($request, RoleTypes::USER, App::environment(['local']) ? ApprovalStatus::APPROVED : ApprovalStatus::PENDING_VERIFICATION);
/** @var Company $company */
$company = $this->createCompanyProcessor->execute($request, BusinessType::IMPORTER, $request->input('type'), ApprovalStatus::PENDING_SUBMISSION);
$company = $this->createCompanyProcessor->execute($request, BusinessType::IMPORTER, $request->input('type') === CompanyType::COMPANY_BUSINESS ? CompanyType::COMPANY_BUSINESS : CompanyType::PERSONAL_BUSINESS, ApprovalStatus::PENDING_SUBMISSION);
$this->createContactProcessor->execute($request, $company);
@@ -65,7 +65,7 @@ class AutoPurchaseOrderFillLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$bookings = Booking::where(function($query){
return $query->whereMonth('created_at', 11)->orWhereMonth('created_at', 12);
return $query->whereMonth('created_at', 01)->orWhereMonth('created_at', 02);
})->whereDoesntHave('transactions', function($q){
$q->where('type', TransactionType::PURCHASE_ORDER);
$q->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]);
@@ -45,7 +45,9 @@ class DownloadBookingDocumentLogic
})->get();
if (!count($bookings)) throw new MalformedRequestException('No available file to download');
if (!count($bookings)) {
return response()->json(['no file to download']);
}
foreach ($bookings as $booking) {
@@ -0,0 +1,104 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Booking;
use App\Models\Company;
use App\Models\Transaction;
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 Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class ExportsAnalyticBookingTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function headings(): array
{
return [
'TransID',
'Company ID',
'Type Of User',
'Group Control / Experiment',
'Payment Date',
'Completed Purchase OrderDate',
'DayTo Closed',
'IsCompleted Purchase Order (1 or 0)',
'Final Payment',
'Discount Amount',
'PaymentType',
'RowUpdateDate'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
return Booking::query();
}
/**
* @param $booking
* @return array
*/
public function map($booking): array
{
$companyType = [];
$companyType[companyType::COMPANY_BUSINESS] = 'COMPANY_BUSINESS';
$companyType[companyType::PERSONAL_BUSINESS] = 'PERSONAL_BUSINESS';
$payments = $booking->transactions()->where('type', 1)->whereIn('status', [2, 3]);
$paymentmethondArray = PaymentMethodType::PAYMENT_METHODS_ID;
$paymentmethondArray[0] = 'Hybrid';
$paymentMethod = '';
foreach ($payments->get() as $payment) {
if ( $paymentMethod == '' ) {
$paymentMethod = $payment->payment_method;
} else if ( $payment->payment_method != $paymentMethod ) {
$paymentMethod = 0; // set it to Hybrid
}
}
$paymentMethod === '' ? '' : $paymentMethod = $paymentmethondArray[$paymentMethod];
$firstPayment = $payments->first();
$CompletedPurchaseOrders = $booking->transactions()->where('type', 7)->whereIn('status', [1, 2]);
$FirstCompletedPurchaseOrder = $CompletedPurchaseOrders->first();
$lastPayment = $booking->transactions()->where('type', 1)->whereIn('status', [2, 3])->orderBy('id', 'desc')->first();
return [
$booking->id,
$booking->company_id,
$companyType[$booking->company->type],
'',
$firstPayment == null ? '' : $firstPayment->created_at,
$FirstCompletedPurchaseOrder == null ? '' : $FirstCompletedPurchaseOrder->created_at,
'',
$CompletedPurchaseOrders->count() > 0 ? '1' : '0',
$lastPayment == null ? '' : $lastPayment->amount,
'',
$paymentMethod,
'',
];
}
}
@@ -0,0 +1,74 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Models\Company;
use App\Models\Transaction;
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 Illuminate\Http\Request;
use Carbon\Carbon;
class ExportsBookingTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function headings(): array
{
return [
'Ref No',
'Creted Date',
'Amount',
'Rate',
'Supplier'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$supplierIds = array_map(function($value){
return ['id' => $value];
}, json_decode($this->request->input('supplierIds')));
$dateFrom =Carbon::parse($this->request->input('startDate'))->format('Y-m-d');
$dateTo =Carbon::parse($this->request->input('endDate'))->format('Y-m-d');
return Transaction::where('type', 3)->whereIn('issuer', $supplierIds)->whereBetween('created_at', [$dateFrom, $dateTo]);
}
/**
* @param $transaction
* @return array
*/
public function map($transaction): array
{
$supplierName = Company::where('id', $transaction->issuer)->get()->first()->name;
$refNo = $transaction->owner->owner == null ? $transaction->owner->marking : $transaction->owner->owner->marking;
$createdAt = $transaction->created_at->format('d-m-Y');
$amount = $transaction->amount;
$rate = $transaction->currency_rate;
return [
$refNo,
$createdAt,
$amount,
$rate,
$supplierName
];
}
}
@@ -5,8 +5,10 @@ namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Company;
use App\Models\Transaction;
use App\Models\Wallet;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
@@ -24,7 +26,7 @@ class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping, Sho
*/
public function query()
{
return Transaction::query();
return Transaction::whereIn('type', [TransactionType::PAYMENT, TransactionType::BILL])->where('owner_type', '!=',Wallet::class);
}
/**
@@ -59,26 +61,24 @@ class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping, Sho
6 => 'EXPIRED'
];
switch ($transaction->owner_type) {
case "App\Models\Booking":
$marking = $transaction->booking->company->reference;
break;
case "App\Models\Transaction":
$marking = $transaction->transactions()->first()->booking->company->reference;
break;
case "App\Models\Wallet":
$marking = $transaction->owner->owner->reference;
break;
default:
$marking = '';
}
$booking = $transaction->owner;
if(!($booking instanceof Booking)){
$booking = $booking->owner;
}
$company = $booking->company;
if(!$company instanceof Company) dd($transaction);
return [
$company->reference,
$booking ? $booking->marking : '',
$transaction->bill_no,
$transaction->owner_id,
$transaction->owner_type,
$transactionTypes[$transaction->type],
$transaction->issuer,
$transaction->issuerCompany->name,
$transaction->reciver,
$transaction->currency_id === 1 ? 'MYR' : 'RMB',
$transaction->amount,
@@ -24,10 +24,10 @@ final class TransactionType {
public const CREDIT_NOTE = 9;
public const WITHDRAW = 10;
public const DEBIT_NOTE = 11;
public const WITHDRAW = 10;
public const TRANSFER_FEE = 12;
public const CASH_BACK = 13;
@@ -15,7 +15,7 @@ class DownloadBookingDocumentController
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function download(Request $request, DownloadBookingDocumentLogic $logic) {
$logic->execute($request);
return $logic->execute($request);
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\Services\ExportsAnalyticBookingTransactions;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Excel;
class ExportAnalyticToExcelController
{
/**
* ExportAnalyticToExcelController constructor.
* @param Request $request
*/
public function __construct(Request $request)
{
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
}
public function bookingData(ExportsAnalyticBookingTransactions $exportsAnalyticBookingTransactions, Request $request){
$response = $exportsAnalyticBookingTransactions->download('bookingData.csv', Excel::CSV, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\Services\ExportsCustomers;
use App\Classes\Modules\Exports\Services\ExportsTransactions;
use App\Classes\Modules\Exports\Services\ExportsBookingTransactions;
use App\Classes\Modules\Exports\Services\ExportsNullDebtors;
use App\Classes\Modules\Exports\Services\ExportsPaymentTransactions;
@@ -54,4 +55,10 @@ class ExportCustomersToExcelController
ob_end_clean();
return $response;
}
public function bookingTransactions(ExportsBookingTransactions $exportsBookingTransactions, Request $request){
$response = $exportsBookingTransactions->download('bookingTransactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ class Booking extends AbstractModel implements Documentable, Transactionable
*/
public function company(): BelongsTo
{
return $this->BelongsTo(Company::class, 'company_id');
return $this->BelongsTo(Company::class, 'company_id')->withTrashed();
}
/**
@@ -121,16 +121,18 @@
<div class="col">
<div class="row">
<div class="col">
<button type="button" class="btn btn-sm p-t-10 p-b-10 btn-default bg-master-lighter b-rad-none" @click="$v.$reset;$store.dispatch('toggleSection', {name: 'registrationForm', status: false})">
<div class="row align-items-center">
<div class="col-auto p-r-10">
<i class="fa fa-angle-left fs-16" style="margin-top: 1px;"></i>
<a :href="route('login')">
<button type="button" class="btn btn-sm p-t-10 p-b-10 btn-default bg-master-lighter b-rad-none" >
<div class="row align-items-center">
<div class="col-auto p-r-10">
<i class="fa fa-angle-left fs-16" style="margin-top: 1px;"></i>
</div>
<div class="col p-l-5">
Already have an account
</div>
</div>
<div class="col p-l-5">
Back To Login
</div>
</div>
</button>
</button>
</a>
</div>
<div class="col text-right">
<button type="button" class="btn btn-sm p-t-10 p-b-10 p-r-35 p-l-35 btn-success b-rad-none" @click="changeStep('next')">Next</button>
@@ -0,0 +1,96 @@
<template>
<div class="row m-b-20">
<div class="col">
<div class="row">
<div class="col">
<div class="row m-l-0 m-r-0 bg-master-light padding-10 parentContainer">
<div class="col">
<div class="row requestModal pointer" data-type="deleteBank">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.supplierNames">
<label>Supplier</label>
<input type="text" class="form-control fs-12 pointer" v-model="parameters.supplierNames" disabled>
</validation-wrapper-component>
</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteBank">
<select-supplier-form-component section="supplierListSection" v-on:input="updateList($event)"></select-supplier-form-component>
</modal-component>
</div>
<div class="col-12 col-md mb-2 mb-md-0">
<validation-wrapper-component :validator="$v.parameters.startDate">
<label class="all-caps">Start Date</label>
<date-picker-component :parameters="parameters" v-model.lazy="parameters.startDate"></date-picker-component>
</validation-wrapper-component>
</div>
<div class="col-12 col-md mb-2 mb-md-0">
<validation-wrapper-component :validator="$v.parameters.endDate">
<label class="all-caps">End Date</label>
<date-picker-component :parameters="parameters" v-model.lazy="parameters.endDate"></date-picker-component>
</validation-wrapper-component>
</div>
<div class="col-12 col-md-auto d-flex justify-content-center align-items-center">
<button type="button" class="btn btn-lg btn-primary fs-11 w-100" @click="submitSearch()">Download</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from "../../../general/mixins/componentHandler";
import { required, minValue} from "vuelidate/lib/validators";
import {VMoney} from 'v-money'
export default {
data(){
return {
parameters: {
startDate: '',
endDate: '',
supplier: null,
supplierIds: [],
supplierNames: []
},
}
},
validations: {
parameters: {
startDate: {
required
},
endDate: {
required
},
supplierIds: {
required
},
supplierNames: {
required
},
}
},
methods: {
submitSearch(){
if(!this.validate()){ return; }
var supplierIds = JSON.stringify(this.parameters.supplierIds);
window.open(route('export.transactions.booking')+'?startDate='+this.parameters.startDate+'&endDate='+this.parameters.endDate+'&supplierIds='+supplierIds, '_blank');
},
updateList(supplierList){
let supplierIds = [];
let supplierNames = [];
supplierList.forEach(function(supplier) {
supplierIds.push(supplier.id);
supplierNames.push(supplier.name);
});
this.parameters.supplierIds = supplierIds;
this.parameters.supplierNames = supplierNames;
},
},
mixins: [componentHandler]
};
</script>
@@ -7,7 +7,14 @@
<div class="col-auto p-r-0"><div class="icon-thumbnail icon-35 mr-0 btn-rounded text-white light animate__animated animate__infinite" :class="[{'bg-danger': !submitted}, {'animate__pulse': !submitted}, {'bg-success': submitted}]"><span v-if="data.status !==3">2</span><i class='fa fa-check' v-if="data.status === 3"></i></div></div>
<div class="col">
<div class="fs-14 bold all-caps" :class="[{'text-success': submitted}]">Purchase Order</div>
<p class="m-b-0 text-danger fs-12" v-if="!submitted">In order for us to process your order, you will need to provide us with your purchase order information.</p>
<p class="m-b-0 fs-12" v-if="!submitted">In order for us to process your order, you will need to provide us with your purchase order information.</p>
</div>
</div>
<div class="row" v-if="!submitted">
<div class="col-auto">
<div class="bg-danger p-l-15 p-r-15 p-t-5 p-b-5">
<p class="m-b-0 text-white fs-12" >Any Purchase Orders that aren't submitted within 60 days will be closed for editing.</p>
</div>
</div>
</div>
<div class="row">
@@ -0,0 +1,43 @@
<template>
<div class="row">
<div class="col b-a b-grey" :class="{'b-gray': !selected, 'b-primary': selected, 'bg-primary-lighter': selected}">
<div class="row">
<div class="col padding-20">
<div class="row align-items-center">
<div class="col-auto pointer align-items-center" @click="selectSupplier()">
<i class="fa fs-30 fa-fw" :class="{'fa-square-o': !selected, 'fa-check-square': selected, 'text-primary':selected}" ></i>
</div>
<div class="col">
<h5 class="no-margin">{{ item.name }}</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from "../../../general/mixins/componentHandler";
export default {
props: {
selectedSupplier: {
type: Array,
required: false,
}
},
data(){
return {
selected: false
}
},
methods: {
selectSupplier(){
this.selected = !this.selected;
this.$emit('input', this.item);
}
},
mixins: [componentHandler]
};
</script>
@@ -0,0 +1,59 @@
<template>
<div class="row bg-white padding-40">
<div class="col">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
<div class="row justify-content-center" v-show="!isLoading">
<div class="col">
<div class="row m-b-20">
<div class="col">
<h3 class="all-caps text-center">Please select the supplier.</h3>
</div>
</div>
<div class="row m-b-20">
<div class="col">
<list-component section="supplierListSection" :endpoint="route('api.company.list')" :options="{business_type: 3}">
<template slot="list" slot-scope="{data}">
<div class="row">
<div class="col">
<select-individual-supplier-form-component :data="data" :selectedSupplier="selectedSupplier" v-on:input="updateList($event)"></select-individual-supplier-form-component>
</div>
</div>
</template>
</list-component>
</div>
</div>
<div class="row">
<div class="col">
<div class="btn btn-sm btn-success btn-block b-rad-none" @click="submitForm()">Confirm</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from "../../../general/mixins/componentHandler";
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
import { required, minValue} from "vuelidate/lib/validators";
import {VMoney} from 'v-money'
export default {
data(){
return {
selectedSupplier: [],
}
},
methods: {
submitForm() {
this.$emit('input', this.selectedSupplier);
this.closeModal();
},
updateList(supplier){
this.selectedSupplier.includes(supplier) ? this.selectedSupplier.splice(this.selectedSupplier.indexOf(supplier), 1) : this.selectedSupplier.push(supplier);
},
},
mixins: [componentHandler, ModalFormHandler]
};
</script>
+1 -1
View File
@@ -5,7 +5,7 @@ export default {
(this.$store.getters.isAuthenticated && !this.isProtectedRoute()&& !this.isWithTokenRoute()) ? window.location.href = this.route('dashboard') : '';
},
isProtectedRoute(){
const unprotectedRoutes = [this.route('login'), this.route('account.email.verification')];
const unprotectedRoutes = [this.route('login'), this.route('signup'), this.route('account.email.verification')];
return !unprotectedRoutes.includes(window.location.href);
},
isWithTokenRoute(){
@@ -64,7 +64,7 @@
<div class="row m-t-15">
<div class="col">
<a href="#">
<button class="btn btn-sm btn-outline-success bold b-rad-none b-thick" @click="$store.dispatch('toggleSection', {name: 'registrationForm', status: true})">Create Account</button>
<a href="{{ route('signup') }}" class="btn btn-sm btn-outline-success bold b-rad-none b-thick">Create Account</a>
</a>
</div>
</div>
@@ -0,0 +1,43 @@
@extends('layouts.base_login')
@section('inner_content')
<transition-component group enter-class="animate__animated animate__fadeInRightBig animate__faster" leave-class="animate__animated animate__fadeOutRightBig">
<div class="row" key="1">
<div class="col-12 col-md p-l-0 p-r-0 p-t-15 p-b-15">
<div class="h-100 bg-white">
<div class="row m-l-0">
<div class="col">
<div class="row">
<div class="col-4 d-none d-md-inline padding-25 bg-primary">
<div class="row h-100 align-items-center justify-content-center text-center">
<div class="col">
<div class="row m-b-10">
<div class="col">
<div class="font-heading text-white fs-20 all-caps bold lh-25">We Are Glad</div>
<div class="font-heading text-white fs-12 all-caps m-b-20 lh-25">You've Decided To join Us</div>
</div>
</div>
<div class="row">
<div class="col">
<img src="{{asset('/images/2853457.png')}}" class="w-100"/>
</div>
</div>
</div>
</div>
</div>
<div class="col p-l-50 p-r-50 p-t-30 p-b-30">
<loading-component style="height: 350px;" key="1" color="primary" v-show="$store.getters.isLoading('loginSection')"></loading-component>
<div class="row" v-show="!$store.getters.isLoading('loginSection')">
<div class="col">
<registration-form-component section="loginSection"></registration-form-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</transition-component>
@endsection
@@ -2,6 +2,7 @@
@section('inner_content')
<div class="row">
<div class="col p-t-15 p-b-15">
<export-booking-transaction-form-component></export-booking-transaction-form-component>
<div class="row">
<div class="col-4">
<div class="row tabsContainer">
+6
View File
@@ -30,6 +30,10 @@ Route::get('', function () {
return view('pages.accounts.login');
})->name('login');
Route::get('/signup', function () {
return view('pages.accounts.sign_up');
})->name('signup');
Route::get('/account/email/verification/{token}', function ($token) {
return view('pages.accounts.email_verified', ['token' => $token]);
})->name('account.email.verification');
@@ -92,6 +96,7 @@ Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callba
Route::get('/export/customers/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@export');
Route::get('/export/transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@transactions');
Route::get('/export/analytic/booking', 'Exports\ExportAnalyticToExcelController@bookingData');
Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) {
return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']);
@@ -151,6 +156,7 @@ Route::get('/export/transactions/f614e339d7058904a831aad742e24d55', 'Exports\Exp
Route::get('/export/null-debtor/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@nullDebtor')->name('newDebtor.export');
Route::get('/export/payment-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@paymentTransactions')->name('paymentTransactions.export');
Route::get('/export/wallet-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@walletTransactions')->name('walletTransactions.export');
Route::get('/export/booking-transactions', 'Exports\ExportCustomersToExcelController@bookingTransactions')->name('export.transactions.booking');
Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) {
$bookings = Booking::where(function($query){