Recipient Bank Details to follow payment overriding the default attached to Booking

This commit is contained in:
Dillon Ngo
2024-08-07 06:46:17 +08:00
parent e80ad9a6ec
commit 3bd708ed0e
36 changed files with 1193 additions and 116 deletions
+5 -1
View File
@@ -41,7 +41,11 @@ class UpdatePerfexCRMPrelude implements ShouldQueue
{
$serviceTypeName = $this->transaction->owner->company->services()->where('id', $this->transaction->owner->service_id)->first()->name;
$booking = $this->transaction->booking;
$bankDetails = $this->generateBankDetails($booking->bank);
$bank = $booking->bank; //cief todo: 66
if($this->transaction->bank){
$bank = $this->transaction->bank;
}
$bankDetails = $this->generateBankDetails($bank);
$data = [
'amount' => number_format($this->transaction->amount, 2, '.', ''),
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractDeleteRecord;
use App\Models\KeyValuePair;
class DeletesKeyValuePair extends AbstractDeleteRecord
{
/**
* @param KeyValuePair $model
* @return mixed
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(KeyValuePair $model) {
return $this->handler($model);
}
}
@@ -3,21 +3,17 @@
namespace App\Classes\Modules\Banks\ControllersLogic;
use App\Http\Resources\BankResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Banks\Services\FetchesBank;
use App\Classes\Modules\Banks\Standards\Rules\CanUpdateBank;
use App\Classes\Modules\Banks\Services\UpdatesBank;
use App\Classes\Modules\Banks\Services\CreatesOrUpdateBank;
use App\Classes\Modules\Banks\Services\CreatesBankLog;
use App\Classes\Modules\Banks\Processors\UpdateBankProcessor;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class UpdateBankLogic extends AbstractControllerLogic
{
@@ -44,24 +40,36 @@ class UpdateBankLogic extends AbstractControllerLogic
/** @var CreatesBankLog */
private $createsBankLog;
/** @var CreatesOrUpdateBank */
private $createsOrUpdateBank;
/** @var UpdateBankProcessor */
private $updateBankProcessor;
/**
* UpdateBankLogic constructor.
* @param CanUpdateBank $canUpdateBank
* @param UpdatesBank $updatesBank
* @param FetchesBank $fetchesBank
* @param CreatesBankLog $createsBankLog
* @param CreatesOrUpdateBank $createsOrUpdateBank
* @param UpdateBankProcessor $updateBankProcessor
*/
public function __construct(
CanUpdateBank $canUpdateBank,
UpdatesBank $updatesBank,
FetchesBank $fetchesBank,
CreatesBankLog $createsBankLog
CreatesBankLog $createsBankLog,
CreatesOrUpdateBank $createsOrUpdateBank,
UpdateBankProcessor $updateBankProcessor
)
{
$this->canUpdateBank = $canUpdateBank;
$this->updatesBank = $updatesBank;
$this->fetchesBank = $fetchesBank;
$this->createsBankLog = $createsBankLog;
$this->createsOrUpdateBank = $createsOrUpdateBank;
$this->updateBankProcessor = $updateBankProcessor;
}
/**
@@ -74,15 +82,15 @@ class UpdateBankLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$bankObject = new BankObject(
$request->input('company_id'),
$request->input('company_id'),
$request->input('account_type'),
$request->input('bank_name'),
$request->input('holder_name'),
$request->input('holder_name'),
$request->input('account_no'),
$request->input('bank_branch'),
$request->input('swift'),
$request->input('bank_branch'),
$request->input('swift'),
$request->input('snap'),
$request->input('country_id'),
$request->input('country_id'),
$request->input('reference')
);
@@ -90,12 +98,10 @@ class UpdateBankLogic extends AbstractControllerLogic
$this->canUpdateBank->passes($bankObject);
$bank_query = $this->updatesBank->execute($bank, $bankObject);
// $bankLog = $this->createsBankLog->execute($bank_query);
$bank_query = $this->updateBankProcessor->execute($bankObject, $bank, $request->input('bill_no') ?? '', (int) $request->input('transaction_id') ?? 0 );
return $this->resourceResponse(new BankResource($bank_query));
}
}
}
@@ -0,0 +1,67 @@
<?php
namespace App\Classes\Modules\Banks\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Banks\Standards\Rules\CanUpdateBankMetadata;
use App\Classes\Modules\Banks\DataTransferObjects\BankMetadataObject;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateBankMetadataLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Update Bank Metadata',
'message' => 'You have successfully updated the Bank metadata'
];
}
/** @var CanUpdateBankMetadata */
private $canUpdateBankMetadata;
/** @var FetchesTransaction */
private $fetchesTransaction;
/**
* UpdateBankMetadataLogic constructor.
* @param CanUpdateBankMetadata $canUpdateBankMetadata
* @param FetchesTransaction $fetchesTransaction
*/
public function __construct(
CanUpdateBankMetadata $canUpdateBankMetadata,
FetchesTransaction $fetchesTransaction
)
{
$this->canUpdateBankMetadata = $canUpdateBankMetadata;
$this->fetchesTransaction = $fetchesTransaction;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$bankMetadataObject = new BankMetadataObject(
$request->input('transactionId'),
);
$this->canUpdateBankMetadata->passes($bankMetadataObject);
$transaction = $this->fetchesTransaction->execute(['id' => $request->input('transactionId')]);
$transaction->attributes()->delete();
return $this->response([]);
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Classes\Modules\Banks\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class BankMetadataObject implements DataTransferObject
{
/** @var int */
private $transaction_id;
/**
* BankMetadataObject constructor.
* @param int $transaction_id
*/
public function __construct(int $transaction_id)
{
$this->transaction_id = $transaction_id;
}
/**
* @return int
*/
public function getTransactionId(): int
{
return $this->transaction_id;
}
}
@@ -0,0 +1,97 @@
<?php
namespace App\Classes\Modules\Banks\Processors;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Banks\Services\UpdatesBank;
use App\Classes\Modules\Banks\Services\CreatesOrUpdateBank;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use Illuminate\Database\Eloquent\Model;
use App\Models\Bank;
class UpdateBankProcessor
{
/** @var UpdatesBank */
private $updatesBank;
/** @var CreatesOrUpdateBank */
private $createsOrUpdateBank;
/** @var CreatesKeyValuePair */
private $createsKeyValuePair;
/** @var FetchesTransaction */
private $fetchesTransaction;
/**
* UpdateBankProcessor constructor.
* @param UpdatesBank $updatesBank
* @param CreatesOrUpdateBank $createsOrUpdateBank
* @param CreatesKeyValuePair $createsKeyValuePair
* @param FetchesTransaction $fetchesTransaction
*/
public function __construct(
UpdatesBank $updatesBank,
CreatesOrUpdateBank $createsOrUpdateBank,
CreatesKeyValuePair $createsKeyValuePair,
FetchesTransaction $fetchesTransaction
)
{
$this->updatesBank = $updatesBank;
$this->createsOrUpdateBank = $createsOrUpdateBank;
$this->createsKeyValuePair = $createsKeyValuePair;
$this->fetchesTransaction = $fetchesTransaction;
}
/**
* @param BankObject $bankObject
* @param Bank $bank
* @param string $billNo
* @param int $transactionId
* @return Model
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(BankObject $bankObject, Bank $bank, string $billNo, int $transactionId) {
$result = null;
if($billNo && $transactionId){
$transaction = $this->fetchesTransaction->execute(['id' => $transactionId]);
//If payment transaction do not have a bank yet, create one
if(!$transaction->bank){
$result = $this->createsOrUpdateBank->execute($bankObject);
// if ($result->wasRecentlyCreated) {
//Key #1 for Bank
$kvp = $bank->attributes()->where('key', 'App\Models\Bank')->where('value', $result->id)->latest()->first();
if(!$kvp){
$keyValuePairObject = new KeyValuePairObject(
"App\Models\Bank",
$result->id
);
$this->createsKeyValuePair->execute($bank, $keyValuePairObject);
}
//Key #2 for Payment Transaction (owner type: booking)
$keyValuePairObject = new KeyValuePairObject(
"App\Models\Bank",
$result->id
);
$this->createsKeyValuePair->execute($transaction, $keyValuePairObject);
// }
}
else{
$result = $this->updatesBank->execute($transaction->bank, $bankObject);
}
}
else{
$result = $this->updatesBank->execute($bank, $bankObject);
}
return $result;
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\Banks\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Bank;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class CreatesOrUpdateBank extends AbstractUpdateRecord
{
/**
* @param BankObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(BankObject $object)
{
$user = Auth::user(); /** @var User $user */
$attributes = [
'company_id' => $object->getCompanyId(),
'account_no' => $object->getAccountNo(),
'reference' => $object->getReference(),
'bank_name' => $object->getBankName(),
'holder_name' => $object->getHolderName(),
'bank_branch' => $object->getBankBranch(),
'type' => $object->getType(),
'country_id' => $object->getCountryId(),
'created_by' => Auth::id(),
'creator_type' => in_array($user->type, RoleTypes::ADMIN_ROLES) ? RoleTypes::ADMIN : RoleTypes::USER,
];
$values = [
'swift' => $object->getSwift(),
'snap' => $object->getSnap(),
];
$model = Bank::updateOrCreate($attributes, $values); //Bank::firstOrCreate($attributes, $values);
return $model;
}
}
@@ -0,0 +1,66 @@
<?php
namespace App\Classes\Modules\Banks\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Banks\DataTransferObjects\BankMetadataObject;
use App\Classes\Modules\Banks\Standards\Validators\BankMetadataValidation;
use App\Classes\ValueObjects\Constants\RoleTypes;
use Illuminate\Support\Facades\Auth;
class CanUpdateBankMetadata extends AbstractRule
{
/** @var BankMetadataValidation */
private $validation;
/**
* CanUpdateBankMetadata constructor.
* @param BankMetadataValidation $validation
*/
public function __construct(BankMetadataValidation $validation)
{
$this->validation = $validation;
}
/**
* @return bool
*/
protected function authorized(): bool
{
//cief todo: 66 - temporary workaround
// if (!Auth::user()->can('update bank_metadata')) {
// return false;
// }
// return true;
if (in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)) {
return true;
}
return false;
}
/**
* @param BankMetadataObject $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->validation->validate($object);
}
/**
* @param BankMetadataObject $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Classes\Modules\Banks\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Banks\DataTransferObjects\BankMetadataObject;
class BankMetadataValidation extends AbstractValidation
{
/**
* @param BankMetadataObject $object
* @return array
*/
protected function data($object): array
{
return [
'transaction_id' => $object->getTransactionId(),
];
}
/**
* @return array
*/
protected function rules(): array
{
return [
'transaction_id' => 'required',
];
}
/**
* @return array
*/
protected function messages(): array
{
return [];
}
}
@@ -65,8 +65,12 @@ class ExportsAnalyticBillingTransactions implements FromCollection, WithHeadings
$bill = $transaction;
$payment = $transaction->owner;
$booking = $payment->owner;
$bank = $booking->bank; //cief todo: 66
if($payment->bank){
$bank = $payment->bank;
}
$company = $booking->company;
$ecommerce = str::contains($booking->bank->bank_name, ['浙江网商银行']);
$ecommerce = str::contains($bank->bank_name, ['浙江网商银行']);
return [
$booking->id,
@@ -88,4 +92,4 @@ class ExportsAnalyticBillingTransactions implements FromCollection, WithHeadings
$bill->created_at
];
}
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Banks;
use App\Classes\Modules\Banks\ControllersLogic\UpdateBankMetadataLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateBankMetadataController
{
/**
* @param Request $request
* @param UpdateBankMetadataLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, UpdateBankMetadataLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+1 -1
View File
@@ -56,7 +56,7 @@ class CompanyResource extends JsonResource
'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments',
'personal_banks' => BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)),
'recipient_banks' => [
'accounts' => BankResource::collection($this->banks->whereIn('type', [BankAccountType::EXTERNAL, BankAccountType::ALIPAY_1688, BankAccountType::ALIPAY_RECIPIENT])),
'accounts' => BankResource::collection($this->banks->whereIn('type', [BankAccountType::EXTERNAL, BankAccountType::ALIPAY_1688, BankAccountType::ALIPAY_RECIPIENT])->whereIn('creator_type', [null])),
'default' => new BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first())
],
'segments' => SegmentResource::collection($this->segments),
@@ -16,8 +16,16 @@ class ListTransactionJobResource extends JsonResource
*/
public function toArray($request)
{
$booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner;
$booking = null; //cief todo: 66
$bank = null;
if(in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])){
$booking = $this->owner->owner;
$bank = $this->owner->bank ?? $booking->bank;
}
else{
$booking = $this->owner;
$bank = $this->bank ?? $booking->bank;
}
$days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1);
return [
@@ -27,7 +35,7 @@ class ListTransactionJobResource extends JsonResource
'bill_no' => $this->bill_no,
'payment_reference' => $this->payment_reference,
'payment_method' => (float) $this->payment_method,
'recipient_bank_account' => new BankResource($booking->bank),
'recipient_bank_account' => new BankResource($bank),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (double) $this->amount,
@@ -18,8 +18,16 @@ class PaymentTransactionResource extends JsonResource
*/
public function toArray($request)
{
$booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner;
$booking = null; //cief todo: 66
$bank = null;
if(in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])){
$booking = $this->owner->owner;
$bank = $this->owner->bank ?? $booking->bank;
}
else{
$booking = $this->owner;
$bank = $this->bank ?? $booking->bank;
}
$booking_marking = '';
switch ($this->owner_type) {
@@ -38,7 +46,7 @@ class PaymentTransactionResource extends JsonResource
'bill_no' => $this->bill_no,
'payment_reference' => $this->payment_reference,
'payment_method' => (float) $this->payment_method,
'recipient_bank_account' => new BankResource($booking->bank),
'recipient_bank_account' => new BankResource($bank),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (double) $this->amount,
+13 -4
View File
@@ -19,8 +19,16 @@ class TransactionResource extends JsonResource
*/
public function toArray($request)
{
$booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND, TransactionType::SUPPLIER_REFUND])? $this->owner->owner : $this->owner;
$booking = null; //cief todo: 66
$bank = null;
if(in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND, TransactionType::SUPPLIER_REFUND])){
$booking = $this->owner->owner;
$bank = $this->owner->bank;
}
else{
$booking = $this->owner;
$bank = $this->bank;
}
$days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1);
return [
@@ -30,7 +38,7 @@ class TransactionResource extends JsonResource
'bill_no' => $this->bill_no,
'payment_reference' => $this->payment_reference,
'payment_method' => (float) $this->payment_method,
'recipient_bank_account' => new BankResource($booking->bank),
'recipient_bank_account' => new BankResource($bank),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('amount') : $this->amount),
@@ -54,7 +62,8 @@ class TransactionResource extends JsonResource
'duration' => $days->diff(Carbon::now())->format('%d'),
],
'remarks' => RemarkResource::collection($this->remarks),
'redemption' => new VoucherRedemptionResource($this->voucherRedemption)
'redemption' => new VoucherRedemptionResource($this->voucherRedemption),
'bank' => ((int) $this->type === TransactionType::PAYMENT) ? new BankResource($bank) : null, //When a transaction (of type payment) has an override recipient bank details on booking, this is NOT null
];
}
}
+1 -1
View File
@@ -82,7 +82,7 @@ class CompanyV2Resource extends JsonResource
'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments',
'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)),
'recipient_banks' => [
'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)),
'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)->whereIn('creator_type', [null])),
'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first())
],
'segments' => V1\SegmentResource::collection($this->segments),
+32 -3
View File
@@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use App\Classes\General\Interfaces\KeyValueInterface;
/**
* Class Bank
@@ -21,10 +23,29 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @property int default
* @property int status
*/
class Bank extends AbstractModel
class Bank extends AbstractModel implements KeyValueInterface
{
use SoftDeletes;
/**
*
* @var array
*/
protected $fillable = [
'company_id',
'reference',
'bank_name',
'holder_name',
'account_no',
'bank_branch',
'swift',
'snap',
'type',
'country_id',
'created_by',
'creator_type',
];
protected $table = 'banks';
/**
@@ -42,7 +63,7 @@ class Bank extends AbstractModel
{
return $this->BelongsTo(Company::class, 'company_id', 'id');
}
/**
* @return HasMany
*/
@@ -50,4 +71,12 @@ class Bank extends AbstractModel
{
return $this->HasMany(Transaction::class, 'recipient_bank_account_id');
}
/**
* @return MorphMany
*/
public function attributes(): MorphMany
{
return $this->morphMany(KeyValuePair::class, 'owner');
}
}
+5 -1
View File
@@ -2,10 +2,14 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class KeyValuePair extends AbstractModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'key_value_pairs';
public function owner(): MorphTo
+23 -1
View File
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Classes\General\Interfaces\Documentable;
use App\Classes\General\Interfaces\KeyValueInterface;
use App\Classes\General\Interfaces\Remarkable;
use App\Classes\General\Interfaces\Transactionable;
use App\Classes\General\Interfaces\Voucherifiable;
@@ -22,7 +23,7 @@ use Staudenmeir\EloquentHasManyDeep\HasTableAlias;
use App\Models\StatementTransactionOwner;
class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable, Remarkable
class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable, Remarkable, KeyValueInterface
{
use HasTableAlias;
use SoftDeletes;
@@ -268,4 +269,25 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
return $this->morphMany(Remark::class, 'owner');
}
/**
* @return MorphMany
*/
public function attributes(): MorphMany
{
return $this->morphMany(KeyValuePair::class, 'owner');
}
/**
*
* @return Model|null
*/
public function getBankAttribute()
{
$keyValuePairs = $this->attributes()->where('key', 'App\Models\Bank')->latest()->first();
if($keyValuePairs){
$bank = Bank::where('id', $keyValuePairs->value)->first();
return $bank;
}
return null;
}
}