EXCHANGE-149, EXCHANGE-156 - Bug fixes, clean-up. Added seeder to create sample transactions

This commit is contained in:
Fairuz
2021-05-15 13:23:23 +08:00
parent 55717afc14
commit 9dd0a8d786
9 changed files with 409 additions and 74 deletions
@@ -23,7 +23,7 @@ abstract class AbstractDeleteMultipleRecord
return ($record_deleted == count($ids)) ? true : false;
} catch (QueryException|\Exception $exception){
throw new MalformedRequestException('Unable to update the record due to unexpected error');
throw new MalformedRequestException('Unable to delete the record due to unexpected error');
}
}
@@ -2,18 +2,18 @@
namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\Exceptions\ErrorException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Bookings\Services\DeleteMultipleTransaction;
use App\Classes\Modules\Bookings\Standards\Rules\CanMergeBooking;
use App\Classes\Modules\Bookings\DataTransferObjects\BookingMergeObject;
use App\Classes\Modules\Bookings\Services\DeleteMultipleBooking;
use App\Classes\Modules\Bookings\Services\GetBookings;
use App\Classes\Modules\Bookings\Standards\Rules\CanMergeBooking;
use App\Classes\Modules\Bookings\Services\UpdatesBookingTransaction;
use App\Classes\Modules\Bookings\Services\DeleteMultipleBooking;
use App\Classes\Modules\Transactions\Services\FetchesTransactionDetail;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class MergeBookingLogic extends AbstractControllerLogic
{
@@ -34,94 +34,113 @@ class MergeBookingLogic extends AbstractControllerLogic
/** @var GetBookings */
private $getBookings;
/** @var FetchesTransactionDetail */
private $fetchesTransactionDetail;
/** @var UpdatesBookingTransaction */
private $updatesBookingTransaction;
/** @var DeleteMultipleBooking */
private $deletesMultipleBooking;
/** @var DeleteMultipleTransaction */
private $deletesMultipleTransaction;
/**
* MergeBookingLogic constructor.
* @param CanMergeBooking $canMergeBooking
* @param GetBookings $getBookings
* @param FetchesTransactionDetail $fetchesTransactionDetail
* @param UpdatesBookingTransaction $updatesBookingTransaction
* @param DeleteMultipleBooking $deletesMultipleBooking
* @param DeleteMultipleTransaction $deletesMultipleTransaction
*/
public function __construct(CanMergeBooking $canMergeBooking, GetBookings $getBookings, UpdatesBookingTransaction $updatesBookingTransaction, DeleteMultipleBooking $deletesMultipleBooking)
public function __construct(CanMergeBooking $canMergeBooking, GetBookings $getBookings, FetchesTransactionDetail $fetchesTransactionDetail, UpdatesBookingTransaction $updatesBookingTransaction, DeleteMultipleBooking $deletesMultipleBooking, DeleteMultipleTransaction $deletesMultipleTransaction)
{
$this->canMergeBooking = $canMergeBooking;
$this->getBookings = $getBookings;
$this->updatesBookingTransaction = $updatesBookingTransaction;
$this->deletesMultipleBooking = $deletesMultipleBooking;
$this->deletesMultipleTransaction = $deletesMultipleTransaction;
$this->fetchesTransactionDetail = $fetchesTransactionDetail;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
try{
$transaction_amount = 0;
$transaction_amount = null;
$transaction_original_amount = null;
$booking_ids_to_merge = [];
$booking_update_values = [];
$booking_ids_to_merge = [];
$booking_update_values = [];
$transaction_ids_to_merge = [];
$transaction_update_values = [];
$transaction_ids_to_merge = [];
$transaction_update_values = [];
$transaction_po_delete = [];
$booking_object = new BookingMergeObject($request->get('id'),$request->get('booking_ids'));
$transaction_details_ids = [];
$transaction_details_values = [];
$this->canMergeBooking->passes($booking_object);
$booking_object = new BookingMergeObject($request->get('id'),$request->get('booking_ids'));
$booking_main = $this->getBookings->handler(['id'=> $booking_object->getId()])[0];
$bookings_to_merge = $this->getBookings->handler(['id_in'=> $booking_object->getBookingIds()]);
$this->canMergeBooking->passes($booking_object);
$booking_amount = $booking_main->fix_amount;
$booking_main_transactions = $booking_main->transactions()->get();
$booking_main = $this->getBookings->handler(['id'=> $booking_object->getId()])[0];
$bookings_to_merge = $this->getBookings->handler(['id_in'=> $booking_object->getBookingIds()]);
foreach($booking_main_transactions as $transaction)
{
$transaction_amount += $transaction->amount;
$booking_amount = $booking_main->fix_amount;
$booking_main_transaction = $booking_main->transactions()->first();
$transaction_amount = $booking_main_transaction->amount;
$transaction_original_amount = $booking_main_transaction->original_amount;
foreach($bookings_to_merge as $booking)
{
$booking_amount += $booking->fix_amount;
$bookings_to_merge_transaction = $booking->transactions()->first();
$transaction_update_values['booking_id']=$booking_main->id;
$transaction_amount += $bookings_to_merge_transaction->amount;
$transaction_original_amount += $bookings_to_merge_transaction->original_amount;
$transaction_ids_to_merge[]=$bookings_to_merge_transaction->id;
if($bookings_to_merge_transaction->type==7) {
$transaction_po_delete[] = $bookings_to_merge_transaction->id;
}
$booking_update_values['status']=1;
$booking_update_values['fix_amount']=$transaction_amount;
$booking_ids_to_merge[]=$booking->id;
foreach($bookings_to_merge as $booking)
{
$booking_amount += $booking->fix_amount;
$bookings_to_merge_transactions = $booking->transactions()->get();
foreach($bookings_to_merge_transaction->transactionDetails()->get() as $transaction_detail){
$transaction_details_ids[] = $transaction_detail->id;
$transaction_details_values['transaction_id'] = $booking_main_transaction->id;
foreach($bookings_to_merge_transactions as $transaction)
{
$transaction_amount += $transaction->amount;
$transaction_update_values['status']=0;
$transaction_update_values['booking_id']=$booking_main->id;
$transaction_ids_to_merge[]=$transaction->id;
}
$booking_ids_to_merge[]=$booking->id;
}
DB::beginTransaction();
//Update all transactions
$this->updatesBookingTransaction->execute($booking_main->id,$booking_update_values, $transaction_ids_to_merge, $transaction_update_values);
//Soft delete merged booking
$this->deletesMultipleBooking->execute($booking_ids_to_merge);
DB::commit();
return $this->response();
} catch (\Exception $exception) {
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
$booking_update_values['fix_amount']=$booking_amount;
//Update all transactions
$this->updatesBookingTransaction->execute(
$booking_main->id,$booking_update_values,
$transaction_ids_to_merge, $transaction_update_values,
$transaction_details_ids, $transaction_details_values
);
//Soft delete merged booking
$this->deletesMultipleBooking->execute($booking_ids_to_merge);
//Soft delete merged transaction with status 7 (purchase order)
if(count($transaction_po_delete)>0) {
$this->deletesMultipleTransaction->execute($transaction_po_delete);
}
return $this->response();
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\Modules\Bookings\Services;
use App\Classes\General\Eloquent\AbstractDeleteMultipleRecord;
use App\Models\Transaction;
class DeleteMultipleTransaction extends AbstractDeleteMultipleRecord
{
/**
* @param array $ids
* @return mixed
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(array $ids) {
return $this->handler(Transaction::query(), $ids);
}
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\Bookings\Services;
use App\Classes\General\Eloquent\AbstractUpdateMultipleRecord;
use App\Models\Booking;
use App\Models\Transaction;
use App\Models\TransactionDetail;
class UpdatesBookingTransaction extends AbstractUpdateMultipleRecord
{
@@ -13,14 +14,17 @@ class UpdatesBookingTransaction extends AbstractUpdateMultipleRecord
* @param array $booking_values
* @param array $transaction_ids
* @param array $transaction_values
* @param array $transaction_detail_ids
* @param array $transaction_detail_values
* @return mixed
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(int $booking_id, array $booking_values, array $transaction_ids, array $transaction_values) {
public function execute(int $booking_id, array $booking_values, array $transaction_ids, array $transaction_values, array $transaction_detail_ids, array $transaction_detail_values) {
$booking_update_success = $this->handler(Booking::query(),[$booking_id],$booking_values);
if($booking_update_success) {
$booking_update_success = $this->handler(Transaction::query(), $transaction_ids, $transaction_values);
$booking_update_success = $this->handler(TransactionDetail::query(), $transaction_detail_ids, $transaction_detail_values);
}
return $booking_update_success;
+291
View File
@@ -0,0 +1,291 @@
<?php
use Illuminate\Database\Seeder;
use App\Classes\ValueObjects\Constants as Constants;
use App\Models as Models;
use Illuminate\Support\Facades\DB;
class FakeBookingTransactions extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
if(App()->environment('local')) {
//Add user to map company, and auth user for bookings
$email = 'bookmaster@cief.com';
$password = 'bo@k!ng$123';
$booking_user = [
'name' => 'Book Master',
'email' => $email,
'password' => bcrypt($password),
'type' => Constants\RoleTypes::USER,
'status' => Constants\ApprovalStatus::APPROVED,
];
$user = Models\User::updateOrCreate(['email' => $email], $booking_user);
$user_id = $user->id;
//Add 3 Entity: 2 company + 1 individual
$companies = [
[
'name' => 'Maersk Line SDN BHD',
'reference' => 'MAERSK-123',
'type' => Constants\CompanyType::COMPANY_BUSINESS,
'business_type' => Constants\BusinessType::FREIGHT_FORWARDER,
'status' => Constants\ApprovalStatus::APPROVED,
],
[
'name' => 'Sunrise Importer SDN BHD',
'reference' => 'SSMID-E',
'type' => Constants\CompanyType::COMPANY_BUSINESS,
'business_type' => Constants\BusinessType::IMPORTER,
'status' => Constants\ApprovalStatus::APPROVED,
],
[
'name' => 'Han Solo',
'reference' => '880101-14-6541',
'type' => Constants\CompanyType::PERSONAL_BUSINESS,
'business_type' => Constants\BusinessType::IMPORTER,
'status' => Constants\ApprovalStatus::APPROVED,
]
];
$addresses = [
[
'company_id' => null, //fill-up later
'country_id' => 1,
'state_id' => 15,
'district_id' => 402,
'postcode' => '63000',
'street_one' => 'Vertex Tower, Cybersquare,',
'street_two' => 'Jalan Teknorat 6, Cyber 5',
'billing' => 1
]
];
$contacts = [
[
'company_id' => null, //fill-up later
'country_id' => 1,
'reference' => 'main',
'phone' => '0123456789',
'email' => 'email@edomain.com'
]
];
$banks = [
[
'company_id' => null, //fill-up later
'reference' => 'CBB',
'bank_name' => 'Citibank Berhad',
'holder_name' => '', //fill-up later, use company name
'account_no' => '0123456789',
'bank_branch' => 'Menara Citibank Kuala Lumpur',
'swift' => null,
'snap' => null,
'type' => Constants\BankAccountType::EXTERNAL,
'default' => 0,
'status' => 2,
'country_id' => 2,
]
];
$company_ids = [];
$address_ids = [];
$contact_ids = [];
$bank_ids = [];
foreach ($companies as $company) {
$check = ['name' => $company['name']];
$added = Models\Company::updateOrCreate($check, $company);
$company_ids[] = $added->id;
//Add address
foreach ($addresses as $address) {
$address['company_id'] = $added->id;
$address['street_one'] = $company['name'] . ", " . $address['street_one'];
$check_address = ['street_one' => $address['street_one']];
$added_address = Models\Address::updateOrCreate($check_address, $address);
$address_ids[$added->id][] = $added_address->id;
}
//Add contact
foreach ($contacts as $contact) {
$contact['company_id'] = $added->id;
$contact['reference'] = $company['name'] . ", " . $contact['reference'];
$check_contact = ['reference' => $contact['reference']];
$added_contact = Models\Contact::updateOrCreate($check_contact, $contact);
$contact_ids[$added->id][] = $added_contact->id;
}
//Add bank
foreach ($banks as $bank) {
$bank['company_id'] = $added->id;
$bank['reference'] = $company['name'] . ", " . $bank['reference'];
$check_bank = ['reference' => $bank['reference']];
$added_bank = Models\Bank::updateOrCreate($check_bank, $bank);
$bank_ids[$added->id][] = $added_bank->id;
}
DB::table('employees')->updateOrInsert(
['company_id' => $added->id, 'user_id' => $user_id, 'status' => 2],
['company_id' => $added->id, 'user_id' => $user_id, 'status' => 2]
);
DB::table('documents')->updateOrInsert(
['owner_id' => $added->id, 'status' => 2],
[
'owner_type' => 'App\Models\Company',
'owner_id' => $added->id,
'status' => 2,
'document_type' => ($company['type'] == Constants\CompanyType::COMPANY_BUSINESS) ? Constants\DocumentType::SSM_REGISTRATION : Constants\DocumentType::IDENTITY_CARD,
'reference' => $company['reference'],
]
);
}
//Booking, Transactions require auth user
$user = new Models\User;
$user->email = $email;
$user->password = $password;
auth()->login($user);
$bookings = [
[
'company_id' => null, //fill-up later
'marking' => null, //fill-up later
'service_id' => 1,
'bank_id' => null, //fill-up later
'fix_amount' => null, //fill-up later
'fix_currency_id' => 2,
'convertible_currency_id' => 2,
'conversion_currency_id' => 1,
'status' => Constants\ApprovalStatus::APPROVED,
],
];
$transactions = [
[
'booking_id' => null, //fill-up later
'type' => null, //fill-up later
'issuer' => null, //fill-up later
'receiver' => 1,
'recipient_bank_account_id' => 1,
'payment_method' => 2,
'payment_reference' => 2,
'bill_no' => null, //fill-up later
'amount' => null, //fill-up later
'original_amount' => null, //fill-up later
'currency_id' => 2,
'original_currency_id' => 2,
'currency_rate' => 1.0,
'tax' => 1.0,
'service_charge' => 0.0,
'expires_on' => null,
'status' => 0,
],
];
$transaction_details = [
[
'transaction_id' => null, //fill-up later
'product_code' => 'MBP15',
'product_name' => 'Macbook Pro 15"',
'quantity' => 10,
'price' => 100,
'amount' => 1000,
],
[
'transaction_id' => null, //fill-up later
'product_code' => 'IP12',
'product_name' => 'iPad Pro 12"',
'quantity' => 10,
'price' => 100,
'amount' => 1000,
],
[
'transaction_id' => null, //fill-up later
'product_code' => 'IMC24',
'product_name' => 'iMac',
'quantity' => 10,
'price' => 100,
'amount' => 1000,
],
];
$booking_ids = [];
$transaction_ids = [];
$transaction_types = [
Constants\TransactionType::PAYMENT_ATTEMPT,
Constants\TransactionType::PAYMENT,
Constants\TransactionType::INVOICE,
Constants\TransactionType::BILL,
Constants\TransactionType::PERFORMA,
Constants\TransactionType::TOP_UP,
Constants\TransactionType::REFUND,
Constants\TransactionType::PURCHASE_ORDER,
Constants\TransactionType::SUPPLIER_DELIVER,
];
foreach ($company_ids as $company_id) {
foreach ($transaction_types as $transaction_type) {
foreach ($bookings as $booking) {
$marking = mt_rand(20000, 20100); //Limit marking within 100 for easier to remember
$booking['company_id'] = $company_id;
$booking['bank_id'] = $bank_ids[$company_id][0];
$booking['marking'] = $marking;
$booking['fix_amount'] = 1000;
$booking['created_at'] = date('Y-m-d H:i:s');
$booking['updated_at'] = date('Y-m-d H:i:s');
$check_booking = ['marking' => $booking['marking']];
$added_booking = Models\Booking::updateOrCreate($check_booking, $booking);
$booking_ids[] = $added_booking->id;
$booking_id = $added_booking->id;
foreach ($transactions as $transaction) {
$bill_no = $code = mt_rand(100000001, 999999999);;
$transaction['booking_id'] = $booking_id;
$transaction['type'] = $transaction_type;
$transaction['issuer'] = $company_id;
$transaction['bill_no'] = $bill_no;
$transaction['amount'] = 1000;
$transaction['original_amount'] = 1000;
$transaction['created_at'] = date('Y-m-d H:i:s');
$transaction['updated_at'] = date('Y-m-d H:i:s');
$check_transaction = ['bill_no' => $transaction['bill_no']];
$added_transaction = Models\Transaction::updateOrCreate($check_transaction, $transaction);
$transaction_ids[] = $added_transaction->id;
$transaction_id = $added_transaction->id;
foreach ($transaction_details as $transaction_detail) {
$transaction_detail['transaction_id'] = $transaction_id;
$transaction_detail['created_at'] = date('Y-m-d H:i:s');
$transaction_detail['updated_at'] = date('Y-m-d H:i:s');
$check_transaction_details = [
'transaction_id' => $transaction_detail['transaction_id'],
'product_code' => $transaction_detail['product_code']
];
Models\TransactionDetail::updateOrCreate($check_transaction_details,
$transaction_detail);
}
}
}
}
}
}
}
}
@@ -1,7 +1,6 @@
<template>
<div class="row m-b-10 parentContainer">
<div class="col">
<div class="row align-items-center">
<div class="col p-t-5 p-b-5">
<div class="col text-center">
@@ -31,19 +30,23 @@
import staticFormHandler from '../../../general/mixins/staticFormHandler'
export default {
props: {
'id': {
type: Number,
'section' : {
type: String,
required:true,
},
'booking': {
type: Object,
required: true
},
'data': {
'bookingToMerge': {
type: Array,
required: true
}
},
},
data(){
return {
parameters:null,
isLoading: true,
isLoading: false,
}
},
methods: {
@@ -52,21 +55,21 @@
this.$root.$emit('setLoading', true);
let bookings=[];
this.data.forEach(function(booking) {
this.bookingToMerge.forEach(function(booking) {
bookings.push(booking.id);
});
this.parameters = {};
if(bookings.length>0) {
this.$set(this.parameters, 'id', this.id);
this.$set(this.parameters, 'id', this.booking.id);
this.$set(this.parameters, 'booking_ids', bookings);
this.submit(route('api.booking.merge'), 'post', this.section, true, true);
}
},
successHandler(){
setTimeout(function(){
window.location.href = this.route('dashboard');
}, 2000);
setTimeout(function(marking){
window.location.href = this.route('booking.details', marking);
}, 2000, this.booking.marking);
},
errorHandler() {
this.$root.$emit('setLoading', false);
@@ -26,14 +26,14 @@
<div class="font-heading fs-11">{{this.item.service.name}}</div>
</div>
<div class="col-auto" :style="minWidth150">
<div class="font-heading fs-11 text-success bold">{{formatAmount(this.item.purchase_order.amount)}} {{this.item.purchase_order.original_currency.short_code}}</div>
<div class="font-heading fs-11 text-success bold" v-if="item.purchase_order!==null">{{formatAmount(this.item.purchase_order.amount)}} {{this.item.purchase_order.original_currency.short_code}}</div>
</div>
<div class="col-auto" :style="minWidth150">
<div class="font-heading fs-11 text-success bold">{{formatAmount(this.item.amount)}} {{this.item.fixed_currency.short_code}}</div>
</div>
</div>
<div class="row text-left no-margin bg-white hide" v-if="item.purchase_order!==null" v-for="po in this.item.purchase_order.details" v-bind:key="po.id">
<div class="row text-left no-margin bg-white hide" v-if="item.purchase_order!==null" v-for="po in (this.item.purchase_order ? this.item.purchase_order.details : [])" v-bind:key="po.id">
<div class="col">
<div class="font-heading fs-11 text-success bold">{{po.description}}</div>
</div>
@@ -111,7 +111,7 @@
<div class="font-heading fs-10">But don't worry you can always merge your transfer orders into one to complete your purchase order successfully and generate your invoice.</div>
</div>
</div>
<a class="btn btn-xs all-caps b-rad-none btn-warning" target="_blank" :href="route('booking.merge',this.data.marking)">Merge Transfer Orders</a>
<a class="btn btn-xs all-caps b-rad-none btn-warning" :href="route('booking.merge',this.data.marking)">Merge Transfer Orders</a>
</div>
</div>
</div>
@@ -50,7 +50,7 @@
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Purchase Order Amount</div>
<div class="font-heading fs-10 text-info">
<div class="font-heading fs-10 text-info" v-if="booking.purchase_order!==null">
{{formatAmount(booking.purchase_order.amount)}}
</div>
</div>
@@ -94,9 +94,9 @@
</div>
<div class="col-auto" :style="minWidth150">
<div class="font-heading fs-10 muted all-caps">Booking Amount</div>
</div>
</div>
</div>
<list-component key="2" section="transferSection" :endpoint="route('api.booking.list')" :options="{per_page: 10, id_not: booking.id, status: 2,service_id:booking.service.id,convertible_currency_id:booking.convertible_currency.id,fixed_currency_id:booking.fixed_currency.id,with_transactions:true}">
<list-component key="2" section="transferSection" :endpoint="route('api.booking.list')" :options="{per_page: 25, id_not: booking.id, company_id: booking.company_id, status: 2,service_id:booking.service.id,convertible_currency_id:booking.convertible_currency.id,fixed_currency_id:booking.fixed_currency.id,with_transactions:true}">
<template slot="list" slot-scope="{data}">
<booking-mergeable-component :data="data"></booking-mergeable-component>
</template>
@@ -137,7 +137,7 @@
</div>
</div>
<modal-component type="mergeTransferModal">
<booking-merge-modal-component section="bookingDetailSection" :id="booking.id" :data="this.bookings"></booking-merge-modal-component>
<booking-merge-modal-component section="bookingDetailSection" :booking="this.booking" :bookingToMerge="this.bookings" :section="section">></booking-merge-modal-component>
</modal-component>
</div>
</div>
@@ -168,7 +168,7 @@
minWidth150:{
minWidth:'150px',
},
section: 'bookingDetailSection',
section: 'bookingMergeSection',
selected_id: '',
isLoading: true,
booking: null,
@@ -187,9 +187,9 @@
},
totalPurchaseAmount(){
let totalPurchase = this.booking.purchase_order.amount;
let totalPurchase = (this.booking.purchase_order) ? this.booking.purchase_order.amount : 0;
this.bookings.forEach(function(booking) {
totalPurchase += booking.purchase_order.amount;
totalPurchase += (booking.purchase_order ? booking.purchase_order.amount : 0);
});
return (Math.round((totalPurchase + Number.EPSILON) * 100) / 100).toFixed(2);
},