This commit is contained in:
edmondlang
2023-06-29 14:47:25 +08:00
21 changed files with 309 additions and 60 deletions
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class BillNo implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('bill_no', $value);
}
}
@@ -32,6 +32,7 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
'DocNo',
'DocDate',
'DebtorCode',
'DebtorCode',
'ShipInfo',
'AccNo',
'DetailDescription',
@@ -126,6 +127,7 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$transaction->created_at->format('m/d/Y H:m'),
$company->debtor,
$order->reference,
$order->reference,
'500-0000',
'X1 Freight Service Charge',
$furtherDescription,
@@ -51,7 +51,7 @@ class FetchContainersUpdatesFromYdPortalProcessor
foreach ($containers as $container) {
$time_start = microtime(true);
$packingList = $container->packingLists()->random();
$packingList = $container->packingLists()->first();
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $packingList->reference
@@ -108,6 +108,8 @@ class FetchContainersUpdatesFromYdPortalProcessor
}
}
dump($delayDate, $unstuffingDate);
if($delayDate){
$delayDate = $delayDate->addDays(2);
$transport = $container->transports()->first();
@@ -51,11 +51,11 @@ class TransactionToPerfexCRMProcessor
PerfexCRMProjectStatus::IN_PROGRESS,
[],
[
PerfexCRMTasks::TASK_1,
PerfexCRMTasks::TASK_POST_PAYMENT_1,
PerfexCRMTasks::TASK_POST_PAYMENT_2,
PerfexCRMTasks::TASK_POST_PAYMENT_3,
PerfexCRMTasks::TASK_POST_PAYMENT_4,
// PerfexCRMTasks::TASK_1,
// PerfexCRMTasks::TASK_POST_PAYMENT_1,
// PerfexCRMTasks::TASK_POST_PAYMENT_2,
// PerfexCRMTasks::TASK_POST_PAYMENT_3,
// PerfexCRMTasks::TASK_POST_PAYMENT_4,
]
);
@@ -0,0 +1,53 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Http\Resources\BookingResource;
use App\Http\Resources\MappableTransactionResource;
use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListMappableTransactionsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Transactions',
'message' => 'You have successfully retrieved a list of transactions'
];
}
/** @var ListsTransactions */
private $listsTransactions;
/**
* ListTransactionsLogic constructor.
* @param ListsTransactions $listsTransactions
*/
public function __construct(ListsTransactions $listsTransactions)
{
$this->listsTransactions = $listsTransactions;
}
public function logic(Request $request) : JsonResponse
{
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters')));
return $this->collectionResponse(MappableTransactionResource::collection($query));
}
}
@@ -20,6 +20,7 @@ use App\Models\Wallet;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\Log;
class CreatePaymentTransactionProcessor
{
@@ -38,7 +39,7 @@ class CreatePaymentTransactionProcessor
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
@@ -69,7 +70,7 @@ class CreatePaymentTransactionProcessor
UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor,
UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor,
UpdatesTransactionStatus $updatesTransactionStatus
)
)
{
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsPaymentTransaction = $createsPaymentTransaction;
@@ -87,7 +88,8 @@ class CreatePaymentTransactionProcessor
public function execute(Transaction $invoice, $payment_method, $bank_code)
{
$amount = $invoice->amount;
$company_module = $invoice->owner()->first()->owner()->first()->companyModule()->first();
Log::info($invoice->owner);
$company_module = $invoice->owner->owner->companyModule()->first();
$approvalStatus = ApprovalStatus::PENDING_SUBMISSION;
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$payment_reference = null;
@@ -97,12 +99,12 @@ class CreatePaymentTransactionProcessor
// create billplz transaction
$payment_method = PaymentMethodType::PAYMENT_GATEWAY;
$billPlzBill = $this->createsBillplzBill->execute(
$company_module->name,
$company_module->name,
(app()->environment(['production'])) ? $company_module->employees()->first()->email : 'uldvstar@gmail.com',
'This payment is for the invoice number . ' . $billNumber,
$amount,
$billNumber,
$bank_code,
$billNumber,
$bank_code,
true
);
@@ -117,7 +119,7 @@ class CreatePaymentTransactionProcessor
}
$walletPaymentBillNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$transaction_object = new TransactionObject($walletPaymentBillNumber, TransactionType::PAYMENT, 1, $company_module->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], '');
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
@@ -6,7 +6,6 @@ namespace App\Classes\Notifications;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use App\Models\PasswordReset;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Storage;
@@ -39,7 +38,7 @@ class InvoiceIssuedEmail extends AbstractEmail
return (new MailMessage)
->subject('Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference)
->attach(Storage::disk('documents')->get($invoiceDocument->file->file_info->original->file), [
->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [
'as' => 'name.pdf',
'mime' => 'application/pdf',
])->view('emails.shipment.invoice', ['user' => $this->user, 'packingList' => $this->packingList]);
@@ -9,6 +9,7 @@ use App\Models\PackingList;
use App\Models\PasswordReset;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Storage;
class ShipmentDepartureEmail extends AbstractEmail
{
@@ -42,7 +43,7 @@ class ShipmentDepartureEmail extends AbstractEmail
return (new MailMessage)
->subject('Your packages are on the way to malaysia - Invoice pending payment for order no.'. $this->packingList->owner->reference)
->attach(Storage::disk('documents')->get($invoiceDocument->file->file_info->original->file), [
->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [
'as' => 'name.pdf',
'mime' => 'application/pdf',
])->bcc(['email_test@cief-malaysia.com'])->view('emails.shipment.ETD', ['user' => $this->user, 'packingList' => $this->packingList]);
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\ListMappableTransactionsLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListMappableTransactionsController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function list(Request $request, ListMappableTransactionsLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,41 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class MappableTransactionResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$reference = null;
if($this->type === TransactionType::TOP_UP) {
$reference = $this->owner->owner->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
}
if($this->type === TransactionType::PAYMENT && $this->owner !== Wallet::class){
$reference = $this->owner->owner->owner->reference;
}
return [
'system' => 'SHIPPING_PORTAL',
'type' => $this->type,
'owner_type' => $this->owner_type,
'owner_id'=> $this->id,
'owner_reference'=> $reference,
];
}
}
+4 -1
View File
@@ -7,6 +7,7 @@ use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
@@ -20,6 +21,8 @@ class OrderResource extends JsonResource
*/
public function toArray($request)
{
$orderId = $this->id;
return [
'id' => $this->id,
'reference' => $this->reference,
@@ -47,7 +50,7 @@ class OrderResource extends JsonResource
'received_packages' => PackingListResource::collection($this->packingLists()->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST)->whereHas('packages')->get()),
];
}),
'invoices' => $this->whenLoaded('packingLists', function() {
'invoices' => $this->whenLoaded('packingLists', function() use ($orderId) {
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get());
}),
'remarks' => RemarkResource::collection($this->remarks),
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\TransportType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
@@ -30,7 +31,7 @@ class OrderV2Resource extends JsonResource
'address' => new AddressResource($this->addresses()->where('status', '=', ApprovalStatus::APPROVED)->first()),
'address_change_request' => new AddressResource($this->addressesPendingVerification()->first()),
'invoices' => $this->whenLoaded('packingLists', function() {
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->get());
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get());
}),
'remarks' => RemarkResource::collection($this->remarks),
'created_at' => $this->created_at->format('d-m-Y')
@@ -22,6 +22,7 @@ class TransactionResource extends JsonResource
{
return [
'id' => $this->id,
'owner_type' => $this->owner_type,
'order' => ($this->owner instanceof Transaction) ? new OrderResource($this->owner->owner->owner) : new OrderResource($this->owner->owner),
'documents' => DocumentResource::collection($this->documents),
'type' => (int) $this->type,
+4
View File
@@ -103,6 +103,10 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
use SoftDeletes;
use LogData;
protected $casts = [
'type' => 'int'
];
protected $table = 'transactions';
public function owner(): morphTo
@@ -1,38 +1,96 @@
<template>
<div class="row m-b-15 align-items-end">
<div class="col-auto">
<div class="row m-b-20">
<div class="col">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Name</div>
<div class="col-3">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Name</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.company_module.name }}</div>
</div>
</div>
</div>
<div class="col-2">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Reference</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.connection.invitee_reference }}</div>
</div>
</div>
</div>
<div class="col-auto">
<a :href="route('customer.profile', item.connection.invitee_reference)" target="_blank">
<button type="button" class="btn btn-xs btn-primary fs-11">Open in new tab</button>
</a>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{this.item.name}}</div>
<!-- company_module_contact -->
<div class="row m-b-10 m-t-5" v-if="item.company_module_contact">
<div class="col-auto">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Company Module Phone</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.company_module_contact.phone }}</div>
</div>
</div>
</div>
<div class="col-auto">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Company Module Email</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.company_module_contact.email }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-2 text-right">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Reference</div>
<!-- company_contact -->
<div class="row m-t-5" v-if="item.company_contact">
<div class="col-auto">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Company Phone</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.company_contact.phone }}</div>
</div>
</div>
</div>
<div class="col-auto">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Company Email</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{ item.company_contact.email }}</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{this.item.reference}}</div>
</div>
</div>
</div>
<div class="col-auto">
<a :href="route('customer.profile', this.item.reference)" target="_blank">
<button type="button" class="btn btn-xs btn-primary fs-11">Open in new tab</button>
</a>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import componentHandler from '../../../general/mixins/componentHandler';
export default {
mixins: [componentHandler]
}
@@ -18,6 +18,12 @@
{{item.currency.short_code}} {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col-auto p-l-0">
<div class="font-heading fs-8 muted all-caps">Bill Number</div>
<div class="font-heading fs-10 bold">
{{ item.bill_no }}
</div>
</div>
</div>
<div class="row">
<div class="col">
@@ -27,6 +27,10 @@
<p class="no-margin fs-10 all-caps">Payment Date</p>
<div>{{ item.payment_history[item.payment_history.length-1].created_at }}</div>
</div>
<div class="col" v-if="['customerPaidInvoiceComponent', 'customerPaidGroupInvoiceComponent'].includes(section)">
<p class="no-margin fs-10 all-caps">Bill Number</p>
<div>{{ item.payment_history[item.payment_history.length-1].payment_reference }}</div>
</div>
<div class="col-auto">
<div v-if="item.documents.length">
<div v-for="file in item.documents[0].files" v-bind:key="file.id" class="col-auto no-padding">
@@ -26,6 +26,11 @@
<div class="font-heading fs-8 all-caps" >Submitted On: {{ item.updated_at }}</div>
</div>
</div>
<div class="row" v-if="$store.getters.isAdmin && item.bill_no">
<div class="col">
<div class="font-heading fs-8 all-caps m-t-5">Bill Number: <b>{{ item.bill_no }}</b></div>
</div>
</div>
</div>
<div class="col-auto bg-master-light">
<div class="row align-items-center h-100">
@@ -66,6 +71,11 @@
<div class="font-heading fs-8 all-caps" >Paid On: {{ item.updated_at }}</div>
</div>
</div>
<div class="row" v-if="$store.getters.isAdmin && item.bill_no">
<div class="col">
<div class="font-heading fs-8 all-caps m-t-5">Bill Number: <b>{{ item.bill_no }}</b></div>
</div>
</div>
</div>
<div class="col-auto pointer bg-success">
<a :href="route('billplz.bill', item.reference)" target="_blank">
@@ -111,6 +121,11 @@
<div class="font-heading fs-8 all-caps" >{{ item.payment_method === 5 ? 'Failed' : 'Rejected' }} On: {{ item.updated_at }}</div>
</div>
</div>
<div class="row" v-if="$store.getters.isAdmin && item.bill_no">
<div class="col">
<div class="font-heading fs-8 all-caps m-t-5">Bill Number: <b>{{ item.bill_no }}</b></div>
</div>
</div>
</div>
<div class="col-auto p-l-5 p-r-5 bg-success pointer" v-if="item.payment_method === 5">
<a :href="route('billplz.bill', item.reference)">
+3 -1
View File
@@ -63,7 +63,9 @@
@if($markingReturn && !$markingNotFound)
<div class="row m-t-20">
<div class="col m-l-30">
<user-company-component class="m-l-5" :data="{{$markingReturn}}"></user-company-component>
@foreach($markingReturn as $marking)
<user-company-component class="m-l-5" :data="{{$marking}}"></user-company-component>
@endforeach
</div>
</div>
@endif
+1
View File
@@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route;
Route::group(['middleware' => 'apipub', 'prefix' => 'v1', 'as' => 'apipub.'], function () {
Route::group(['middleware' => 'token.check'], function () {
Route::get('transactions/query', 'Transactions\ListTransactionsController@list')->name('transaction.list');
Route::get('transactions/mappable/query', 'Transactions\ListMappableTransactionsController@list')->name('transaction.mappable.list');
Route::get('groups/query', 'Transactions\ListGroupsController@list')->name('group.list');
});
});
+32 -18
View File
@@ -169,12 +169,27 @@ Route::post('/support', function (Request $request) {
if ($marking) {
$orderNo = null;
$markingReturn = CompanyConnection::where('invitee_reference', $marking)->get();
$markingReturn = CompanyConnection::where('invitee_reference', 'LIKE', '%'. $marking .'%')->get();
$dataReturn = [];
if (count($markingReturn)) {
$markingReturn = $markingReturn->first();
$markingReturn = $markingReturn->invitee;
$markingReturn->reference = $marking;
$markingReturn = $markingReturn->toJson();
$markingReturn = $markingReturn;
foreach ($markingReturn as $connection) {
$company_module = $connection->invitee;
$company_module_contact = $company_module->contacts()->first();
$company = $company_module->company;
$company_contact = $company->contacts()->first();
$dataReturn[] = json_encode(
[
'connection' => $connection ? $connection->toArray() : null,
'company_module' => $company_module ? $company_module->toArray() : null,
'company_module_contact' => $company_module_contact ? $company_module_contact->toArray() : null,
'company' => $company ? $company->toArray() : null,
'company_contact' => $company_contact ? $company_contact->toArray() : null,
]
);
}
} else {
$markingNotFound = true;
}
@@ -185,7 +200,7 @@ Route::post('/support', function (Request $request) {
'orderNo' => $orderNo,
'orderNoNotFound' => $orderNoNotFound,
'marking' => $marking,
'markingReturn' => $markingReturn,
'markingReturn' => $dataReturn,
'markingNotFound' => $markingNotFound,
]);
})->name('support');
@@ -246,7 +261,7 @@ Route::get('/customer/{marking}/payment-and-billing', function ($marking) {
return view('pages.customers.paymentsBilling', ['company_module_id' => $company_module_id]);
})->name('customer.payment-and-billing');
Route::get('/customer-invoices/{company_module_id}/payment-and-billing', function ($company_module_id) {
Route::get('/customer-invoices/{company_module_id}/payment-and-billing', function ($company_module_id) {
// todo-new: check company_module_id
return view('pages.customers.paymentsBilling', ['company_module_id' => $company_module_id]);
})->name('customer.payment-and-billing-by-company-module-id');
@@ -359,12 +374,11 @@ Route::group(['prefix' => 'yd', 'as' => 'yd.'], function () {
});
Route::get('/yd', function (Request $request){
// $start = $request->input('start_date') ? Carbon::parse($request->input('start_date')): null;
// $end = $request->input('end_date') ? Carbon::parse($request->input('end_date')): null;
// (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute($start, $end);
// (App()->make(\App\Classes\Modules\PackingLists\Processors\FetchPackingListsFromYdPortalProcessor::class))->execute($start, $end);
// (App()->make(\App\Classes\Modules\PackingLists\Processors\FetchContainersFromYdPortalProcessor::class))->execute();
// (App()->make(\App\Classes\Modules\PackingLists\Processors\FetchContainersUpdatesFromYdPortalProcessor::class))->execute();
$start = $request->input('start_date') ? Carbon::parse($request->input('start_date')): null;
$end = $request->input('end_date') ? Carbon::parse($request->input('end_date')): null;
// (App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute($start, $end);
// (App()->make(FetchContainersFromYdPortalProcessor::class))->execute();
(App()->make(FetchContainersUpdatesFromYdPortalProcessor::class))->execute();
// (App()->make(FetchDeliveryUpdatesFromYdPortalProcessor::class))->execute();
// (App()->make(FetchPackingListFromVTPortalProcessor::class))->execute();
})->name('yd.refresh');
@@ -1101,12 +1115,12 @@ Route::get('/final-duplicated-invoice-debug', function(){
foreach ($duplicatedTransactions as $transaction) {
$transactionIds = explode(',', $transaction->transaction_ids);
$duplicatedInvoice = Transaction::whereIn('id', $transactionIds)->get();
$order_reference = $duplicatedInvoice->first()->owner->owner->reference ?? null;
$duplicatedInvoice = Transaction::whereIn('id', $transactionIds)->get();
$order_reference = $duplicatedInvoice->first()->owner->owner->reference ?? null;
if ($transaction->type == TransactionType::PAYMENT) {
$order_reference = $duplicatedInvoice->first()->owner->owner->owner->reference ?? null;
$order_reference = $duplicatedInvoice->first()->owner->owner->owner->reference ?? null;
}
echo '<tr>';
@@ -1125,4 +1139,4 @@ Route::get('/final-duplicated-invoice-debug', function(){
}
echo '</table>';
});