create Transaction & Transaction Detail

- Supplier (AP)
	- PO
	- DO
	- INV

- Customer (AR)
	- PO
	- DO
	- INV
This commit is contained in:
weiken.intex
2020-12-07 14:00:24 +08:00
parent 3eef8cff25
commit 9ed67e74e2
19 changed files with 987 additions and 0 deletions
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Company;
class FetchesCompany extends AbstractFetchRecord
{
/** @var Company */
private $repository;
/**
* FetchesUser constructor.
* @param Currency $repository
*/
public function __construct(Company $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,147 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Standards\Rules\CanCreateTransaction;
use App\Classes\Modules\Transactions\Standards\Rules\CanCreateTransactionDetail;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNo;
use App\Http\Resources\TransactionResource;
use App\Http\Resources\TransactionDetailResource;
use App\Classes\Modules\Currencies\Services\FetchesCurrency;
use App\Classes\Modules\Currencies\Services\RateCalculatesCurrency;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class CreateTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Created Transaction',
'message' => 'You have successfully created a transaction'
];
}
/** @var GeneratesTransactionBillNo */
private $generatesTransactionBillNo;
/** @var CanCreateTransaction */
private $canCreateTransaction;
private $fetchesCurrency;
private $rateCalculatesCurrency;
private $fetchesCompany;
private $createsTransaction;
private $canCreateTransactionDetail;
private $createsTransactionDetail;
/**
* CreateWalletLogic constructor.
* @param CreatesWallet $createsWallet
* @param GeneratesWalletCode $generatesWalletCode
* @param CanCreateCompanyWallet $canCreateCompanyWallet
*/
public function __construct(
GeneratesTransactionBillNo $generatesTransactionBillNo, CanCreateTransaction $canCreateTransaction,
FetchesCurrency $fetchesCurrency,RateCalculatesCurrency $rateCalculatesCurrency, FetchesCompany $fetchesCompany,
CreatesTransaction $createsTransaction,
CanCreateTransactionDetail $canCreateTransactionDetail, CreatesTransactionDetail $createsTransactionDetail
){
$this->generatesTransactionBillNo = $generatesTransactionBillNo;
$this->canCreateTransaction = $canCreateTransaction;
$this->fetchesCurrency = $fetchesCurrency;
$this->rateCalculatesCurrency = $rateCalculatesCurrency;
$this->fetchesCompany = $fetchesCompany;
$this->createsTransaction =$createsTransaction;
$this->canCreateTransactionDetail =$canCreateTransactionDetail;
$this->createsTransactionDetail = $createsTransactionDetail;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
DB::beginTransaction();
$json_array = json_decode($request->getContent(), true);
$company = $this->fetchesCompany->execute(['id' => $json_array['company_id']]);
$conversion_currency = $this->fetchesCurrency->execute(['id' => $json_array['currency_id']]);
$convertable_currency = $this->fetchesCurrency->execute(['id' => 1]);//MYR
$convert_amount = $this->rateCalculatesCurrency->execute($conversion_currency, $convertable_currency, $json_array['amount']);
$convert_rate = $this->rateCalculatesCurrency->execute_rate($conversion_currency, $convertable_currency);
/*
int $bill_no,string $trans_type1,string $trans_type2,
float $amount, int $currency_id, int $original_amount,
int $original_currency_id, float $currency_rate,
string $dt_transaction,int $status,int $booking_id,
int $company_id
*/
$object = new TransactionObject(
$this->generatesTransactionBillNo->execute(),$json_array['trans_type1'],$json_array['trans_type2'],
number_format( (float) $convert_amount, 5, '.', ''), 1 , number_format( (float) $json_array['amount'], 5, '.', ''),
$json_array['currency_id'],number_format( (float) $convert_rate, 5, '.', ''),
$json_array['dt_transaction'],1,$request->route('id'),
$company->id
);
$this->canCreateTransaction->passes($object);
$transaction = $this->createsTransaction->execute($object);
$transaction_array = new TransactionResource($transaction);
$transaction_detail_array = array();
foreach ($json_array['transaction_detail'] as $key => $value) {
$object_detail = new TransactionDetailObject(
$json_array['trans_type1'],$json_array['trans_type2'],
$transaction->id,$value['product_code'],$value['product_name'],
(int)$value['qty'],number_format( (float) $convert_amount, 5, '.', ''), number_format( (float) $json_array['amount'], 5, '.', '')
);
$this->canCreateTransactionDetail->passes($object_detail);
$transaction_detail = $this->createsTransactionDetail->execute($object_detail);
//array_push($stack, "apple", "raspberry");
$transaction_detail_resource= new TransactionDetailResource($transaction_detail);
$transaction_detail_array[]= $transaction_detail_resource->toArray($request);
}
//$transaction_array['transaction_detail']= $transaction_detail_array;
//print_r($transaction_detail_array);
//dd($transaction_detail_array);
DB::commit();
return $this->resourceResponse($transaction_array);
//return $this->resourceResponse($json_array);
} catch (\Exception $exception) {
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,113 @@
<?php
namespace App\Classes\Modules\Transactions\DataTransferObjects;
use App\Classes\Interfaces\DataTransferObject;
class TransactionDetailObject implements DataTransferObject
{
/*
*
* $table->string('trans_type1');
$table->string('trans_type2');
$table->bigInteger('transaction_id')->unsigned();
$table->string('product_code');
$table->string('product_name');
$table->integer('qty')->default(0);
$table->decimal('price', 14, 5)->default(0.00);
$table->decimal('amount', 14, 5)->default(0.00);
*/
private $trans_type1;
private $trans_type2;
private $transaction_id;
private $product_code;
private $product_name;
private $qty;
private $price;
private $amount;
public function __construct(
string $trans_type1,string $trans_type2,
int $transaction_id, string $product_code, $product_name,
int $qty, float $price,float $amount
){
$this->trans_type1= $trans_type1;
$this->trans_type2 = $trans_type2;
$this->transaction_id = $transaction_id;
$this->product_code = $product_code;
$this->product_name = $product_name;
$this->qty = $qty;
$this->price = $price;
$this->amount = $amount;
}
/**
* @return string
*/
public function getTransType1(): string
{
return $this->trans_type1;
}
/**
* @return string
*/
public function getTransType2(): string
{
return $this->trans_type2;
}
/**
* @return int
*/
public function getTransactionId(): int
{
return $this->transaction_id;
}
/**
* @return string
*/
public function getProductCode(): string
{
return $this->product_code;
}
/**
* @return string
*/
public function getProductName(): string
{
return $this->product_name;
}
/**
* @return int
*/
public function getQty(): int
{
return $this->qty;
}
public function getPrice(): float
{
return $this->price;
}
public function getAmount(): float
{
return $this->amount;
}
}
@@ -0,0 +1,150 @@
<?php
namespace App\Classes\Modules\Transactions\DataTransferObjects;
use App\Classes\Interfaces\DataTransferObject;
class TransactionObject implements DataTransferObject
{
/*
*
* return [
'id' => $this->id,
'trans_type1' => $this->trans_type1,
'trans_type2' => $this->trans_type2,
'bill_no' => (int) $this->bill_no,
'amount' => (double) $this->amount,
'currency_id' => (int) $this->currency_id,
'original_amount' => (double) $this->original_amount,
'original_currency_id' => (int) $this->original_currency_id,
'currency_rate' => (double) $this->currency_rate,
'dt_transaction' => $this->dt_transaction,
'status' => (int) $this->status,
'booking_id' => (int) $this->booking_id,
'company_id' => (int) $this->company_id
];
*/
private $trans_type1;
private $trans_type2;
private $bill_no;
private $amount;
private $currency_id;
private $original_amount;
private $original_currency_id;
private $currency_rate;
private $dt_transaction;
private $status;
private $booking_id;
private $company_id;
public function __construct(
int $bill_no,string $trans_type1,string $trans_type2,
float $amount, int $currency_id, int $original_amount,
int $original_currency_id, float $currency_rate,
string $dt_transaction,int $status,int $booking_id,
int $company_id
){
$this->bill_no = $bill_no;
$this->trans_type1= $trans_type1;
$this->trans_type2 = $trans_type2;
$this->amount= $amount;
$this->currency_id = $currency_id;
$this->original_amount = $original_amount;
$this->original_currency_id = $original_currency_id;
$this->currency_rate = $currency_rate;
$this->dt_transaction = $dt_transaction;
$this->status = $status;
$this->booking_id = $booking_id;
$this->company_id = $company_id;
}
/**
* @return int
*/
public function getBillNo(): int
{
return $this->bill_no;
}
/**
* @return string
*/
public function getTransType1(): string
{
return $this->trans_type1;
}
/**
* @return string
*/
public function getTransType2(): string
{
return $this->trans_type2;
}
public function getAmount(): float
{
return $this->amount;
}
/**
* @return int
*/
public function getCurrency(): int
{
return $this->currency_id;
}
public function getOriginalAmount(): float
{
return $this->original_amount;
}
public function getOriginalCurrency(): int
{
return $this->original_currency_id;
}
public function getCurrencyRate(): float
{
return $this->currency_rate;
}
/**
* @return string
*/
public function getDtTransaction(): string
{
return $this->dt_transaction;
}
public function getStatus(): int
{
return $this->original_currency_id;
}
public function getBookingId(): int
{
return $this->booking_id;
}
public function getCompanyId(): int
{
return $this->company_id;
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use App\Models\Transaction;
class ChecksIfTransactionBillNoExists
{
private $repository;
public function __construct(Transaction $repository)
{
$this->repository = $repository;
}
public function execute(int $bill_no): bool {
return $this->repository->where('bill_no', $bill_no)->exists();
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Models\Transaction;
class CreatesTransaction extends AbstractUpdateRecord
{
/**
* @param WalletObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(TransactionObject $object) {
$model = new Transaction();
$model->bill_no = $object->getBillNo();
$model->trans_type1 = $object->getTransType1();
$model->trans_type2 = $object->getTransType2();
$model->amount = $object->getAmount();
$model->currency_id = $object->getCurrency();
$model->original_amount = $object->getOriginalAmount();
$model->original_currency_id = $object->getOriginalCurrency();
$model->currency_rate = $object->getCurrencyRate();
$model->dt_transaction = $object->getDtTransaction();
$model->status = $object->getStatus();
$model->booking_id = $object->getBookingId();
$model->company_id = $object->getCompanyId();
return $this->handler($model);
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Models\TransactionDetail;
class CreatesTransactionDetail extends AbstractUpdateRecord
{
/**
* @param WalletObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(TransactionDetailObject $object) {
$model = new TransactionDetail();
$model->trans_type1 = $object->getTransType1();
$model->trans_type2 = $object->getTransType2();
$model->transaction_id = $object->getTransactionId();
$model->product_code = $object->getProductCode();
$model->product_name = $object->getProductName();
$model->qty = $object->getQty();
$model->price = $object->getPrice();
$model->amount = $object->getAmount();
return $this->handler($model);
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
class GeneratesTransactionBillNo
{
private $transationBillNoExists;
public function __construct(ChecksIfTransactionBillNoExists $transationBillNoExists)
{
$this->transationBillNoExists = $transationBillNoExists;
}
public function execute(): int {
$code = mt_rand(100000001, 999999999);
return !$this->transationBillNoExists->execute($code) ? $code : self::execute();
}
}
@@ -0,0 +1,50 @@
<?php
namespace App\Classes\Modules\Transactions\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Transactions\Standards\Validators\TransactionValidation;
class CanCreateTransaction extends AbstractRule
{
/** @var WalletTransactionValidation */
private $transactionValidation;
public function __construct(TransactionValidation $transactionValidation)
{
$this->transactionValidation = $transactionValidation;
}
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param CompanyWalletValidation $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->transactionValidation->validate($object);
}
/**
* @param SegmentCompanyValidation $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,50 @@
<?php
namespace App\Classes\Modules\Transactions\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Transactions\Standards\Validators\TransactionDetailValidation;
class CanCreateTransactionDetail extends AbstractRule
{
/** @var WalletTransactionValidation */
private $transactionDetailValidation;
public function __construct(TransactionDetailValidation $transactionDetailValidation)
{
$this->transactionDetailValidation = $transactionDetailValidation;
}
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param CompanyWalletValidation $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->transactionDetailValidation->validate($object);
}
/**
* @param SegmentCompanyValidation $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,63 @@
<?php
namespace App\Classes\Modules\Transactions\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
class TransactionDetailValidation extends AbstractValidation
{
/*
*
* $this->bill_no = $bill_no;
$this->trans_type1= $trans_type1;
$this->trans_type2 = $trans_type2;
$this->amount= $amount;
$this->currency_id = $currency_id;
$this->original_amount = $original_amount;
$this->original_currency_id = $original_currency_id;
$this->currency_rate = $currency_rate;
$this->dt_transaction = $dt_transaction;
$this->status = $status;
$this->booking_id = $booking_id;
$this->company_id = $company_id;
*/
protected function data($object): array
{
return [
'trans_type1' => $object->getTransType1(),
'trans_type2' => $object->getTransType2(),
'transaction_id' => $object->getTransactionId(),
'product_code' => $object->getProductCode(),
'product_name'=>$object->getProductName(),
'qty'=>$object->getQty(),
'price'=>$object->getPrice(),
'amount' => $object->getAmount()
];
}
/**
* @return array
*/
protected function rules(): array
{
return [
'trans_type1' => 'required',
'trans_type2' => 'required',
'transaction_id' => 'required',
'product_code' => 'required',
'product_name'=>'required',
'qty'=>'required',
'price'=>'required',
'amount' => 'required'
];
}
/**
* @return array
*/
protected function messages(): array
{
return [];
}
}
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\Transactions\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
class TransactionValidation extends AbstractValidation
{
/*
*
* $this->bill_no = $bill_no;
$this->trans_type1= $trans_type1;
$this->trans_type2 = $trans_type2;
$this->amount= $amount;
$this->currency_id = $currency_id;
$this->original_amount = $original_amount;
$this->original_currency_id = $original_currency_id;
$this->currency_rate = $currency_rate;
$this->dt_transaction = $dt_transaction;
$this->status = $status;
$this->booking_id = $booking_id;
$this->company_id = $company_id;
*/
protected function data($object): array
{
return [
'bill_no' => $object->getBillNo(),
'trans_type1' => $object->getBillNo(),
'trans_type2' => $object->getTransType2(),
'amount' => $object->getAmount(),
'currency_id' => $object->getCurrency(),
'original_amount' => $object->getOriginalAmount(),
'original_currency_id'=>$object->getOriginalCurrency(),
'dt_transaction'=>$object->getDtTransaction(),
'status'=>$object->getStatus(),
'booking_id'=>$object->getBookingId(),
'company_id'=>$object->getCompanyId()
];
}
/**
* @return array
*/
protected function rules(): array
{
return [
'bill_no' => 'required',
'trans_type1' => 'required',
'trans_type2' => 'required',
'amount' => 'required',
'currency_id' => 'required',
'original_amount' => 'required',
'original_currency_id'=>'required',
'dt_transaction'=>'required',
'status'=>'required',
'booking_id'=>'required',
'company_id'=>'required'
];
}
/**
* @return array
*/
protected function messages(): array
{
return [];
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\CreateTransactionLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateTransactionController
{
public function create(Request $request, CreateTransactionLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class TransactionDetailResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'trans_type1' => $this->trans_type1,
'trans_type2' => $this->trans_type2,
'transaction_id' => (int) $this->transaction_id,
'product_code' => $this->product_code,
'product_name' => $this->product_name,
'qty' => (int) $this->qty,
'price' => (double) $this->price,
'amount' => (double) $this->amount
];
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class TransactionResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'trans_type1' => $this->trans_type1,
'trans_type2' => $this->trans_type2,
'bill_no' => (int) $this->bill_no,
'amount' => (double) $this->amount,
'currency_id' => (int) $this->currency_id,
'original_amount' => (double) $this->original_amount,
'original_currency_id' => (int) $this->original_currency_id,
'currency_rate' => (double) $this->currency_rate,
'dt_transaction' => $this->dt_transaction,
'status' => (int) $this->status,
'booking_id' => (int) $this->booking_id,
'company_id' => (int) $this->company_id
];
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Transaction extends AbstractModel
{
protected $table = 'transaction';
public function company(): HasOne
{
return $this->hasOne(Companies::class, 'company_id', 'id');
}
public function currency(): HasOne
{
return $this->hasOne(Currency::class, 'currency_id', 'id');
}
public function original_currency(): HasOne
{
return $this->hasOne(Currency::class, 'original_currency_id', 'id');
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\HasOne;
class TransactionDetail extends AbstractModel
{
protected $table = 'transaction_detail';
public function transaction(): HasOne
{
return $this->hasOne(Transaction::class, 'transaction_id', 'id');
}
}
@@ -0,0 +1,63 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTransactionTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('transaction', function (Blueprint $table) {
$table->id();
$table->string('trans_type1');
$table->string('trans_type2');
$table->bigInteger('bill_no')->unsigned();
$table->decimal('amount', 14, 5)->default(0.00);
$table->decimal('original_amount', 14, 5)->default(0.00);
$table->bigInteger('currency_id')->unsigned();
$table->bigInteger('original_currency_id')->unsigned();
$table->decimal('currency_rate', 14, 5)->default(0.00);
$table->date('dt_transaction');
$table->integer('status');
$table->bigInteger('booking_id')->unsigned();
$table->bigInteger('company_id')->unsigned();
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->foreign('currency_id')->references('id')->on('currencies')->onDelete('cascade');
$table->foreign('original_currency_id')->references('id')->on('currencies')->onDelete('cascade');
});
Schema::create('transaction_detail', function (Blueprint $table) {
$table->id();
$table->string('trans_type1');
$table->string('trans_type2');
$table->bigInteger('transaction_id')->unsigned();
$table->string('product_code');
$table->string('product_name');
$table->integer('qty')->default(0);
$table->decimal('price', 14, 5)->default(0.00);
$table->decimal('amount', 14, 5)->default(0.00);
$table->timestamps();
$table->foreign('transaction_id')->references('id')->on('transaction')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('transaction');
Schema::dropIfExists('transaction_detail');
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => 'transaction.'], function () {
Route::post('/create/{id}', 'CreateTransactionController@create')->name('create');
//Route::post('/create-transaction/{id}', 'CreateWalletTransactionController@create')->name('create_transaction');
});