Merge pull request #1627 from burakcakirel/import-export-transfers
Import export for Transfers
This commit is contained in:
commit
5fca662685
@ -5,6 +5,7 @@ namespace App\BulkActions\Banking;
|
|||||||
use App\Abstracts\BulkAction;
|
use App\Abstracts\BulkAction;
|
||||||
use App\Jobs\Banking\DeleteTransfer;
|
use App\Jobs\Banking\DeleteTransfer;
|
||||||
use App\Models\Banking\Transfer;
|
use App\Models\Banking\Transfer;
|
||||||
|
use App\Exports\Banking\Transfers as Export;
|
||||||
|
|
||||||
class Transfers extends BulkAction
|
class Transfers extends BulkAction
|
||||||
{
|
{
|
||||||
@ -16,6 +17,11 @@ class Transfers extends BulkAction
|
|||||||
'message' => 'bulk_actions.message.delete',
|
'message' => 'bulk_actions.message.delete',
|
||||||
'permission' => 'delete-banking-transfers',
|
'permission' => 'delete-banking-transfers',
|
||||||
],
|
],
|
||||||
|
'export' => [
|
||||||
|
'name' => 'general.export',
|
||||||
|
'message' => 'bulk_actions.message.export',
|
||||||
|
'type' => 'download',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
public function destroy($request)
|
public function destroy($request)
|
||||||
@ -30,4 +36,11 @@ class Transfers extends BulkAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function export($request)
|
||||||
|
{
|
||||||
|
$selected = $this->getSelectedInput($request);
|
||||||
|
|
||||||
|
return \Excel::download(new Export($selected), \Str::filename(trans_choice('general.transfers', 2)) . '.xlsx');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
60
app/Exports/Banking/Transfers.php
Normal file
60
app/Exports/Banking/Transfers.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports\Banking;
|
||||||
|
|
||||||
|
use App\Abstracts\Export;
|
||||||
|
use App\Models\Banking\Transfer as Model;
|
||||||
|
use App\Utilities\Date;
|
||||||
|
|
||||||
|
class Transfers extends Export
|
||||||
|
{
|
||||||
|
public function collection()
|
||||||
|
{
|
||||||
|
$model = Model::with(
|
||||||
|
'expense_transaction',
|
||||||
|
'expense_transaction.account',
|
||||||
|
'income_transaction',
|
||||||
|
'income_transaction.account'
|
||||||
|
)->usingSearchString(request('search'));
|
||||||
|
|
||||||
|
if (!empty($this->ids)) {
|
||||||
|
$model->whereIn('id', (array) $this->ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model->cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($model): array
|
||||||
|
{
|
||||||
|
$model->transferred_at = Date::parse($model->expense_transaction->paid_at)->format('Y-m-d');
|
||||||
|
$model->amount = $model->expense_transaction->amount;
|
||||||
|
$model->from_account_name = $model->expense_transaction->account->name;
|
||||||
|
$model->from_currency_code = $model->expense_transaction->currency_code;
|
||||||
|
$model->from_currency_rate = $model->expense_transaction->currency_rate;
|
||||||
|
$model->to_account_name = $model->income_transaction->account->name;
|
||||||
|
$model->to_currency_code = $model->income_transaction->currency_code;
|
||||||
|
$model->to_currency_rate = $model->income_transaction->currency_rate;
|
||||||
|
$model->description = $model->income_transaction->description;
|
||||||
|
$model->payment_method = $model->income_transaction->payment_method;
|
||||||
|
$model->reference = $model->income_transaction->reference;
|
||||||
|
|
||||||
|
return parent::map($model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fields(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'transferred_at',
|
||||||
|
'amount',
|
||||||
|
'from_currency_code',
|
||||||
|
'from_currency_rate',
|
||||||
|
'from_account_name',
|
||||||
|
'to_currency_code',
|
||||||
|
'to_currency_rate',
|
||||||
|
'to_account_name',
|
||||||
|
'description',
|
||||||
|
'payment_method',
|
||||||
|
'reference',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,9 @@ namespace App\Http\Controllers\Banking;
|
|||||||
|
|
||||||
use App\Abstracts\Http\Controller;
|
use App\Abstracts\Http\Controller;
|
||||||
use App\Http\Requests\Banking\Transfer as Request;
|
use App\Http\Requests\Banking\Transfer as Request;
|
||||||
|
use App\Exports\Banking\Transfers as Export;
|
||||||
|
use App\Http\Requests\Common\Import as ImportRequest;
|
||||||
|
use App\Imports\Banking\Transfers as Import;
|
||||||
use App\Jobs\Banking\CreateTransfer;
|
use App\Jobs\Banking\CreateTransfer;
|
||||||
use App\Jobs\Banking\UpdateTransfer;
|
use App\Jobs\Banking\UpdateTransfer;
|
||||||
use App\Jobs\Banking\DeleteTransfer;
|
use App\Jobs\Banking\DeleteTransfer;
|
||||||
@ -218,4 +221,32 @@ class Transfers extends Controller
|
|||||||
|
|
||||||
return response()->json($response);
|
return response()->json($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import the specified resource.
|
||||||
|
*
|
||||||
|
* @param ImportRequest $request
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function import(ImportRequest $request)
|
||||||
|
{
|
||||||
|
\Excel::import(new Import(), $request->file('import'));
|
||||||
|
|
||||||
|
$message = trans('messages.success.imported', ['type' => trans_choice('general.transfers', 2)]);
|
||||||
|
|
||||||
|
flash($message)->success();
|
||||||
|
|
||||||
|
return redirect()->route('transfers.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export the specified resource.
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
return \Excel::download(new Export(), \Str::filename(trans_choice('general.transfers', 2)) . '.xlsx');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
118
app/Imports/Banking/Transfers.php
Normal file
118
app/Imports/Banking/Transfers.php
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Imports\Banking;
|
||||||
|
|
||||||
|
use App\Abstracts\Import;
|
||||||
|
use App\Models\Banking\Transaction;
|
||||||
|
use App\Models\Banking\Transfer as Model;
|
||||||
|
use App\Models\Setting\Category;
|
||||||
|
use App\Traits\Currencies;
|
||||||
|
|
||||||
|
class Transfers extends Import
|
||||||
|
{
|
||||||
|
use Currencies;
|
||||||
|
|
||||||
|
public function model(array $row)
|
||||||
|
{
|
||||||
|
return new Model($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($row): array
|
||||||
|
{
|
||||||
|
$row = parent::map($row);
|
||||||
|
|
||||||
|
$row['from_account_id'] = $this->getFromAccountId($row);
|
||||||
|
$row['to_account_id'] = $this->getToAccountId($row);
|
||||||
|
$row['expense_transaction_id'] = $this->getExpenseTransactionId($row);
|
||||||
|
$row['income_transaction_id'] = $this->getIncomeTransactionId($row);
|
||||||
|
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'from_account_id' => 'required|integer',
|
||||||
|
'from_currency_code' => 'required|string|currency',
|
||||||
|
'from_currency_rate' => 'required',
|
||||||
|
'to_account_id' => 'required|integer',
|
||||||
|
'to_currency_code' => 'required|string|currency',
|
||||||
|
'to_currency_rate' => 'required',
|
||||||
|
'amount' => 'required|amount',
|
||||||
|
'transferred_at' => 'required|date_format:Y-m-d',
|
||||||
|
'payment_method' => 'required|string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getExpenseTransactionId($row)
|
||||||
|
{
|
||||||
|
$expense_transaction = Transaction::create([
|
||||||
|
'company_id' => session('company_id'),
|
||||||
|
'type' => 'expense',
|
||||||
|
'account_id' => $row['from_account_id'],
|
||||||
|
'paid_at' => $row['transferred_at'],
|
||||||
|
'currency_code' => $row['from_currency_code'],
|
||||||
|
'currency_rate' => $row['from_currency_rate'],
|
||||||
|
'amount' => $row['amount'],
|
||||||
|
'contact_id' => 0,
|
||||||
|
'description' => $row['description'],
|
||||||
|
'category_id' => Category::transfer(), // Transfer Category ID
|
||||||
|
'payment_method' => $row['payment_method'],
|
||||||
|
'reference' => $row['reference'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $expense_transaction->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIncomeTransactionId($row)
|
||||||
|
{
|
||||||
|
$amount = $row['amount'];
|
||||||
|
// Convert amount if not same currency
|
||||||
|
if ($row['from_currency_code'] !== $row['to_currency_code']) {
|
||||||
|
$amount = $this->convertBetween(
|
||||||
|
$amount,
|
||||||
|
$row['from_currency_code'],
|
||||||
|
$row['from_currency_rate'],
|
||||||
|
$row['to_currency_code'],
|
||||||
|
$row['to_currency_rate']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$income_transaction = Transaction::create([
|
||||||
|
'company_id' => session('company_id'),
|
||||||
|
'type' => 'income',
|
||||||
|
'account_id' => $row['to_account_id'],
|
||||||
|
'paid_at' => $row['transferred_at'],
|
||||||
|
'currency_code' => $row['to_currency_code'],
|
||||||
|
'currency_rate' => $row['to_currency_rate'],
|
||||||
|
'amount' => $amount,
|
||||||
|
'contact_id' => 0,
|
||||||
|
'description' => $row['description'],
|
||||||
|
'category_id' => Category::transfer(), // Transfer Category ID
|
||||||
|
'payment_method' => $row['payment_method'],
|
||||||
|
'reference' => $row['reference'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $income_transaction->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFromAccountId($row)
|
||||||
|
{
|
||||||
|
$row['account_id'] = $row['from_account_id'] ?? null;
|
||||||
|
$row['account_name'] = $row['from_account_name'] ?? null;
|
||||||
|
$row['account_number'] = $row['from_account_number'] ?? null;
|
||||||
|
$row['currency_code'] = $row['from_currency_code'] ?? null;
|
||||||
|
|
||||||
|
return $this->getAccountId($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToAccountId($row)
|
||||||
|
{
|
||||||
|
$row['account_id'] = $row['to_account_id'] ?? null;
|
||||||
|
$row['account_name'] = $row['to_account_name'] ?? null;
|
||||||
|
$row['account_number'] = $row['to_account_number'] ?? null;
|
||||||
|
$row['currency_code'] = $row['to_currency_code'] ?? null;
|
||||||
|
|
||||||
|
return $this->getAccountId($row);
|
||||||
|
}
|
||||||
|
}
|
BIN
public/files/import/transfers.xlsx
Normal file
BIN
public/files/import/transfers.xlsx
Normal file
Binary file not shown.
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
@section('title', trans_choice('general.transfers', 2))
|
@section('title', trans_choice('general.transfers', 2))
|
||||||
|
|
||||||
@permission('create-banking-transfers')
|
@section('new_button')
|
||||||
@section('new_button')
|
@permission('create-banking-transfers')
|
||||||
<a href="{{ route('transfers.create') }}" class="btn btn-success btn-sm">{{ trans('general.add_new') }}</a>
|
<a href="{{ route('transfers.create') }}" class="btn btn-success btn-sm header-button-top"><span class="fa fa-plus"></span> {{ trans('general.add_new') }}</a>
|
||||||
@endsection
|
@endpermission
|
||||||
@endpermission
|
<span><a href="{{ route('import.create', ['banking', 'transfers']) }}" class="btn btn-white btn-sm header-button-top"><span class="fa fa-upload "></span> {{ trans('import.import') }}</a></span>
|
||||||
|
<span><a href="{{ route('transfers.export', request()->input()) }}" class="btn btn-white btn-sm header-button-top"><span class="fa fa-download"></span> {{ trans('general.export') }}</a></span>
|
||||||
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
@if ($transfers->count())
|
@if ($transfers->count())
|
||||||
|
@ -134,6 +134,8 @@ Route::group(['prefix' => 'banking'], function () {
|
|||||||
Route::get('transactions/export', 'Banking\Transactions@export')->name('transactions.export');
|
Route::get('transactions/export', 'Banking\Transactions@export')->name('transactions.export');
|
||||||
Route::resource('transactions', 'Banking\Transactions');
|
Route::resource('transactions', 'Banking\Transactions');
|
||||||
|
|
||||||
|
Route::post('transfers/import', 'Banking\Transfers@import')->name('transfers.import');
|
||||||
|
Route::get('transfers/export', 'Banking\Transfers@export')->name('transfers.export');
|
||||||
Route::resource('transfers', 'Banking\Transfers', ['middleware' => ['date.format', 'money']]);
|
Route::resource('transfers', 'Banking\Transfers', ['middleware' => ['date.format', 'money']]);
|
||||||
|
|
||||||
Route::post('reconciliations/calculate', 'Banking\Reconciliations@calculate')->middleware(['money']);
|
Route::post('reconciliations/calculate', 'Banking\Reconciliations@calculate')->middleware(['money']);
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
namespace Tests\Feature\Banking;
|
namespace Tests\Feature\Banking;
|
||||||
|
|
||||||
use App\Models\Banking\Account;
|
use App\Exports\Banking\Transfers as Export;
|
||||||
use Tests\Feature\FeatureTestCase;
|
|
||||||
use App\Jobs\Banking\CreateTransfer;
|
use App\Jobs\Banking\CreateTransfer;
|
||||||
|
use App\Models\Banking\Account;
|
||||||
|
use App\Models\Banking\Transfer;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
use Tests\Feature\FeatureTestCase;
|
||||||
|
|
||||||
class TransfersTest extends FeatureTestCase
|
class TransfersTest extends FeatureTestCase
|
||||||
{
|
{
|
||||||
@ -69,6 +73,69 @@ class TransfersTest extends FeatureTestCase
|
|||||||
$this->assertFlashLevel('success');
|
$this->assertFlashLevel('success');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItShouldExportTransfers()
|
||||||
|
{
|
||||||
|
$count = 5;
|
||||||
|
factory(Transfer::class, $count)->create();
|
||||||
|
|
||||||
|
\Excel::fake();
|
||||||
|
|
||||||
|
$this->loginAs()
|
||||||
|
->get(route('transfers.export'))
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
\Excel::assertDownloaded(
|
||||||
|
\Str::filename(trans_choice('general.transfers', 2)) . '.xlsx',
|
||||||
|
function (Export $export) use ($count) {
|
||||||
|
// Assert that the correct export is downloaded.
|
||||||
|
return $export->collection()->count() === $count;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItShouldExportSelectedTransfers()
|
||||||
|
{
|
||||||
|
$count = 5;
|
||||||
|
$transfers = factory(Transfer::class, $count)->create();
|
||||||
|
|
||||||
|
\Excel::fake();
|
||||||
|
|
||||||
|
$this->loginAs()
|
||||||
|
->post(
|
||||||
|
route('bulk-actions.action', ['group' => 'banking', 'type' => 'transfers']),
|
||||||
|
['handle' => 'export', 'selected' => [$transfers->random()->id]]
|
||||||
|
)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
\Excel::assertDownloaded(
|
||||||
|
\Str::filename(trans_choice('general.transfers', 2)) . '.xlsx',
|
||||||
|
function (Export $export) {
|
||||||
|
return $export->collection()->count() === 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItShouldImportTransfers()
|
||||||
|
{
|
||||||
|
\Excel::fake();
|
||||||
|
|
||||||
|
$this->loginAs()
|
||||||
|
->post(
|
||||||
|
route('transfers.import'),
|
||||||
|
[
|
||||||
|
'import' => UploadedFile::fake()->createWithContent(
|
||||||
|
'transfers.xlsx',
|
||||||
|
File::get(public_path('files/import/transfers.xlsx'))
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->assertStatus(302);
|
||||||
|
|
||||||
|
\Excel::assertImported('transfers.xlsx');
|
||||||
|
|
||||||
|
$this->assertFlashLevel('success');
|
||||||
|
}
|
||||||
|
|
||||||
public function getRequest()
|
public function getRequest()
|
||||||
{
|
{
|
||||||
$from_account = factory(Account::class)->states('enabled', 'default_currency')->create();
|
$from_account = factory(Account::class)->states('enabled', 'default_currency')->create();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user