diff --git a/app/Classes/General/Eloquent/Filters/IsMappedWithMultiple.php b/app/Classes/General/Eloquent/Filters/IsMappedWithMultiple.php index 066fa6ef..c9c92438 100644 --- a/app/Classes/General/Eloquent/Filters/IsMappedWithMultiple.php +++ b/app/Classes/General/Eloquent/Filters/IsMappedWithMultiple.php @@ -2,6 +2,7 @@ namespace App\Classes\General\Eloquent\Filters; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use Illuminate\Database\Eloquent\Builder; class IsMappedWithMultiple implements Filter @@ -14,7 +15,10 @@ class IsMappedWithMultiple implements Filter */ public static function apply(Builder $builder, $value) { - return $value ? $builder->has('owners', '>', 1) : $builder->has('owners', '=',1); + $query = $builder->withCount(['owners' => function ($query){ + $query->where('status', ApprovalStatus::PENDING_VERIFICATION); + }]); + return $value ? $query->having('owners_count', '>', 1) : $query->having('owners_count', '=', 1); } } diff --git a/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerStatusIn.php b/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerStatusIn.php index e309cd4d..f2dfe546 100644 --- a/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerStatusIn.php +++ b/app/Classes/General/Eloquent/Filters/StatementTransactionOwnerStatusIn.php @@ -15,7 +15,7 @@ class StatementTransactionOwnerStatusIn implements Filter public static function apply(Builder $builder, $value) { return $builder->whereHas('owners', function ($query) use ($value) { - return $query->whereIn('status', $value); + return $query->whereIn('statement_transaction_owners.status', $value); }); } diff --git a/app/Classes/Modules/Accounting/ControllersLogic/ApproveDuplicateBankStatementDetailsStatusLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/ApproveDuplicateBankStatementDetailsStatusLogic.php index d9be0c51..e7d1a7c9 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/ApproveDuplicateBankStatementDetailsStatusLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/ApproveDuplicateBankStatementDetailsStatusLogic.php @@ -14,6 +14,7 @@ use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; use App\Classes\Modules\Accounting\Services\FetchesBankStatementDetails; use App\Classes\Modules\Accounting\Services\ListsBankStatementDetails; use App\Models\StatementTransactionOwner; +use Illuminate\Support\Collection; class ApproveDuplicateBankStatementDetailsStatusLogic extends AbstractControllerLogic { @@ -29,79 +30,254 @@ class ApproveDuplicateBankStatementDetailsStatusLogic extends AbstractController ]; } - /** @var ListsBankStatementDetails */ - private $listsBankStatementDetails; - - /** @var FetchesBankStatementDetails */ - private $fetchesBankStatementDetails; - /** @var UpdatesBankStatementTransactionOwnerStatus */ private $updatesBankStatementTransactionOwnerStatus; - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - /** - * UpdateAnnouncementLogic constructor. - * @param ListsBankStatementDetails $listsBankStatementDetails - * @param FetchesBankStatementDetails $fetchesBankStatementDetails * @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus - * @param UpdatesTransactionStatus $updatesTransactionStatus */ - public function __construct( - listsBankStatementDetails $listsBankStatementDetails, - FetchesBankStatementDetails $fetchesBankStatementDetails, - UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, - UpdatesTransactionStatus $updatesTransactionStatus - ) { - $this->listsBankStatementDetails = $listsBankStatementDetails; - $this->fetchesBankStatementDetails = $fetchesBankStatementDetails; + public function __construct(UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus) + { $this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus; - $this->updatesTransactionStatus = $updatesTransactionStatus; } +// /** +// * Perform logic for approving or rejecting a statement transaction owner and handle matching records. +// * +// * @param Request $request The request object containing route parameters and data. +// * @return JsonResponse The JSON response indicating the result of the logic. +// */ +// public function logic(Request $request): JsonResponse +// { +// // Determine the status based on the 'status' route parameter +// $status = $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED; +// +// // Find the statement transaction owner based on the 'id' route parameter +// $owner = StatementTransactionOwner::find($request->route('id')); +// +// // Execute an update action to change the status of the owner +// $this->updatesBankStatementTransactionOwnerStatus->execute($owner, $status); +// +// // If the status is 'approved', reject all other owners with the same system, owner type, and owner ID +// if ($status === ApprovalStatus::APPROVED) { +// StatementTransactionOwner::where('system', $owner->system) +// ->where('owner_type', $owner->owner_type) +// ->where('owner_id', $owner->owner_id) +// ->where('id', '!=', $owner->id) +// ->update(['status' => ApprovalStatus::REJECTED]); +// } +// +// // Find all siblings (owners with the same statement transaction ID) +// $siblings = StatementTransactionOwner::where('statement_transaction_id', $owner->statement_transaction_id) +// ->where('id', '!=', $owner->id) +// ->get(); +// +// // Process each sibling +// foreach ($siblings as $sibling) { +// +// // If the status is 'approved', reject the sibling and save the changes +// if ($status === ApprovalStatus::APPROVED) { +// $sibling->status = ApprovalStatus::REJECTED; +// $sibling->save(); +// } +// +// // Find all twins (owners with the same system, owner type, and owner ID) +// $twins = StatementTransactionOwner::where('system', $sibling->system) +// ->where('owner_type', $sibling->owner_type) +// ->where('owner_id', $sibling->owner_id) +// ->where('id', '!=', $sibling->id) +// ->get(); +// +// // Process each twin +// foreach ($twins as $twin) { +// // Find all owners with the same statement transaction ID as the twin +// $owners = StatementTransactionOwner::where('statement_transaction_id', $twin->statement_transaction_id) +// ->where('id', '!=', $twin->id) +// ->get(); +// +// // If there is only one owner (the twin itself), execute an update action to change its status to 'approved' +// if (count($owners) === 1) { +// $this->updatesBankStatementTransactionOwnerStatus->execute($twin, ApprovalStatus::APPROVED); +// } +// } +// } +// +// // Find all remaining matching owners for the related transaction +// $remainingMatches = StatementTransactionOwner::where('system', $owner->system) +// ->where('owner_type', $owner->owner_type) +// ->where('owner_id', $owner->owner_id) +// ->where('status', ApprovalStatus::PENDING_VERIFICATION) // Consider only pending owners +// ->get(); +// +// // Process each remaining match +// foreach ($remainingMatches as $match) { +// // Find all owners with the same statement transaction ID as the match +// $owners = StatementTransactionOwner::where('statement_transaction_id', $match->statement_transaction_id) +// ->where('id', '!=', $match->id) +// ->get(); +// +// // If there is only one owner (the match itself), execute an update action to change its status to 'approved' +// if (count($owners) === 1) { +// $this->updatesBankStatementTransactionOwnerStatus->execute($match, ApprovalStatus::APPROVED); +// } +// } +// +// // Return an empty response +// return $this->response([]); +// } + /** - * @param Request $request - * @return JsonResponse - * @throws \App\Classes\Exceptions\AccessForbiddenException - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\RequestValidationException + * Perform logic for approving or rejecting a statement transaction owner and handle matching records. + * + * @param Request $request The request object containing route parameters and data. + * @return JsonResponse The JSON response indicating the result of the logic. */ public function logic(Request $request): JsonResponse { - $bankSatementDetails = $this->fetchesBankStatementDetails->execute(['id' => $request->route('id')]); + // Determine the approval status + $status = $this->getApprovalStatus($request); - $this->updatesBankStatementTransactionOwnerStatus->execute($bankSatementDetails, ApprovalStatus::APPROVED); + // Find the statement transaction owner + $owner = $this->getOwner($request); - // todo-new: approve payments status, need to check the owner(if system is shipping, need to api with shipping portal) - // if ($bankSatementDetails->transaction->type === StatementTransactionOwnerType::SALES) { - // if ($bankSatementDetails->owner->status === ApprovalStatus::PENDING_VERIFICATION) { - // $this->updatesTransactionStatus->execute($bankSatementDetails->owner, ApprovalStatus::APPROVED); - // } - // } + // Update owner status + $this->updateOwnerStatus($owner, $status); - $rejectedBankSatementDetails = $this->listsBankStatementDetails->execute(['id_not' => $request->route('id'), 'owner_id' => $bankSatementDetails->owner_id]); - - if (count($rejectedBankSatementDetails) == 1) { - $otherBankStatement = $rejectedBankSatementDetails->first(); - - $otherSetBankStatement = StatementTransactionOwner::where('system', $otherBankStatement->system)->where('owner_type', $otherBankStatement->owner_type)->where('owner_id', $otherBankStatement->owner_id)->get(); - foreach ($otherSetBankStatement as $otherStatement) { - // todo: check is this id verification needed? - if ($otherStatement->id == $request->route('id')) { - $this->updatesBankStatementTransactionOwnerStatus->execute($otherStatement, ApprovalStatus::REJECTED); - } else { - $this->updatesBankStatementTransactionOwnerStatus->execute($otherStatement, ApprovalStatus::APPROVED); - } - } + // If the status is 'approved', handle the approval process + if ($status === ApprovalStatus::APPROVED) { + $this->handleApprovedStatus($owner); } - foreach ($rejectedBankSatementDetails as $statement) { - $this->updatesBankStatementTransactionOwnerStatus->execute($statement, ApprovalStatus::REJECTED); - } - - dd($bankSatementDetails); + // Check and approve remaining matches if any + $this->checkAndApproveRemainingMatches($owner); + // Return an empty response return $this->response([]); } + + private function getApprovalStatus(Request $request): int + { + return $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED; + } + + private function getOwner(Request $request): StatementTransactionOwner + { + return StatementTransactionOwner::find($request->route('id')); + } + + private function updateOwnerStatus(StatementTransactionOwner $owner, int $status): void + { + $this->updatesBankStatementTransactionOwnerStatus->execute($owner, $status); + } + + private function handleApprovedStatus(StatementTransactionOwner $owner): void + { + // Reject all other owners with the same system, owner type, and owner ID + $this->rejectOtherOwners($owner); + + // Find all siblings and process them + $siblings = $this->getSiblings($owner); + $this->processSiblings($siblings); + } + + private function rejectOtherOwners(StatementTransactionOwner $owner): void + { + StatementTransactionOwner::where('system', $owner->system) + ->where('owner_type', $owner->owner_type) + ->where('owner_id', $owner->owner_id) + ->where('id', '!=', $owner->id) + ->update(['status' => ApprovalStatus::REJECTED]); + } + + private function getSiblings(StatementTransactionOwner $owner): Collection + { + return StatementTransactionOwner::where('statement_transaction_id', $owner->statement_transaction_id) + ->where('id', '!=', $owner->id) + ->get(); + } + + private function processSiblings(Collection $siblings): void + { + foreach ($siblings as $sibling) { + $this->processSibling($sibling); + } + } + + private function processSibling(StatementTransactionOwner $sibling): void + { + // Reject the sibling and save the changes + $sibling->status = ApprovalStatus::REJECTED; + $sibling->save(); + + // Find all twins and process them + $twins = $this->getTwins($sibling); + $this->processTwins($twins); + } + + private function getTwins(StatementTransactionOwner $sibling): Collection + { + return StatementTransactionOwner::where('system', $sibling->system) + ->where('owner_type', $sibling->owner_type) + ->where('owner_id', $sibling->owner_id) + ->where('id', '!=', $sibling->id) + ->get(); + } + + private function processTwins(Collection $twins): void + { + foreach ($twins as $twin) { + $this->processTwin($twin); + } + } + + private function processTwin(StatementTransactionOwner $twin): void + { + // Find all owners with the same statement transaction ID as the twin + $owners = $this->getOwners($twin); + + // If there is only one owner (the twin itself), approve it + if ($owners->count() === 1) { + $this->updateOwnerStatus($twin, ApprovalStatus::APPROVED); + } + } + + private function getOwners(StatementTransactionOwner $transactionOwner): Collection + { + return StatementTransactionOwner::where('statement_transaction_id', $transactionOwner->statement_transaction_id) + ->where('id', '!=', $transactionOwner->id) + ->get(); + } + + private function checkAndApproveRemainingMatches(StatementTransactionOwner $owner): void + { + // Find all remaining matching owners for the related transaction + $remainingMatches = $this->getRemainingMatches($owner); + + // Process each remaining match + foreach ($remainingMatches as $match) { + $this->processRemainingMatch($match); + } + } + + private function getRemainingMatches(StatementTransactionOwner $owner): Collection + { + return StatementTransactionOwner::where('system', $owner->system) + ->where('owner_type', $owner->owner_type) + ->where('owner_id', $owner->owner_id) + ->where('status', ApprovalStatus::PENDING_VERIFICATION) + ->get(); + } + + private function processRemainingMatch(StatementTransactionOwner $match): void + { + // Find all owners with the same statement transaction ID as the match + $owners = $this->getOwners($match); + + // If there is only one owner (the match itself), approve it + if ($owners->count() === 1) { + $this->updateOwnerStatus($match, ApprovalStatus::APPROVED); + } + + } + } diff --git a/app/Classes/Modules/Accounting/ControllersLogic/GroupApproveStatementTransactionLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/GroupApproveStatementTransactionLogic.php index 7c312865..3b220146 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/GroupApproveStatementTransactionLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/GroupApproveStatementTransactionLogic.php @@ -2,6 +2,7 @@ namespace App\Classes\Modules\Accounting\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Accounting\Services\ListsBankStatementTransactions; use App\Http\Resources\BankStatementTransactionResource; @@ -15,6 +16,7 @@ use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; class GroupApproveStatementTransactionLogic extends AbstractControllerLogic { + /** * @return array */ @@ -36,16 +38,12 @@ class GroupApproveStatementTransactionLogic extends AbstractControllerLogic private $updatesTransactionStatus; /** - * UpdateAnnouncementLogic constructor. * @param ListsBankStatementTransactions $listsBankStatementTransactions * @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus * @param UpdatesTransactionStatus $updatesTransactionStatus */ - public function __construct( - ListsBankStatementTransactions $listsBankStatementTransactions, - UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, - UpdatesTransactionStatus $updatesTransactionStatus - ) { + public function __construct(ListsBankStatementTransactions $listsBankStatementTransactions, UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, UpdatesTransactionStatus $updatesTransactionStatus) + { $this->listsBankStatementTransactions = $listsBankStatementTransactions; $this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus; $this->updatesTransactionStatus = $updatesTransactionStatus; @@ -54,30 +52,35 @@ class GroupApproveStatementTransactionLogic extends AbstractControllerLogic /** * @param Request $request * @return JsonResponse - * @throws \App\Classes\Exceptions\AccessForbiddenException - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\RequestValidationException + * @throws MalformedRequestException */ public function logic(Request $request): JsonResponse { - $statementTrasactions = $this->listsBankStatementTransactions->execute($this->listsBankStatementTransactions->deserializeFilters( - json_decode("{min_amount: 0, is_mapped: true, is_mapped_with_multiple: false, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [1], per_page: 100, order_by: {column: 'posting_date', DESC: true}}", true) - )); - foreach ($statementTrasactions as $statementTrasaction) { - $statementTrasactionOwner = $statementTrasaction->owners; + $filters = [ + "min_amount" => 0, + "is_mapped" => true, + "is_mapped_with_multiple" => false, + "statement_transaction_owner_type_in" => [1, 2], + "statement_transaction_owner_status_in" => [1] + ]; + $statementTransactions = $this->listsBankStatementTransactions->execute($filters); - if (count($statementTrasactionOwner)) { - $this->updatesBankStatementTransactionOwnerStatus->execute($statementTrasactionOwner->first(), ApprovalStatus::APPROVED); + foreach ($statementTransactions as $statementTransaction) { + $owners = $statementTransaction->owners; - if ($statementTrasactionOwner->owner->type !== StatementTransactionOwnerType::SALES) continue; + if (count($owners)) { + $this->updatesBankStatementTransactionOwnerStatus->execute($owners->first(), ApprovalStatus::APPROVED); - if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION ) { - $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED); - } + // automatically approve payment if pending verification + +// if ($statementTrasactionOwner->owner->type !== StatementTransactionOwnerType::SALES) continue; +// if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION ) { +// $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED); +// } } } - return $this->collectionResponse(BankStatementTransactionResource::collection($statementTrasactions)); + return $this->response([]); } } diff --git a/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php index b7f737da..0355c554 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php @@ -86,7 +86,7 @@ class ImportBankStatementLogic extends AbstractControllerLogic $account->statements()->save($statement); - CreateBankStatementTransactionOwners::dispatch($statement); +// CreateBankStatementTransactionOwners::dispatch($statement); $sheet->map(function ($row) use ($statement, $account) { diff --git a/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php index f29bd627..e9a14323 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/UpdateBankStatementDetailLogic.php @@ -3,15 +3,20 @@ namespace App\Classes\Modules\Accounting\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Accounting\Services\UpdatesBankStatementDetails; use App\Classes\Modules\Accounting\Services\FetchesBankStatementDetails; -use App\Classes\Modules\Accounting\Standards\Rules\CanUpdateCompany; -use App\Classes\Modules\Accounting\DataTransferObjects\BankStatementDetailObject; -use App\Http\Resources\BankStatementDetailResource; +use App\Classes\Modules\Accounting\Services\CreatesBankStatementTransactionOwner; +use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction; +use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; +use App\Classes\ValueObjects\Constants\SystemType; +use App\Classes\Modules\Accounting\Processors\ChecksBillNumber; +use App\Models\Transaction; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use ErrorException; +use Illuminate\Support\Facades\Log; class UpdateBankStatementDetailLogic extends AbstractControllerLogic { @@ -35,15 +40,30 @@ class UpdateBankStatementDetailLogic extends AbstractControllerLogic /** @var FetchesBankStatementDetails */ private $fetchesBankStatementDetails; + /** @var FetchesBankStatementTransaction */ + private $fetchesBankStatementTransaction; + + /** @var CreatesBankStatementTransactionOwner */ + private $createsBankStatementTransactionOwner; + + /** @var ChecksBillNumber */ + private $checksBillNumber; + /** * UpdateBankStatementDetailLogic constructor. * @param UpdatesBankStatementDetails $updatesBankStatementDetails * @param FetchesBankStatementDetails $fetchesBankStatementDetails + * @param fetchesBankStatementTransaction $fetchesBankStatementTransaction + * @param CreatesBankStatementTransactionOwner $createsBankStatementTransactionOwner + * @param ChecksBillNumber $checksBillNumber */ - public function __construct(UpdatesBankStatementDetails $updatesBankStatementDetails, FetchesBankStatementDetails $fetchesBankStatementDetails) + public function __construct(UpdatesBankStatementDetails $updatesBankStatementDetails, FetchesBankStatementDetails $fetchesBankStatementDetails, FetchesBankStatementTransaction $fetchesBankStatementTransaction, CreatesBankStatementTransactionOwner $createsBankStatementTransactionOwner, ChecksBillNumber $checksBillNumber) { $this->updatesBankStatementDetails = $updatesBankStatementDetails; $this->fetchesBankStatementDetails = $fetchesBankStatementDetails; + $this->fetchesBankStatementTransaction = $fetchesBankStatementTransaction; + $this->createsBankStatementTransactionOwner = $createsBankStatementTransactionOwner; + $this->checksBillNumber = $checksBillNumber; } @@ -52,15 +72,144 @@ class UpdateBankStatementDetailLogic extends AbstractControllerLogic * @return JsonResponse * @throws ErrorException */ - public function logic(Request $request) : JsonResponse + public function logic(Request $request): JsonResponse { - $object = new BankStatementDetailObject($request->input('pay_for'), $request->input('system_references')); + $bankStatementTransaction = $this->fetchesBankStatementTransaction->execute(['id' => $request->route('id')]); - $query = $this->fetchesBankStatementDetails->execute(['id' => $request->route('id')]); + $owner_type = null; + $owner_id = null; + $statementTransactionOwnerType = null; + $system = null; + $owner_reference = null; - $query = $this->updatesBankStatementDetails->execute($query, $object); + switch ($request->input('pay_for')) { + case 'sales': + if (in_array($request->input('system_references'), ['exchange', 'izyim'])) { + // $transaction = $this->verifyBillNumber($request->input('transaction_reference'), $request->input('system_references')); + $transaction = $this->checksBillNumber->execute($request->input('transaction_reference'), $request->input('system_references')); - return $this->resourceResponse(new BankStatementDetailResource($query)); + // todo-new: update / test on izyim system + + $owner_type = Transaction::class; + $owner_id = $transaction->id; + // todo-new: owner_reference + // booking number / order number + $owner_reference = null; + $statementTransactionOwnerType = StatementTransactionOwnerType::SALES; + $system = $request->input('system_references'); + } else { + + switch ($request->input('system_references')) { + case 'lite': + $statementTransactionOwnerType = StatementTransactionOwnerType::SALES_LITE; + break; + case 'cntr': + $statementTransactionOwnerType = StatementTransactionOwnerType::SALES_CNTR; + break; + case 'probashi': + $statementTransactionOwnerType = StatementTransactionOwnerType::SALES_PROBASHI; + break; + case 'pets': + $statementTransactionOwnerType = StatementTransactionOwnerType::SALES_PETS; + break; + default: + throw new MalformedRequestException('System Reference not allowed'); + } + } + break; + + case 'top_up': + + // $transaction = $this->verifyBillNumber($request->input('transaction_reference'), $request->input('system_references')); + $transaction = $this->checksBillNumber->execute($request->input('transaction_reference'), $request->input('system_references')); + + $owner_type = Transaction::class; + $owner_id = $transaction->id; + // todo-new: owner_reference + // top_up - store customer marking + $owner_reference = null; + $statementTransactionOwnerType = StatementTransactionOwnerType::WALLET_TOP_UP; + $system = $request->input('system_references'); + break; + + case 'internal_bank_transfer': + $statementTransactionOwnerType = StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_IN; // if negative -> out, positive -> in + $system = $request->input('system_references'); + break; + + case 'others': + $owner_reference = $request->input('transaction_reference'); + $statementTransactionOwnerType = StatementTransactionOwnerType::NON_OPERATIONAL; + $system = $request->input('system_references'); + break; + + default: + throw new MalformedRequestException('Transaction Type Not Allowed'); + } + + $system == null ? '' : $system = SystemType::SYSTEM_NAMES[$system]; + + dd([ + 'type' => $statementTransactionOwnerType, + 'system' => $system, + // 'owner_type' => Transaction::class, + // todo-new: make sure owner_type is a class + 'owner_type' => $owner_type, + 'owner_id' => $owner_id, + 'owner_reference' => $owner_reference + ]); + + $bankStatementTransaction->owners()->firstOrCreate([ + 'type' => $statementTransactionOwnerType, + 'system' => $system, + // 'owner_type' => Transaction::class, + // todo-new: make sure owner_type is a class + 'owner_type' => $owner_type, + 'owner_id' => $owner_id, + 'owner_reference' => $owner_reference + ]); + + dd($bankStatementTransaction->owners()->first()); + + // $this->canCreateUser->passes($user_object); + + // $user = $this->createsBankStatementTransactionOwner->execute($bankStatementTransactionObject); + + // return $this->resourceResponse(new BankStatementDetailResource($query)); } + // public function verifyBillNumber($bill_no, $system_reference) + // { + // if ($system_reference == 'izyim') { + // try { + // $url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/query'; + // $client = new \GuzzleHttp\Client(['verify' => false]); + // $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"bill_no":' . $bill_no . '}'); + // $body = $response->getBody(); + // $data = json_decode($body, true); + // dd($data); + // $payload = $data['payload']; + // $transactions2 = $payload['data']; + // dd($transactions2); + // return $transactions2; + // } catch (\Exception $exception) { + // Log::error($exception); + // dd($exception); + // preg_match('/\{.*\}/s', $exception->getMessage(), $matches); + // $jsonError = json_decode($matches[0]); + // // Retrieved Transactions failed + // throw new MalformedRequestException($jsonError->title); + // } + // } + + // if ($system_reference == 'exchange') { + // $transaction = Transaction::where('bill_no', $bill_no)->first(); + // if ($transaction) { + // return $transaction; + // } + // } + + // // if not found + // throw new MalformedRequestException('Bill Number Not Found.'); + // } } diff --git a/app/Classes/Modules/Accounting/Processors/ChecksBillNumber.php b/app/Classes/Modules/Accounting/Processors/ChecksBillNumber.php new file mode 100644 index 00000000..ddaa55c3 --- /dev/null +++ b/app/Classes/Modules/Accounting/Processors/ChecksBillNumber.php @@ -0,0 +1,45 @@ + false]); + $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"bill_no":' . $bill_no . '}'); + $body = $response->getBody(); + $data = json_decode($body, true); + dd($data); + $payload = $data['payload']; + $transactions2 = $payload['data']; + dd($transactions2); + return $transactions2; + } catch (\Exception $exception) { + Log::error($exception); + dd($exception); + preg_match('/\{.*\}/s', $exception->getMessage(), $matches); + $jsonError = json_decode($matches[0]); + // Retrieved Transactions failed + throw new MalformedRequestException($jsonError->title); + } + } + + if ($system_reference == 'exchange') { + $transaction = Transaction::where('bill_no', $bill_no)->first(); + if ($transaction) { + return $transaction; + } + } + + // if not found + throw new MalformedRequestException('Bill Number Not Found.'); + } +} diff --git a/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php b/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php index da701af0..0c126c5f 100644 --- a/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php +++ b/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php @@ -2,22 +2,18 @@ namespace App\Classes\Modules\Accounting\Processors; -use App\Classes\Exceptions\MalformedRequestException; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; use App\Classes\ValueObjects\Constants\TransactionType; -use App\Models\AccountStatement; use App\Models\Booking; use App\Models\Company; use App\Models\Group; use App\Models\StatementTransaction; -use App\Models\StatementTransactionOwner; use App\Models\Transaction; use App\Models\Wallet; use Carbon\Carbon; use Illuminate\Support\Facades\Log; -use DateTime; class CreateBankStatementTransactionOwnersProcessor { @@ -29,7 +25,7 @@ class CreateBankStatementTransactionOwnersProcessor $transactions = StatementTransaction::whereDoesntHave('owners', function($query){ return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - })->get(); + })->orderBy('posting_date')->get(); // $transactions = StatementTransaction::whereDoesntHave('owners')->where('amount', '<', 0)->get(); @@ -40,8 +36,6 @@ class CreateBankStatementTransactionOwnersProcessor // Exchange Sales $creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); foreach ($creditTransactions as $creditTransaction) { - dd($creditTransaction->owner); - $transaction->owners()->firstOrCreate([ 'type' => StatementTransactionOwnerType::SALES, 'system' => 'EXCHANGE', @@ -117,7 +111,7 @@ class CreateBankStatementTransactionOwnersProcessor 'system' => 'EXCHANGE', 'owner_type' => Group::class, 'owner_id'=> $debitTransaction->id, - 'owner_reference'=> $debitTransaction->bill_no + 'owner_reference'=> $debitTransaction->reference ]); } diff --git a/app/Classes/Modules/Accounting/Services/CreatesBankStatementTransactionOwner.php b/app/Classes/Modules/Accounting/Services/CreatesBankStatementTransactionOwner.php new file mode 100644 index 00000000..92a3ea33 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/CreatesBankStatementTransactionOwner.php @@ -0,0 +1,34 @@ +statement_transaction_id = $object->getStatementTransactionId(); + $model->type = $object->getType(); + $model->system = $object->getSystem(); + $model->owner_type = $object->getOwnerType(); + $model->owner_id = $object->getOwnerId(); + $model->invoice_reference = $object->getInvoiceReference(); + $model->receipt_reference = $object->getReceipteReference(); + $model->is_auto_mapped = $object->getIsAutoMapped(); + $model->status = $object->getStatus(); + + return $this->handler($model); + } +} diff --git a/app/Classes/ValueObjects/Constants/StatementTransactionOwnerType.php b/app/Classes/ValueObjects/Constants/StatementTransactionOwnerType.php index 24d31516..58d89c78 100644 --- a/app/Classes/ValueObjects/Constants/StatementTransactionOwnerType.php +++ b/app/Classes/ValueObjects/Constants/StatementTransactionOwnerType.php @@ -34,4 +34,12 @@ final class StatementTransactionOwnerType { public const NON_OPERATIONAL = 14; + public const SALES_LITE = 15; + + public const SALES_CNTR = 16; + + public const SALES_PROBASHI = 17; + + public const SALES_PETS = 18; + } diff --git a/app/Classes/ValueObjects/Constants/SystemType.php b/app/Classes/ValueObjects/Constants/SystemType.php new file mode 100644 index 00000000..dd948f13 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/SystemType.php @@ -0,0 +1,16 @@ + self::EXCHANGE, + 'shipping_portal' => self::SHIPPING_PORTAL, + 'izyim' => self::SHIPPING_PORTAL, + ]; +} diff --git a/app/Http/Controllers/Imports/ImportStatementInvoiceController.php b/app/Http/Controllers/Imports/ImportStatementInvoiceController.php new file mode 100644 index 00000000..a59f9463 --- /dev/null +++ b/app/Http/Controllers/Imports/ImportStatementInvoiceController.php @@ -0,0 +1,99 @@ +input('files'), '', ApprovalStatus::APPROVED, 'imports'); + $file = json_decode($object->getFiles()[0])->file_info->original->file; + + $import = new GenericImport(); + Excel::import($import, $file); + $excelRows = $import->rows; + $excelRows = $excelRows->toArray(); + + foreach ($excelRows as $row) { + dd($row); + // $row['debtor_code'] + + // attempt 1 - try map by amount and date + // $transactionDate = $this->changeExcelDate($row['date']); + // $transaction = Transaction::where('original_amount', $row['total'])->whereDate('created_at', $transactionDate)->get(); + // if ($transaction) { + // // check company + // // $company = Company::where('debtor', $row['debtor_code'])->first(); + // // dd($company); + // // try to verify is it the correct transaction + // } + + // Shipping Info + // TOPUP -> map with transaction.bill_no + if (str_starts_with($row['shipping_info'], 'TOPUP')) { + // find in exchange first, if cannont then find in izyim + // (App()->make(ChecksBillNumber::class))->execute($bill_no, 'exchange'); + } + + // if 5 digits -> exchange booking reference + // find transation + // find statement_transaction_owners, and fill up the details + + // if <5 digits, find the transaction id (order number in izyim), find the payment in izyim + // find transation + // find statement_transaction_owners, and fill up the details + + // dd([ + // 'type' => $statementTransactionOwnerType, + // 'system' => $system, + // // 'owner_type' => Transaction::class, + // // todo-new: make sure owner_type is a class + // 'owner_type' => $owner_type, + // 'owner_id' => $owner_id, + // 'owner_reference' => $owner_reference + // ]); + + // $bankStatementTransaction->owners()->firstOrCreate([ + // 'type' => $statementTransactionOwnerType, + // 'system' => $system, + // // 'owner_type' => Transaction::class, + // // todo-new: make sure owner_type is a class + // 'owner_type' => $owner_type, + // 'owner_id' => $owner_id, + // 'owner_reference' => $owner_reference + // ]); + + + } + } + + public function changeExcelDate($date) + { + $unixTime = (($date - 25569) * 86400); + $date = new DateTime("@$unixTime"); + return $date->format('Y-m-d'); // Change the format to 'Y-m-d' + } +} diff --git a/app/Http/Controllers/Imports/ImportStatementReceiptsController.php b/app/Http/Controllers/Imports/ImportStatementReceiptsController.php new file mode 100644 index 00000000..22111881 --- /dev/null +++ b/app/Http/Controllers/Imports/ImportStatementReceiptsController.php @@ -0,0 +1,50 @@ +input('files'), '', ApprovalStatus::APPROVED, 'imports'); + $file = json_decode($object->getFiles()[0])->file_info->original->file; + + $import = new GenericImport(); + Excel::import($import, $file); + $excelRows = $import->rows; + $excelRows = $excelRows->toArray(); + + foreach ($excelRows as $row) { + // if has date column + // $transactionDate = $this->changeExcelDate($row['date']); + } + } + + public function changeExcelDate($date) + { + $unixTime = (($date - 25569) * 86400); + $date = new DateTime("@$unixTime"); + return $date->format('Y-m-d'); // Change the format to 'Y-m-d' + } +} diff --git a/app/Http/Resources/BankStatementTransactionOwnerResource.php b/app/Http/Resources/BankStatementTransactionOwnerResource.php index 0066eafa..468d9ec5 100644 --- a/app/Http/Resources/BankStatementTransactionOwnerResource.php +++ b/app/Http/Resources/BankStatementTransactionOwnerResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; use App\Models\Booking; use App\Models\Group; use App\Models\Transaction; @@ -18,34 +19,28 @@ class BankStatementTransactionOwnerResource extends JsonResource */ public function toArray($request) { - $reference = null; + $referenceLink = null; if($this->system === 'EXCHANGE') { if($this->owner_type === Transaction::class){ - $transaction = Transaction::find($this->owner_id); - - if($transaction->owner_type === Booking::class){ - $reference = $transaction->owner->marking; - $referenceLink = route('booking.details', $transaction->owner->marking); + if($this->type === StatementTransactionOwnerType::SALES){ + $referenceLink = route('booking.details', $this->owner_reference); } - if($transaction->owner_type === Wallet::class) { - $reference = $transaction->owner->owner->reference; - $referenceLink = route('wallet.details', $transaction->owner->owner->reference); + if($this->type === StatementTransactionOwnerType::WALLET_TOP_UP){ + $referenceLink = route('booking.details', $this->owner_reference); } } - - if($this->owner_type === Group::class){ - $transaction = Group::find($this->owner_id); - $reference = $transaction->reference; -// $referenceLink = route('booking.details', $transaction->owner->marking); - } } if($this->system === 'SHIPPING_PORTAL') { if($this->owner_type === Transaction::class){ - $transaction = Transaction::find($this->owner_id); - + if($this->type === StatementTransactionOwnerType::SALES){ + $referenceLink = 'https://izyim.cief-malaysia.com/order/show/'. $this->owner_reference; + } + if($this->type === StatementTransactionOwnerType::WALLET_TOP_UP){ + $referenceLink = 'https://izyim.cief-malaysia.com/wallet/'. $this->owner_reference .'/details'; + } } } @@ -55,8 +50,8 @@ class BankStatementTransactionOwnerResource extends JsonResource 'system' => $this->system, 'owner_type' => $this->owner_type, 'owner_id' => $this->owner_id, + 'reference' => $this->owner_reference, 'reference_link' => $referenceLink, - 'reference' => $reference, 'invoice_reference' => $this->invoice_reference, 'receipt_reference' => $this->receipt_reference, 'status' => $this->status diff --git a/app/Http/Resources/BankStatementTransactionResource.php b/app/Http/Resources/BankStatementTransactionResource.php index 09768f51..993b8c93 100644 --- a/app/Http/Resources/BankStatementTransactionResource.php +++ b/app/Http/Resources/BankStatementTransactionResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use Illuminate\Http\Resources\Json\JsonResource; class BankStatementTransactionResource extends JsonResource @@ -30,7 +31,11 @@ class BankStatementTransactionResource extends JsonResource 'transaction_description_3' => $this->transaction_description_3, 'transaction_description_4' => $this->transaction_description_4, 'transaction_description_5' => $this->transaction_description_5, - 'owners' => BankStatementTransactionOwnerResource::collection($this->owners) + 'owners' => [ + 'approved' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::APPROVED])->get()), + 'pending_verification' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->get()), + 'rejected' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::REJECTED])->get()) + ] ]; } } diff --git a/database/migrations/2023_04_07_212512_create_statement_transaction_owners_table.php b/database/migrations/2023_04_07_212512_create_statement_transaction_owners_table.php index 2ac51506..5d22c520 100644 --- a/database/migrations/2023_04_07_212512_create_statement_transaction_owners_table.php +++ b/database/migrations/2023_04_07_212512_create_statement_transaction_owners_table.php @@ -22,7 +22,7 @@ class CreateStatementTransactionOwnersTable extends Migration $table->string('system')->nullable(); $table->string('owner_type')->nullable(); $table->bigInteger('owner_id')->nullable(); - $table->bigInteger('owner_reference')->nullable(); + $table->string('owner_reference')->nullable(); $table->string('invoice_reference')->nullable(); $table->string('receipt_reference')->nullable(); $table->string('is_auto_mapped')->default(false); diff --git a/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue index b160eeac..ed3f8388 100644 --- a/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue +++ b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue @@ -1,44 +1,68 @@