mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-01-07 06:33:57 -06:00
Merge branch 'release/3.4.7'
This commit is contained in:
commit
b2b82124e6
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,4 +32,5 @@ addNewLines.php
|
||||
.env.backup
|
||||
.env.local
|
||||
|
||||
tests/_output/*
|
||||
tests/_output/*
|
14
README.md
14
README.md
@ -61,19 +61,19 @@ Everything is organised:
|
||||
|
||||
_Please note that everything in these screenshots is fictional and may not be realistic._
|
||||
|
||||
![Index](https://i.nder.be/gdryw73q)
|
||||
![Index](https://i.nder.be/c6hz06d3)
|
||||
|
||||
![Accounts](https://i.nder.be/hmpkq8q0)
|
||||
![Accounts](https://i.nder.be/gzxxyz6n)
|
||||
|
||||
![Budgets](https://i.nder.be/cbq2n5g9)
|
||||
![Budgets](https://i.nder.be/hhu3krqk)
|
||||
|
||||
![Reports 1](https://i.nder.be/cmwvqrds)
|
||||
![Reports 1](https://i.nder.be/cc3yspf6)
|
||||
|
||||
![Reports 2](https://i.nder.be/cv4dqbp4)
|
||||
![Reports 2](https://i.nder.be/h6fp7xkb)
|
||||
|
||||
![Bills](https://i.nder.be/gmkxqdw7)
|
||||
![Bills](https://i.nder.be/c30zkcpv)
|
||||
|
||||
![Piggy banks](https://i.nder.be/cc5u6h3b)
|
||||
![Piggy banks](https://i.nder.be/g20k0mdq)
|
||||
|
||||
## Running and installing
|
||||
|
||||
|
@ -20,6 +20,7 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
|
@ -64,32 +64,7 @@ class GoogleAccountChartGenerator implements AccountChartGenerator
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
return $this->all($accounts, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 27/06/15
|
||||
* Time: 17:21
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Bill;
|
||||
|
||||
@ -30,28 +24,23 @@ class ChartJsBillChartGenerator implements BillChartGenerator
|
||||
*/
|
||||
public function frontpage(Collection $paid, Collection $unpaid)
|
||||
{
|
||||
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
bcscale(2);
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
foreach ($paid as $entry) { // loop paid and create single entry:
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
$paidAmount = bcadd($paidAmount, $entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
foreach ($unpaid as $entry) { // loop unpaid:
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
$unpaidAmount = bcadd($unpaidAmount, $amount);
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,14 @@ class GoogleBillChartGenerator implements BillChartGenerator
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
bcscale(2);
|
||||
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
$paidAmount = bcadd($paidAmount, $entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
@ -44,7 +46,7 @@ class GoogleBillChartGenerator implements BillChartGenerator
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
$unpaidAmount = bcadd($unpaidAmount, $amount);
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
@ -77,7 +79,11 @@ class GoogleBillChartGenerator implements BillChartGenerator
|
||||
|
||||
/** @var TransactionJournal $result */
|
||||
foreach ($entries as $result) {
|
||||
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
|
||||
$chart->addRow(
|
||||
clone $result->date,
|
||||
floatval($bill->amount_max),
|
||||
floatval($bill->amount_min),
|
||||
floatval($result->amount));
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
@ -28,7 +28,6 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator
|
||||
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
@ -45,6 +44,8 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator
|
||||
|
||||
}
|
||||
|
||||
$data['count'] = count($data['datasets']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@ -118,7 +119,6 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
@ -37,6 +37,7 @@ class GoogleBudgetChartGenerator implements BudgetChartGenerator
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
|
@ -17,7 +17,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
* @param string $dateFormat
|
||||
* @param string $dateFormat
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -76,6 +76,7 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
|
@ -99,6 +99,7 @@ class GoogleCategoryChartGenerator implements CategoryChartGenerator
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace FireflyIII\Generator\Chart\Report;
|
||||
|
||||
use Config;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
@ -78,6 +77,7 @@ class ChartJsReportChartGenerator implements ReportChartGenerator
|
||||
$data['datasets'][1]['data'][] = round($expense, 2);
|
||||
$data['datasets'][0]['data'][] = round(($income / $count), 2);
|
||||
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
29
app/Helpers/Csv/Converter/AccountId.php
Normal file
29
app/Helpers/Csv/Converter/AccountId.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class AccountId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AccountId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$account = Auth::user()->accounts()->find($this->value);
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
26
app/Helpers/Csv/Converter/Amount.php
Normal file
26
app/Helpers/Csv/Converter/Amount.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class Amount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Amount extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (is_numeric($this->value)) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
68
app/Helpers/Csv/Converter/AssetAccountIban.php
Normal file
68
app/Helpers/Csv/Converter/AssetAccountIban.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccountIban
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AssetAccountIban extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
if (strlen($this->value) > 0) {
|
||||
// find or create new account:
|
||||
$account = $this->findAccount();
|
||||
$accountType = AccountType::where('type', 'Asset account')->first();
|
||||
|
||||
if (is_null($account)) {
|
||||
// create it if doesn't exist.
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'name' => $this->value,
|
||||
'iban' => $this->value,
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'active' => 1,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function findAccount()
|
||||
{
|
||||
$set = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
if ($entry->iban == $this->value) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
51
app/Helpers/Csv/Converter/AssetAccountName.php
Normal file
51
app/Helpers/Csv/Converter/AssetAccountName.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccountName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class AssetAccountName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
}
|
||||
// find or create new account:
|
||||
$accountType = AccountType::where('type', 'Asset account')->first();
|
||||
$set = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get();
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
if ($entry->name == $this->value) {
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
||||
// create it if doesnt exist.
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'name' => $this->value,
|
||||
'iban' => '',
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'active' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
122
app/Helpers/Csv/Converter/BasicConverter.php
Normal file
122
app/Helpers/Csv/Converter/BasicConverter.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Class BasicConverter
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BasicConverter
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
/** @var string */
|
||||
protected $field;
|
||||
/** @var int */
|
||||
protected $index;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var string */
|
||||
protected $role;
|
||||
/** @var string */
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField()
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*/
|
||||
public function setField($field)
|
||||
{
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*/
|
||||
public function setIndex($index)
|
||||
{
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMapped()
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped($mapped)
|
||||
{
|
||||
$this->mapped = $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRole()
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $role
|
||||
*/
|
||||
public function setRole($role)
|
||||
{
|
||||
$this->role = $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
}
|
30
app/Helpers/Csv/Converter/BillId.php
Normal file
30
app/Helpers/Csv/Converter/BillId.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill;
|
||||
|
||||
/**
|
||||
* Class BillId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BillId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$bill = Auth::user()->bills()->find($this->value);
|
||||
}
|
||||
|
||||
return $bill;
|
||||
}
|
||||
}
|
38
app/Helpers/Csv/Converter/BillName.php
Normal file
38
app/Helpers/Csv/Converter/BillName.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill;
|
||||
|
||||
/**
|
||||
* Class BillName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BillName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$bill = null;
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
|
||||
$bills = Auth::user()->bills()->get();
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
if ($bill->name == $this->value) {
|
||||
return $bill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bill;
|
||||
}
|
||||
}
|
29
app/Helpers/Csv/Converter/BudgetId.php
Normal file
29
app/Helpers/Csv/Converter/BudgetId.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Budget;
|
||||
|
||||
/**
|
||||
* Class AccountId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BudgetId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Budget
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$budget = Auth::user()->budgets()->find($this->value);
|
||||
}
|
||||
|
||||
return $budget;
|
||||
}
|
||||
}
|
35
app/Helpers/Csv/Converter/BudgetName.php
Normal file
35
app/Helpers/Csv/Converter/BudgetName.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Budget;
|
||||
|
||||
/**
|
||||
* Class BudgetName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class BudgetName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Budget
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$budget = Budget::firstOrCreateEncrypted(
|
||||
[
|
||||
'name' => $this->value,
|
||||
'user_id' => Auth::user()->id,
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $budget;
|
||||
}
|
||||
}
|
29
app/Helpers/Csv/Converter/CategoryId.php
Normal file
29
app/Helpers/Csv/Converter/CategoryId.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Category;
|
||||
|
||||
/**
|
||||
* Class CategoryId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CategoryId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Category
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$category = Auth::user()->categories()->find($this->value);
|
||||
}
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
34
app/Helpers/Csv/Converter/CategoryName.php
Normal file
34
app/Helpers/Csv/Converter/CategoryName.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Category;
|
||||
|
||||
/**
|
||||
* Class CategoryName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CategoryName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Category
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
// is mapped? Then it's easy!
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$category = Category::firstOrCreateEncrypted(
|
||||
[
|
||||
'name' => $this->value,
|
||||
'user_id' => Auth::user()->id
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
49
app/Helpers/Csv/Converter/ConverterInterface.php
Normal file
49
app/Helpers/Csv/Converter/ConverterInterface.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Interface ConverterInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
interface ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function convert();
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data);
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
*/
|
||||
public function setField($field);
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*/
|
||||
public function setIndex($index);
|
||||
|
||||
/**
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped($mapped);
|
||||
|
||||
/**
|
||||
* @param string $role
|
||||
*/
|
||||
public function setRole($role);
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value);
|
||||
|
||||
}
|
28
app/Helpers/Csv/Converter/CurrencyCode.php
Normal file
28
app/Helpers/Csv/Converter/CurrencyCode.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Class CurrencyCode
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyCode extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed|static
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$currency = TransactionCurrency::whereCode($this->value)->first();
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
28
app/Helpers/Csv/Converter/CurrencyId.php
Normal file
28
app/Helpers/Csv/Converter/CurrencyId.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Class CurrencyId
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed|static
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$currency = TransactionCurrency::find($this->value);
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
28
app/Helpers/Csv/Converter/CurrencyName.php
Normal file
28
app/Helpers/Csv/Converter/CurrencyName.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Class CurrencyName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencyName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed|static
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$currency = TransactionCurrency::whereName($this->value)->first();
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
28
app/Helpers/Csv/Converter/CurrencySymbol.php
Normal file
28
app/Helpers/Csv/Converter/CurrencySymbol.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Class CurrencySymbol
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class CurrencySymbol extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return mixed|static
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]);
|
||||
} else {
|
||||
$currency = TransactionCurrency::whereSymbol($this->value)->first();
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
27
app/Helpers/Csv/Converter/Date.php
Normal file
27
app/Helpers/Csv/Converter/Date.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class Date
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Date extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$format = Session::get('csv-date-format');
|
||||
|
||||
$date = Carbon::createFromFormat($format, $this->value);
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
21
app/Helpers/Csv/Converter/Description.php
Normal file
21
app/Helpers/Csv/Converter/Description.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
/**
|
||||
* Class Description
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Description extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
return trim($this->data['description'] . ' ' . $this->value);
|
||||
}
|
||||
}
|
22
app/Helpers/Csv/Converter/Ignore.php
Normal file
22
app/Helpers/Csv/Converter/Ignore.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class Amount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class Ignore extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
57
app/Helpers/Csv/Converter/OpposingAccountIban.php
Normal file
57
app/Helpers/Csv/Converter/OpposingAccountIban.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class OpposingAccountIban
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* If mapped, return account. Otherwise, only return the name itself.
|
||||
*
|
||||
* @return Account|string
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
} else {
|
||||
if (strlen($this->value) > 0) {
|
||||
$account = $this->findAccount();
|
||||
if (!is_null($account)) {
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function findAccount()
|
||||
{
|
||||
$set = Auth::user()->accounts()->get();
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
if ($account->iban == $this->value) {
|
||||
Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ' . $account->name . ') with IBAN ' . $this->value);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
32
app/Helpers/Csv/Converter/OpposingAccountId.php
Normal file
32
app/Helpers/Csv/Converter/OpposingAccountId.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class OpposingName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountId extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return Account
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
} else {
|
||||
$account = Auth::user()->accounts()->find($this->value);
|
||||
}
|
||||
|
||||
return $account;
|
||||
|
||||
}
|
||||
}
|
31
app/Helpers/Csv/Converter/OpposingAccountName.php
Normal file
31
app/Helpers/Csv/Converter/OpposingAccountName.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class OpposingName
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class OpposingAccountName extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* If mapped, return account. Otherwise, only return the name itself.
|
||||
*
|
||||
* @return Account|string
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if (isset($this->mapped[$this->index][$this->value])) {
|
||||
$account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]);
|
||||
|
||||
return $account;
|
||||
} else {
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
}
|
26
app/Helpers/Csv/Converter/RabobankDebetCredit.php
Normal file
26
app/Helpers/Csv/Converter/RabobankDebetCredit.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
|
||||
/**
|
||||
* Class RabobankDebetCredit
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class RabobankDebetCredit extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
if ($this->value == 'D') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
40
app/Helpers/Csv/Converter/TagsComma.php
Normal file
40
app/Helpers/Csv/Converter/TagsComma.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Tag;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class TagsComma
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class TagsComma extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$tags = new Collection;
|
||||
|
||||
$strings = explode(',', $this->value);
|
||||
foreach ($strings as $string) {
|
||||
$tag = Tag::firstOrCreateEncrypted(
|
||||
[
|
||||
'tag' => $string,
|
||||
'tagMode' => 'nothing',
|
||||
'user_id' => Auth::user()->id,
|
||||
]
|
||||
);
|
||||
$tags->push($tag);
|
||||
}
|
||||
$tags = $tags->merge($this->data['tags']);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
40
app/Helpers/Csv/Converter/TagsSpace.php
Normal file
40
app/Helpers/Csv/Converter/TagsSpace.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Converter;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Tag;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class TagsSpace
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Converter
|
||||
*/
|
||||
class TagsSpace extends BasicConverter implements ConverterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Bill
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
$tags = new Collection;
|
||||
|
||||
$strings = explode(' ', $this->value);
|
||||
foreach ($strings as $string) {
|
||||
$tag = Tag::firstOrCreateEncrypted(
|
||||
[
|
||||
'tag' => $string,
|
||||
'tagMode' => 'nothing',
|
||||
'user_id' => Auth::user()->id,
|
||||
]
|
||||
);
|
||||
$tags->push($tag);
|
||||
}
|
||||
$tags = $tags->merge($this->data['tags']);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
}
|
263
app/Helpers/Csv/Data.php
Normal file
263
app/Helpers/Csv/Data.php
Normal file
@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use Crypt;
|
||||
use League\Csv\Reader;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class Data
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Data
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
protected $csvFileContent;
|
||||
|
||||
/** @var string */
|
||||
protected $csvFileLocation;
|
||||
/** @var string */
|
||||
protected $dateFormat;
|
||||
/** @var bool */
|
||||
protected $hasHeaders;
|
||||
|
||||
/** @var array */
|
||||
protected $map;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var Reader */
|
||||
protected $reader;
|
||||
/** @var array */
|
||||
protected $roles;
|
||||
|
||||
/** @var array */
|
||||
protected $specifix;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->sessionHasHeaders();
|
||||
$this->sessionDateFormat();
|
||||
$this->sessionCsvFileLocation();
|
||||
$this->sessionMap();
|
||||
$this->sessionRoles();
|
||||
$this->sessionMapped();
|
||||
$this->sessionSpecifix();
|
||||
}
|
||||
|
||||
protected function sessionHasHeaders()
|
||||
{
|
||||
if (Session::has('csv-has-headers')) {
|
||||
$this->hasHeaders = (bool)Session::get('csv-has-headers');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionDateFormat()
|
||||
{
|
||||
if (Session::has('csv-date-format')) {
|
||||
$this->dateFormat = (string)Session::get('csv-date-format');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionCsvFileLocation()
|
||||
{
|
||||
if (Session::has('csv-file')) {
|
||||
$this->csvFileLocation = (string)Session::get('csv-file');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionMap()
|
||||
{
|
||||
if (Session::has('csv-map')) {
|
||||
$this->map = (array)Session::get('csv-map');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionRoles()
|
||||
{
|
||||
if (Session::has('csv-roles')) {
|
||||
$this->roles = (array)Session::get('csv-roles');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionMapped()
|
||||
{
|
||||
if (Session::has('csv-mapped')) {
|
||||
$this->mapped = (array)Session::get('csv-mapped');
|
||||
}
|
||||
}
|
||||
|
||||
protected function sessionSpecifix()
|
||||
{
|
||||
if (Session::has('csv-specifix')) {
|
||||
$this->specifix = (array)Session::get('csv-specifix');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
return $this->dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $dateFormat
|
||||
*/
|
||||
public function setDateFormat($dateFormat)
|
||||
{
|
||||
Session::put('csv-date-format', $dateFormat);
|
||||
$this->dateFormat = $dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHeaders()
|
||||
{
|
||||
return $this->hasHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $hasHeaders
|
||||
*/
|
||||
public function setHasHeaders($hasHeaders)
|
||||
{
|
||||
Session::put('csv-has-headers', $hasHeaders);
|
||||
$this->hasHeaders = $hasHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
*/
|
||||
public function setMap(array $map)
|
||||
{
|
||||
Session::put('csv-map', $map);
|
||||
$this->map = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMapped()
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mapped
|
||||
*/
|
||||
public function setMapped(array $mapped)
|
||||
{
|
||||
Session::put('csv-mapped', $mapped);
|
||||
$this->mapped = $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reader
|
||||
*/
|
||||
public function getReader()
|
||||
{
|
||||
|
||||
if (strlen($this->csvFileContent) === 0) {
|
||||
$this->loadCsvFile();
|
||||
}
|
||||
|
||||
if (is_null($this->reader)) {
|
||||
$this->reader = Reader::createFromString($this->getCsvFileContent());
|
||||
}
|
||||
|
||||
return $this->reader;
|
||||
}
|
||||
|
||||
protected function loadCsvFile()
|
||||
{
|
||||
$file = $this->getCsvFileLocation();
|
||||
$content = file_get_contents($file);
|
||||
$contentDecrypted = Crypt::decrypt($content);
|
||||
$this->setCsvFileContent($contentDecrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCsvFileLocation()
|
||||
{
|
||||
return $this->csvFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $csvFileLocation
|
||||
*/
|
||||
public function setCsvFileLocation($csvFileLocation)
|
||||
{
|
||||
Session::put('csv-file', $csvFileLocation);
|
||||
$this->csvFileLocation = $csvFileLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCsvFileContent()
|
||||
{
|
||||
return $this->csvFileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $csvFileContent
|
||||
*/
|
||||
public function setCsvFileContent($csvFileContent)
|
||||
{
|
||||
$this->csvFileContent = $csvFileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRoles()
|
||||
{
|
||||
return $this->roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $roles
|
||||
*/
|
||||
public function setRoles(array $roles)
|
||||
{
|
||||
Session::put('csv-roles', $roles);
|
||||
$this->roles = $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecifix()
|
||||
{
|
||||
return $this->specifix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $specifix
|
||||
*/
|
||||
public function setSpecifix($specifix)
|
||||
{
|
||||
Session::put('csv-specifix', $specifix);
|
||||
$this->specifix = $specifix;
|
||||
}
|
||||
|
||||
|
||||
}
|
331
app/Helpers/Csv/Importer.php
Normal file
331
app/Helpers/Csv/Importer.php
Normal file
@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Config;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Converter\ConverterInterface;
|
||||
use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface;
|
||||
use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\MessageBag;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Importer
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Importer
|
||||
{
|
||||
|
||||
/** @var Data */
|
||||
protected $data;
|
||||
/** @var array */
|
||||
protected $errors;
|
||||
/** @var array */
|
||||
protected $importData;
|
||||
/** @var array */
|
||||
protected $importRow;
|
||||
/** @var int */
|
||||
protected $imported = 0;
|
||||
/** @var array */
|
||||
protected $map;
|
||||
/** @var array */
|
||||
protected $mapped;
|
||||
/** @var array */
|
||||
protected $roles;
|
||||
/** @var int */
|
||||
protected $rows = 0;
|
||||
/** @var array */
|
||||
protected $specifix;
|
||||
|
||||
/**
|
||||
* Used by CsvController.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImported()
|
||||
{
|
||||
return $this->imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by CsvController
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRows()
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$this->map = $this->data->getMap();
|
||||
$this->roles = $this->data->getRoles();
|
||||
$this->mapped = $this->data->getMapped();
|
||||
$this->specifix = $this->data->getSpecifix();
|
||||
|
||||
foreach ($this->data->getReader() as $index => $row) {
|
||||
if ($this->parseRow($index)) {
|
||||
$this->rows++;
|
||||
$result = $this->importRow($row);
|
||||
if (!($result === true)) {
|
||||
Log::error('Caught error at row #' . $index . ': ' . $result);
|
||||
$this->errors[$index] = $result;
|
||||
} else {
|
||||
$this->imported++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseRow($index)
|
||||
{
|
||||
return (($this->data->hasHeaders() && $index > 1) || !$this->data->hasHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $row
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function importRow($row)
|
||||
{
|
||||
$data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional
|
||||
foreach ($row as $index => $value) {
|
||||
$role = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore';
|
||||
$class = Config::get('csv.roles.' . $role . '.converter');
|
||||
$field = Config::get('csv.roles.' . $role . '.field');
|
||||
|
||||
/** @var ConverterInterface $converter */
|
||||
$converter = App::make('FireflyIII\Helpers\Csv\Converter\\' . $class);
|
||||
$converter->setData($data); // the complete array so far.
|
||||
$converter->setField($field);
|
||||
$converter->setIndex($index);
|
||||
$converter->setMapped($this->mapped);
|
||||
$converter->setValue($value);
|
||||
$converter->setRole($role);
|
||||
$data[$field] = $converter->convert();
|
||||
|
||||
}
|
||||
// move to class vars.
|
||||
$this->importData = $data;
|
||||
$this->importRow = $row;
|
||||
unset($data, $row);
|
||||
// post processing and validating.
|
||||
$this->postProcess();
|
||||
$result = $this->validateData();
|
||||
|
||||
if (!($result === true)) {
|
||||
return $result; // return error.
|
||||
}
|
||||
$journal = $this->createTransactionJournal();
|
||||
if ($journal instanceof TransactionJournal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getFiller()
|
||||
{
|
||||
$filler = [];
|
||||
foreach (Config::get('csv.roles') as $role) {
|
||||
if (isset($role['field'])) {
|
||||
$fieldName = $role['field'];
|
||||
$filler[$fieldName] = null;
|
||||
}
|
||||
}
|
||||
// some extra's:
|
||||
$filler['bill-id'] = null;
|
||||
$filler['opposing-account-object'] = null;
|
||||
$filler['amount-modifier'] = '1';
|
||||
|
||||
return $filler;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Row denotes the original data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function postProcess()
|
||||
{
|
||||
// do bank specific fixes (must be enabled but now all of them.
|
||||
|
||||
foreach ($this->getSpecifix() as $className) {
|
||||
/** @var SpecifixInterface $specifix */
|
||||
$specifix = App::make('FireflyIII\Helpers\Csv\Specifix\\' . $className);
|
||||
$specifix->setData($this->importData);
|
||||
$specifix->setRow($this->importRow);
|
||||
$this->importData = $specifix->fix();
|
||||
}
|
||||
|
||||
|
||||
$set = Config::get('csv.post_processors');
|
||||
foreach ($set as $className) {
|
||||
/** @var PostProcessorInterface $postProcessor */
|
||||
$postProcessor = App::make('FireflyIII\Helpers\Csv\PostProcessing\\' . $className);
|
||||
$postProcessor->setData($this->importData);
|
||||
$this->importData = $postProcessor->process();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecifix()
|
||||
{
|
||||
return $this->specifix;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function validateData()
|
||||
{
|
||||
if (is_null($this->importData['date']) && is_null($this->importData['date-rent'])) {
|
||||
return 'No date value for this row.';
|
||||
}
|
||||
if (is_null($this->importData['opposing-account-object'])) {
|
||||
return 'Opposing account is null';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return TransactionJournal|string
|
||||
*/
|
||||
protected function createTransactionJournal()
|
||||
{
|
||||
bcscale(2);
|
||||
$date = $this->importData['date'];
|
||||
if (is_null($this->importData['date'])) {
|
||||
$date = $this->importData['date-rent'];
|
||||
}
|
||||
$transactionType = $this->getTransactionType(); // defaults to deposit
|
||||
$errors = new MessageBag;
|
||||
$journal = TransactionJournal::create(
|
||||
['user_id' => Auth::user()->id, 'transaction_type_id' => $transactionType->id, 'transaction_currency_id' => $this->importData['currency']->id,
|
||||
'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],]
|
||||
);
|
||||
if ($journal->getErrors()->count() == 0) {
|
||||
$accountId = $this->importData['asset-account']->id; // create first transaction:
|
||||
$amount = $this->importData['amount'];
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors();
|
||||
$accountId = $this->importData['opposing-account-object']->id; // create second transaction:
|
||||
$amount = bcmul($this->importData['amount'], -1);
|
||||
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
|
||||
$errors = $transaction->getErrors()->merge($errors);
|
||||
}
|
||||
if ($errors->count() == 0) {
|
||||
$journal->completed = 1;
|
||||
$journal->save();
|
||||
} else {
|
||||
$text = join(',', $errors->all());
|
||||
|
||||
return $text;
|
||||
}
|
||||
$this->saveBudget($journal);
|
||||
$this->saveCategory($journal);
|
||||
$this->saveTags($journal);
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TransactionType
|
||||
*/
|
||||
protected function getTransactionType()
|
||||
{
|
||||
$transactionType = TransactionType::where('type', 'Deposit')->first();
|
||||
if ($this->importData['amount'] < 0) {
|
||||
$transactionType = TransactionType::where('type', 'Withdrawal')->first();
|
||||
}
|
||||
|
||||
if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) {
|
||||
$transactionType = TransactionType::where('type', 'Transfer')->first();
|
||||
}
|
||||
|
||||
return $transactionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveBudget(TransactionJournal $journal)
|
||||
{
|
||||
// add budget:
|
||||
if (!is_null($this->importData['budget'])) {
|
||||
$journal->budgets()->save($this->importData['budget']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveCategory(TransactionJournal $journal)
|
||||
{
|
||||
// add category:
|
||||
if (!is_null($this->importData['category'])) {
|
||||
$journal->categories()->save($this->importData['category']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
protected function saveTags(TransactionJournal $journal)
|
||||
{
|
||||
if (!is_null($this->importData['tags'])) {
|
||||
foreach ($this->importData['tags'] as $tag) {
|
||||
$journal->tags()->save($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Data $data
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
}
|
34
app/Helpers/Csv/Mapper/AnyAccount.php
Normal file
34
app/Helpers/Csv/Mapper/AnyAccount.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class AnyAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class AnyAccount implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->accounts()->with('accountType')->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
|
||||
$list = [];
|
||||
/** @var Account $account */
|
||||
foreach ($result as $account) {
|
||||
$list[$account->id] = $account->name . ' (' . $account->accountType->type . ')';
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
45
app/Helpers/Csv/Mapper/AssetAccount.php
Normal file
45
app/Helpers/Csv/Mapper/AssetAccount.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* Class AssetAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class AssetAccount implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->accounts()->with(
|
||||
['accountmeta' => function (HasMany $query) {
|
||||
$query->where('name', 'accountRole');
|
||||
}]
|
||||
)->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
|
||||
$list = [];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($result as $account) {
|
||||
$name = $account->name;
|
||||
if (strlen($account->iban) > 0) {
|
||||
$name .= ' (' . $account->iban . ')';
|
||||
}
|
||||
$list[$account->id] = $name;
|
||||
}
|
||||
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
34
app/Helpers/Csv/Mapper/Bill.php
Normal file
34
app/Helpers/Csv/Mapper/Bill.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Bill as BillModel;
|
||||
|
||||
/**
|
||||
* Class Bill
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Bill implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->bills()->get(['bills.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var BillModel $bill */
|
||||
foreach ($result as $bill) {
|
||||
$list[$bill->id] = $bill->name . ' [' . $bill->match . ']';
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
34
app/Helpers/Csv/Mapper/Budget.php
Normal file
34
app/Helpers/Csv/Mapper/Budget.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Budget as BudgetModel;
|
||||
|
||||
/**
|
||||
* Class Budget
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Budget implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->budgets()->get(['budgets.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var BudgetModel $budget */
|
||||
foreach ($result as $budget) {
|
||||
$list[$budget->id] = $budget->name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
34
app/Helpers/Csv/Mapper/Category.php
Normal file
34
app/Helpers/Csv/Mapper/Category.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Category as CategoryModel;
|
||||
|
||||
/**
|
||||
* Class Category
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Category implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->categories()->get(['categories.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var CategoryModel $category */
|
||||
foreach ($result as $category) {
|
||||
$list[$category->id] = $category->name;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
16
app/Helpers/Csv/Mapper/MapperInterface.php
Normal file
16
app/Helpers/Csv/Mapper/MapperInterface.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
/**
|
||||
* Interface MapperInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
interface MapperInterface
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap();
|
||||
}
|
34
app/Helpers/Csv/Mapper/Tag.php
Normal file
34
app/Helpers/Csv/Mapper/Tag.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Tag as TagModel;
|
||||
|
||||
/**
|
||||
* Class Tag
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class Tag implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$result = Auth::user()->budgets()->get(['tags.*']);
|
||||
$list = [];
|
||||
|
||||
/** @var TagModel $tag */
|
||||
foreach ($result as $tag) {
|
||||
$list[$tag->id] = $tag->tag;
|
||||
}
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
32
app/Helpers/Csv/Mapper/TransactionCurrency.php
Normal file
32
app/Helpers/Csv/Mapper/TransactionCurrency.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Mapper;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency as TC;
|
||||
|
||||
/**
|
||||
* Class TransactionCurrency
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Mapper
|
||||
*/
|
||||
class TransactionCurrency implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap()
|
||||
{
|
||||
$currencies = TC::get();
|
||||
$list = [];
|
||||
foreach ($currencies as $currency) {
|
||||
$list[$currency->id] = $currency->name . ' (' . $currency->code . ')';
|
||||
}
|
||||
|
||||
asort($list);
|
||||
|
||||
array_unshift($list, trans('firefly.csv_do_not_map'));
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
35
app/Helpers/Csv/PostProcessing/Amount.php
Normal file
35
app/Helpers/Csv/PostProcessing/Amount.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Amount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Amount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
bcscale(2);
|
||||
$this->data['amount'] = bcmul($this->data['amount'], $this->data['amount-modifier']);
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
37
app/Helpers/Csv/PostProcessing/Bill.php
Normal file
37
app/Helpers/Csv/PostProcessing/Bill.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Bill
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Bill implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
|
||||
// get bill id.
|
||||
if (!is_null($this->data['bill'])) {
|
||||
$this->data['bill-id'] = $this->data['bill']->id;
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
41
app/Helpers/Csv/PostProcessing/Currency.php
Normal file
41
app/Helpers/Csv/PostProcessing/Currency.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class Currency
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Currency implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
|
||||
// fix currency
|
||||
if (is_null($this->data['currency'])) {
|
||||
$currencyPreference = Preferences::get('currencyPreference', 'EUR');
|
||||
$this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first();
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
38
app/Helpers/Csv/PostProcessing/Description.php
Normal file
38
app/Helpers/Csv/PostProcessing/Description.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
/**
|
||||
* Class Description
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class Description implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
$this->data['description'] = trim($this->data['description']);
|
||||
if (strlen($this->data['description']) == 0) {
|
||||
$this->data['description'] = trans('firefly.csv_empty_description');
|
||||
}
|
||||
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
196
app/Helpers/Csv/PostProcessing/OpposingAccount.php
Normal file
196
app/Helpers/Csv/PostProcessing/OpposingAccount.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use Log;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class OpposingAccount
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
class OpposingAccount implements PostProcessorInterface
|
||||
{
|
||||
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
$result = $this->checkIdNameObject();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkIbanString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->checkNameString();
|
||||
if (!is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function checkIdNameObject()
|
||||
{
|
||||
if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-id'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-iban'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkIbanString()
|
||||
{
|
||||
$rules = ['iban' => 'iban'];
|
||||
$check = ['iban' => $this->data['opposing-account-iban']];
|
||||
$validator = Validator::make($check, $rules);
|
||||
if (!$validator->fails()) {
|
||||
$this->data['opposing-account-object'] = $this->parseIbanString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseIbanString()
|
||||
{
|
||||
// create by name and/or iban.
|
||||
$accounts = Auth::user()->accounts()->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->iban == $this->data['opposing-account-iban']) {
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
$account = $this->createAccount();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function createAccount()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
|
||||
// create if not exists:
|
||||
$name = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name']
|
||||
: $this->data['opposing-account-iban'];
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $name,
|
||||
'iban' => $this->data['opposing-account-iban'],
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AccountType
|
||||
*/
|
||||
protected function getAccountType()
|
||||
{
|
||||
// opposing account type:
|
||||
if ($this->data['amount'] < 0) {
|
||||
// create expense account:
|
||||
|
||||
return AccountType::where('type', 'Expense account')->first();
|
||||
} else {
|
||||
// create revenue account:
|
||||
|
||||
return AccountType::where('type', 'Revenue account')->first();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
protected function checkNameString()
|
||||
{
|
||||
if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any.
|
||||
$this->data['opposing-account-object'] = $this->data['opposing-account-name'];
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
if (is_string($this->data['opposing-account-name'])) {
|
||||
$this->data['opposing-account-object'] = $this->parseNameString();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Account|null
|
||||
*/
|
||||
protected function parseNameString()
|
||||
{
|
||||
$accountType = $this->getAccountType();
|
||||
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
|
||||
foreach ($accounts as $entry) {
|
||||
if ($entry->name == $this->data['opposing-account-name']) {
|
||||
Log::debug('Found an account with this name (#' . $entry->id . ': ' . $entry->name . ')');
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
// create if not exists:
|
||||
$account = Account::firstOrCreateEncrypted(
|
||||
[
|
||||
'user_id' => Auth::user()->id,
|
||||
'account_type_id' => $accountType->id,
|
||||
'name' => $this->data['opposing-account-name'],
|
||||
'iban' => '',
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return $account;
|
||||
}
|
||||
}
|
29
app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
Normal file
29
app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 05/07/15
|
||||
* Time: 19:20
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\PostProcessing;
|
||||
|
||||
|
||||
/**
|
||||
* Interface PostProcessorInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\PostProcessing
|
||||
*/
|
||||
interface PostProcessorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function process();
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data);
|
||||
}
|
45
app/Helpers/Csv/Specifix/Dummy.php
Normal file
45
app/Helpers/Csv/Specifix/Dummy.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Specifix;
|
||||
|
||||
/**
|
||||
* Class Dummy
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
class Dummy
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/** @var array */
|
||||
protected $row;
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function fix()
|
||||
{
|
||||
return $this->data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow($row)
|
||||
{
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
|
||||
}
|
58
app/Helpers/Csv/Specifix/RabobankDescription.php
Normal file
58
app/Helpers/Csv/Specifix/RabobankDescription.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv\Specifix;
|
||||
|
||||
/**
|
||||
* Class RabobankDescription
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
class RabobankDescription
|
||||
{
|
||||
/** @var array */
|
||||
protected $data;
|
||||
|
||||
/** @var array */
|
||||
protected $row;
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function fix()
|
||||
{
|
||||
$this->rabobankFixEmptyOpposing();
|
||||
|
||||
return $this->data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes Rabobank specific thing.
|
||||
*/
|
||||
protected function rabobankFixEmptyOpposing()
|
||||
{
|
||||
if (strlen($this->data['opposing-account-name']) == 0) {
|
||||
$this->data['opposing-account-name'] = $this->row[10];
|
||||
}
|
||||
$this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow($row)
|
||||
{
|
||||
$this->row = $row;
|
||||
}
|
||||
|
||||
|
||||
}
|
25
app/Helpers/Csv/Specifix/SpecifixInterface.php
Normal file
25
app/Helpers/Csv/Specifix/SpecifixInterface.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv\Specifix;
|
||||
|
||||
/**
|
||||
* Interface SpecifixInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv\Specifix
|
||||
*/
|
||||
interface SpecifixInterface
|
||||
{
|
||||
/**
|
||||
* Implement bank and locale related fixes.
|
||||
*/
|
||||
public function fix();
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData($data);
|
||||
|
||||
/**
|
||||
* @param array $row
|
||||
*/
|
||||
public function setRow($row);
|
||||
}
|
180
app/Helpers/Csv/Wizard.php
Normal file
180
app/Helpers/Csv/Wizard.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Config;
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Mapper\MapperInterface;
|
||||
use League\Csv\Reader;
|
||||
use ReflectionException;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class Wizard
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
class Wizard implements WizardInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Reader $reader
|
||||
* @param array $map
|
||||
* @param bool $hasHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMappableValues($reader, array $map, $hasHeaders)
|
||||
{
|
||||
$values = [];
|
||||
/*
|
||||
* Loop over the CSV and collect mappable data:
|
||||
*/
|
||||
$keys = array_keys($map);
|
||||
foreach ($reader as $index => $row) {
|
||||
if ($this->useRow($hasHeaders, $index)) {
|
||||
// collect all map values
|
||||
|
||||
foreach ($keys as $column) {
|
||||
$values[$column][] = $row[$column];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Make each one unique.
|
||||
*/
|
||||
foreach ($values as $column => $found) {
|
||||
$values[$column] = array_unique($found);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $roles
|
||||
* @param mixed $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedMapping(array $roles, $map)
|
||||
{
|
||||
$configRoles = Config::get('csv.roles');
|
||||
$maps = [];
|
||||
|
||||
|
||||
if (is_array($map)) {
|
||||
foreach ($map as $index => $field) {
|
||||
if (isset($roles[$index])) {
|
||||
$name = $roles[$index];
|
||||
if ($configRoles[$name]['mappable']) {
|
||||
$maps[$index] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $maps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedRoles($input)
|
||||
{
|
||||
$roles = [];
|
||||
|
||||
|
||||
/*
|
||||
* Store all rows for each column:
|
||||
*/
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $index => $role) {
|
||||
if ($role != '_ignore') {
|
||||
$roles[$index] = $role;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionHasValues(array $fields)
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
if (!Session::has($field)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function showOptions(array $map)
|
||||
{
|
||||
$options = [];
|
||||
foreach ($map as $index => $columnRole) {
|
||||
|
||||
$mapper = Config::get('csv.roles.' . $columnRole . '.mapper');
|
||||
if (is_null($mapper)) {
|
||||
throw new FireflyException('Cannot map field of type "' . $columnRole . '".');
|
||||
}
|
||||
$class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper;
|
||||
try {
|
||||
/** @var MapperInterface $mapObject */
|
||||
$mapObject = App::make($class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because class ' . $mapper . ' does not exist.');
|
||||
}
|
||||
$set = $mapObject->getMap();
|
||||
$options[$index] = $set;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function storeCsvFile($path)
|
||||
{
|
||||
$time = str_replace(' ', '-', microtime());
|
||||
$fileName = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted';
|
||||
$fullPath = storage_path('upload') . DIRECTORY_SEPARATOR . $fileName;
|
||||
$content = file_get_contents($path);
|
||||
$contentEncrypted = Crypt::encrypt($content);
|
||||
file_put_contents($fullPath, $contentEncrypted);
|
||||
|
||||
return $fullPath;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $hasHeaders
|
||||
* @param int $index
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function useRow($hasHeaders, $index)
|
||||
{
|
||||
return ($hasHeaders && $index > 1) || !$hasHeaders;
|
||||
}
|
||||
}
|
59
app/Helpers/Csv/WizardInterface.php
Normal file
59
app/Helpers/Csv/WizardInterface.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Csv;
|
||||
|
||||
use League\Csv\Reader;
|
||||
|
||||
/**
|
||||
* Interface WizardInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Csv
|
||||
*/
|
||||
interface WizardInterface
|
||||
{
|
||||
/**
|
||||
* @param Reader $reader
|
||||
* @param array $map
|
||||
* @param bool $hasHeaders
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMappableValues($reader, array $map, $hasHeaders);
|
||||
|
||||
/**
|
||||
* @param array $roles
|
||||
* @param mixed $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedMapping(array $roles, $map);
|
||||
|
||||
/**
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function processSelectedRoles($input);
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sessionHasValues(array $fields);
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function showOptions(array $map);
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function storeCsvFile($path);
|
||||
|
||||
}
|
@ -60,9 +60,10 @@ class ReportHelper implements ReportHelperInterface
|
||||
|
||||
|
||||
$accounts = $this->query->getAllAccounts($date, $end, $shared);
|
||||
$start = 0;
|
||||
$end = 0;
|
||||
$diff = 0;
|
||||
$start = '0';
|
||||
$end = '0';
|
||||
$diff = '0';
|
||||
bcscale(2);
|
||||
|
||||
// remove cash account, if any:
|
||||
$accounts = $accounts->filter(
|
||||
@ -77,9 +78,9 @@ class ReportHelper implements ReportHelperInterface
|
||||
|
||||
// summarize:
|
||||
foreach ($accounts as $account) {
|
||||
$start += $account->startBalance;
|
||||
$end += $account->endBalance;
|
||||
$diff += ($account->endBalance - $account->startBalance);
|
||||
$start = bcadd($start, $account->startBalance);
|
||||
$end = bcadd($end, $account->endBalance);
|
||||
$diff = bcadd($diff, ($account->endBalance - $account->startBalance));
|
||||
}
|
||||
|
||||
$object = new AccountCollection;
|
||||
@ -201,11 +202,10 @@ class ReportHelper implements ReportHelperInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param boolean $shared
|
||||
*
|
||||
* @return BillCollection
|
||||
*/
|
||||
public function getBillReport(Carbon $start, Carbon $end, $shared)
|
||||
public function getBillReport(Carbon $start, Carbon $end)
|
||||
{
|
||||
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
|
@ -37,11 +37,10 @@ interface ReportHelperInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param boolean $shared
|
||||
*
|
||||
* @return BillCollection
|
||||
*/
|
||||
public function getBillReport(Carbon $start, Carbon $end, $shared);
|
||||
public function getBillReport(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
|
@ -54,9 +54,7 @@ class ReportQuery implements ReportQueryInterface
|
||||
$query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine.
|
||||
}
|
||||
$query->orderBy('transaction_journals.date');
|
||||
|
||||
// get everything
|
||||
$data = $query->get(
|
||||
$data = $query->get( // get everything
|
||||
['transaction_journals.*', 'transaction_types.type', 'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted']
|
||||
);
|
||||
|
||||
@ -227,11 +225,10 @@ class ReportQuery implements ReportQueryInterface
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false)
|
||||
public function spentNoBudget(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
return
|
||||
Auth::user()->transactionjournals()
|
||||
|
@ -71,11 +71,10 @@ interface ReportQueryInterface
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false);
|
||||
public function spentNoBudget(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use Steam;
|
||||
use URL;
|
||||
@ -89,7 +88,7 @@ class AccountController extends Controller
|
||||
Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name]));
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::to(Session::get('accounts.delete.url'));
|
||||
return redirect(Session::get('accounts.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,13 +198,15 @@ class AccountController extends Controller
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
'openingBalance' => floatval($request->input('openingBalance')),
|
||||
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
|
||||
];
|
||||
$account = $repository->store($accountData);
|
||||
|
||||
$account = $repository->store($accountData);
|
||||
|
||||
Session::flash('success', 'New account "' . $account->name . '" stored!');
|
||||
Preferences::mark();
|
||||
@ -214,13 +215,11 @@ class AccountController extends Controller
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('accounts.create.fromStore', true);
|
||||
|
||||
return Redirect::route('accounts.create')->withInput();
|
||||
return redirect(route('accounts.create', [$request->input('what')]))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('accounts.create.url'));
|
||||
|
||||
|
||||
return redirect(Session::get('accounts.create.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,6 +236,7 @@ class AccountController extends Controller
|
||||
'name' => $request->input('name'),
|
||||
'active' => $request->input('active'),
|
||||
'user' => Auth::user()->id,
|
||||
'iban' => $request->input('iban'),
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'openingBalance' => floatval($request->input('openingBalance')),
|
||||
@ -246,6 +246,7 @@ class AccountController extends Controller
|
||||
'ccMonthlyPaymentDate' => $request->input('ccMonthlyPaymentDate'),
|
||||
];
|
||||
|
||||
|
||||
$repository->update($account, $accountData);
|
||||
|
||||
Session::flash('success', 'Account "' . $account->name . '" updated.');
|
||||
@ -255,11 +256,11 @@ class AccountController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('accounts.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('accounts.edit', [$account->id])->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('accounts.edit', [$account->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('accounts.edit.url'));
|
||||
return redirect(Session::get('accounts.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
@ -79,8 +78,7 @@ class BillController extends Controller
|
||||
Session::flash('success', 'The bill was deleted.');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::to(Session::get('bills.delete.url'));
|
||||
|
||||
return redirect(Session::get('bills.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +131,7 @@ class BillController extends Controller
|
||||
if (intval($bill->active) == 0) {
|
||||
Session::flash('warning', 'Inactive bills cannot be scanned.');
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
return redirect(URL::previous());
|
||||
}
|
||||
|
||||
$journals = $repository->getPossiblyRelatedJournals($bill);
|
||||
@ -146,7 +144,7 @@ class BillController extends Controller
|
||||
Session::flash('success', 'Rescanned everything.');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
return redirect(URL::previous());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,11 +180,11 @@ class BillController extends Controller
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('bills.create.fromStore', true);
|
||||
|
||||
return Redirect::route('bills.create')->withInput();
|
||||
return redirect(route('bills.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('bills.create.url'));
|
||||
return redirect(Session::get('bills.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@ -209,11 +207,11 @@ class BillController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('bills.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('bills.edit', [$bill->id])->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('bills.edit.url'));
|
||||
return redirect(Session::get('bills.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
@ -106,7 +105,7 @@ class BudgetController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
|
||||
return Redirect::to(Session::get('budgets.delete.url'));
|
||||
return redirect(Session::get('budgets.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,7 +199,7 @@ class BudgetController extends Controller
|
||||
Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount')));
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::route('budgets.index');
|
||||
return redirect(route('budgets.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,11 +253,11 @@ class BudgetController extends Controller
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('budgets.create.fromStore', true);
|
||||
|
||||
return Redirect::route('budgets.create')->withInput();
|
||||
return redirect(route('budgets.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('budgets.create.url'));
|
||||
return redirect(Session::get('budgets.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@ -285,11 +284,11 @@ class BudgetController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('budgets.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('budgets.edit', [$budget->id])->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('budgets.edit.url'));
|
||||
return redirect(Session::get('budgets.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
@ -80,7 +79,7 @@ class CategoryController extends Controller
|
||||
Session::flash('success', 'The category "' . e($name) . '" was deleted.');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::to(Session::get('categories.delete.url'));
|
||||
return redirect(Session::get('categories.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,10 +177,10 @@ class CategoryController extends Controller
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('categories.create.fromStore', true);
|
||||
|
||||
return Redirect::route('categories.create')->withInput();
|
||||
return redirect(route('categories.create'))->withInput();
|
||||
}
|
||||
|
||||
return Redirect::route('categories.index');
|
||||
return redirect(route('categories.index'));
|
||||
}
|
||||
|
||||
|
||||
@ -206,11 +205,11 @@ class CategoryController extends Controller
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('categories.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('categories.edit', [$category->id]);
|
||||
return redirect(route('categories.edit', [$category->id]));
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('categories.edit.url'));
|
||||
return redirect(Session::get('categories.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,7 @@ class BudgetController extends Controller
|
||||
{
|
||||
$start = clone $repetition->startdate;
|
||||
$end = $repetition->enddate;
|
||||
bcscale(2);
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
@ -113,8 +114,8 @@ class BudgetController extends Controller
|
||||
/*
|
||||
* Sum of expenses on this day:
|
||||
*/
|
||||
$sum = $repository->expensesOnDayCorrected($budget, $start);
|
||||
$amount += $sum;
|
||||
$sum = $repository->expensesOnDayCorrected($budget, $start);
|
||||
$amount = bcadd($amount, $sum);
|
||||
$entries->push([clone $start, $amount]);
|
||||
$start->addDay();
|
||||
}
|
||||
|
@ -176,9 +176,7 @@ class CategoryController extends Controller
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache = new CacheProperties; // chart properties for cache:
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category');
|
||||
@ -192,14 +190,11 @@ class CategoryController extends Controller
|
||||
$entries = new Collection;
|
||||
|
||||
while ($start < $end) {
|
||||
// month is the current end of the period:
|
||||
$month = clone $start;
|
||||
$month = clone $start; // month is the current end of the period
|
||||
$month->endOfMonth();
|
||||
// make a row:
|
||||
$row = [clone $start];
|
||||
$row = [clone $start]; // make a row:
|
||||
|
||||
// each budget, fill the row:
|
||||
foreach ($categories as $category) {
|
||||
foreach ($categories as $category) { // each budget, fill the row
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
}
|
||||
|
401
app/Http/Controllers/CsvController.php
Normal file
401
app/Http/Controllers/CsvController.php
Normal file
@ -0,0 +1,401 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use App;
|
||||
use Config;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Csv\Data;
|
||||
use FireflyIII\Helpers\Csv\Importer;
|
||||
use FireflyIII\Helpers\Csv\WizardInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Input;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class CsvController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class CsvController extends Controller
|
||||
{
|
||||
|
||||
/** @var Data */
|
||||
protected $data;
|
||||
/** @var WizardInterface */
|
||||
protected $wizard;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
View::share('title', trans('firefly.csv'));
|
||||
View::share('mainTitleIcon', 'fa-file-text-o');
|
||||
|
||||
if (Config::get('firefly.csv_import_enabled') === false) {
|
||||
throw new FireflyException('CSV Import is not enabled.');
|
||||
}
|
||||
|
||||
$this->wizard = App::make('FireflyIII\Helpers\Csv\WizardInterface');
|
||||
$this->data = App::make('FireflyIII\Helpers\Csv\Data');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Define column roles and mapping.
|
||||
*
|
||||
* STEP THREE
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function columnRoles()
|
||||
{
|
||||
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
$subTitle = trans('firefly.csv_define_column_roles');
|
||||
$firstRow = $this->data->getReader()->fetchOne();
|
||||
$count = count($firstRow);
|
||||
$headers = [];
|
||||
$example = $this->data->getReader()->fetchOne(1);
|
||||
$availableRoles = [];
|
||||
$roles = $this->data->getRoles();
|
||||
$map = $this->data->getMap();
|
||||
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$headers[] = trans('firefly.csv_column') . ' #' . $i;
|
||||
}
|
||||
if ($this->data->hasHeaders()) {
|
||||
$headers = $firstRow;
|
||||
}
|
||||
|
||||
foreach (Config::get('csv.roles') as $name => $role) {
|
||||
$availableRoles[$name] = trans('firefly.csv_column_' . $name);//$role['name'];
|
||||
}
|
||||
ksort($availableRoles);
|
||||
|
||||
return view('csv.column-roles', compact('availableRoles', 'map', 'roles', 'headers', 'example', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional download of mapping.
|
||||
*
|
||||
* STEP FOUR THREE-A
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|string
|
||||
*/
|
||||
public function downloadConfig()
|
||||
{
|
||||
$fields = ['csv-date-format', 'csv-has-headers'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
$data = [
|
||||
'date-format' => Session::get('date-format'),
|
||||
'has-headers' => Session::get('csv-has-headers')
|
||||
];
|
||||
if (Session::has('csv-map')) {
|
||||
$data['map'] = Session::get('csv-map');
|
||||
}
|
||||
if (Session::has('csv-roles')) {
|
||||
$data['roles'] = Session::get('csv-roles');
|
||||
}
|
||||
if (Session::has('csv-mapped')) {
|
||||
$data['mapped'] = Session::get('csv-mapped');
|
||||
}
|
||||
|
||||
$result = json_encode($data, JSON_PRETTY_PRINT);
|
||||
$name = 'csv-configuration-' . date('Y-m-d') . '.json';
|
||||
|
||||
header('Content-disposition: attachment; filename=' . $name);
|
||||
header('Content-type: application/json');
|
||||
echo $result;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function downloadConfigPage()
|
||||
{
|
||||
$subTitle = trans('firefly.csv_download_config_title');
|
||||
|
||||
return view('csv.download-config', compact('subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method shows the initial upload form.
|
||||
*
|
||||
* STEP ONE
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.csv_import');
|
||||
|
||||
Session::forget('csv-date-format');
|
||||
Session::forget('csv-has-headers');
|
||||
Session::forget('csv-file');
|
||||
Session::forget('csv-map');
|
||||
Session::forget('csv-roles');
|
||||
Session::forget('csv-mapped');
|
||||
Session::forget('csv-specifix');
|
||||
|
||||
// get list of supported specifix
|
||||
$specifix = [];
|
||||
foreach (Config::get('csv.specifix') as $entry) {
|
||||
$specifix[$entry] = trans('firefly.csv_specifix_' . $entry);
|
||||
}
|
||||
|
||||
// can actually upload?
|
||||
$uploadPossible = is_writable(storage_path('upload'));
|
||||
$path = storage_path('upload');
|
||||
|
||||
return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the file.
|
||||
*
|
||||
* STEP FOUR
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function initialParse()
|
||||
{
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
// process given roles and mapping:
|
||||
$roles = $this->wizard->processSelectedRoles(Input::get('role'));
|
||||
$maps = $this->wizard->processSelectedMapping($roles, Input::get('map'));
|
||||
|
||||
Session::put('csv-map', $maps);
|
||||
Session::put('csv-roles', $roles);
|
||||
|
||||
// Go back when no roles defined:
|
||||
if (count($roles) === 0) {
|
||||
Session::flash('warning', 'Please select some roles.');
|
||||
|
||||
return redirect(route('csv.column-roles'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue with map specification when necessary.
|
||||
*/
|
||||
if (count($maps) > 0) {
|
||||
return redirect(route('csv.map'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Or simply start processing.
|
||||
*/
|
||||
|
||||
// proceed to download config
|
||||
return redirect(route('csv.download-config-page'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Map first if necessary,
|
||||
*
|
||||
* STEP FIVE.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
|
||||
// Make sure all fields we need are accounted for.
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
/*
|
||||
* The "options" array contains all options the user has
|
||||
* per column, where the key represents the column.
|
||||
*
|
||||
* For each key there is an array which in turn represents
|
||||
* all the options available: grouped by ID.
|
||||
*
|
||||
* options[column index] = [
|
||||
* field id => field identifier.
|
||||
* ]
|
||||
*/
|
||||
try {
|
||||
$options = $this->wizard->showOptions($this->data->getMap());
|
||||
} catch (FireflyException $e) {
|
||||
return view('error', ['message' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
// After these values are prepped, read the actual CSV file
|
||||
$reader = $this->data->getReader();
|
||||
$map = $this->data->getMap();
|
||||
$hasHeaders = $this->data->hasHeaders();
|
||||
$values = $this->wizard->getMappableValues($reader, $map, $hasHeaders);
|
||||
$map = $this->data->getMap();
|
||||
$mapped = $this->data->getMapped();
|
||||
$subTitle = trans('firefly.csv_map_values');
|
||||
|
||||
return view('csv.map', compact('map', 'options', 'values', 'mapped', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Finally actually process the CSV file.
|
||||
*
|
||||
* STEP SEVEN
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function process()
|
||||
{
|
||||
/*
|
||||
* Make sure all fields we need are accounted for.
|
||||
*/
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-mapped'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
Log::debug('Created importer');
|
||||
$importer = new Importer;
|
||||
$importer->setData($this->data);
|
||||
try {
|
||||
$importer->run();
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Catch error: ' . $e->getMessage());
|
||||
|
||||
return view('error', ['message' => $e->getMessage()]);
|
||||
}
|
||||
Log::debug('Done importing!');
|
||||
|
||||
$rows = $importer->getRows();
|
||||
$errors = $importer->getErrors();
|
||||
$imported = $importer->getImported();
|
||||
|
||||
Preferences::mark();
|
||||
|
||||
$subTitle = trans('firefly.csv_process_title');
|
||||
|
||||
return view('csv.process', compact('rows', 'errors', 'imported', 'subTitle'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the mapping the user has made. This is
|
||||
*
|
||||
* STEP SIX
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function saveMapping()
|
||||
{
|
||||
/*
|
||||
* Make sure all fields we need are accounted for.
|
||||
*/
|
||||
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles'];
|
||||
if (!$this->wizard->sessionHasValues($fields)) {
|
||||
Session::flash('warning', 'Could not recover upload.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
// save mapping to session.
|
||||
$mapped = [];
|
||||
if (!is_array(Input::get('mapping'))) {
|
||||
Session::flash('warning', 'Invalid mapping.');
|
||||
|
||||
return redirect(route('csv.map'));
|
||||
}
|
||||
|
||||
foreach (Input::get('mapping') as $index => $data) {
|
||||
$mapped[$index] = [];
|
||||
foreach ($data as $value => $mapping) {
|
||||
if (intval($mapping) !== 0) {
|
||||
$mapped[$index][$value] = $mapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
Session::put('csv-mapped', $mapped);
|
||||
|
||||
// proceed to process.
|
||||
return redirect(route('csv.download-config-page'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This method processes the file, puts it away somewhere safe
|
||||
* and sends you onwards.
|
||||
*
|
||||
* STEP TWO
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function upload(Request $request)
|
||||
{
|
||||
if (!$request->hasFile('csv')) {
|
||||
Session::flash('warning', 'No file uploaded.');
|
||||
|
||||
return redirect(route('csv.index'));
|
||||
}
|
||||
|
||||
$fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath());
|
||||
$settings = [];
|
||||
$settings['date-format'] = Input::get('date_format');
|
||||
$settings['has-headers'] = intval(Input::get('has_headers')) === 1;
|
||||
$settings['specifix'] = Input::get('specifix');
|
||||
$settings['map'] = [];
|
||||
$settings['mapped'] = [];
|
||||
$settings['roles'] = [];
|
||||
|
||||
/*
|
||||
* Process config file if present.
|
||||
*/
|
||||
if ($request->hasFile('csv_config')) {
|
||||
$data = file_get_contents($request->file('csv_config')->getRealPath());
|
||||
$json = json_decode($data, true);
|
||||
if (is_array($json)) {
|
||||
$settings = array_merge($settings, $json);
|
||||
}
|
||||
}
|
||||
|
||||
$this->data->setCsvFileLocation($fullPath);
|
||||
$this->data->setDateFormat($settings['date-format']);
|
||||
$this->data->setHasHeaders($settings['has-headers']);
|
||||
$this->data->setMap($settings['map']);
|
||||
$this->data->setMapped($settings['mapped']);
|
||||
$this->data->setRoles($settings['roles']);
|
||||
$this->data->setSpecifix($settings['specifix']);
|
||||
|
||||
return redirect(route('csv.column-roles'));
|
||||
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
@ -65,7 +64,7 @@ class CurrencyController extends Controller
|
||||
Cache::forget('FFCURRENCYSYMBOL');
|
||||
Cache::forget('FFCURRENCYCODE');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
return redirect(route('currency.index'));
|
||||
|
||||
}
|
||||
|
||||
@ -81,7 +80,7 @@ class CurrencyController extends Controller
|
||||
if ($repository->countJournals($currency) > 0) {
|
||||
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
return redirect(route('currency.index'));
|
||||
}
|
||||
|
||||
// put previous url in session
|
||||
@ -106,7 +105,7 @@ class CurrencyController extends Controller
|
||||
if ($repository->countJournals($currency) > 0) {
|
||||
Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
return redirect(route('currency.index'));
|
||||
}
|
||||
|
||||
Session::flash('success', 'Currency "' . e($currency->name) . '" deleted');
|
||||
@ -114,7 +113,7 @@ class CurrencyController extends Controller
|
||||
$currency->delete();
|
||||
}
|
||||
|
||||
return Redirect::to(Session::get('currency.delete.url'));
|
||||
return redirect(Session::get('currency.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,11 +177,11 @@ class CurrencyController extends Controller
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('currency.create.fromStore', true);
|
||||
|
||||
return Redirect::route('currency.create')->withInput();
|
||||
return redirect(route('currency.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('currency.create.url'));
|
||||
return redirect(Session::get('currency.create.url'));
|
||||
|
||||
|
||||
}
|
||||
@ -207,11 +206,11 @@ class CurrencyController extends Controller
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('currency.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('currency.edit', [$currency->id]);
|
||||
return redirect(route('currency.edit', [$currency->id]));
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('currency.edit.url'));
|
||||
return redirect(Session::get('currency.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Route;
|
||||
use Session;
|
||||
use Steam;
|
||||
@ -40,6 +39,9 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
|
||||
Preferences::mark();
|
||||
|
||||
// get all tags.
|
||||
// update all counts:
|
||||
$tags = Tag::get();
|
||||
@ -56,7 +58,7 @@ class HomeController extends Controller
|
||||
|
||||
Session::clear();
|
||||
|
||||
return Redirect::route('index');
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,10 +70,11 @@ class HomeController extends Controller
|
||||
{
|
||||
$types = Config::get('firefly.accountTypesByIdentifier.asset');
|
||||
$count = $repository->countAccounts($types);
|
||||
bcscale(2);
|
||||
|
||||
|
||||
if ($count == 0) {
|
||||
return Redirect::route('new-user.index');
|
||||
return redirect(route('new-user.index'));
|
||||
}
|
||||
|
||||
$title = 'Firefly';
|
||||
@ -90,7 +93,7 @@ class HomeController extends Controller
|
||||
|
||||
$savingsTotal = 0;
|
||||
foreach ($savings as $savingAccount) {
|
||||
$savingsTotal += Steam::balance($savingAccount, $end);
|
||||
$savingsTotal = bcadd($savingsTotal, Steam::balance($savingAccount, $end));
|
||||
}
|
||||
|
||||
$sum = $repository->sumOfEverything();
|
||||
@ -123,7 +126,7 @@ class HomeController extends Controller
|
||||
if (!Auth::user()->hasRole('owner')) {
|
||||
Session::flash('warning', 'This page is broken.');
|
||||
|
||||
return Redirect::route('index');
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
// get all routes:
|
||||
|
@ -36,6 +36,7 @@ class JsonController extends Controller
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
bcscale(2);
|
||||
|
||||
// works for json too!
|
||||
$cache = new CacheProperties;
|
||||
@ -54,7 +55,7 @@ class JsonController extends Controller
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$amount += $repository->billPaymentsInRange($bill, $start, $end);
|
||||
$amount = bcadd($amount, $repository->billPaymentsInRange($bill, $start, $end));
|
||||
}
|
||||
unset($bill, $bills);
|
||||
|
||||
@ -69,7 +70,7 @@ class JsonController extends Controller
|
||||
if ($balance == 0) {
|
||||
// find a transfer TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
$amount += $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount');
|
||||
$amount = bcadd($amount, $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount'));
|
||||
}
|
||||
}
|
||||
$data = ['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
|
||||
@ -90,6 +91,7 @@ class JsonController extends Controller
|
||||
$amount = 0;
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
bcscale(2);
|
||||
|
||||
// works for json too!
|
||||
$cache = new CacheProperties;
|
||||
@ -131,7 +133,7 @@ class JsonController extends Controller
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$amount += $current;
|
||||
$amount = bcadd($amount, $current);
|
||||
}
|
||||
|
||||
$data = ['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
|
||||
|
@ -7,7 +7,6 @@ use FireflyIII\Http\Requests\NewUserFormRequest;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
@ -35,7 +34,7 @@ class NewUserController extends Controller
|
||||
$count = $repository->countAccounts($types);
|
||||
|
||||
if ($count > 0) {
|
||||
return Redirect::route('index');
|
||||
return redirect(route('index'));
|
||||
|
||||
}
|
||||
|
||||
@ -106,6 +105,6 @@ class NewUserController extends Controller
|
||||
Session::flash('success', 'New account(s) created!');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::route('index');
|
||||
return redirect(route('index'));
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use Steam;
|
||||
use URL;
|
||||
@ -112,7 +111,7 @@ class PiggyBankController extends Controller
|
||||
Preferences::mark();
|
||||
$repository->destroy($piggyBank);
|
||||
|
||||
return Redirect::to(Session::get('piggy-banks.delete.url'));
|
||||
return redirect(Session::get('piggy-banks.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,6 +166,7 @@ class PiggyBankController extends Controller
|
||||
/** @var Collection $piggyBanks */
|
||||
$piggyBanks = $piggyRepository->getPiggyBanks();
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
bcscale(2);
|
||||
|
||||
$accounts = [];
|
||||
/** @var PiggyBank $piggyBank */
|
||||
@ -189,9 +189,9 @@ class PiggyBankController extends Controller
|
||||
'leftToSave' => $piggyBank->leftToSave
|
||||
];
|
||||
} else {
|
||||
$accounts[$account->id]['sumOfSaved'] += $piggyBank->savedSoFar;
|
||||
$accounts[$account->id]['sumOfTargets'] += floatval($piggyBank->targetamount);
|
||||
$accounts[$account->id]['leftToSave'] += $piggyBank->leftToSave;
|
||||
$accounts[$account->id]['sumOfSaved'] = bcadd($accounts[$account->id]['sumOfSaved'], $piggyBank->savedSoFar);
|
||||
$accounts[$account->id]['sumOfTargets'] = bcadd($accounts[$account->id]['sumOfTargets'], $piggyBank->targetamount);
|
||||
$accounts[$account->id]['leftToSave'] = bcadd($accounts[$account->id]['leftToSave'], $piggyBank->leftToSave);
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,10 +231,11 @@ class PiggyBankController extends Controller
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);
|
||||
bcscale(2);
|
||||
|
||||
if ($amount <= $maxAmount) {
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
$repetition->currentamount += $amount;
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
@ -246,7 +247,7 @@ class PiggyBankController extends Controller
|
||||
Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
|
||||
}
|
||||
|
||||
return Redirect::route('piggy-banks.index');
|
||||
return redirect(route('piggy-banks.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,12 +259,13 @@ class PiggyBankController extends Controller
|
||||
public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
$amount = floatval(Input::get('amount'));
|
||||
bcscale(2);
|
||||
|
||||
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
|
||||
|
||||
if ($amount <= $savedSoFar) {
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
$repetition->currentamount -= $amount;
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
$repetition->currentamount = bcsub($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
@ -275,7 +277,7 @@ class PiggyBankController extends Controller
|
||||
Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
|
||||
}
|
||||
|
||||
return Redirect::route('piggy-banks.index');
|
||||
return redirect(route('piggy-banks.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,12 +333,12 @@ class PiggyBankController extends Controller
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('piggy-banks.create.fromStore', true);
|
||||
|
||||
return Redirect::route('piggy-banks.create')->withInput();
|
||||
return redirect(route('piggy-banks.create'))->withInput();
|
||||
}
|
||||
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('piggy-banks.create.url'));
|
||||
return redirect(Session::get('piggy-banks.create.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,12 +368,12 @@ class PiggyBankController extends Controller
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('piggy-banks.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('piggy-banks.edit', [$piggyBank->id]);
|
||||
return redirect(route('piggy-banks.edit', [$piggyBank->id]));
|
||||
}
|
||||
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('piggy-banks.edit.url'));
|
||||
return redirect(Session::get('piggy-banks.edit.url'));
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ use Config;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
@ -79,7 +78,7 @@ class PreferencesController extends Controller
|
||||
Session::flash('success', 'Preferences saved!');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::route('preferences');
|
||||
return redirect(route('preferences'));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
|
||||
use FireflyIII\Http\Requests\ProfileFormRequest;
|
||||
use Hash;
|
||||
use Redirect;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
@ -56,13 +55,13 @@ class ProfileController extends Controller
|
||||
if (!Hash::check($request->get('current_password'), Auth::user()->password)) {
|
||||
Session::flash('error', 'Invalid current password!');
|
||||
|
||||
return Redirect::route('profile.change-password');
|
||||
return redirect(route('profile.change-password'));
|
||||
}
|
||||
$result = $this->validatePassword($request->get('current_password'), $request->get('new_password'));
|
||||
if (!($result === true)) {
|
||||
Session::flash('error', $result);
|
||||
|
||||
return Redirect::route('profile.change-password');
|
||||
return redirect(route('profile.change-password'));
|
||||
}
|
||||
|
||||
// update the user with the new password.
|
||||
@ -71,7 +70,7 @@ class ProfileController extends Controller
|
||||
|
||||
Session::flash('success', 'Password changed!');
|
||||
|
||||
return Redirect::route('profile');
|
||||
return redirect(route('profile'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,7 +102,7 @@ class ProfileController extends Controller
|
||||
if (!Hash::check($request->get('password'), Auth::user()->password)) {
|
||||
Session::flash('error', 'Invalid password!');
|
||||
|
||||
return Redirect::route('profile.delete-account');
|
||||
return redirect(route('profile.delete-account'));
|
||||
}
|
||||
|
||||
// DELETE!
|
||||
@ -112,7 +111,7 @@ class ProfileController extends Controller
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'delete-account');
|
||||
|
||||
return Redirect::route('index');
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,7 +88,7 @@ class ReportController extends Controller
|
||||
$budgets = $this->helper->getBudgetReport($start, $end, $shared);
|
||||
$categories = $this->helper->getCategoryReport($start, $end, $shared);
|
||||
$balance = $this->helper->getBalanceReport($start, $end, $shared);
|
||||
$bills = $this->helper->getBillReport($start, $end, $shared);
|
||||
$bills = $this->helper->getBillReport($start, $end);
|
||||
|
||||
Session::flash('gaEventCategory', 'report');
|
||||
Session::flash('gaEventAction', 'month');
|
||||
|
@ -10,7 +10,6 @@ use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
@ -108,7 +107,7 @@ class TagController extends Controller
|
||||
Session::flash('success', 'Tag "' . e($tagName) . '" was deleted.');
|
||||
Preferences::mark();
|
||||
|
||||
return Redirect::to(route('tags.index'));
|
||||
return redirect(route('tags.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,9 +220,9 @@ class TagController extends Controller
|
||||
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
|
||||
{
|
||||
if (Input::get('setTag') == 'true') {
|
||||
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
|
||||
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
|
||||
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
|
||||
$latitude = $request->get('latitude');
|
||||
$longitude = $request->get('longitude');
|
||||
$zoomLevel = $request->get('zoomLevel');
|
||||
} else {
|
||||
$latitude = null;
|
||||
$longitude = null;
|
||||
@ -248,11 +247,11 @@ class TagController extends Controller
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('tags.create.fromStore', true);
|
||||
|
||||
return Redirect::route('tags.create')->withInput();
|
||||
return redirect(route('tags.create'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('tags.create.url'));
|
||||
return redirect(Session::get('tags.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@ -295,10 +294,10 @@ class TagController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('tags.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('tags.edit', [$tag->id])->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('tags.edit', [$tag->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('tags.edit.url'));
|
||||
return redirect(Session::get('tags.edit.url'));
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Events\JournalCreated;
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
@ -12,7 +13,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
@ -108,7 +108,7 @@ class TransactionController extends Controller
|
||||
Preferences::mark();
|
||||
|
||||
// redirect to previous URL:
|
||||
return Redirect::to(Session::get('transactions.delete.url'));
|
||||
return redirect(Session::get('transactions.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,31 +190,12 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function index(JournalRepositoryInterface $repository, $what)
|
||||
{
|
||||
$types = [];
|
||||
switch ($what) {
|
||||
case 'expenses':
|
||||
case 'withdrawal':
|
||||
$subTitleIcon = 'fa-long-arrow-left';
|
||||
$subTitle = trans('firefly.expenses');
|
||||
$types = ['Withdrawal'];
|
||||
break;
|
||||
case 'revenue':
|
||||
case 'deposit':
|
||||
$subTitleIcon = 'fa-long-arrow-right';
|
||||
$subTitle = trans('firefly.income');
|
||||
$types = ['Deposit'];
|
||||
break;
|
||||
case 'transfer':
|
||||
case 'transfers':
|
||||
$subTitleIcon = 'fa-exchange';
|
||||
$subTitle = trans('firefly.transfers');
|
||||
$types = ['Transfer'];
|
||||
break;
|
||||
}
|
||||
|
||||
$page = intval(Input::get('page'));
|
||||
$offset = $page > 0 ? ($page - 1) * 50 : 0;
|
||||
$journals = $repository->getJournalsOfTypes($types, $offset, $page);
|
||||
$subTitleIcon = Config::get('firefly.transactionIconsByWhat.' . $what);
|
||||
$types = Config::get('firefly.transactionTypesByWhat.' . $what);
|
||||
$subTitle = trans('firefly.title_' . $what);
|
||||
$page = intval(Input::get('page'));
|
||||
$offset = $page > 0 ? ($page - 1) * 50 : 0;
|
||||
$journals = $repository->getJournalsOfTypes($types, $offset, $page);
|
||||
|
||||
$journals->setPath('transactions/' . $what);
|
||||
|
||||
@ -295,11 +276,11 @@ class TransactionController extends Controller
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('transactions.create.fromStore', true);
|
||||
|
||||
return Redirect::route('transactions.create', [$request->input('what')])->withInput();
|
||||
return redirect(route('transactions.create', [$request->input('what')]))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('transactions.create.url'));
|
||||
return redirect(Session::get('transactions.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@ -327,11 +308,11 @@ class TransactionController extends Controller
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('transactions.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('transactions.edit', [$journal->id])->withInput(['return_to_edit' => 1]);
|
||||
return redirect(route('transactions.edit', [$journal->id]))->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('transactions.edit.url'));
|
||||
return redirect(Session::get('transactions.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ class AccountFormRequest extends Request
|
||||
'id' => $idRule,
|
||||
'name' => $nameRule,
|
||||
'openingBalance' => 'numeric',
|
||||
'iban' => 'iban',
|
||||
'virtualBalance' => 'numeric',
|
||||
'openingBalanceDate' => 'date',
|
||||
'accountRole' => 'in:' . $accountRoles,
|
||||
|
@ -161,6 +161,43 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
|
||||
// CSV:
|
||||
Breadcrumbs::register(
|
||||
'csv.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('firefly.csv_index_title'), route('csv.index'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'csv.column-roles', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('csv.index');
|
||||
$breadcrumbs->push(trans('firefly.csv_define_column_roles'), route('csv.column-roles'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'csv.map', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('csv.index');
|
||||
$breadcrumbs->push(trans('firefly.csv_map_values'), route('csv.map'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'csv.download-config-page', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('csv.index');
|
||||
$breadcrumbs->push(trans('firefly.csv_download_config'), route('csv.download-config-page'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'csv.process', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('csv.index');
|
||||
$breadcrumbs->push(trans('firefly.csv_process_title'), route('csv.process'));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// currencies.
|
||||
Breadcrumbs::register(
|
||||
'currency.index', function (Generator $breadcrumbs) {
|
||||
|
@ -181,7 +181,7 @@ Route::group(
|
||||
* Bills Controller
|
||||
*/
|
||||
Route::get('/bills', ['uses' => 'BillController@index', 'as' => 'bills.index']);
|
||||
Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching.
|
||||
Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']);
|
||||
Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']);
|
||||
Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']);
|
||||
Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
|
||||
@ -194,7 +194,7 @@ Route::group(
|
||||
* Budget Controller
|
||||
*/
|
||||
Route::get('/budgets', ['uses' => 'BudgetController@index', 'as' => 'budgets.index']);
|
||||
Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']); # extra.
|
||||
Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']);
|
||||
Route::get('/budgets/create', ['uses' => 'BudgetController@create', 'as' => 'budgets.create']);
|
||||
Route::get('/budgets/edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']);
|
||||
Route::get('/budgets/delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']);
|
||||
@ -219,6 +219,21 @@ Route::group(
|
||||
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
|
||||
Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']);
|
||||
|
||||
|
||||
/**
|
||||
* CSV controller
|
||||
*/
|
||||
Route::get('/csv', ['uses' => 'CsvController@index', 'as' => 'csv.index']);
|
||||
Route::post('/csv/upload', ['uses' => 'CsvController@upload', 'as' => 'csv.upload']);
|
||||
Route::get('/csv/column_roles', ['uses' => 'CsvController@columnRoles', 'as' => 'csv.column-roles']);
|
||||
Route::post('/csv/initial_parse', ['uses' => 'CsvController@initialParse', 'as' => 'csv.initial_parse']);
|
||||
Route::get('/csv/map', ['uses' => 'CsvController@map', 'as' => 'csv.map']);
|
||||
Route::get('/csv/download-config', ['uses' => 'CsvController@downloadConfig', 'as' => 'csv.download-config']);
|
||||
Route::get('/csv/download', ['uses' => 'CsvController@downloadConfigPage', 'as' => 'csv.download-config-page']);
|
||||
Route::post('/csv/save_mapping', ['uses' => 'CsvController@saveMapping', 'as' => 'csv.save_mapping']);
|
||||
|
||||
Route::get('/csv/process', ['uses' => 'CsvController@process', 'as' => 'csv.process']);
|
||||
|
||||
/**
|
||||
* Currency Controller
|
||||
*/
|
||||
@ -297,8 +312,8 @@ Route::group(
|
||||
* Piggy Bank Controller
|
||||
*/
|
||||
Route::get('/piggy-banks', ['uses' => 'PiggyBankController@index', 'as' => 'piggy-banks.index']);
|
||||
Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'piggy-banks.addMoney']); # add money
|
||||
Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'piggy-banks.removeMoney']); #remove money
|
||||
Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'piggy-banks.addMoney']);
|
||||
Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'piggy-banks.removeMoney']);
|
||||
Route::get('/piggy-banks/create', ['uses' => 'PiggyBankController@create', 'as' => 'piggy-banks.create']);
|
||||
Route::get('/piggy-banks/edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'piggy-banks.edit']);
|
||||
Route::get('/piggy-banks/delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'piggy-banks.delete']);
|
||||
@ -306,8 +321,8 @@ Route::group(
|
||||
Route::post('/piggy-banks/store', ['uses' => 'PiggyBankController@store', 'as' => 'piggy-banks.store']);
|
||||
Route::post('/piggy-banks/update/{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'piggy-banks.update']);
|
||||
Route::post('/piggy-banks/destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'piggy-banks.destroy']);
|
||||
Route::post('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy-banks.add']); # add money
|
||||
Route::post('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy-banks.remove']); # remove money.
|
||||
Route::post('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy-banks.add']);
|
||||
Route::post('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy-banks.remove']);
|
||||
Route::post('/piggy-banks/sort', ['uses' => 'PiggyBankController@order', 'as' => 'piggy-banks.order']);
|
||||
|
||||
/**
|
||||
|
@ -47,18 +47,21 @@ use Watson\Validating\ValidatingTrait;
|
||||
* @property mixed piggyBalance
|
||||
* @property mixed difference
|
||||
* @property mixed percentage
|
||||
* @property string $iban
|
||||
* @property-read mixed $name_for_editform
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereIban($value)
|
||||
*/
|
||||
class Account extends Model
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance'];
|
||||
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban'];
|
||||
protected $hidden = ['virtual_balance_encrypted', 'encrypted'];
|
||||
protected $rules
|
||||
= [
|
||||
'user_id' => 'required|exists:users,id',
|
||||
'account_type_id' => 'required|exists:account_types,id',
|
||||
'name' => 'required|between:1,1024|uniqueAccountForUser',
|
||||
'name' => 'required',
|
||||
'active' => 'required|boolean'
|
||||
];
|
||||
|
||||
@ -71,11 +74,12 @@ class Account extends Model
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Account::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$query = Account::orderBy('id');
|
||||
$search = $fields;
|
||||
unset($search['name'], $search['iban']);
|
||||
|
||||
foreach ($search as $name => $value) {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$set = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
@ -84,6 +88,11 @@ class Account extends Model
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
// account must have a name. If not set, use IBAN.
|
||||
if (!isset($fields['name'])) {
|
||||
$fields['name'] = $fields['iban'];
|
||||
}
|
||||
|
||||
// create it!
|
||||
$account = Account::create($fields);
|
||||
|
||||
@ -99,11 +108,11 @@ class Account extends Model
|
||||
public static function firstOrNullEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Account::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$query = Account::orderBy('id');
|
||||
$search = $fields;
|
||||
unset($search['name']);
|
||||
foreach ($search as $name => $value) {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$set = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
@ -143,6 +152,22 @@ class Account extends Model
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIbanAttribute($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $fieldName
|
||||
@ -236,6 +261,16 @@ class Account extends Model
|
||||
$query->where($joinName . '.data', json_encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param $value
|
||||
*/
|
||||
public function setIbanAttribute($value)
|
||||
{
|
||||
$this->attributes['iban'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
|
@ -40,6 +40,7 @@ class Budget extends Model
|
||||
/**
|
||||
* @param array $fields
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return Budget
|
||||
@ -47,11 +48,11 @@ class Budget extends Model
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Budget::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$query = Budget::orderBy('id');
|
||||
$search = $fields;
|
||||
unset($search['name']);
|
||||
foreach ($search as $name => $value) {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$set = $query->get(['budgets.*']);
|
||||
/** @var Budget $budget */
|
||||
|
@ -43,11 +43,12 @@ class Category extends Model
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Category::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$query = Category::orderBy('id');
|
||||
$search = $fields;
|
||||
unset($search['name']);
|
||||
foreach ($search as $name => $value) {
|
||||
$query->where($name, $value);
|
||||
|
||||
}
|
||||
$set = $query->get(['categories.*']);
|
||||
/** @var Category $category */
|
||||
|
@ -37,6 +37,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
|
||||
* @property PiggyBankRepetition currentRep
|
||||
* @property string $reminder
|
||||
* @property integer $reminder_skip
|
||||
* @property boolean $remind_me
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
|
||||
*/
|
||||
class PiggyBank extends Model
|
||||
{
|
||||
|
@ -62,14 +62,13 @@ class Tag extends Model
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the tag:
|
||||
if (isset($fields['tagMode'])) {
|
||||
unset($fields['tagMode']);
|
||||
}
|
||||
unset($fields['tagMode']);
|
||||
$search = $fields;
|
||||
unset($search['name']);
|
||||
|
||||
$query = Tag::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'tag') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
foreach ($search as $name => $value) {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
$set = $query->get(['tags.*']);
|
||||
/** @var Tag $tag */
|
||||
|
@ -91,6 +91,9 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
|
||||
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
|
||||
|
||||
// CSV import
|
||||
$this->app->bind('FireflyIII\Helpers\Csv\WizardInterface', 'FireflyIII\Helpers\Csv\Wizard');
|
||||
|
||||
// make charts:
|
||||
// alternative is Google instead of ChartJs
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Account\AccountChartGenerator', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator');
|
||||
|
@ -389,7 +389,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
public function store(array $data)
|
||||
{
|
||||
$newAccount = $this->storeAccount($data);
|
||||
$this->storeMetadata($newAccount, $data);
|
||||
if (!is_null($newAccount)) {
|
||||
$this->storeMetadata($newAccount, $data);
|
||||
}
|
||||
|
||||
|
||||
// continue with the opposing account:
|
||||
@ -401,9 +403,12 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'virtualBalance' => 0,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
'iban' => '',
|
||||
];
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
$this->storeInitialBalance($newAccount, $opposing, $data);
|
||||
if (!is_null($opposing) && !is_null($newAccount)) {
|
||||
$this->storeInitialBalance($newAccount, $opposing, $data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -431,6 +436,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$account->name = $data['name'];
|
||||
$account->active = $data['active'] == '1' ? true : false;
|
||||
$account->virtual_balance = $data['virtualBalance'];
|
||||
$account->iban = $data['iban'];
|
||||
$account->save();
|
||||
|
||||
$this->updateMetadata($account, $data);
|
||||
@ -453,7 +459,9 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'virtualBalance' => 0,
|
||||
];
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
$this->storeInitialBalance($account, $opposing, $data);
|
||||
if (!is_null($opposing)) {
|
||||
$this->storeInitialBalance($account, $opposing, $data);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -481,6 +489,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'name' => $data['name'],
|
||||
'virtual_balance' => $data['virtualBalance'],
|
||||
'active' => $data['active'] === true ? true : false,
|
||||
'iban' => $data['iban'],
|
||||
]
|
||||
);
|
||||
|
||||
@ -490,7 +499,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'user_id' => $data['user'],
|
||||
'account_type_id' => $accountType->id,
|
||||
'virtual_balance' => $data['virtualBalance'],
|
||||
'name' => $data['name']
|
||||
'name' => $data['name'],
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
||||
if (!$existingAccount) {
|
||||
@ -556,7 +566,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
);
|
||||
$journal->save();
|
||||
|
||||
|
||||
if ($data['openingBalance'] < 0) {
|
||||
$firstAccount = $opposing;
|
||||
$secondAccount = $account;
|
||||
@ -568,26 +577,11 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$firstAmount = $data['openingBalance'];
|
||||
$secondAmount = $data['openingBalance'] * -1;
|
||||
}
|
||||
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
|
||||
$one->save();// first transaction: from
|
||||
|
||||
// first transaction: from
|
||||
$one = new Transaction(
|
||||
[
|
||||
'account_id' => $firstAccount->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'amount' => $firstAmount
|
||||
]
|
||||
);
|
||||
$one->save();
|
||||
|
||||
// second transaction: to
|
||||
$two = new Transaction(
|
||||
[
|
||||
'account_id' => $secondAccount->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'amount' => $secondAmount
|
||||
]
|
||||
);
|
||||
$two->save();
|
||||
$two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
|
||||
$two->save(); // second transaction: to
|
||||
|
||||
return $journal;
|
||||
|
||||
@ -596,6 +590,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function updateMetadata(Account $account, array $data)
|
||||
{
|
||||
|
@ -115,14 +115,14 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param int $journalId
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function getWithDate($id, Carbon $date)
|
||||
public function getWithDate($journalId, Carbon $date)
|
||||
{
|
||||
return Auth::user()->transactionjournals()->where('id', $id)->where('date', $date->format('Y-m-d 00:00:00'))->first();
|
||||
return Auth::user()->transactionjournals()->where('id', $journalId)->where('date', $date->format('Y-m-d 00:00:00'))->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +143,9 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
foreach ($array as $name) {
|
||||
if (strlen(trim($name)) > 0) {
|
||||
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
|
||||
$tagRepository->connect($journal, $tag);
|
||||
if (!is_null($tag)) {
|
||||
$tagRepository->connect($journal, $tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,19 +188,19 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
}
|
||||
|
||||
// store accounts (depends on type)
|
||||
list($from, $to) = $this->storeAccounts($transactionType, $data);
|
||||
list($fromAccount, $toAccount) = $this->storeAccounts($transactionType, $data);
|
||||
|
||||
// store accompanying transactions.
|
||||
Transaction::create( // first transaction.
|
||||
[
|
||||
'account_id' => $from->id,
|
||||
'account_id' => $fromAccount->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'amount' => $data['amount'] * -1
|
||||
]
|
||||
);
|
||||
Transaction::create( // second transaction.
|
||||
[
|
||||
'account_id' => $to->id,
|
||||
'account_id' => $toAccount->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'amount' => $data['amount']
|
||||
]
|
||||
@ -246,7 +248,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
}
|
||||
|
||||
// store accounts (depends on type)
|
||||
list($from, $to) = $this->storeAccounts($journal->transactionType, $data);
|
||||
list($fromAccount, $toAccount) = $this->storeAccounts($journal->transactionType, $data);
|
||||
|
||||
// update the from and to transaction.
|
||||
/** @var Transaction $transaction */
|
||||
@ -254,12 +256,12 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
if (floatval($transaction->amount) < 0) {
|
||||
// this is the from transaction, negative amount:
|
||||
$transaction->amount = $data['amount'] * -1;
|
||||
$transaction->account_id = $from->id;
|
||||
$transaction->account_id = $fromAccount->id;
|
||||
$transaction->save();
|
||||
}
|
||||
if (floatval($transaction->amount) > 0) {
|
||||
$transaction->amount = $data['amount'];
|
||||
$transaction->account_id = $to->id;
|
||||
$transaction->account_id = $toAccount->id;
|
||||
$transaction->save();
|
||||
}
|
||||
}
|
||||
|
@ -62,12 +62,12 @@ interface JournalRepositoryInterface
|
||||
public function getTransactionType($type);
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param int $journalId
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function getWithDate($id, Carbon $date);
|
||||
public function getWithDate($journalId, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
|
@ -26,9 +26,7 @@ class ComponentRepository
|
||||
*/
|
||||
protected function spentInPeriod($object, Carbon $start, Carbon $end, $shared = false)
|
||||
{
|
||||
// we must cache this.
|
||||
|
||||
$cache = new CacheProperties;
|
||||
$cache = new CacheProperties; // we must cache this.
|
||||
$cache->addProperty($object->id);
|
||||
$cache->addProperty(get_class($object));
|
||||
$cache->addProperty($start);
|
||||
@ -40,21 +38,13 @@ class ComponentRepository
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
if ($shared === true) {
|
||||
// shared is true.
|
||||
// always ignore transfers between accounts!
|
||||
$sum
|
||||
= $object->transactionjournals()
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->before($end)->after($start)->get(['transaction_journals.*'])->sum('amount');
|
||||
|
||||
if ($shared === true) { // shared is true: always ignore transfers between accounts!
|
||||
$sum = $object->transactionjournals()->transactionTypes(['Withdrawal'])->before($end)->after($start)
|
||||
->get(['transaction_journals.*'])->sum('amount');
|
||||
} else {
|
||||
// do something else, SEE budgets.
|
||||
// get all journals in this month where the asset account is NOT shared.
|
||||
$sum = $object->transactionjournals()
|
||||
->before($end)
|
||||
->after($start)
|
||||
$sum = $object->transactionjournals()->before($end)->after($start)
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
@ -62,9 +52,7 @@ class ComponentRepository
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->where('account_meta.data', '!=', '"sharedAsset"')
|
||||
->get(['transaction_journals.*'])->sum('amount');
|
||||
)->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('amount');
|
||||
}
|
||||
|
||||
$cache->store($sum);
|
||||
|
@ -65,7 +65,6 @@ class Amount
|
||||
return '<span class="text-danger">' . $symbol . ' ' . $string . '</span>';
|
||||
}
|
||||
|
||||
// €
|
||||
return $symbol . ' ' . $string;
|
||||
}
|
||||
|
||||
|
@ -262,6 +262,27 @@ class ExpandedForm
|
||||
return $selectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $list
|
||||
* @param null $selected
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function multiCheckbox($name, array $list = [], $selected = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$selected = $this->fillFieldValue($name, $selected);
|
||||
|
||||
unset($options['class']);
|
||||
$html = View::make('form.multiCheckbox', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $list
|
||||
@ -347,6 +368,23 @@ class ExpandedForm
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function file($name, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$html = View::make('form.file', compact('classes', 'name', 'label', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
|
@ -83,7 +83,7 @@ class Navigation
|
||||
$subDay = ['week', 'weekly', '1W', 'month', 'monthly', '1M', '3M', 'quarter', 'quarterly', '6M', 'half-year', 'year', 'yearly'];
|
||||
|
||||
if (!isset($functionMap[$repeatFreq])) {
|
||||
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq "' . $repeatFreq . '"');
|
||||
}
|
||||
$function = $functionMap[$repeatFreq];
|
||||
if (isset($modifierMap[$repeatFreq])) {
|
||||
@ -204,7 +204,7 @@ class Navigation
|
||||
|
||||
return $date;
|
||||
}
|
||||
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq "' . $repeatFreq . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,7 +246,7 @@ class Navigation
|
||||
return $date;
|
||||
}
|
||||
|
||||
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq "' . $repeatFreq . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,7 +282,7 @@ class Navigation
|
||||
|
||||
return $end;
|
||||
}
|
||||
throw new FireflyException('updateEndDate cannot handle $range "' . $range.'"');
|
||||
throw new FireflyException('updateEndDate cannot handle $range "' . $range . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,7 +316,7 @@ class Navigation
|
||||
|
||||
return $start;
|
||||
}
|
||||
throw new FireflyException('updateStartDate cannot handle $range "' . $range.'"');
|
||||
throw new FireflyException('updateStartDate cannot handle $range "' . $range . '"');
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,7 +11,6 @@ use Zizaco\Entrust\Traits\EntrustUserTrait;
|
||||
* Class User
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @package FireflyIII
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
|
@ -54,6 +54,41 @@ class FireflyValidator extends Validator
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validateIban($attribute, $value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($value) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = strtoupper($value);
|
||||
if (strlen($value) < 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$search = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||
$replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31',
|
||||
'32', '33', '34', '35'];
|
||||
|
||||
// take
|
||||
$first = substr($value, 0, 4);
|
||||
$last = substr($value, 4);
|
||||
$iban = $last . $first;
|
||||
$iban = str_replace($search, $replace, $iban);
|
||||
$checksum = bcmod($iban, '97');
|
||||
|
||||
return (intval($checksum) === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
@ -173,9 +208,10 @@ class FireflyValidator extends Validator
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $parameters
|
||||
*
|
||||
* @return bool
|
||||
* @internal param $parameters
|
||||
*
|
||||
*/
|
||||
protected function validateByAccountId($value)
|
||||
{
|
||||
|
21
codeception.yml
Normal file
21
codeception.yml
Normal file
@ -0,0 +1,21 @@
|
||||
actor: Tester
|
||||
paths:
|
||||
tests: tests
|
||||
log: tests/_output
|
||||
data: tests/_data
|
||||
support: tests/_support
|
||||
envs: tests/_envs
|
||||
settings:
|
||||
bootstrap: _bootstrap.php
|
||||
colors: true
|
||||
memory_limit: 1024M
|
||||
extensions:
|
||||
enabled:
|
||||
- Codeception\Extension\RunFailed
|
||||
modules:
|
||||
config:
|
||||
Db:
|
||||
dsn: ''
|
||||
user: ''
|
||||
password: ''
|
||||
dump: tests/_data/dump.sql
|
@ -28,7 +28,9 @@
|
||||
"illuminate/html": "~5.0",
|
||||
"league/commonmark": "0.7.*",
|
||||
"rcrowe/twigbridge": "0.7.x@dev",
|
||||
"zizaco/entrust": "dev-laravel-5"
|
||||
"zizaco/entrust": "dev-laravel-5",
|
||||
"codeception/codeception": "*",
|
||||
"league/csv": "^7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "@stable",
|
||||
|
1490
composer.lock
generated
1490
composer.lock
generated
File diff suppressed because it is too large
Load Diff
197
config/csv.php
Normal file
197
config/csv.php
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
return [
|
||||
'specifix' => [
|
||||
'RabobankDescription',
|
||||
'Dummy'
|
||||
],
|
||||
'post_processors' => [
|
||||
'Description',
|
||||
'Amount',
|
||||
'Currency',
|
||||
'Bill',
|
||||
'OpposingAccount', // must be after Amount!
|
||||
|
||||
],
|
||||
'roles' => [
|
||||
'_ignore' => [
|
||||
'name' => '(ignore this column)',
|
||||
'mappable' => false,
|
||||
'converter' => 'Ignore',
|
||||
'field' => 'ignored',
|
||||
],
|
||||
'bill-id' => [
|
||||
'name' => 'Bill ID (matching Firefly)',
|
||||
'mappable' => false,
|
||||
'field' => 'bill',
|
||||
'converter' => 'BillId',
|
||||
'mapper' => 'Bill',
|
||||
],
|
||||
'bill-name' => [
|
||||
'name' => 'Bill name',
|
||||
'mappable' => true,
|
||||
'converter' => 'BillName',
|
||||
'field' => 'bill',
|
||||
'mapper' => 'Bill',
|
||||
],
|
||||
'currency-id' => [
|
||||
'name' => 'Currency ID (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyId',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
],
|
||||
'currency-name' => [
|
||||
'name' => 'Currency name (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyName',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
],
|
||||
'currency-code' => [
|
||||
'name' => 'Currency code (ISO 4217)',
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyCode',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
],
|
||||
'currency-symbol' => [
|
||||
'name' => 'Currency symbol (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencySymbol',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
],
|
||||
'description' => [
|
||||
'name' => 'Description',
|
||||
'mappable' => false,
|
||||
'converter' => 'Description',
|
||||
'field' => 'description',
|
||||
],
|
||||
'date-transaction' => [
|
||||
'name' => 'Date',
|
||||
'mappable' => false,
|
||||
'converter' => 'Date',
|
||||
'field' => 'date',
|
||||
],
|
||||
'date-rent' => [
|
||||
'name' => 'Rent calculation date',
|
||||
'mappable' => false,
|
||||
'converter' => 'Date',
|
||||
'field' => 'date-rent',
|
||||
],
|
||||
'budget-id' => [
|
||||
'name' => 'Budget ID (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'converter' => 'BudgetId',
|
||||
'field' => 'budget',
|
||||
'mapper' => 'Budget',
|
||||
],
|
||||
'budget-name' => [
|
||||
'name' => 'Budget name',
|
||||
'mappable' => true,
|
||||
'converter' => 'BudgetName',
|
||||
'field' => 'budget',
|
||||
'mapper' => 'Budget',
|
||||
],
|
||||
'rabo-debet-credit' => [
|
||||
'name' => 'Rabobank specific debet/credit indicator',
|
||||
'mappable' => false,
|
||||
'converter' => 'RabobankDebetCredit',
|
||||
'field' => 'amount-modifier',
|
||||
],
|
||||
'category-id' => [
|
||||
'name' => 'Category ID (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'converter' => 'CategoryId',
|
||||
'field' => 'category',
|
||||
'mapper' => 'Category',
|
||||
],
|
||||
'category-name' => [
|
||||
'name' => 'Category name',
|
||||
'mappable' => true,
|
||||
'converter' => 'CategoryName',
|
||||
'field' => 'category',
|
||||
'mapper' => 'Category',
|
||||
],
|
||||
'tags-comma' => [
|
||||
'name' => 'Tags (comma separated)',
|
||||
'mappable' => true,
|
||||
'field' => 'tags',
|
||||
'converter' => 'TagsComma',
|
||||
'mapper' => 'Tag',
|
||||
],
|
||||
'tags-space' => [
|
||||
'name' => 'Tags (space separated)',
|
||||
'mappable' => true,
|
||||
'field' => 'tags',
|
||||
'converter' => 'TagsSpace',
|
||||
'mapper' => 'Tag',
|
||||
],
|
||||
'account-id' => [
|
||||
'name' => 'Asset account ID (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'mapper' => 'AssetAccount',
|
||||
'field' => 'asset-account',
|
||||
'converter' => 'AccountId'
|
||||
],
|
||||
'account-name' => [
|
||||
'name' => 'Asset account name',
|
||||
'mappable' => true,
|
||||
'mapper' => 'AssetAccount',
|
||||
'field' => 'asset-account',
|
||||
'converter' => 'AssetAccountName'
|
||||
],
|
||||
'account-iban' => [
|
||||
'name' => 'Asset account IBAN',
|
||||
'mappable' => true,
|
||||
'converter' => 'AssetAccountIban',
|
||||
'field' => 'asset-account',
|
||||
'mapper' => 'AssetAccount'
|
||||
],
|
||||
'opposing-id' => [
|
||||
'name' => 'Opposing account account ID (matching Firefly)',
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-id',
|
||||
'converter' => 'OpposingAccountId',
|
||||
'mapper' => 'AnyAccount',
|
||||
],
|
||||
'opposing-name' => [
|
||||
'name' => 'Opposing account name',
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-name',
|
||||
'converter' => 'OpposingAccountName',
|
||||
'mapper' => 'AnyAccount',
|
||||
],
|
||||
'opposing-iban' => [
|
||||
'name' => 'Opposing account IBAN',
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-iban',
|
||||
'converter' => 'OpposingAccountIban',
|
||||
'mapper' => 'AnyAccount',
|
||||
],
|
||||
'amount' => [
|
||||
'name' => 'Amount',
|
||||
'mappable' => false,
|
||||
'converter' => 'Amount',
|
||||
'field' => 'amount',
|
||||
],
|
||||
'sepa-ct-id' => [
|
||||
'name' => 'SEPA Credit Transfer end-to-end ID',
|
||||
'mappable' => false,
|
||||
'converter' => 'Description',
|
||||
'field' => 'description',
|
||||
],
|
||||
'sepa-ct-op' => [
|
||||
'name' => 'SEPA Credit Transfer opposing account',
|
||||
'mappable' => false,
|
||||
'converter' => 'Description',
|
||||
'field' => 'description',
|
||||
],
|
||||
'sepa-db' => [
|
||||
'name' => 'SEPA Direct Debet',
|
||||
'mappable' => false,
|
||||
'converter' => 'Description',
|
||||
'field' => 'description',
|
||||
],
|
||||
]
|
||||
];
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user