James Cole 2025-01-19 07:18:07 +01:00
parent 4b2807de48
commit 950c60d55c
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Support\Export;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
@ -50,6 +52,8 @@ use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Support\Collection;
@ -82,8 +86,8 @@ class ExportDataGenerator
public function __construct()
{
$this->accounts = new Collection();
$this->start = today(config('app.timezone'));
$this->accounts = new Collection();
$this->start = today(config('app.timezone'));
$this->start->subYear();
$this->end = today(config('app.timezone'));
$this->exportTransactions = false;
@ -141,7 +145,7 @@ class ExportDataGenerator
*/
private function exportAccounts(): string
{
$header = [
$header = [
'user_id',
'account_id',
'created_at',
@ -162,7 +166,7 @@ class ExportDataGenerator
];
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($this->user);
$allAccounts = $repository->getAccountsByType([]);
$records = [];
@ -192,7 +196,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -230,8 +234,8 @@ class ExportDataGenerator
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->setUser($this->user);
$bills = $repository->getBills();
$header = [
$bills = $repository->getBills();
$header = [
'user_id',
'bill_id',
'created_at',
@ -245,7 +249,7 @@ class ExportDataGenerator
'skip',
'active',
];
$records = [];
$records = [];
/** @var Bill $bill */
foreach ($bills as $bill) {
@ -266,7 +270,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -296,7 +300,7 @@ class ExportDataGenerator
*/
private function exportBudgets(): string
{
$header = [
$header = [
'user_id',
'budget_id',
'name',
@ -310,9 +314,9 @@ class ExportDataGenerator
$budgetRepos = app(BudgetRepositoryInterface::class);
$budgetRepos->setUser($this->user);
$limitRepos = app(BudgetLimitRepositoryInterface::class);
$budgets = $budgetRepos->getBudgets();
$records = [];
$limitRepos = app(BudgetLimitRepositoryInterface::class);
$budgets = $budgetRepos->getBudgets();
$records = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
@ -335,7 +339,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -365,10 +369,10 @@ class ExportDataGenerator
*/
private function exportCategories(): string
{
$header = ['user_id', 'category_id', 'created_at', 'updated_at', 'name'];
$header = ['user_id', 'category_id', 'created_at', 'updated_at', 'name'];
/** @var CategoryRepositoryInterface $catRepos */
$catRepos = app(CategoryRepositoryInterface::class);
$catRepos = app(CategoryRepositoryInterface::class);
$catRepos->setUser($this->user);
$records = [];
@ -386,7 +390,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -417,14 +421,14 @@ class ExportDataGenerator
private function exportPiggies(): string
{
/** @var PiggyBankRepositoryInterface $piggyRepos */
$piggyRepos = app(PiggyBankRepositoryInterface::class);
$piggyRepos = app(PiggyBankRepositoryInterface::class);
$piggyRepos->setUser($this->user);
/** @var AccountRepositoryInterface $accountRepos */
$accountRepos = app(AccountRepositoryInterface::class);
$accountRepos->setUser($this->user);
$header = [
$header = [
'user_id',
'piggy_bank_id',
'created_at',
@ -440,8 +444,8 @@ class ExportDataGenerator
'order',
'active',
];
$records = [];
$piggies = $piggyRepos->getPiggyBanks();
$records = [];
$piggies = $piggyRepos->getPiggyBanks();
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
@ -466,7 +470,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -499,7 +503,7 @@ class ExportDataGenerator
/** @var RecurringRepositoryInterface $recurringRepos */
$recurringRepos = app(RecurringRepositoryInterface::class);
$recurringRepos->setUser($this->user);
$header = [
$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',
@ -508,8 +512,8 @@ class ExportDataGenerator
// 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();
$records = [];
$recurrences = $recurringRepos->getAll();
/** @var Recurrence $recurrence */
foreach ($recurrences as $recurrence) {
@ -542,7 +546,7 @@ class ExportDataGenerator
$piggyBankId = $recurringRepos->getPiggyBank($transaction);
$tags = $recurringRepos->getTags($transaction);
$records[] = [
$records[] = [
// recurrence
$this->user->id,
$recurrence->id,
@ -558,7 +562,7 @@ class ExportDataGenerator
}
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -595,8 +599,8 @@ class ExportDataGenerator
'action_type', 'action_value', 'action_order', 'action_active', 'action_stop_processing'];
$ruleRepos = app(RuleRepositoryInterface::class);
$ruleRepos->setUser($this->user);
$rules = $ruleRepos->getAll();
$records = [];
$rules = $ruleRepos->getAll();
$records = [];
/** @var Rule $rule */
foreach ($rules as $rule) {
@ -635,7 +639,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -665,12 +669,12 @@ class ExportDataGenerator
*/
private function exportTags(): string
{
$header = ['user_id', 'tag_id', 'created_at', 'updated_at', 'tag', 'date', 'description', 'latitude', 'longitude', 'zoom_level'];
$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 = [];
$tags = $tagRepos->get();
$records = [];
/** @var Tag $tag */
foreach ($tags as $tag) {
@ -689,7 +693,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {
@ -728,33 +732,57 @@ class ExportDataGenerator
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', 'notes'];
$header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'currency_code', 'amount', 'foreign_currency_code', 'foreign_amount', 'native_currency_code', 'native_amount', 'native_foreign_amount', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban', 'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags', 'notes'];
$metaFields = config('firefly.journal_meta_fields');
$header = array_merge($header, $metaFields);
$default = Amount::getDefaultCurrency();
$collector = app(GroupCollectorInterface::class);
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user);
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
->withBudgetInformation()->withTagInformation()->withNotes()
;
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()->withBudgetInformation()->withTagInformation()->withNotes();
if (0 !== $this->accounts->count()) {
$collector->setAccounts($this->accounts);
}
$journals = $collector->getExtractedJournals();
$journals = $collector->getExtractedJournals();
// get repository for meta data:
$repository = app(TransactionGroupRepositoryInterface::class);
$repository->setUser($this->user);
$records = [];
$records = [];
/** @var array $journal */
foreach ($journals as $journal) {
$metaData = $repository->getMetaFields($journal['transaction_journal_id'], $metaFields);
$metaData = $repository->getMetaFields($journal['transaction_journal_id'], $metaFields);
$amount = Steam::bcround(Steam::negative($journal['amount']), $journal['currency_decimal_places']);
$foreignAmount = null === $journal['foreign_amount'] ? null : Steam::bcround(Steam::negative($journal['foreign_amount']), $journal['foreign_currency_decimal_places']);
$nativeAmount = null === $journal['native_amount'] ? null : Steam::bcround(Steam::negative($journal['native_amount'], $default->decimal_places));
$nativeForeignAmount = null === $journal['native_foreign_amount'] ? null : Steam::bcround(Steam::negative($journal['native_foreign_amount'], $default->decimal_places));
if (TransactionTypeEnum::WITHDRAWAL->value !== $journal['transaction_type_type']) {
$amount = Steam::bcround(Steam::positive($journal['amount']), $journal['currency_decimal_places']);
$foreignAmount = null === $journal['foreign_amount'] ? null : Steam::bcround(Steam::positive($journal['foreign_amount']), $journal['foreign_currency_decimal_places']);
$nativeAmount = null === $journal['native_amount'] ? null : Steam::bcround(Steam::positive($journal['native_amount'], $default->decimal_places));
$nativeForeignAmount = null === $journal['native_foreign_amount'] ? null : Steam::bcround(Steam::positive($journal['native_foreign_amount'], $default->decimal_places));
}
// opening balance depends on source account type.
if (TransactionTypeEnum::OPENING_BALANCE->value === $journal['transaction_type_type'] && AccountTypeEnum::ASSET->value === $journal['source_account_type']) {
$amount = Steam::bcround(Steam::negative($journal['amount']), $journal['currency_decimal_places']);
$foreignAmount = null === $journal['foreign_amount'] ? null : Steam::bcround(Steam::negative($journal['foreign_amount']), $journal['foreign_currency_decimal_places']);
$nativeAmount = null === $journal['native_amount'] ? null : Steam::bcround(Steam::negative($journal['native_amount'], $default->decimal_places));
$nativeForeignAmount = null === $journal['native_foreign_amount'] ? null : Steam::bcround(Steam::negative($journal['native_foreign_amount'], $default->decimal_places));
}
$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'],
$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'],
// amounts and currencies
$journal['currency_code'], $amount, $journal['foreign_currency_code'], $foreignAmount, $default->code, $nativeAmount, $nativeForeignAmount,
// more fields
$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'],
$this->mergeTags($journal['tags']),
$this->clearStringKeepNewlines($journal['notes']),
@ -773,7 +801,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = Writer::createFromString();
// insert the header
try {