mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Code to export stuff. #2667
This commit is contained in:
parent
63fa6aa6c0
commit
5dd5351b0a
@ -19,27 +19,65 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
namespace FireflyIII\Console\Commands\Export;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Console\Commands\VerifiesAccessToken;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use InvalidArgumentException;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ExportData
|
||||
*/
|
||||
class ExportData extends Command
|
||||
{
|
||||
use VerifiesAccessToken;
|
||||
|
||||
/** @var JournalRepositoryInterface */
|
||||
private $journalRepository;
|
||||
|
||||
/** @var AccountRepositoryInterface */
|
||||
private $accountRepository;
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'I export data.';
|
||||
protected $description = 'Command to export data from Firefly III.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:export-data';
|
||||
protected $signature = 'firefly-iii:export-data
|
||||
{--user=1 : The user ID that the export should run for.}
|
||||
{--token= : The user\'s access token.}
|
||||
{--start= : First transaction to export. Defaults to your very first transaction. Only applies to transaction export.}
|
||||
{--end= : Last transaction to export. Defaults to today. Only applies to transaction export.}
|
||||
{--accounts= : From which accounts or liabilities to export. Only applies to transaction export. Defaults to all of your asset accounts.}
|
||||
{--export_directory=./ : Where to store the export files.}
|
||||
{--export-transactions : Create a file with all your transactions and their meta data. This flag and the other flags can be combined.}
|
||||
{--export-accounts : Create a file with all your accounts and some meta data.}
|
||||
{--export-budgets : Create a file with all your budgets and some meta data.}
|
||||
{--export-categories : Create a file with all your categories and some meta data.}
|
||||
{--export-tags : Create a file with all your tags and some meta data.}
|
||||
{--export-recurring : Create a file with all your recurring transactions and some meta data.}
|
||||
{--export-rules : Create a file with all your rules and some meta data.}
|
||||
{--export-bills : Create a file with all your bills and some meta data.}
|
||||
{--export-piggies : Create a file with all your piggy banks and some meta data.}
|
||||
{--force : Force overwriting of previous exports if found.}';
|
||||
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@ -54,10 +92,206 @@ class ExportData extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
* @return int
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle()
|
||||
public function handle(): int
|
||||
{
|
||||
//
|
||||
// verify access token
|
||||
if (!$this->verifyAccessToken()) {
|
||||
$this->error('Invalid access token.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
// set up repositories.
|
||||
$this->stupidLaravel();
|
||||
$this->user = $this->getUser();
|
||||
$this->journalRepository->setUser($this->user);
|
||||
$this->accountRepository->setUser($this->user);
|
||||
// get the options.
|
||||
try {
|
||||
$options = $this->parseOptions();
|
||||
} catch (FireflyException $e) {
|
||||
$this->error(sprintf('Could not work with your options: %s', $e));
|
||||
|
||||
return 1;
|
||||
}
|
||||
// make export object and configure it.
|
||||
|
||||
/** @var ExportDataGenerator $exporter */
|
||||
$exporter = app(ExportDataGenerator::class);
|
||||
$exporter->setUser($this->user);
|
||||
$exporter->setStart($options['start']);
|
||||
$exporter->setEnd($options['end']);
|
||||
$exporter->setExportTransactions($options['export']['transactions']);
|
||||
$exporter->setExportAccounts($options['export']['accounts']);
|
||||
$exporter->setExportBudgets($options['export']['budgets']);
|
||||
$exporter->setExportCategories($options['export']['categories']);
|
||||
$exporter->setExportTags($options['export']['tags']);
|
||||
$exporter->setExportRecurring($options['export']['recurring']);
|
||||
$exporter->setExportRules($options['export']['rules']);
|
||||
$exporter->setExportBills($options['export']['bills']);
|
||||
$exporter->setExportPiggies($options['export']['piggies']);
|
||||
|
||||
$data = $exporter->export();
|
||||
|
||||
try {
|
||||
$this->exportData($options, $data);
|
||||
} catch (FireflyException $e) {
|
||||
$this->error(sprintf('Could not store data: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @param array $data
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function exportData(array $options, array $data): void
|
||||
{
|
||||
$date = date('Y_m_d');
|
||||
foreach ($data as $key => $content) {
|
||||
$file = sprintf('%s%s_%s.csv', $options['directory'], $date, $key);
|
||||
if (false === $options['force'] && file_exists($file)) {
|
||||
throw new FireflyException(sprintf('File "%s" exists already. Use --force to overwrite.', $file));
|
||||
}
|
||||
if (true === $options['force'] && file_exists($file)) {
|
||||
$this->warn(sprintf('File "%s" exists already but will be replaced.', $file));
|
||||
}
|
||||
// continue to write to file.
|
||||
file_put_contents($file, $content);
|
||||
$this->info(sprintf('Wrote %s-export to file "%s".', $key, $file));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getAccountsParameter(): Collection
|
||||
{
|
||||
$final = new Collection;
|
||||
$accounts = new Collection;
|
||||
$accountList = $this->option('accounts');
|
||||
$types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||
if (null !== $accountList && '' !== (string)$accountList) {
|
||||
$accountIds = explode(',', $accountList);
|
||||
$accounts = $this->accountRepository->getAccountsById($accountIds);
|
||||
}
|
||||
if (null === $accountList) {
|
||||
$accounts = $this->accountRepository->getAccountsByType($types);
|
||||
}
|
||||
// filter accounts,
|
||||
/** @var AccountType $account */
|
||||
foreach ($accounts as $account) {
|
||||
if (in_array($account->accountType->type, $types, true)) {
|
||||
$final->push($account);
|
||||
}
|
||||
}
|
||||
if (0 === $final->count()) {
|
||||
throw new FireflyException('Ended up with zero valid accounts to export from.');
|
||||
}
|
||||
|
||||
return $final;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getDateParameter(string $field): Carbon
|
||||
{
|
||||
$date = null;
|
||||
if (null !== $this->option($field)) {
|
||||
try {
|
||||
$date = Carbon::createFromFormat('Y-m-d', $this->option($field));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::error($e->getMessage());
|
||||
throw new FireflyException(sprintf('%s date "%s" must be formatted YYYY-MM-DD', $field, $this->option('start')));
|
||||
}
|
||||
}
|
||||
if (null === $date && 'start' === $field) {
|
||||
$journal = $this->journalRepository->firstNull();
|
||||
$date = null === $journal ? Carbon::now()->subYear() : $date;
|
||||
}
|
||||
if (null === $date && 'end' === $field) {
|
||||
$date = new Carbon;
|
||||
}
|
||||
if ('start' === $date) {
|
||||
$date->startOfDay();
|
||||
}
|
||||
if ('end' === $date) {
|
||||
$date->endOfDay();
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function getExportDirectory(): string
|
||||
{
|
||||
$directory = $this->option('export_directory');
|
||||
if (null === $directory) {
|
||||
$directory = './';
|
||||
}
|
||||
if (!is_writable($directory)) {
|
||||
throw new FireflyException(sprintf('Directory "%s" isn\'t writeable.', $directory));
|
||||
}
|
||||
|
||||
return $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function parseOptions(): array
|
||||
{
|
||||
$start = $this->getDateParameter('start');
|
||||
$end = $this->getDateParameter('end');
|
||||
$accounts = $this->getAccountsParameter();
|
||||
$export = $this->getExportDirectory();
|
||||
|
||||
return [
|
||||
'export' => [
|
||||
'transactions' => $this->option('export-transactions'),
|
||||
'accounts' => $this->option('export-accounts'),
|
||||
'budgets' => $this->option('export-budgets'),
|
||||
'categories' => $this->option('export-categories'),
|
||||
'tags' => $this->option('export-tags'),
|
||||
'recurring' => $this->option('export-recurring'),
|
||||
'rules' => $this->option('export-rules'),
|
||||
'bills' => $this->option('export-bills'),
|
||||
'piggies' => $this->option('export-piggies'),
|
||||
],
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'accounts' => $accounts,
|
||||
'directory' => $export,
|
||||
'force' => $this->option('force'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
|
||||
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
|
||||
* be called from the handle method instead of using the constructor to initialize the command.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function stupidLaravel(): void
|
||||
{
|
||||
$this->journalRepository = app(JournalRepositoryInterface::class);
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace FireflyIII\Http\Controllers\Export;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\Export\ExportFileGenerator;
|
||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
|
||||
/**
|
||||
@ -63,8 +63,11 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
/** @var ExportFileGenerator $generator */
|
||||
$generator = app(ExportFileGenerator::class);
|
||||
/** @var ExportDataGenerator $generator */
|
||||
$generator = app(ExportDataGenerator::class);
|
||||
$generator->setUser(auth()->user());
|
||||
|
||||
$generator->setExportTransactions(true);
|
||||
|
||||
// get first transaction in DB:
|
||||
$firstDate = new Carbon;
|
||||
|
708
app/Support/Export/ExportDataGenerator.php
Normal file
708
app/Support/Export/ExportDataGenerator.php
Normal file
@ -0,0 +1,708 @@
|
||||
<?php
|
||||
/**
|
||||
* ExportDataGenerator.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Support\Export;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceRepetition;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use League\Csv\Writer;
|
||||
|
||||
/**
|
||||
* Class ExportDataGenerator
|
||||
*/
|
||||
class ExportDataGenerator
|
||||
{
|
||||
/** @var Carbon */
|
||||
private $end;
|
||||
/** @var bool */
|
||||
private $exportTransactions;
|
||||
/** @var Carbon */
|
||||
private $start;
|
||||
/** @var bool */
|
||||
private $exportAccounts;
|
||||
/** @var bool */
|
||||
private $exportBudgets;
|
||||
/** @var bool */
|
||||
private $exportCategories;
|
||||
/** @var bool */
|
||||
private $exportTags;
|
||||
/** @var bool */
|
||||
private $exportRecurring;
|
||||
/** @var bool */
|
||||
private $exportRules;
|
||||
/** @var bool */
|
||||
private $exportBills;
|
||||
/** @var bool */
|
||||
private $exportPiggies;
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->start = new Carbon;
|
||||
$this->start->subYear();
|
||||
$this->end = new Carbon;
|
||||
$this->exportTransactions = false;
|
||||
$this->exportAccounts = false;
|
||||
$this->exportBudgets = false;
|
||||
$this->exportCategories = false;
|
||||
$this->exportTags = false;
|
||||
$this->exportRecurring = false;
|
||||
$this->exportRules = false;
|
||||
$this->exportBills = false;
|
||||
$this->exportPiggies = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \League\Csv\CannotInsertRecord
|
||||
*/
|
||||
public function export(): array
|
||||
{
|
||||
$return = [];
|
||||
if ($this->exportAccounts) {
|
||||
$return['accounts'] = $this->exportAccounts();
|
||||
}
|
||||
if ($this->exportBills) {
|
||||
$return['bills'] = $this->exportBills();
|
||||
}
|
||||
if ($this->exportBudgets) {
|
||||
$return['budgets'] = $this->exportBudgets();
|
||||
}
|
||||
if ($this->exportCategories) {
|
||||
$return['categories'] = $this->exportCategories();
|
||||
}
|
||||
if ($this->exportPiggies) {
|
||||
$return['piggies'] = $this->exportPiggies();
|
||||
}
|
||||
if ($this->exportRecurring) {
|
||||
$return['recurrences'] = $this->exportRecurring();
|
||||
}
|
||||
if ($this->exportRules) {
|
||||
$return['rules'] = $this->exportRules();
|
||||
}
|
||||
if ($this->exportTags) {
|
||||
$return['tags'] = $this->exportTags();
|
||||
}
|
||||
if ($this->exportTransactions) {
|
||||
$return['transactions'] = $this->exportTransactions();
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportAccounts
|
||||
*/
|
||||
public function setExportAccounts(bool $exportAccounts): void
|
||||
{
|
||||
$this->exportAccounts = $exportAccounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportBudgets
|
||||
*/
|
||||
public function setExportBudgets(bool $exportBudgets): void
|
||||
{
|
||||
$this->exportBudgets = $exportBudgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportCategories
|
||||
*/
|
||||
public function setExportCategories(bool $exportCategories): void
|
||||
{
|
||||
$this->exportCategories = $exportCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportTags
|
||||
*/
|
||||
public function setExportTags(bool $exportTags): void
|
||||
{
|
||||
$this->exportTags = $exportTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportRecurring
|
||||
*/
|
||||
public function setExportRecurring(bool $exportRecurring): void
|
||||
{
|
||||
$this->exportRecurring = $exportRecurring;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportRules
|
||||
*/
|
||||
public function setExportRules(bool $exportRules): void
|
||||
{
|
||||
$this->exportRules = $exportRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportBills
|
||||
*/
|
||||
public function setExportBills(bool $exportBills): void
|
||||
{
|
||||
$this->exportBills = $exportBills;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportPiggies
|
||||
*/
|
||||
public function setExportPiggies(bool $exportPiggies): void
|
||||
{
|
||||
$this->exportPiggies = $exportPiggies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $end
|
||||
*/
|
||||
public function setEnd(Carbon $end): void
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportTransactions
|
||||
*/
|
||||
public function setExportTransactions(bool $exportTransactions): void
|
||||
{
|
||||
$this->exportTransactions = $exportTransactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
*/
|
||||
public function setStart(Carbon $start): void
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportRules(): string
|
||||
{
|
||||
$header = ['user_id', 'rule_id', 'row_contains', 'created_at', 'updated_at', 'group_id', 'group_name', 'title', 'description', 'order', 'active',
|
||||
'stop_processing', 'strict', 'trigger_type', 'trigger_value', 'trigger_order', 'trigger_active', 'trigger_stop_processing', 'action_type',
|
||||
'action_value', 'action_order', 'action_active', 'action_stop_processing',];
|
||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||
$ruleRepos->setUser($this->user);
|
||||
$rules = $ruleRepos->getAll();
|
||||
$records = [];
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$records[] = [
|
||||
$this->user->id, $rule->id, 'rule',
|
||||
$rule->created_at->toAtomString(), $rule->updated_at->toAtomString(),
|
||||
$rule->ruleGroup->id, $rule->ruleGroup->name,
|
||||
$rule->title, $rule->description, $rule->order, $rule->active, $rule->stop_processing, $rule->strict,
|
||||
];
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
$records[] = [
|
||||
$this->user->id, $rule->id, 'trigger',
|
||||
null, null,
|
||||
null, null,
|
||||
null, null, null, null, null, null,
|
||||
$trigger->trigger_type, $trigger->trigger_value, $trigger->order, $trigger->active, $trigger->stop_processing,
|
||||
];
|
||||
}
|
||||
|
||||
/** @var RuleAction $action */
|
||||
foreach ($rule->ruleActions as $action) {
|
||||
$records[] = [
|
||||
$this->user->id, $rule->id, 'action',
|
||||
null, null,
|
||||
null, null,
|
||||
null, null, null, null, null, null,
|
||||
null, null, null, null, null,
|
||||
$action->action_type, $action->action_value, $action->order, $action->active, $action->stop_processing,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportAccounts(): string
|
||||
{
|
||||
$header = ['user_id', 'account_id', 'created_at', 'updated_at', 'type', 'name', 'virtual_balance', 'iban', 'number', 'active', 'currency_code', 'role',
|
||||
'cc_type', 'cc_payment_date', 'in_net_worth', 'interest', 'interest_period',];
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser($this->user);
|
||||
$accounts = $repository->getAccountsByType([]);
|
||||
$records = [];
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $repository->getAccountCurrency($account);
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$account->id,
|
||||
$account->created_at->toAtomString(),
|
||||
$account->updated_at->toAtomString(),
|
||||
$account->accountType->type,
|
||||
$account->name,
|
||||
$account->virtual_balance,
|
||||
$account->iban,
|
||||
$account->account_number,
|
||||
$account->active,
|
||||
$currency ? $currency->code : null,
|
||||
$repository->getMetaValue($account, 'account_role'),
|
||||
$repository->getMetaValue($account, 'cc_type'),
|
||||
$repository->getMetaValue($account, 'cc_monthly_payment_date'),
|
||||
$repository->getMetaValue($account, 'include_net_worth'),
|
||||
$repository->getMetaValue($account, 'interest'),
|
||||
$repository->getMetaValue($account, 'interest_period'),
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportBills(): string
|
||||
{
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser($this->user);
|
||||
$bills = $repository->getBills();
|
||||
$header = ['user_id', 'bill_id', 'created_at', 'updated_at', 'currency_code', 'name', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip',
|
||||
'active',];
|
||||
$records = [];
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$bill->id,
|
||||
$bill->created_at->toAtomString(),
|
||||
$bill->updated_at->toAtomString(),
|
||||
$bill->transactionCurrency->code,
|
||||
$bill->name,
|
||||
$bill->amount_min,
|
||||
$bill->amount_max,
|
||||
$bill->date->format('Y-m-d'),
|
||||
$bill->repeat_freq,
|
||||
$bill->skip,
|
||||
$bill->active,
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \League\Csv\CannotInsertRecord
|
||||
*/
|
||||
private function exportBudgets(): string
|
||||
{
|
||||
$header = [
|
||||
'user_id',
|
||||
'budget_id',
|
||||
'name',
|
||||
'active',
|
||||
'order',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'currency_code',
|
||||
'amount',
|
||||
];
|
||||
|
||||
$budgetRepos = app(BudgetRepositoryInterface::class);
|
||||
$budgetRepos->setUser($this->user);
|
||||
$limitRepos = app(BudgetLimitRepositoryInterface::class);
|
||||
$budgets = $budgetRepos->getBudgets();
|
||||
$records = [];
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$limits = $limitRepos->getBudgetLimits($budget);
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$budget->id,
|
||||
$budget->name,
|
||||
$budget->active,
|
||||
$budget->order,
|
||||
$limit->start_date->format('Y-m-d'),
|
||||
$limit->end_date->format('Y-m-d'),
|
||||
$limit->transactionCurrency->code,
|
||||
$limit->amount,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportCategories(): string
|
||||
{
|
||||
$header = ['user_id', 'category_id', 'created_at', 'updated_at', 'name'];
|
||||
|
||||
/** @var CategoryRepositoryInterface $catRepos */
|
||||
$catRepos = app(CategoryRepositoryInterface::class);
|
||||
$catRepos->setUser($this->user);
|
||||
|
||||
$records = [];
|
||||
$categories = $catRepos->getCategories();
|
||||
|
||||
/** @var Category $category */
|
||||
foreach ($categories as $category) {
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$category->id,
|
||||
$category->created_at->toAtomString(),
|
||||
$category->updated_at->toAtomString(),
|
||||
$category->name,
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportPiggies(): string
|
||||
{
|
||||
/** @var PiggyBankRepositoryInterface $piggyRepos */
|
||||
$piggyRepos = app(PiggyBankRepositoryInterface::class);
|
||||
$piggyRepos->setUser($this->user);
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepos */
|
||||
$accountRepos = app(AccountRepositoryInterface::class);
|
||||
$accountRepos->setUser($this->user);
|
||||
|
||||
$header = ['user_id', 'piggy_bank_id', 'created_at', 'updated_at', 'account_name', 'account_type', 'name',
|
||||
'currency_code', 'target_amount', 'current_amount', 'start_date', 'target_date', 'order',
|
||||
'active'];
|
||||
$records = [];
|
||||
$piggies = $piggyRepos->getPiggyBanks();
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
$repetition = $piggyRepos->getRepetition($piggy);
|
||||
$currency = $accountRepos->getAccountCurrency($piggy->account);
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$piggy->id,
|
||||
$piggy->created_at->toAtomString(),
|
||||
$piggy->updated_at->toAtomString(),
|
||||
$piggy->account->name,
|
||||
$piggy->account->accountType->type,
|
||||
$piggy->name,
|
||||
$currency ? $currency->code : null,
|
||||
$piggy->targetamount,
|
||||
$repetition ? $repetition->currentamount : null,
|
||||
$piggy->startdate->format('Y-m-d'),
|
||||
$piggy->targetdate ? $piggy->targetdate->format('Y-m-d') : null,
|
||||
$piggy->order,
|
||||
$piggy->active,
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportRecurring(): string
|
||||
{
|
||||
/** @var RecurringRepositoryInterface $recurringRepos */
|
||||
$recurringRepos = app(RecurringRepositoryInterface::class);
|
||||
$recurringRepos->setUser($this->user);
|
||||
$header = [
|
||||
// recurrence:
|
||||
'user_id', 'recurrence_id', 'row_contains', 'created_at', 'updated_at', 'type', 'title', 'description', 'first_date', 'repeat_until',
|
||||
'latest_date', 'repetitions', 'apply_rules', 'active',
|
||||
|
||||
// repetition info:
|
||||
'type', 'moment', 'skip', 'weekend',
|
||||
// transactions + meta:
|
||||
'currency_code', 'foreign_currency_code', 'source_name', 'source_type', 'destination_name', 'destination_type', 'amount', 'foreign_amount',
|
||||
'category', 'budget', 'piggy_bank', 'tags',
|
||||
];
|
||||
$records = [];
|
||||
$recurrences = $recurringRepos->getAll();
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($recurrences as $recurrence) {
|
||||
// add recurrence:
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$recurrence->id,
|
||||
'recurrence',
|
||||
$recurrence->created_at->toAtomString(),
|
||||
$recurrence->updated_at->toAtomString(),
|
||||
$recurrence->transactionType->type,
|
||||
$recurrence->title,
|
||||
$recurrence->description,
|
||||
$recurrence->first_date ? $recurrence->first_date->format('Y-m-d') : null,
|
||||
$recurrence->repeat_until ? $recurrence->repeat_until->format('Y-m-d') : null,
|
||||
$recurrence->latest_date ? $recurrence->repeat_until->format('Y-m-d') : null,
|
||||
$recurrence->repetitions,
|
||||
$recurrence->apply_rules,
|
||||
$recurrence->active,
|
||||
];
|
||||
// add new row for each repetition
|
||||
/** @var RecurrenceRepetition $repetition */
|
||||
foreach ($recurrence->recurrenceRepetitions as $repetition) {
|
||||
$records[] = [
|
||||
// recurrence
|
||||
$this->user->id,
|
||||
$recurrence->id, 'repetition', null, null, null, null, null, null, null, null, null, null, null,
|
||||
|
||||
// repetition:
|
||||
$repetition->repetition_type, $repetition->repetition_moment, $repetition->repetition_skip, $repetition->weekend,
|
||||
];
|
||||
}
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
||||
$categoryName = $recurringRepos->getCategory($transaction);
|
||||
$budgetId = $recurringRepos->getBudget($transaction);
|
||||
$piggyBankId = $recurringRepos->getPiggyBank($transaction);
|
||||
$tags = $recurringRepos->getTags($transaction);
|
||||
|
||||
$records[] = [
|
||||
// recurrence
|
||||
$this->user->id,
|
||||
$recurrence->id, 'transaction', null, null, null, null, null, null, null, null, null, null, null,
|
||||
|
||||
// repetition:
|
||||
null, null, null, null,
|
||||
|
||||
// transaction:
|
||||
$transaction->transactionCurrency->code, $transaction->foreignCurrency ? $transaction->foreignCurrency->code : null,
|
||||
$transaction->sourceAccount->name, $transaction->sourceAccount->accountType->type, $transaction->destinationAccount->name,
|
||||
$transaction->destinationAccount->accountType->type, $transaction->amount, $transaction->foreign_amount,
|
||||
$categoryName, $budgetId, $piggyBankId, implode(',', $tags),
|
||||
];
|
||||
}
|
||||
}
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportTags(): string
|
||||
{
|
||||
$header = ['user_id', 'tag_id', 'created_at', 'updated_at', 'tag', 'date', 'description', 'latitude', 'longitude', 'zoom_level'];
|
||||
|
||||
$tagRepos = app(TagRepositoryInterface::class);
|
||||
$tagRepos->setUser($this->user);
|
||||
$tags = $tagRepos->get();
|
||||
$records = [];
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$records[] = [
|
||||
$this->user->id,
|
||||
$tag->id,
|
||||
$tag->created_at->toAtomString(),
|
||||
$tag->updated_at->toAtomString(),
|
||||
$tag->tag,
|
||||
$tag->date ? $tag->date->format('Y-m-d') : null,
|
||||
$tag->description,
|
||||
$tag->latitude,
|
||||
$tag->longitude,
|
||||
$tag->zoomLevel,
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportTransactions(): string
|
||||
{
|
||||
// TODO better place for keys?
|
||||
$header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'amount', 'foreign_amount', 'currency_code',
|
||||
'foreign_currency_code', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban',
|
||||
'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags',];
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($this->user);
|
||||
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
|
||||
->withBudgetInformation();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
$records = [];
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$records[] = [
|
||||
$journal['user_id'],
|
||||
$journal['transaction_group_id'],
|
||||
$journal['transaction_journal_id'],
|
||||
$journal['created_at']->toAtomString(),
|
||||
$journal['updated_at']->toAtomString(),
|
||||
$journal['transaction_group_title'],
|
||||
$journal['transaction_type_type'],
|
||||
$journal['amount'],
|
||||
$journal['foreign_amount'],
|
||||
$journal['currency_code'],
|
||||
$journal['foreign_currency_code'],
|
||||
$journal['description'],
|
||||
$journal['date']->toAtomString(),
|
||||
$journal['source_account_name'],
|
||||
$journal['source_account_iban'],
|
||||
$journal['source_account_type'],
|
||||
$journal['destination_account_name'],
|
||||
$journal['destination_account_iban'],
|
||||
$journal['destination_account_type'],
|
||||
$journal['reconciled'],
|
||||
$journal['category_name'],
|
||||
$journal['budget_name'],
|
||||
$journal['bill_name'],
|
||||
implode(',', $journal['tags']),
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ExportFileGenerator.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Support\Export;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use League\Csv\Writer;
|
||||
|
||||
/**
|
||||
* Class ExportFileGenerator
|
||||
*/
|
||||
class ExportFileGenerator
|
||||
{
|
||||
/** @var Carbon */
|
||||
private $end;
|
||||
/** @var bool */
|
||||
private $exportTransactions;
|
||||
/** @var Carbon */
|
||||
private $start;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->start = new Carbon;
|
||||
$this->start->subYear();
|
||||
$this->end = new Carbon;
|
||||
$this->exportTransactions = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function export(): array
|
||||
{
|
||||
$return = [];
|
||||
if ($this->exportTransactions) {
|
||||
$return['transactions'] = $this->exportTransactions();
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $end
|
||||
*/
|
||||
public function setEnd(Carbon $end): void
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $exportTransactions
|
||||
*/
|
||||
public function setExportTransactions(bool $exportTransactions): void
|
||||
{
|
||||
$this->exportTransactions = $exportTransactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
*/
|
||||
public function setStart(Carbon $start): void
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function exportTransactions(): string
|
||||
{
|
||||
// TODO better place for keys?
|
||||
$header = [
|
||||
'user_id',
|
||||
'group_id',
|
||||
'journal_id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'group_title',
|
||||
'type',
|
||||
'amount',
|
||||
'foreign_amount',
|
||||
'currency_code',
|
||||
'foreign_currency_code',
|
||||
'description',
|
||||
'date',
|
||||
'source_name',
|
||||
'source_iban',
|
||||
'source_type',
|
||||
'destination_name',
|
||||
'destination_iban',
|
||||
'destination_type',
|
||||
'reconciled',
|
||||
'category',
|
||||
'budget',
|
||||
'bill',
|
||||
'tags',
|
||||
];
|
||||
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
|
||||
->withBudgetInformation();
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
$records = [];
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$records[] = [
|
||||
$journal['user_id'],
|
||||
$journal['transaction_group_id'],
|
||||
$journal['transaction_journal_id'],
|
||||
$journal['created_at']->toAtomString(),
|
||||
$journal['updated_at']->toAtomString(),
|
||||
$journal['transaction_group_title'],
|
||||
$journal['transaction_type_type'],
|
||||
$journal['amount'],
|
||||
$journal['foreign_amount'],
|
||||
$journal['currency_code'],
|
||||
$journal['foreign_currency_code'],
|
||||
$journal['description'],
|
||||
$journal['date']->toAtomString(),
|
||||
$journal['source_account_name'],
|
||||
$journal['source_account_iban'],
|
||||
$journal['source_account_type'],
|
||||
$journal['destination_account_name'],
|
||||
$journal['destination_account_iban'],
|
||||
$journal['destination_account_type'],
|
||||
$journal['reconciled'],
|
||||
$journal['category_name'],
|
||||
$journal['budget_name'],
|
||||
$journal['bill_name'],
|
||||
implode(',', $journal['tags']),
|
||||
];
|
||||
}
|
||||
|
||||
//load the CSV document from a string
|
||||
$csv = Writer::createFromString('');
|
||||
|
||||
//insert the header
|
||||
$csv->insertOne($header);
|
||||
|
||||
//insert all the records
|
||||
$csv->insertAll($records);
|
||||
|
||||
return $csv->getContent(); //returns the CSV document as a string
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user