supplier bill group dashboard

This commit is contained in:
JiaSheng
2023-12-22 18:16:04 +08:00
parent 89eaa78ee9
commit 72797d8885
39 changed files with 2251 additions and 11 deletions
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Database\Eloquent\Builder;
class HasPendingVerifyTransaction implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('transactions', function ($q) {
$q->where('status', ApprovalStatus::PENDING_VERIFICATION);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Eloquent\Builder;
class WithoutBillGroup implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDoesntHave('billGroup');
}
}
@@ -0,0 +1,93 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\ApprovesDocument;
use App\Classes\Modules\Documents\Services\RejectsDocument;
use App\Classes\Modules\Transactions\Services\CalculatesBillGroupPaymentAmount;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ApproveBillGroupPaymentVerificationLogic extends AbstractControllerLogic
{
/**
* ApproveBillGroupPaymentVerificationLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param ApprovesDocument $approvesDocument
* @param RejectsDocument $rejectsDocument
* @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->approvesDocument = $approvesDocument;
$this->rejectsDocument = $rejectsDocument;
$this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount;
}
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Payment Status',
'message' => 'You have successfully updated the payment status'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var ApprovesDocument */
private $approvesDocument;
/** @var RejectsDocument */
private $rejectsDocument;
/** @var CalculatesBillGroupPaymentAmount */
private $calculatesBillGroupPaymentAmount;
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$status = $request->route('status');
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$status === 'approve' ? $this->approvesDocument->execute($transaction->documents()->first()) : $this->rejectsDocument->execute($transaction->documents()->first());
$this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
$billGroup = $transaction->owner;
$billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup);
if ($status === 'reject') {
$billGroup->status = ApprovalStatus::PENDING_SUBMISSION;
$billGroup->save();
} else {
if ($billGroupPayment['outstanding_amount'] <= 0) {
$billGroup->status = ApprovalStatus::APPROVED;
$billGroup->save();
}
}
return $this->response([]);
}
}
@@ -0,0 +1,94 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Transactions\Services\CalculatesBillGroupPaymentAmount;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Document;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateBillGroupPaymentProofDocumentLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Payment Proof Document',
'message' => 'You have successfully submitted your payment proof document'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFile;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CalculatesBillGroupPaymentAmount */
private $calculatesBillGroupPaymentAmount;
/**
* CreateBillGroupPaymentProofDocumentLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount
*/
public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$object = new DocumentObject(DocumentType::BILL_GROUP_PAYMENT_PROOF, $request->input('files'), '', ApprovalStatus::PENDING_VERIFICATION, 'bill_group_payments');
/** @var Document $document */
$document = $this->createsDocument->execute($transaction, $object);
$this->createsFile->execute($document, $object);
$this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION);
$billGroup = $transaction->owner;
$billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup);
if ($billGroupPayment['outstanding_amount'] <= 0) {
$billGroup->status = ApprovalStatus::PENDING_VERIFICATION;
$billGroup->save();
}
return $this->response([]);
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CalculatesBillGroupPaymentAmount;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\FetchesBillGroup;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BillGroupResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateBillGroupPaymentTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Create Bill Group Payment Transaction',
'message' => 'You have successfully created payment for this Bill Group'
];
}
/** @var FetchesBillGroup */
private $fetchesBillGroup;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CalculatesBillGroupPaymentAmount */
private $calculatesBillGroupPaymentAmount;
/**
* CreateBillGroupPaymentTransactionLogic constructor.
* @param FetchesBillGroup $fetchesBillGroup
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount
*/
public function __construct(FetchesBillGroup $fetchesBillGroup, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount)
{
$this->fetchesBillGroup = $fetchesBillGroup;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]);
$billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup);
$outstanding_amount = $billGroupPayment['outstanding_amount'];
$payAmount = floatval(str_replace(',', '', $request->input('payAmount')));
if($payAmount > round($outstanding_amount, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding_amount .'.');
$billNumber = $this->generatesTransactionBillNumber->execute('SPLR-PYMT-');
$transaction_object = new TransactionObject($billNumber, TransactionType::SUPPLIER_PAYMENT, $billGroup->issuer,
$billGroup->receiver, $billGroup->issuerCompany->banks()->where('default', true)->first()->id, PaymentMethodType::CASH,
$payAmount, $payAmount, 1, 1, 1,
0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], '');
$this->createsTransaction->execute($billGroup, $transaction_object);
return $this->resourceResponse(new BillGroupResource($billGroup));
}
}
@@ -0,0 +1,117 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Models\Document;
use App\Models\Group;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\BillGroup;
class CreateSupplierBillGroupLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Create Supplier White Form Order',
'message' => 'You have successfully created currency supplier white form order'
];
}
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFile;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/**
* CreateSupplierBillGroupLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param CreatesTransaction $createsTransaction
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
*/
public function __construct(FetchesCompany $fetchesCompany, CreatesTransaction $createsTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber)
{
$this->fetchesCompany = $fetchesCompany;
$this->createsTransaction = $createsTransaction;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
}
public function logic(Request $request) : JsonResponse
{
$supplier = $this->fetchesCompany->execute(['id' => $request->route('id')]);
throw new MalformedRequestException('testing only');
dd("pass through");
$service_charges = round(floatval(str_replace(',', '', $request->input('service_charges'))), 2);
$payments = $request->input('payments');
$amount = 0;
$original_amount = 0;
foreach ($payments as $payment) {
$amount += round($payment['amount'], 2);
$original_amount += round($payment['original_amount'], 2);
}
$rate = $original_amount / $amount;
$billGroup = new BillGroup();
$billGroup->issuer = $supplier->id;
$billGroup->receiver = 1;
$billGroup->reference = $this->generatesTransactionBillNumber->execute('BSPO-');
$billGroup->amount = $amount;
$billGroup->original_amount = $original_amount;
$billGroup->currency_id = 1;
$billGroup->original_currency_id = $payments[0]['original_currency']['id'];
$billGroup->currency_rate = $rate;
$billGroup->tax = 0;
$billGroup->service_charge = $service_charges;
$billGroup->status = ApprovalStatus::PENDING_SUBMISSION;
$billGroup->save();
foreach ($payments as $payment) {
$billGroup->groups()->sync($payment['id'], false);
}
return $this->response([]);
}
}
@@ -105,6 +105,10 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
$service_charge += $row->service_charge;
}
$transferFee = (float)$this->createSupplierTransactionProcessor->getTransferTransactions()->sum('service_charge');
$original_amount += $transferFee;
$amount += $transferFee / $currency_rate;
$group->issuer = $issuer;
$group->receiver = $receiver;
$group->reference = $this->generatesTransactionBillNumber->execute('SPO-');
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesBillGroup;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use App\Http\Resources\BillGroupResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeleteBillGroupLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Delete Bill Group Transaction',
'message' => 'You have successfully deleted this Bill Group Transaction'
];
}
/** @var FetchesBillGroup */
private $fetchesBillGroup;
/** @var DeletesTransaction */
private $deletesTransaction;
/**
* DeleteBillGroupLogic constructor.
* @param FetchesBillGroup $fetchesBillGroup
* @param DeletesTransaction $deletesTransaction
*/
public function __construct(FetchesBillGroup $fetchesBillGroup, DeletesTransaction $deletesTransaction)
{
$this->fetchesBillGroup = $fetchesBillGroup;
$this->deletesTransaction = $deletesTransaction;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]);
$transactions = $billGroup->transactions()->get();
foreach($transactions as $transaction) {
$this->deletesTransaction->execute($transaction);
}
$groups = $billGroup->groups()->get();
foreach($groups as $group) {
$billGroup->groups()->detach($group->id);
}
$billGroup->delete();
return $this->resourceResponse(new BillGroupResource($billGroup));
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsBillGroups;
use App\Http\Resources\BillGroupResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListBillGroupsLogic extends AbstractControllerLogic
{
/**
* ListTransactionsLogic constructor.
* @param ListsBillGroups $listsBillGroups
*/
public function __construct(ListsBillGroups $listsBillGroups)
{
$this->listsBillGroups = $listsBillGroups;
}
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Bill Groups',
'message' => 'You have successfully retrieved a list of bill groups'
];
}
/** @var ListsBillGroups */
private $listsBillGroups;
public function logic(Request $request) : JsonResponse
{
$query = $this->listsBillGroups->execute($this->listsBillGroups->deserializeFilters($request->input('filters')));
return $this->collectionResponse(BillGroupResource::collection($query));
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\BillGroup;
class CalculatesBillGroupPaymentAmount
{
public function execute(BillGroup $billGroup){
$floating_amount = floatval($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount'));
$paid_amount = floatval($billGroup->transactions()->where('status', ApprovalStatus::APPROVED)->sum('amount'));
$outstanding_amount = $billGroup->amount - $paid_amount - $floating_amount + $billGroup->service_charge;
return [
'floating_amount' => $floating_amount,
'paid_amount' => $paid_amount,
'outstanding_amount' => $outstanding_amount,
];
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use Illuminate\Database\Eloquent\Builder;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use App\Models\BillGroup;
class FetchesBillGroup extends AbstractFetchRecord
{
/** @var BillGroup */
private $repository;
/**
* FetchesBillGroup constructor.
* @param BillGroup $repository
*/
public function __construct(BillGroup $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use Illuminate\Database\Eloquent\Builder;
use App\Classes\General\Eloquent\AbstractListRecord;
use App\Models\BillGroup;
class ListsBillGroups extends AbstractListRecord
{
/** @var BillGroup */
private $repository;
/**
* ListsBookings constructor.
* @param Group $repository
*/
public function __construct(BillGroup $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -25,4 +25,6 @@ final class DocumentType {
public const INVOICE = 'INVOICE';
public const SUPPLIER_DELIVER_ORDER = 'SUPPLIER_DELIVER_ORDER';
public const BULK_PURCHASE_ORDER = 'BULK_PURCHASE_ORDER';
public const BILL_GROUP_PAYMENT_PROOF = 'BILL_GROUP_PAYMENT_PROOF';
}
@@ -31,4 +31,6 @@ final class TransactionType {
public const TRANSFER_FEE = 12;
public const CASH_BACK = 13;
public const SUPPLIER_PAYMENT = 14;
}
@@ -49,9 +49,6 @@ class UpdateGroupWithTransferFee extends Command
ini_set('max_execution_time', 0);
set_time_limit(0);
$groups = Group::whereDate('updated_at', '<', Carbon::now())->get();
$this->info($groups->count());
// $groups = Group::where('id', 999)->get();
foreach ($groups as $group) {
$originalTransferFees = (float)Transaction::where('type', TransactionType::TRANSFER_FEE)->whereIn('owner_id', $group->transactions->pluck('id'))->sum('service_charge');
@@ -62,14 +59,10 @@ class UpdateGroupWithTransferFee extends Command
$correctAmount += $transferFees;
if ($group->original_amount != $correctOriginalAmount) {
// $group->original_amount = $correctOriginalAmount;
// $group->amount = $correctAmount;
// $group->save();
$this->info("Update group id: " . $group->id . " correct original amount is: " . $correctOriginalAmount . " transfer fee is " . $originalTransferFees);
} else {
$this->info("No update for group id: " . $group->id);
$group->original_amount = $correctOriginalAmount;
$group->amount = $correctAmount;
$group->save();
}
}
$this->info(Carbon::now() . ' : ' . 'updateGroupWithTransferFee ------ completed');
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\ApproveBillGroupPaymentVerificationLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ApproveBillGroupPaymentVerificationController
{
/**
* @param Request $request
* @param ApproveBillGroupPaymentVerificationLogic $logic
* @return JsonResponse
*/
public function approve(Request $request, ApproveBillGroupPaymentVerificationLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\CreateBillGroupPaymentProofDocumentLogic;
class CreateBillGroupPaymentProofDocumentController
{
/**
* @param Request $request
* @param CreateBillGroupPaymentProofDocumentLogic $logic
* @return JsonResponse
*/
public function create(Request $request, CreateBillGroupPaymentProofDocumentLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\CreateBillGroupPaymentTransactionLogic;
class CreateBillGroupPaymentTransactionController
{
/**
* @param Request $request
* @param DeleteGroupTransactionLogic $logic
* @return JsonResponse
*/
public function pay(Request $request, CreateBillGroupPaymentTransactionLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\CreateSupplierBillGroupLogic;
class CreateSupplierBillGroupController
{
/**
* @param Request $request
* @param CreateSupplierBillGroupLogic $logic
* @return JsonResponse
*/
public function create(Request $request, CreateSupplierBillGroupLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\DeleteBillGroupLogic;
class DeleteBillGroupController
{
/**
* @param Request $request
* @param DeleteGroupTransactionLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, DeleteBillGroupLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\ListBillGroupsLogic;
class ListBillGroupsController
{
/**
* @param Request $request
* @param ListBillGroupsLogic $logic
* @return JsonResponse
*/
public function list(Request $request, ListBillGroupsLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace App\Http\Resources;
use App\Classes\Modules\Transactions\Services\CalculatesBillGroupPaymentAmount;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class BillGroupResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$billGroupPayment = (App()->make(CalculatesBillGroupPaymentAmount::class))->execute($this->resource);
$floating_amount = $billGroupPayment['floating_amount'];
$paid_amount = $billGroupPayment['paid_amount'];
$outstanding_amount = $billGroupPayment['outstanding_amount'];
return [
'id' => $this->id,
'reference' => $this->reference,
'original_amount' => (float) $this->original_amount,
'original_currency' => new CurrencyResource($this->original_currency),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (float) $this->amount,
'service_charge' => (float) $this->service_charge,
'currency' => new CurrencyResource($this->currency),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'),
'currency_rate' => (float) $this->currency_rate,
'status' => $this->status,
'groups' => GroupResource::collection($this->groups),
'floating_amount' => $floating_amount,
'paid_amount' => $paid_amount,
'outstanding_amount' => $outstanding_amount,
'payment_history' => $this->transactions->map(function ($transaction) {
return [
'id' => $transaction->id,
'type' => (int) $transaction->type,
'bill_no' => $transaction->bill_no,
'payment_method' => (float) $transaction->payment_method,
'amount' => (double) $transaction->amount,
'original_amount' => (double) $transaction->original_amount,
'currency' => new CurrencyResource($transaction->currency),
'original_currency' => new CurrencyResource($transaction->original_currency),
'service_charge' => (double) $transaction->service_charge,
'tax' => (double) $transaction->tax,
'status' => (int) $transaction->status,
'statusText' => ApprovalStatus::APPROVAL_STATUS_ID[(int) $transaction->status],
'documents' => $transaction->documents()->first() ? new DocumentResource($transaction->documents()->first()) : null,
'updated_at' => Carbon::parse($transaction->updated_at)->format('d-m-Y h:i:s A'),
];
}),
];
}
}
+68
View File
@@ -0,0 +1,68 @@
<?php
namespace App\Models;
use App\Classes\General\Traits\LogData;
use Illuminate\Database\Eloquent\Model;
use App\Classes\General\Interfaces\Documentable;
use App\Classes\General\Interfaces\Transactionable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
class BillGroup extends Model implements Documentable, Transactionable
{
use SoftDeletes;
protected $table = 'bill_groups';
protected $dates = ['deleted_at'];
/**
* @return MorphMany
*/
public function transactions(): MorphMany
{
return $this->MorphMany(Transaction::class, 'owner');
}
/**
* @return MorphMany
*/
public function documents(): morphMany
{
return $this->morphMany(Document::class, 'owner');
}
/**
* @return BelongsTo
*/
public function currency(): BelongsTo
{
return $this->BelongsTo(Currency::class, 'currency_id', 'id');
}
/**
* @return BelongsTo
*/
public function issuerCompany(): BelongsTo
{
return $this->BelongsTo( Company::class, 'issuer', 'id');
}
/**
* @return BelongsTo
*/
public function original_currency(): BelongsTo
{
return $this->BelongsTo(Currency::class, 'original_currency_id', 'id');
}
public function groups()
{
return $this->belongsToMany(Group::class, BillGroupPayment::class, 'bill_group_id', 'group_id');
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class BillGroupPayment extends Model
{
protected $table = 'bill_group_payments';
/**
* @return BelongsTo
*/
public function billGroup(): BelongsTo
{
return $this->BelongsTo(BillGroup::class, 'bill_group_id', 'id');
}
/**
* @return BelongsTo
*/
public function group(): BelongsTo
{
return $this->BelongsTo(Group::class, 'group_id', 'id');
}
}
+9
View File
@@ -6,6 +6,7 @@ use App\Classes\General\Traits\LogData;
use Illuminate\Database\Eloquent\Model;
use App\Classes\General\Interfaces\Documentable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
@@ -60,4 +61,12 @@ class Group extends Model implements Documentable
{
return $this->BelongsTo(Currency::class, 'original_currency_id', 'id');
}
/**
* @return BelongsToMany
*/
public function billGroup(): BelongsToMany
{
return $this->belongsToMany(BillGroup::class, BillGroupPayment::class, 'group_id', 'bill_group_id');
}
}
@@ -0,0 +1,44 @@
<?php
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBillGroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bill_groups', function (Blueprint $table) {
$table->id();
$table->string('reference')->unique();
$table->foreignId('issuer')->unsigned();
$table->foreignId('receiver')->unsigned();
$table->decimal('amount', 14, 5)->default(0.00);
$table->decimal('original_amount', 14, 5)->default(0.00);
$table->foreignId('currency_id')->unsigned();
$table->foreignId('original_currency_id')->unsigned();
$table->decimal('currency_rate', 14, 5)->default(0.00);
$table->decimal('tax', 14, 5)->default(0.00);
$table->decimal('service_charge', 14, 5)->default(0.00);
$table->integer('status')->default(ApprovalStatus::PENDING_VERIFICATION);
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bill_groups');
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBillGroupPaymentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bill_group_payments', function (Blueprint $table) {
$table->id();
$table->foreignId('bill_group_id')->constrained('bill_groups');
$table->foreignId('group_id')->constrained('groups');
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bill_group_payments');
}
}
@@ -0,0 +1,254 @@
<template>
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="row parentContainer m-b-10">
<div class="col p-l-0">
<div class="row m-l-15 p-t-10 b-a align-items-center pointer shadow bg-white rounded" :class="{'b-white': !(this.selectedBillGroup.id === item.id), 'b-primary': this.selectedBillGroup.id === item.id}" @click="select()">
<div class="col-12">
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Date</div>
<div class="font-heading fs-12">
{{item.updated_at}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Reference</div>
<div class="font-heading fs-12">
{{item.reference}}
</div>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<div class="font-heading fs-12 muted all-caps">Supplier</div>
<div class="font-heading fs-12">
{{item.issuer_name}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Amount</div>
<div class="font-heading fs-12">
{{ item.currency.short_code }} {{formatAmount(item.amount)}}
</div>
</div>
<div class="col parentContainer position-static">
<div class="row align-items-center justify-content-end">
<div class="col-auto position-static no-padding requestModal" data-type="deleteBillGroup" v-if="section !== 'paidBillGroupList'">
<div class="btn bg-grey no-border">
<i class="fa fa-times text-danger"></i>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" type="deleteBillGroup">
<general-confirmation-form-component
contentText="Are you sure you want to delete this Bill Group?"
modalType="delete"
class="text-center"
:apiRoute="route('api.transaction.group.bill.delete', item.id)"
apiMethod="delete"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
</div>
<div class="col-auto no-padding">
<div class="btn btn-sm btn-default b-rad-none no-border" @click="expanded = !expanded">
<i class="fa fa-fw" :class="[{'fa-angle-up': expanded}, {'fa-angle-down': !expanded}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded">
<div class="row m-b-10">
<div class="font-heading fs-12 all-caps text-underline">Payment History</div>
</div>
<div class="row m-b-10" v-for="payment in item.payment_history">
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Date</div>
<div class="font-heading fs-12">
{{payment.updated_at}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Reference</div>
<div class="font-heading fs-12">
{{payment.bill_no}}
</div>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<div class="font-heading fs-12 muted all-caps">Amount</div>
<div class="font-heading fs-12">
{{ payment.currency.short_code }} {{ formatAmount(payment.amount) }}
</div>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<div class="font-heading fs-12 muted all-caps">Status</div>
<div class="font-heading fs-12" :class="[{'text-danger': payment.status === 0 || payment.status === 4}, {'text-success': payment.status === 2 || payment.status === 3}, {'text-warning': payment.status === 1}]">
{{ payment.statusText }}
</div>
</div>
<div class="col parentContainer position-static align-items-center">
<div class="row align-items-center justify-content-end">
<div v-if="!payment.documents && section === 'paymentInProgressBillGroupList'">
<div class="btn no-border muted btn-success requestModal" data-type="paymentProofModal" @click="selectedTransactionID(payment.id)">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="30" height="30" viewBox="0 0 172 172" style=" fill:#000000;"><defs><linearGradient x1="86" y1="70.76994" x2="86" y2="116.46013" gradientUnits="userSpaceOnUse" id="color-1_52139_gr1"><stop offset="0" stop-color="#ffffff"></stop><stop offset="1" stop-color="#ffffff"></stop></linearGradient><linearGradient x1="61.8125" y1="34.48869" x2="61.8125" y2="144.97181" gradientUnits="userSpaceOnUse" id="color-2_52139_gr2"><stop offset="0" stop-color="#ffffff"></stop><stop offset="1" stop-color="#ffffff"></stop></linearGradient><linearGradient x1="130.34375" y1="34.48869" x2="130.34375" y2="144.97181" gradientUnits="userSpaceOnUse" id="color-3_52139_gr3"><stop offset="0" stop-color="#ffffff"></stop><stop offset="1" stop-color="#ffffff"></stop></linearGradient><linearGradient x1="86" y1="32.25" x2="86" y2="148.71013" gradientUnits="userSpaceOnUse" id="color-4_52139_gr4"><stop offset="0" stop-color="#ffffff"></stop><stop offset="1" stop-color="#ffffff"></stop></linearGradient></defs><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g><path d="M102.45825,99.43213h-5.70825c-1.4835,0 -2.6875,1.16637 -2.6875,2.65256v8.10013c0,1.48081 -1.19862,2.68481 -2.67944,2.68481h-10.76612c-1.48081,0 -2.67944,-1.204 -2.67944,-2.68481v-8.10013c0,-1.48619 -1.204,-2.65256 -2.6875,-2.65256h-5.70825c-1.93769,0 -3.04225,-2.39188 -1.88125,-4.05275l14.577,-20.855c1.8275,-2.61494 5.69481,-2.61763 7.52231,-0.00538l14.577,20.86306c1.16369,1.66088 0.05644,4.05006 -1.87856,4.05006z" fill="url(#color-1_52139_gr1)"></path><path d="M51.0625,67.1875h5.375c0,-8.0625 7.23206,-16.12231 16.125,-16.12231v-5.375c-11.85456,0 -21.5,10.74731 -21.5,21.49731z" fill="url(#color-2_52139_gr2)"></path><path d="M139.75,80.625c0,-10.75 -8.44144,-18.80981 -18.8125,-18.80981v5.375c7.40944,0 13.4375,5.37231 13.4375,13.43481z" fill="url(#color-3_52139_gr3)"></path><path d="M148.09738,92.27263c1.59369,-3.68188 2.40263,-7.59219 2.40263,-11.64494c0,-16.29969 -13.26281,-29.5625 -29.5625,-29.5625c-6.5145,0 -12.68769,2.08819 -17.78588,5.96088c-4.30269,-13.03438 -16.52006,-22.08587 -30.58912,-22.08587c-17.78319,0 -32.25,14.46681 -32.25,32.25c0,4.14681 0.16662,8.05981 1.42437,10.74731h-1.42437c-13.33806,0 -24.1875,10.84944 -24.1875,24.1875c0,11.56431 8.16194,21.24737 19.0275,23.62044c1.02394,6.39894 6.53869,11.31706 13.2225,11.31706h56.4375h16.125h5.375c6.54944,0 12.00238,-4.71388 13.18488,-10.92469c9.2235,-1.20131 16.37762,-9.08913 16.37762,-18.63513c0,-6.09256 -2.924,-11.72019 -7.77762,-15.23006zM126.3125,131.6875h-5.375h-16.125h-56.4375c-3.49912,0 -6.45538,-2.6875 -7.568,-5.375h93.0735c-1.11263,2.6875 -4.06888,5.375 -7.568,5.375zM137.0625,120.9375h-96.75c-10.37106,0 -18.8125,-8.44144 -18.8125,-18.8125c0,-10.37106 8.44144,-18.8125 18.8125,-18.8125h9.51375l-1.68506,-3.78131c-2.23063,-5.01488 -2.45369,-7.48737 -2.45369,-12.341c0,-14.81888 12.05613,-26.875 26.875,-26.875c13.01825,0 24.13106,9.29875 26.42619,22.11275l0.92719,5.17075l3.64962,-3.77325c4.60638,-4.76225 10.77687,-7.38525 17.372,-7.38525c13.33806,0 24.1875,10.84944 24.1875,24.1875c0,3.6765 -0.81431,7.21056 -2.37575,10.41944l-1.763,3.32713l2.37037,1.26044c4.40481,2.34081 7.14338,6.88806 7.14338,11.868c0,7.40944 -6.02806,13.43481 -13.4375,13.43481z" fill="url(#color-4_52139_gr4)"></path></g></g></svg>
</div>
<modal-component type="paymentProofModal">
<bill-group-payment-proof-form-component v-if="selected_transaction_id === payment.id" :section="section" :data="{item}" :id="payment.id"></bill-group-payment-proof-form-component>
</modal-component>
</div>
<div v-if="payment.documents">
<document-file-viewer-component :file="payment.documents.files[0]">
<template slot="button">
<div class="btn no-border muted btn-success">
<i class="fa fa-file-pdf-o"></i>
</div>
</template>
</document-file-viewer-component>
</div>
<div v-if="section === 'paymentVerificationBillGroupList' && payment.status === 1">
<div class="col-auto">
<div class="row">
<div class="col-6 col-md-auto text-right">
<button class="btn btn-xs btn-outline-danger b-rad-none m-r-5 requestModal" data-type="rejectPayment">
<i class="fa fa-times fa-fw"></i>
</button>
<button class="btn btn-xs btn-success b-rad-none requestModal" data-type="approvePayment">
<i class="fa fa-check fa-fw"></i>
</button>
<modal-component small type="rejectPayment">
<general-confirmation-form-component
contentText="Are you sure you want to reject this payment?"
modalType="delete"
class="text-center"
:apiRoute="route('api.transaction.group.bill.payment_proof.approval', payment.id, 'reject')"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<modal-component small type="approvePayment">
<general-confirmation-form-component
contentText="Are you sure you want to approve this payment?"
modalType="confirm"
class="text-center"
:apiRoute="route('api.transaction.group.bill.payment_proof.approval', payment.id, 'approve')"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-t-20 m-b-20" v-if="item.payment_history.length === 0">
<div class="col">
<div class="font-heading fs-12 text-center all-caps">No Payments</div>
</div>
</div>
</div>
<div class="col b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded">
<div class="row m-b-10">
<div class="font-heading fs-12 all-caps text-underline">Currency Orders</div>
</div>
<div class="row m-t-10 m-b-20" v-for="group in item.groups">
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Date</div>
<div class="font-heading fs-12">
{{group.created_at}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Currency Rate</div>
<div class="font-heading fs-12">
{{group.currency_rate}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">Original Amount</div>
<div class="font-heading fs-12">
{{ group.original_currency.short_code }} {{formatAmount(group.original_amount)}}
</div>
</div>
<div class="col-2">
<div class="font-heading fs-12 muted all-caps">Amount</div>
<div class="font-heading fs-12">
{{ group.currency.short_code }} {{formatAmount(group.amount)}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-12 muted all-caps">PO Completion</div>
<div class="col">
<p class="font-heading fs-12 bold text-success pointer"><span :class="[{'text-danger': group.complete_transactions.length !== group.transactions.length}]">{{group.complete_transactions.length}}</span>/{{group.transactions.length}}</p>
</div>
</div>
<div class="col parentContainer position-static align-items-center">
<div class="row align-items-center justify-content-end">
<div v-if="group.documents.currency_order">
<document-file-viewer-component :file="group.documents.currency_order.files[0]">
<template slot="button">
<div class="btn no-border muted btn-success">
<i class="fa fa-file-pdf-o"></i>
</div>
</template>
</document-file-viewer-component>
</div>
<div v-else>
<div class="btn bg-grey no-border muted invisible">
<i class="fa fa-file-pdf-o"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
props: {
selectedBillGroup: {
type: Object,
required: true
},
section: {
type: String,
required: true
}
},
data(){
return {
selected_id: '',
selected: false,
expanded: false,
selected_transaction_id: '',
}
},
methods: {
selectedTransactionID(id){
this.selected_transaction_id = id;
},
formatAmount(amount) {
return (Math.round((amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
},
select(){
this.$emit('input', this.item)
this.selected = this.selectedBillGroup.id === this.item.id;
},
},
mixins: [componentHandler]
}
</script>
@@ -0,0 +1,154 @@
<template>
<div class="row mt-3 mt-md-0">
<div class="col">
<div class="row m-l-10 p-t-20 p-b-20 shadow bg-white rounded">
<div class="col">
<div class="row align-items-end m-b-10 text-complete">
<div class="col">
<div class="font-heading all-caps fs-12">Transfer Total:</div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.original_currency.short_code}} {{formatAmount(selectedBillGroup.original_amount)}}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">CNY 0.00</div>
</div>
</div>
<div class="row align-items-end m-b-10 text-complete">
<div class="col">
<div class="font-heading all-caps fs-12"></div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.currency.short_code}} {{formatAmount(selectedBillGroup.amount)}}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">MYR 0.00</div>
</div>
</div>
<div class="row align-items-end m-b-10 text-complete">
<div class="col">
<div class="font-heading all-caps fs-12">Service Charge:</div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.currency.short_code}} {{formatAmount(selectedBillGroup.service_charge)}}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">MYR 0.00</div>
</div>
</div>
<div class="row align-items-end m-b-10 text-success">
<div class="col">
<div class="font-heading all-caps fs-12">Paid Total:</div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.currency.short_code}} {{ formatAmount(selectedBillGroup.paid_amount) }}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">MYR 0.00</div>
</div>
</div>
<div class="row align-items-end m-b-10">
<div class="col">
<div class="font-heading all-caps fs-12">Floating Amount:</div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.currency.short_code}} {{ formatAmount(selectedBillGroup.floating_amount) }}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">MYR 0.00</div>
</div>
</div>
<div class="row align-items-end bold text-danger">
<div class="col">
<div class="font-heading all-caps fs-12">OutStanding Total:</div>
</div>
<div class="col-auto text-right" v-if="selectedBillGroup.id">
<div class="font-heading fs-12">{{selectedBillGroup.currency.short_code}} {{ formatAmount(selectedBillGroup.outstanding_amount) }}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading fs-12">MYR 0.00</div>
</div>
</div>
<div v-if="selectedBillGroup.status === 0 && selectedBillGroup.outstanding_amount > 0">
<div class="row p-r-15 m-t-20 m-b-10">
<div class="col p-r-0">
<validation-wrapper-component :validator="$v.parameters.payAmount">
<label>Amount</label>
<input class="form-control" v-model.lazy="parameters.payAmount" v-money="{decimal: '.',thousands: ',', precision: 2}">
</validation-wrapper-component>
</div>
<div class="col-auto b-r b-t b-b b-grey">
<div class="row h-100 align-items-center">
<div class="col">
<div class="font-heading fs-10 muted">{{ selectedBillGroup.id ? selectedBillGroup.currency.short_code : "MYR" }}</div>
</div>
</div>
</div>
</div>
<div class="row m-t-20">
<div class="col">
<button id="payment-btn" class="btn btn-sm all-caps b-rad-none btn-success btn-block" @click="submitForm">Make Payment</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ModalComponent from "../../general/elements/ModalComponent";
import componentHandler from '../../../general/mixins/componentHandler';
import { required } from "vuelidate/lib/validators";
import {VMoney} from 'v-money'
export default {
props: {
selectedBillGroup: {
type: Object,
required: true
},
refreshList: {
type: Function,
required: true
},
},
watch: {
selectedBillGroup(){
this.parameters.payAmount = (Math.round((this.selectedBillGroup.outstanding_amount + Number.EPSILON) * 100) / 100).toFixed(2)
}
},
data(){
return {
parameters: {
payAmount: 0
}
}
},
validations: {
parameters: {
payAmount: {
required
}
}
},
methods: {
formatAmount(amount) {
return (Math.round((amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
},
submitForm(){
this.submit(route('api.transaction.group.bill.pay', this.selectedBillGroup.id), 'post', this.section, true, true)
},
successHandler(){
this.refreshList();
// this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')});
this.parameters = {
payments: [],
};
},
},
mixins: [componentHandler],
directives: {money: VMoney}
}
</script>
@@ -0,0 +1,140 @@
<template>
<div class="row m-b-10 parentContainer">
<div class="col">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row align-items-center pointer p-b-5 b-b b-grey" v-show="!isLoading" @click="activate()">
<div class="col-auto p-r-0">
<div class="b-grey b-a fs-10 btn-rounded icon-thumbnail icon-25 m-r-0" :class="[{'bg-primary': active}, {'bg-transparent': !active}]">
<i class="fa fa-check text-white fs-12 fa-fw"></i>
</div>
</div>
<div class="col">
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Date</div>
<div class="font-heading fs-10">
{{item.created_at}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Supplier</div>
<div class="font-heading fs-10">
{{item.issuer_name}}
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Currency Rate</div>
<div class="font-heading fs-10">
{{item.currency_rate}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Currency Amount</div>
<div class="font-heading fs-10">
{{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col text-right">
<div class="font-heading fs-10 muted all-caps">Amount</div>
<div class="font-heading fs-14 text-success bold">
{{item.currency.short_code}} {{((Math.round(( item.amount + Number.EPSILON) * 100) / 100)).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">reference</div>
<document-file-viewer-component v-if="item.documents.currency_order" :file="item.documents.currency_order.files[0]">
<template slot="button">
<button class="btn btn-xs btn-default bg-master-lightest b-rad-none no-border">
<i class="fa fa-eye"></i>
</button>
</template>
</document-file-viewer-component>
</div>
<div class="col">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">PO Completion</div>
</div>
</div>
<div class="row">
<div class="col-auto p-r-0" v-if="item.documents.purchase_order" >
<document-file-viewer-component :file="item.documents.purchase_order.files[0]">
<template slot="button">
<button class="btn btn-xs btn-default bg-master-lightest b-rad-none no-border">
<i class="fa fa-file-pdf-o"></i>
</button>
</template>
</document-file-viewer-component>
</div>
<div class="col">
<p class="font-heading fs-12 bold text-success pointer" @click="expand($event)"><span :class="[{'text-danger': item.complete_transactions.length !== item.transactions.length}]">{{item.complete_transactions.length}}</span>/{{item.transactions.length}}</p>
</div>
</div>
</div>
</div>
<div class="row" v-if="expanded">
<div class="col">
<div class="row" v-for="transaction in item.transactions">
<div class="col">
<a :href="route('booking.details', transaction)" target="_blank">
<span :class="[{'text-success': item.complete_transactions.includes(transaction)}, {'text-danger': !item.complete_transactions.includes(transaction)}]">{{ transaction }}</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import staticFormHandler from '../../../general/mixins/staticFormHandler'
export default {
props: {
section:{
type: String,
required: true
},
payments:{
type: Array,
required: true
}
},
data(){
return {
expanded: false,
active: this.item ? this.payments.some(payment => payment.id === this.item.id) : false,
}
},
created(){
this.active = this.payments.some(payment => payment.id === this.item.id);
},
methods: {
deleteGroupTransaction() {
this.isLoading = true;
this.submit(this.route('api.transaction.group.delete', this.item.id), 'delete', this.section, true, true);
},
updateDo() {
this.isLoading = true;
this.submit(this.route('api.transaction.group.bulk.po'), 'post', this.section, true, true);
},
activate(){
this.active = !this.active;
this.$emit('input', this.item)
},
expand(event){
this.expanded = !this.expanded;
event.stopPropagation();
}
},
mixins: [componentHandler, staticFormHandler]
}
</script>
@@ -0,0 +1,80 @@
<template>
<div class="row" @keyup.enter="submitForm">
<div class="col">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="$store.getters.isLoading(section)"></loading-component>
<div class="row" v-show="!$store.getters.isLoading(section)">
<div class="col">
<div class="row m-b-10">
<div class="col">
<div class="font-heading fs-16 all-caps bold m-b-15">Payment Proof</div>
</div>
</div>
<error-message-component class="m-b-20" :error="error"></error-message-component>
<div class="row">
<div class="col">
<file-input-component :validator="$v.files" v-model="files">
<template slot="label">
<div class="font-heading fs-11 text-primary all-caps">Payment Proof</div>
</template>
</file-input-component>
</div>
</div>
<div class="row m-t-20">
<div class="col">
<div class="row">
<div class="col-auto">
<button type="button" class="btn btn-sm bg-master-lighter p-t-10 p-b-10 p-r-35 p-l-35 btn-default b-rad-none" data-dismiss="modal">Cancel</button>
</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="submitForm">Save and continue</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ModalFromHandler from '../../../general/mixins/modalFormHandler'
import { required } from "vuelidate/lib/validators";
export default {
props: {
id: {
required: true,
type: Number
}
},
data(){
return {
files: [],
parameters: {}
}
},
validations: {
files: {
required
}
},
methods: {
submitForm(){
this.parameters = {
files: this.files
};
this.submit(this.route('api.transaction.group.bill.payment_proof.create', this.id), 'post', this.section, true, true)
},
successHandler(){
this.closeModal();
this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')});
this.$store.dispatch('toggleSection', {name: 'paymentVerificationBillGroupList', status: !this.$store.getters.isShowing('paymentVerificationBillGroupList')});
this.files = []
},
},
mixins: [ModalFromHandler]
}
</script>
@@ -0,0 +1,201 @@
<template>
<div class="row mt-3 mt-md-0">
<div class="col">
<div class="row">
<div class="col">
<div class="row align-items-end m-b-10">
<div class="col">
<div class="font-heading all-caps fs-10">Supplier:</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10">{{this.supplier.name}}</div>
</div>
</div>
<div class="row align-items-end m-b-5 text-info">
<div class="col">
<div class="font-heading all-caps fs-10">Order Total:</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-11">{{ this.payments.length > 0 ? this.payments[0].original_currency.short_code : "CNY"}} {{(Math.round((this.originalTotal + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-5 text-info" v-if="!is1688Supplier">
<div class="col">
<div class="font-heading all-caps fs-10"></div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-11">MYR {{(Math.round((this.total + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-5 text-info" v-if="!is1688Supplier">
<div class="col">
<div class="font-heading all-caps fs-10">Service Charges:</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-11">MYR {{service_charges}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 text-primary" v-if="is1688Supplier">
<div class="col">
<div class="font-heading all-caps fs-10">Currency Rate:</div>
</div>
<div class="col-auto text-right">
<div class="font-heading bold">{{ billGroupCurrencyRate }}</div>
</div>
</div>
<div class="row align-items-end m-b-10 text-success">
<div class="col">
<div class="font-heading all-caps fs-10">Payment Total:</div>
</div>
<div class="col-auto text-right" v-if="is1688Supplier">
<div class="font-heading bold">MYR {{ payment_total }}</div>
</div>
<div class="col-auto text-right" v-else>
<div class="font-heading bold">MYR {{(Math.round((paymentTotal + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col p-r-0">
<validation-wrapper-component :validator="$v.parameters.payment_total">
<label class="all-caps">Payment Total</label>
<input type="text" class="form-control" v-model="payment_total" v-money="productPrice">
</validation-wrapper-component>
</div>
<div class="col-auto b-r b-t b-b b-grey m-r-15">
<div class="row h-100 align-items-center">
<div class="col">
<div class="font-heading fs-10 muted">MYR</div>
</div>
</div>
</div>
</div>
<div class="row" >
<div class="col">
<validation-wrapper-component :validator="$v.parameters.service_charges">
<label class="all-caps">Service Charges</label>
<input type="text" class="form-control" v-model="service_charges" v-money="productPrice">
</validation-wrapper-component>
</div>
</div>
<div class="row" v-if="paymentTotal > 0">
<div class="col">
<button class="btn btn-xs btn-success b-rad-none p-t-5 p-b-5 all-caps fs-10 btn-block" @click="submitForm()">Create Bill Group</button>
</div>
</div>
</div>
</div>
</template>
<script>
import FormHandler from '../../../general/mixins/formHandler';
import { required, minValue, requiredIf} from "vuelidate/lib/validators";
import ModalComponent from "../../general/elements/ModalComponent";
export default {
components: {ModalComponent},
props: {
payments: {
type: Array,
required: true
},
supplier: {
type: Object,
required: true
},
refreshList: {
type: Function,
required: true
},
},
data(){
return {
service_charges: '0',
payment_total: '0',
}
},
validations: {
parameters: {
service_charges: {
required: requiredIf(function () {
return !this.is1688Supplier;
})
},
payment_total: {
required: requiredIf(function () {
return this.is1688Supplier;
}),
minValue: minValue(1)
}
}
},
// watch: {
// supplier(){
// this.$v.$reset();
// },
// },
computed: {
originalTotal(){
return this.payments.reduce(function (total, currentValue) {
return total + currentValue.original_amount;
}, 0);
},
total(){
return this.payments.reduce(function (total, currentValue) {
return total + currentValue.amount;
}, 0);
},
paymentTotal(){
return this.total ? this.total + parseFloat(this.service_charges.replaceAll(',', '')) : 0;
},
billGroupCurrencyRate(){
const paymentTotal = parseFloat(this.payment_total.replaceAll(',', ''));
return this.originalTotal && paymentTotal > 0 ? (this.originalTotal / paymentTotal).toFixed(5) : 1;
},
is1688Supplier(){
return (this.supplier.id === 4548 || this.supplier.id === 2729)
}
},
methods: {
submitForm(){
if (this.is1688Supplier) {
this.parameters = {
payments: this.payments,
payment_total: parseFloat(this.payment_total.replaceAll(',', '')),
};
} else {
this.parameters = {
payments: this.payments,
service_charges: this.service_charges,
};
}
console.log(this.parameters)
console.log(this.$v)
console.log(this.validate)
this.submit(route('api.transaction.supplier.bill_group.create', this.supplier.id), 'post', 'transactionGroupsListPaymentSection', true, true)
},
successHandler(){
// this.$v.$reset();
this.refreshList();
this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')});
this.parameters = {
payments: [],
service_charges: '0',
payment_total: '0',
};
this.service_charges = '0';
this.payment_total = '0';
},
errorHandler(error){
console.log(error)
// this.$v.$reset();
},
},
mixins: [FormHandler]
}
</script>
@@ -0,0 +1,136 @@
<template>
<div class="row p-r-10">
<div class="col p-r-5">
<div class="row m-b-20">
<div class="col-7">
<div class="row m-b-15">
<div class="col-12">
<div class="row m-b-5">
<div class="col p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="selectedSupplier.status = !selectedSupplier.status">
<div class="row">
<div class="col p-t-5 p-b-5 fs-9">
{{selectedSupplier.name}} - {{selectedSupplier.reference}}
</div>
<div class="col-auto b-l b-success">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa" :class="[{'fa-angle-down': !selectedSupplier.status}, {'fa-angle-up': selectedSupplier.status}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="relative w-100">
<div class="absolute w-100 b-l b-b b-r b-primary" :class="[{'hide': !selectedSupplier.status}]" style="top: 100%; right: 0; z-index: 1;">
<div class="row text-left no-margin bg-white">
<div class="col no-padding">
<div class="row no-margin" v-for="supplier in suppliers" v-bind:key="supplier.id" :data="supplier">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10" :class="[{'bg-primary-light': selectedSupplier.id === supplier.id}, {'text-white': selectedSupplier.id === supplier.id}, {'hover-primary': selectedSupplier.id !== supplier.id}, {'pointer': selectedSupplier.id !== supplier.id}]" @click="updateSupplier(supplier)">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">{{supplier.name}} - {{supplier.reference}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col" v-if="section === 'paymentInProgressBillGroupList'">
<list-component :key="key" section="paymentInProgressBillGroupListSection" :endpoint="route('api.transaction.group.bill.list')" :options="{per_page: 20, status: 0, ...this.selectedSupplier.id && {issuer_in: [this.selectedSupplier.id]}, order_by: {column: 'id', DESC: true}}">
<template slot="list" slot-scope="{data}">
<bill-group-component :data="data" :section="section" :selectedBillGroup="selectedBillGroup" v-on:input="selectBillGroup($event)"></bill-group-component>
</template>
</list-component>
</div>
<div class="col" v-if="section === 'paymentVerificationBillGroupList'">
<list-component :key="key" section="paymentVerificationBillGroupListSection" :endpoint="route('api.transaction.group.bill.list')" :options="{per_page: 20, has_pending_verify_transaction: true, ...this.selectedSupplier.id && {issuer_in: [this.selectedSupplier.id]}, order_by: {column: 'id', DESC: true}}">
<template slot="list" slot-scope="{data}">
<bill-group-component :data="data" :section="section" :selectedBillGroup="selectedBillGroup" v-on:input="selectBillGroup($event)"></bill-group-component>
</template>
</list-component>
</div>
<div class="col" v-if="section === 'paidBillGroupList'">
<list-component :key="key" section="paidBillGroupListSection" :endpoint="route('api.transaction.group.bill.list')" :options="{per_page: 20, status_in: [2, 3], ...this.selectedSupplier.id && {issuer_in: [this.selectedSupplier.id]}, order_by: {column: 'id', DESC: true}}">
<template slot="list" slot-scope="{data}">
<bill-group-component :data="data" :section="section" :selectedBillGroup="selectedBillGroup" v-on:input="selectBillGroup($event)"></bill-group-component>
</template>
</list-component>
</div>
</div>
</div>
<div class="col-12 col-md" v-if="section === 'paymentInProgressBillGroupList'">
<bill-group-payment-summary-component :selectedBillGroup="selectedBillGroup" :refreshList="updateList" section="paymentInProgressBillGroupList"></bill-group-payment-summary-component>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
section:{
type: String,
required: true
},
},
data(){
return {
suppliers: [],
selectedSupplier: {
id: '',
name: '',
status: false
},
selectedBillGroup: {
id: ''
},
key: 1
}
},
computed: {
pendingQueue() {
return this.$store.getters.isShowing(this.section);
}
},
watch: {
pendingQueue(){
this.updateList();
},
},
created(){
this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'transactionGroupsListPaymentSection', false, false)
},
methods: {
successHandler(response){
this.suppliers = response.payload.data;
},
updateSupplier(supplier){
if(supplier !== this.selectedSupplier){
this.selectedSupplier = supplier;
this.updateList();
}
},
updateList(){
this.selectedSupplier.status = false;
this.selectedBillGroup = {
id: ''
};
this.key++;
},
selectBillGroup(billGroup){
this.selectedBillGroup = billGroup;
}
}
}
</script>
@@ -0,0 +1,113 @@
<template>
<div class="row">
<div class="col">
<div class="row">
<div class="col p-r-5">
<div class="row m-b-20">
<div class="col-12 col-md-7">
<div class="row m-b-15">
<div class="col">
<div class="row m-b-5">
<div class="col p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="selectedSupplier.status = !selectedSupplier.status">
<div class="row">
<div class="col p-t-5 p-b-5 fs-9">
{{selectedSupplier.name}} - {{selectedSupplier.reference}}
</div>
<div class="col-auto b-l b-success">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa" :class="[{'fa-angle-down': !selectedSupplier.status}, {'fa-angle-up': selectedSupplier.status}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="relative w-100">
<div class="absolute w-100 b-l b-b b-r b-primary" :class="[{'hide': !selectedSupplier.status}]" style="top: 100%; right: 0; z-index: 1;">
<div class="row text-left no-margin bg-white">
<div class="col no-padding">
<div class="row no-margin" v-for="supplier in suppliers" v-bind:key="supplier.id" :data="supplier">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10" :class="[{'bg-primary-light': selectedSupplier.id === supplier.id}, {'text-white': selectedSupplier.id === supplier.id}, {'hover-primary': selectedSupplier.id !== supplier.id}, {'pointer': selectedSupplier.id !== supplier.id}]" @click="updateSupplier(supplier)">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">{{supplier.name}} - {{supplier.reference}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="this.selectedSupplier.id !== ''">
<div class="col">
<list-component :key="currencyOrderKey" section="transactionGroupsListPaymentSection" :options="{'per_page': 20, 'without_bill_group': true, 'issuer_in': [this.selectedSupplier.id]}" :endpoint="route('api.transaction.group.list')">
<template slot="list" slot-scope="{data}">
<transaction-group-payment-component section="transactionGroupsListPaymentSection" :data="data" :payments="payments" v-on:input="updateOrder($event)"></transaction-group-payment-component>
</template>
</list-component>
</div>
</div>
<div class="row" v-else>
<div class="col">
<loading-component style="height: 200px; top: 0;" key="1" color="success"></loading-component>
</div>
</div>
</div>
<div class="col-12 col-md">
<supplier-white-form-place-order-form-component :payments="payments" :refreshList="updateList" :supplier="selectedSupplier" section="transactionGroupsListPaymentSection"></supplier-white-form-place-order-form-component>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
suppliers: [],
selectedSupplier: {
id: '',
name: '',
status: false
},
payments: [],
currencyOrderKey: 1,
}
},
created(){
this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'transactionGroupsListPaymentSection', false, false)
},
methods: {
successHandler(response){
this.suppliers = response.payload.data;
this.selectedSupplier= this.suppliers[0];
this.updateList();
},
updateSupplier(supplier){
if(supplier !== this.selectedSupplier){
this.selectedSupplier= supplier;
this.updateList();
}
},
updateList(){
this.currencyOrderKey ++;
this.selectedSupplier.status = false;
this.payments = [];
},
updateOrder(payment){
this.payments.some(item => item.id === payment.id) ? this.payments = this.payments.filter(item => item.id !== payment.id) : this.payments.push(payment);
}
}
}
</script>
@@ -57,7 +57,16 @@
submitForm() {
if (this.params) this.parameters = this.params;
return this.submit(this.apiRoute, this.apiMethod, this.section, true, true);
}
},
successHandler(){
this.closeModal();
this.formHandler();
if (this.section && (this.section === 'paymentInProgressBillGroupList' || this.section === 'paymentVerificationBillGroupList')) {
this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')});
this.$store.dispatch('toggleSection', {name: 'paymentVerificationBillGroupList', status: !this.$store.getters.isShowing('paymentVerificationBillGroupList')});
this.$store.dispatch('toggleSection', {name: 'paidBillGroupList', status: !this.$store.getters.isShowing('paidBillGroupList')});
}
},
},
mixins: [componentHandler, ModalFormHandler]
File diff suppressed because one or more lines are too long
@@ -38,6 +38,11 @@
<div class="text-white all-caps fs-12">Currency Orders</div>
</a>
</div>
<div class="col-auto p-r-20" v-if="$store.getters.isAdmin">
<a href="{{route('supplier.payments')}}">
<div class="text-white all-caps fs-12">Supplier Currency Orders</div>
</a>
</div>
<div class="col-auto p-r-20" v-if="$store.getters.isAdmin">
<a href="{{route('bookings')}}">
<div class="text-white all-caps fs-12">Transfers</div>
+10
View File
@@ -8,6 +8,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
Route::delete('/suspend/{id}', 'SuspendTransactionController@suspend')->name('suspend');
route::post('/supplier/{id}/bill/create', 'CreateSupplierTransactionController@create')->name('supplier.create');
route::post('/supplier/{id}/bill/group/create', 'CreateSupplierBillGroupController@create')->name('supplier.bill_group.create');
route::post('{id}/bill/verification', 'CreatePaymentProofDocumentController@verify')->name('bill.verification');
route::post('{id}/bill/pay', 'CreatePaymentProofDocumentController@pay')->name('bill.pay');
Route::put('/{id}/bill/{status}', 'UpdatePaymentTransactionStatusController@update')->where('status', 'pending|complete')->name('bill.status');
@@ -33,5 +34,14 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
Route::put('/{id}/update', 'UpdateGroupController@update')->name('update');
Route::post('/{id}/approve', 'CreateBulkPurchaseOrderDocumentController@aprove')->name('approve');
Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po');
Route::group(['prefix' => 'bills', 'as' => 'bill.'], function () {
Route::get('/list', 'ListBillGroupsController@list')->name('list');
Route::post('/transaction/{id}', 'CreateBillGroupPaymentProofDocumentController@create')->name('payment_proof.create');
Route::post('/transaction/{id}/approval/{status}', 'ApproveBillGroupPaymentVerificationController@approve')->where('status', 'approve|reject')->name('payment_proof.approval');
Route::delete('/{id}/delete', 'DeleteBillGroupController@delete')->name('delete');
Route::post('/{id}/pay', 'CreateBillGroupPaymentTransactionController@pay')->name('pay');
// Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po');
});
});
});
+4
View File
@@ -88,6 +88,10 @@ Route::get('/payments', function () {
return view('pages.payments');
})->name('payments');
Route::get('/supplier-payments', function () {
return view('pages.supplier-payments');
})->name('supplier.payments');
Route::get('/billings', function () {
return view('pages.billings');
})->name('billings');