fixing unable mapping records and filtering function in Pending Export tab and listing data not same in Pending Export tab with export Invoice to autocount and calculate mapped percentage

This commit is contained in:
Steve Ng
2023-10-23 09:20:35 +08:00
parent 8e67c219a9
commit 05b5823fe4
8 changed files with 182 additions and 39 deletions
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionPostingEnd implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('posting_date', '<=', date('Y-m-d',strtotime($value)));
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionPostingStart implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('posting_date', '>=', date('Y-m-d',strtotime($value)));
}
}
@@ -28,6 +28,7 @@ class CreateBankStatementTransactionOwnersProcessor
// $transactions = StatementTransaction::whereDoesntHave('owners')->where('amount', '<', 0)->get();
foreach ($transactions as $transaction) {
$mapped = false;
$keywords = array_filter(explode(" ", $transaction->transaction_description . " " . $transaction->transaction_description_2));
if($transaction->amount > 0){
@@ -36,7 +37,7 @@ class CreateBankStatementTransactionOwnersProcessor
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($creditTransactions as $creditTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -45,12 +46,11 @@ class CreateBankStatementTransactionOwnersProcessor
]);
}
// Shipping Portal Sales
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 2, PaymentMethodType::WALLET);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), [2], PaymentMethodType::WALLET);
foreach ($creditTransactions as $creditTransaction) {
if($creditTransaction['owner_type'] === Wallet::class) continue;
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
@@ -63,7 +63,7 @@ class CreateBankStatementTransactionOwnersProcessor
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($creditTransactions as $creditTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -72,9 +72,9 @@ class CreateBankStatementTransactionOwnersProcessor
]);
}
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 5, null);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), [5,15], null);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
@@ -85,7 +85,7 @@ class CreateBankStatementTransactionOwnersProcessor
// fpx charge refund
if($transaction->transaction_description === 'DUITNOW S/CHRG REFUND'){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE_REFUND
]);
}
@@ -94,7 +94,7 @@ class CreateBankStatementTransactionOwnersProcessor
// INTERNAL_BANK_TRANSFER_IN
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_IN
]);
}
@@ -119,7 +119,7 @@ class CreateBankStatementTransactionOwnersProcessor
->where('amount', '<=', (($transaction->amount * -1) + 0.01))->whereDate('created_at', '>=', $paymentDateStart)->whereDate('created_at', '<=', $paymentDateEnd)->get();
foreach ($debitTransactions as $debitTransaction) {
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SUPPLIER_PAYMENT,
'system' => 'EXCHANGE',
'owner_type' => Group::class,
@@ -135,7 +135,7 @@ class CreateBankStatementTransactionOwnersProcessor
$debitTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::DEBIT_NOTE, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($debitTransactions as $debitTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_WITHDRAWAL,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -148,50 +148,52 @@ class CreateBankStatementTransactionOwnersProcessor
// STATUTORY
if(str_contains($transaction->transaction_description_2, 'PEMBANGUNAN SUMBER') || str_contains($transaction->transaction_description_2, 'HASIL') || str_contains($transaction->transaction_description_2, 'PERTUBUHAN KESELAMAT') || str_contains($transaction->transaction_description_2, 'KUMPULAN WANG SIMPAN')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::STATUTORY
]);
}
// FPX_CHARGE
if($transaction->transaction_description === 'DR DUITNOW S/CHRG' || str_contains($transaction->transaction_description, 'Manual FPX') || str_contains($transaction->transaction_description, 'CMS - DR FPX CHG')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE
]);
}
// BANK_CHARGE
if($transaction->transaction_description === 'CMS - DR CORP CHG' || $transaction->transaction_description === 'MONTHLY PROFIT DEBIT'){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::BANK_CHARGE
]);
}
// CREDIT_CARD_PAYMENT
if(str_contains($transaction->transaction_description_2, 'VISA CARD')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::CREDIT_CARD_PAYMENT
]);
}
// INTERNAL_BANK_TRANSFER_OUT
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE') || str_contains($transaction->transaction_description_2, 'CIEF WORLWIDE') || str_contains($transaction->transaction_description_2, 'IZYIM GLOBAL')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_OUT
]);
}
// non-operational charges
if(str_contains($transaction->transaction_description_2, 'HIRE PURCHASE') || str_contains($transaction->transaction_description_2, 'TENAGA NASIONAL') || str_contains($transaction->transaction_description, 'CABLE CHARGE') || str_contains($transaction->transaction_description_2, 'CTOS DATA SYSTEMS') || str_contains($transaction->transaction_description_2, 'MAXIS')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::NON_OPERATIONAL
]);
}
}
if (isset($data) && $data->wasRecentlyCreated) $mapped = true;
$this->updateMappedRate($transaction, $mapped);
}
}
}
private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) {
private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) {
$dateRange = $this->getDateRange($date, 4);
if (App::environment(['production'])) {
$query = $model::whereIn('status', $statuses)
@@ -318,7 +320,7 @@ class CreateBankStatementTransactionOwnersProcessor
try{
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2]'.$paymentMethodFilter.',"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).',"type_in":['.$type.']}');
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2]'.$paymentMethodFilter.',"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).',"type_in":'.json_encode($type).'}');
$body = $response->getBody();
$data = json_decode($body, true);
$payload = $data['payload'];
@@ -345,4 +347,11 @@ class CreateBankStatementTransactionOwnersProcessor
'end_date' => $nextDay,
];
}
private function updateMappedRate($transaction, $mapped) {
$statement = $transaction->statement;
$statement->total_rows = StatementTransaction::where('account_statement_id',$transaction->account_statement_id)->count();
$statement->mapped_rows = $mapped ? $statement->mapped_rows+1 : $statement->mapped_rows;
$statement->save();
}
}
@@ -4,7 +4,6 @@ namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use App\Models\StatementTransactionOwner;
use App\Models\Transaction;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
@@ -18,6 +17,8 @@ use App\Classes\Modules\Accounting\Processors\ListShippingPortalTransactions;
use App\Classes\ValueObjects\Constants\ShippingTransactionType;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Models\StatementTransaction;
class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
@@ -64,10 +65,9 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
*/
public function query()
{
$data = StatementTransactionOwner::whereNull('invoice_reference')
->whereIn('type', [StatementTransactionOwnerType::SALES, StatementTransactionOwnerType::WALLET_TOP_UP])
->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED]);
if ($this->request->has('bankStatementOwnerId')) $data = $data->whereIn('id',json_decode($this->request->input('bankStatementOwnerId')));
$data = (new ApplyFiltersToQuery())->execute(StatementTransaction::query(), json_decode($this->request->input('filter'), true));
if ($this->request->has('bankStatementTransactionId')) $data = $data->whereIn('id',json_decode($this->request->input('bankStatementTransactionId'), true));
return $data;
}
@@ -78,11 +78,12 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
*/
public function map($transaction): array
{
$statementTransactionOwner = $transaction->owners()->whereIn('status', [ApprovalStatus::APPROVED])->first();
$logArray = [
'counter' => $this->counter,
'system' => $transaction->system,
'StatementTransactionOwner_id' => $transaction->id,
'transaction_table_id' => $transaction->owner_id,
'system' => $statementTransactionOwner->system,
'StatementTransactionOwner_id' => $statementTransactionOwner->id,
'transaction_table_id' => $statementTransactionOwner->owner_id,
];
$this->counter += 1;
$logArray = json_encode($logArray);
@@ -92,8 +93,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' ' . $logArray . PHP_EOL;
file_put_contents($filePath, $textToAppend, FILE_APPEND);
if ($transaction->system == 'EXCHANGE') {
$row = (App()->make($transaction->owner_type))->where('id', $transaction->owner_id)->first();
if ($statementTransactionOwner->system == 'EXCHANGE') {
$row = (App()->make($statementTransactionOwner->owner_type))->where('id', $statementTransactionOwner->owner_id)->first();
$company = $row->type === TransactionType::PAYMENT ? $row->owner->company : $row->owner->owner;
$booking = $row->owner;
@@ -116,15 +117,15 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
];
} else {
$row = (App()->make(ListShippingPortalTransactions::class))->execute([
'id' => $transaction->owner_id,
'id' => $statementTransactionOwner->owner_id,
'with_company' => true,
]);
if (empty($row) || $row[0]['status'] != 'success') {
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Fetch Shipping Transaction Fail ' . json_encode([
'id' => $transaction->owner_id,
'id' => $statementTransactionOwner->owner_id,
'with_company' => true,
'StatementTransactionOwner_id' => $transaction->id,
'StatementTransactionOwner_id' => $statementTransactionOwner->id,
]) . PHP_EOL;
file_put_contents($errorFilePath, $textToAppend, FILE_APPEND);
+2
View File
@@ -16,6 +16,8 @@ class AccountStatement extends Model
'total_amount',
'begin_balance',
'end_balance',
'total_rows',
'mapped_rows',
];
protected $casts = [
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddMappedRateToAccountStatementsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('account_statements', function (Blueprint $table) {
$table->integer('total_rows')->unsigned()->default(0)->after('end_balance');
$table->integer('mapped_rows')->unsigned()->default(0)->after('end_balance');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('account_statements', function (Blueprint $table) {
$table->dropColumn('total_rows');
$table->dropColumn('mapped_rows');
});
}
}
@@ -126,7 +126,7 @@
<!-- Pending Export tab for checkbox here -->
<div class="col-1" v-if="item.owners.approved.length === 1">
<input type="checkbox" class="request_export_item" v-model="selectAll" :value="item.owners.approved[0].id">
<input type="checkbox" class="request_export_item" v-model="selectAll" :value="item.id">
</div>
<div class="col-1 text-danger" v-if="!item.owners.approved.length">Pending...</div>
@@ -74,6 +74,32 @@
</general-confirmation-form-component>
</modal-component>
</div>
<!-- filter for Pending Export tab -->
<div v-if="stage === 4">
<div class="row pt-3 pb-3">
<div class="col-5 col-md-3 ">
<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-5 col-md-3 ">
<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-2 col-md-auto">
<div class="btn btn-lg btn-primary fs-11 w-100 h-100 d-flex justify-content-center align-items-center" @click="startMapping(4)">
<span>
Search
</span>
</div>
</div>
</div>
</div>
<div class="row m-t-10 m-b-10">
<div class="col">
<div class="row p-t-10 p-b-10 b-b b-grey text-master-light">
@@ -202,6 +228,10 @@ export default {
data(){
return {
parameters: {
startDate: '',
endDate: '',
},
type: null,
stage: null,
exportStage: 0,
@@ -215,6 +245,14 @@ export default {
}
},
validations: {
parameters: {
startDate: {
required
},
endDate: {
required
},
},
files: {
// required // todo-new: set required if is pdf section
}
@@ -227,17 +265,31 @@ export default {
this.mappedTrue = true;
},
exportInvoiceToAutoCount(){
window.open(this.route('invoiceTransactions.export')+'?bankStatementOwnerId='+this.getCheckedStatementOwners()+'&type=invoices', '_blank');
const checkedStatementTransactions = this.getCheckedStatementOwners();
let route = this.route('invoiceTransactions.export')+'?type=invoices&filter='+JSON.stringify(this.filter);
if (checkedStatementTransactions) {
route += '&bankStatementTransactionId='+checkedStatementTransactions;
}
window.open(route, '_blank');
},
exportReceiptToAutoCount(){
window.open(this.route('invoiceTransactions.export')+'?bankStatementOwnerId='+this.getCheckedStatementOwners()+'&type=receipts', '_blank');
const checkedStatementTransactions = this.getCheckedStatementOwners();
let route = this.route('invoiceTransactions.export')+'?type=receipts&filter='+JSON.stringify(this.filter);
if (checkedStatementTransactions) {
route += '&bankStatementTransactionId='+checkedStatementTransactions;
}
window.open(route, '_blank');
},
getCheckedStatementOwners() {
let bankStatementOwnerId = [];
let bankStatementTransactionId = [];
$('.request_export_item:checked').each(function() {
bankStatementOwnerId.push($(this).val());
bankStatementTransactionId.push($(this).val());
});
return JSON.stringify(bankStatementOwnerId);
return (bankStatementTransactionId.length > 0 ? JSON.stringify(bankStatementTransactionId) : null);
},
successHandler(){
this.step += 1;
@@ -263,6 +315,10 @@ export default {
break;
case 4:
this.filter = {min_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [2], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
if (typeof this.parameters.startDate != 'undefined' && this.parameters.startDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_start: this.parameters.startDate}};
if (typeof this.parameters.endDate != 'undefined' && this.parameters.endDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_end:this.parameters.endDate}};
break;
}
}
@@ -280,6 +336,11 @@ export default {
break;
case 4:
this.filter = {max_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [3, 5], statement_transaction_owner_status_in: [2], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
if (typeof this.parameters.startDate != 'undefined' && this.parameters.startDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_start: this.parameters.startDate}};
if (typeof this.parameters.endDate != 'undefined' && this.parameters.endDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_end:this.parameters.endDate}};
break;
}
}