diff --git a/app/Api/V2/Controllers/Transaction/List/TransactionController.php b/app/Api/V2/Controllers/Transaction/List/TransactionController.php
index 326c4cb907..50731dbf73 100644
--- a/app/Api/V2/Controllers/Transaction/List/TransactionController.php
+++ b/app/Api/V2/Controllers/Transaction/List/TransactionController.php
@@ -83,7 +83,7 @@ class TransactionController extends Controller
// collect transactions:
/** @var GroupCollectorInterface $collector */
- $collector = app(GroupCollectorInterface::class);
+ $collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setStartRow($request->getStartRow())
@@ -92,8 +92,8 @@ class TransactionController extends Controller
->setSorting($instructions)
;
- $start = $this->parameters->get('start');
- $end = $this->parameters->get('end');
+ $start = $this->parameters->get('start');
+ $end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
@@ -101,8 +101,8 @@ class TransactionController extends Controller
$collector->setEnd($end);
}
- $paginator = $collector->getPaginatedGroups();
- $params = $request->buildParams();
+ $paginator = $collector->getPaginatedGroups();
+ $params = $request->buildParams();
$paginator->setPath(
sprintf(
'%s?%s',
diff --git a/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php b/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php
index c341890e1a..90d6df7fe0 100644
--- a/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php
+++ b/app/Api/V2/Request/Model/Transaction/InfiniteListRequest.php
@@ -88,26 +88,28 @@ class InfiniteListRequest extends FormRequest
return 0 === $page || $page > 65536 ? 1 : $page;
}
- public function getSortInstructions(): array {
+ public function getSortInstructions(): array
+ {
$allowed = config('firefly.sorting.allowed.transactions');
- $set = $this->get('sorting', []);
- $result= [];
- if(0 === count($set)) {
+ $set = $this->get('sorting', []);
+ $result = [];
+ if (0 === count($set)) {
return [];
}
- foreach($set as $info) {
- $column = $info['column'] ?? 'NOPE';
- $direction = $info['direction'] ?? 'NOPE';
- if('asc' !== $direction && 'desc' !== $direction) {
+ foreach ($set as $info) {
+ $column = $info['column'] ?? 'NOPE';
+ $direction = $info['direction'] ?? 'NOPE';
+ if ('asc' !== $direction && 'desc' !== $direction) {
// skip invalid direction
continue;
}
- if(in_array($column, $allowed, true) === false) {
+ if (false === in_array($column, $allowed, true)) {
// skip invalid column
continue;
}
$result[$column] = $direction;
}
+
return $result;
}
diff --git a/app/Helpers/Collector/Extensions/CollectorProperties.php b/app/Helpers/Collector/Extensions/CollectorProperties.php
index aa8a3c58dc..e111761fa4 100644
--- a/app/Helpers/Collector/Extensions/CollectorProperties.php
+++ b/app/Helpers/Collector/Extensions/CollectorProperties.php
@@ -33,7 +33,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
*/
trait CollectorProperties
{
-
public array $sorting;
public const string TEST = 'Test';
private ?int $endRow;
diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php
index da37788608..bf86d91f98 100644
--- a/app/Helpers/Collector/GroupCollector.php
+++ b/app/Helpers/Collector/GroupCollector.php
@@ -61,15 +61,15 @@ class GroupCollector implements GroupCollectorInterface
*/
public function __construct()
{
- $this->sorting = [];
- $this->postFilters = [];
- $this->tags = [];
- $this->user = null;
- $this->userGroup = null;
- $this->limit = null;
- $this->page = null;
- $this->startRow = null;
- $this->endRow = null;
+ $this->sorting = [];
+ $this->postFilters = [];
+ $this->tags = [];
+ $this->user = null;
+ $this->userGroup = null;
+ $this->limit = null;
+ $this->page = null;
+ $this->startRow = null;
+ $this->endRow = null;
$this->hasAccountInfo = false;
$this->hasCatInformation = false;
@@ -291,7 +291,7 @@ class GroupCollector implements GroupCollectorInterface
if (is_int($param)) {
$replace = (string)$param;
}
- $pos = strpos($query, '?');
+ $pos = strpos($query, '?');
if (false !== $pos) {
$query = substr_replace($query, $replace, $pos, 1);
}
@@ -459,16 +459,16 @@ class GroupCollector implements GroupCollectorInterface
// add to query:
$this->query->orWhereIn('transaction_journals.transaction_group_id', $groupIds);
}
- $result = $this->query->get($this->fields);
+ $result = $this->query->get($this->fields);
// now to parse this into an array.
- $collection = $this->parseArray($result);
+ $collection = $this->parseArray($result);
// filter the array using all available post filters:
- $collection = $this->postFilterCollection($collection);
+ $collection = $this->postFilterCollection($collection);
// sort the collection, if sort instructions are present.
- $collection = $this->sortCollection($collection);
+ $collection = $this->sortCollection($collection);
// count it and continue:
$this->total = $collection->count();
@@ -501,12 +501,12 @@ class GroupCollector implements GroupCollectorInterface
/** @var TransactionJournal $augumentedJournal */
foreach ($collection as $augumentedJournal) {
- $groupId = (int)$augumentedJournal->transaction_group_id;
+ $groupId = (int)$augumentedJournal->transaction_group_id;
if (!array_key_exists($groupId, $groups)) {
// make new array
- $parsedGroup = $this->parseAugmentedJournal($augumentedJournal);
- $groupArray = [
+ $parsedGroup = $this->parseAugmentedJournal($augumentedJournal);
+ $groupArray = [
'id' => (int)$augumentedJournal->transaction_group_id,
'user_id' => $augumentedJournal->user_id,
'user_group_id' => $augumentedJournal->user_group_id,
@@ -578,7 +578,7 @@ class GroupCollector implements GroupCollectorInterface
}
// try to process meta date value (if present)
- $dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date'];
+ $dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date'];
if (array_key_exists('meta_name', $result) && in_array($result['meta_name'], $dates, true)) {
$name = $result['meta_name'];
if (array_key_exists('meta_data', $result) && '' !== (string)$result['meta_data']) {
@@ -587,15 +587,15 @@ class GroupCollector implements GroupCollectorInterface
}
// convert values to integers:
- $result = $this->convertToInteger($result);
+ $result = $this->convertToInteger($result);
// convert back to strings because SQLite is dumb like that.
- $result = $this->convertToStrings($result);
+ $result = $this->convertToStrings($result);
- $result['reconciled'] = 1 === (int)$result['reconciled'];
+ $result['reconciled'] = 1 === (int)$result['reconciled'];
if (array_key_exists('tag_id', $result) && null !== $result['tag_id']) { // assume the other fields are present as well.
- $tagId = (int)$augumentedJournal['tag_id'];
- $tagDate = null;
+ $tagId = (int)$augumentedJournal['tag_id'];
+ $tagDate = null;
try {
$tagDate = Carbon::parse($augumentedJournal['tag_date']);
@@ -659,9 +659,9 @@ class GroupCollector implements GroupCollectorInterface
{
$newArray = $newJournal->toArray();
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
- $tagId = (int)$newJournal['tag_id'];
+ $tagId = (int)$newJournal['tag_id'];
- $tagDate = null;
+ $tagDate = null;
try {
$tagDate = Carbon::parse($newArray['tag_date']);
@@ -684,7 +684,7 @@ class GroupCollector implements GroupCollectorInterface
{
$newArray = $newJournal->toArray();
if (array_key_exists('attachment_id', $newArray)) {
- $attachmentId = (int)$newJournal['attachment_id'];
+ $attachmentId = (int)$newJournal['attachment_id'];
$existingJournal['attachments'][$attachmentId] = [
'id' => $attachmentId,
@@ -703,7 +703,7 @@ class GroupCollector implements GroupCollectorInterface
foreach ($groups as $groudId => $group) {
/** @var array $transaction */
foreach ($group['transactions'] as $transaction) {
- $currencyId = (int)$transaction['currency_id'];
+ $currencyId = (int)$transaction['currency_id'];
if (null === $transaction['amount']) {
throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId));
}
@@ -719,7 +719,7 @@ class GroupCollector implements GroupCollectorInterface
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']);
if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) {
- $currencyId = (int)$transaction['foreign_currency_id'];
+ $currencyId = (int)$transaction['foreign_currency_id'];
// set default:
if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) {
@@ -752,7 +752,7 @@ class GroupCollector implements GroupCollectorInterface
*/
foreach ($this->postFilters as $function) {
app('log')->debug('Applying filter...');
- $nextCollection = new Collection();
+ $nextCollection = new Collection();
// loop everything in the current collection
// and save it (or not) in the new collection.
@@ -988,7 +988,8 @@ class GroupCollector implements GroupCollectorInterface
'transactions as source',
static function (JoinClause $join): void {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')
- ->where('source.amount', '<', 0);
+ ->where('source.amount', '<', 0)
+ ;
}
)
// join destination transaction
@@ -996,7 +997,8 @@ class GroupCollector implements GroupCollectorInterface
'transactions as destination',
static function (JoinClause $join): void {
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')
- ->where('destination.amount', '>', 0);
+ ->where('destination.amount', '>', 0)
+ ;
}
)
// left join transaction type.
@@ -1011,7 +1013,8 @@ class GroupCollector implements GroupCollectorInterface
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
- ->orderBy('source.amount', 'DESC');
+ ->orderBy('source.amount', 'DESC')
+ ;
}
/**
@@ -1042,7 +1045,8 @@ class GroupCollector implements GroupCollectorInterface
'transactions as source',
static function (JoinClause $join): void {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')
- ->where('source.amount', '<', 0);
+ ->where('source.amount', '<', 0)
+ ;
}
)
// join destination transaction
@@ -1050,7 +1054,8 @@ class GroupCollector implements GroupCollectorInterface
'transactions as destination',
static function (JoinClause $join): void {
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')
- ->where('destination.amount', '>', 0);
+ ->where('destination.amount', '>', 0)
+ ;
}
)
// left join transaction type.
@@ -1065,7 +1070,8 @@ class GroupCollector implements GroupCollectorInterface
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
- ->orderBy('source.amount', 'DESC');
+ ->orderBy('source.amount', 'DESC')
+ ;
}
/**
@@ -1076,23 +1082,22 @@ class GroupCollector implements GroupCollectorInterface
// include source + destination account name and type.
$this->withAccountInformation()
// include category ID + name (if any)
- ->withCategoryInformation()
+ ->withCategoryInformation()
// include budget ID + name (if any)
- ->withBudgetInformation()
+ ->withBudgetInformation()
// include bill ID + name (if any)
- ->withBillInformation();
+ ->withBillInformation()
+ ;
return $this;
}
- /**
- * @inheritDoc
- */
- #[\Override] public function sortCollection(Collection $collection): Collection
+ #[\Override]
+ public function sortCollection(Collection $collection): Collection
{
foreach ($this->sorting as $field => $direction) {
- $func = $direction === 'ASC' ? 'sortBy' : 'sortByDesc';
- $collection = $collection->$func(function (array $product, int $key) use ($field, $direction) {
+ $func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
+ $collection = $collection->{$func}(function (array $product, int $key) use ($field) {
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {
@@ -1101,22 +1106,22 @@ class GroupCollector implements GroupCollectorInterface
if (count($product['transactions']) > 1) {
return $product['title'];
}
+
return 'zzz';
}
- die('here we are');
+
+ exit('here we are');
});
}
-
return $collection;
}
- /**
- * @inheritDoc
- */
- #[\Override] public function setSorting(array $instructions): GroupCollectorInterface
+ #[\Override]
+ public function setSorting(array $instructions): GroupCollectorInterface
{
$this->sorting = $instructions;
+
return $this;
}
}
diff --git a/app/Helpers/Collector/GroupCollectorInterface.php b/app/Helpers/Collector/GroupCollectorInterface.php
index d2d26b70b1..a77fb36adb 100644
--- a/app/Helpers/Collector/GroupCollectorInterface.php
+++ b/app/Helpers/Collector/GroupCollectorInterface.php
@@ -285,22 +285,10 @@ interface GroupCollectorInterface
*/
public function getPaginatedGroups(): LengthAwarePaginator;
- /**
- *
- *
- * @param array $instructions
- *
- * @return self
- */
public function setSorting(array $instructions): self;
-
/**
* Sort the collection on a column.
- *
- * @param Collection $collection
- *
- * @return Collection
*/
public function sortCollection(Collection $collection): Collection;
diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php
index a1b96fe76e..44116553ce 100644
--- a/app/Http/Controllers/DebugController.php
+++ b/app/Http/Controllers/DebugController.php
@@ -115,12 +115,12 @@ class DebugController extends Controller
*/
public function index()
{
- $table = $this->generateTable();
- $table = str_replace(["\n", "\t", ' '], '', $table);
- $now = now(config('app.timezone'))->format('Y-m-d H:i:s');
+ $table = $this->generateTable();
+ $table = str_replace(["\n", "\t", ' '], '', $table);
+ $now = now(config('app.timezone'))->format('Y-m-d H:i:s');
// get latest log file:
- $logger = Log::driver();
+ $logger = Log::driver();
// PHPstan doesn't recognize the method because of its polymorphic nature.
$handlers = $logger->getHandlers(); // @phpstan-ignore-line
$logContent = '';
@@ -134,7 +134,7 @@ class DebugController extends Controller
}
if ('' !== $logContent) {
// last few lines
- $logContent = 'Truncated from this point <----|' . substr((string)$logContent, -16384);
+ $logContent = 'Truncated from this point <----|'.substr((string)$logContent, -16384);
}
return view('debug', compact('table', 'now', 'logContent'));
@@ -214,7 +214,7 @@ class DebugController extends Controller
private function getAppInfo(): array
{
- $userGuard = config('auth.defaults.guard');
+ $userGuard = config('auth.defaults.guard');
$config = app('fireflyconfig')->get('last_rt_job', 0);
$lastTime = (int)$config->data;
@@ -239,24 +239,24 @@ class DebugController extends Controller
// any of the cron jobs will do, they always run at the same time.
// but this job is the oldest, so the biggest chance it ran once
- 'last_cronjob' => $lastCronjob,
- 'last_cronjob_ago' => $lastCronjobAgo,
+ 'last_cronjob' => $lastCronjob,
+ 'last_cronjob_ago' => $lastCronjobAgo,
];
}
private function getuserInfo(): array
{
- $userFlags = $this->getUserFlags();
+ $userFlags = $this->getUserFlags();
// user info
- $userAgent = request()->header('user-agent');
+ $userAgent = request()->header('user-agent');
// set languages, see what happens:
$original = setlocale(LC_ALL, '0');
$localeAttempts = [];
$parts = app('steam')->getLocaleArray(app('steam')->getLocale());
foreach ($parts as $code) {
- $code = trim($code);
+ $code = trim($code);
app('log')->debug(sprintf('Trying to set %s', $code));
$result = setlocale(LC_ALL, $code);
$localeAttempts[$code] = $result === $code;
@@ -280,7 +280,7 @@ class DebugController extends Controller
$flags = [];
/** @var User $user */
- $user = auth()->user();
+ $user = auth()->user();
// has liabilities
if ($user->accounts()->accountTypeIn([AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE])->count() > 0) {
@@ -293,7 +293,7 @@ class DebugController extends Controller
}
// has stored reconciliations
- $type = TransactionType::whereType(TransactionType::RECONCILIATION)->first();
+ $type = TransactionType::whereType(TransactionType::RECONCILIATION)->first();
if ($user->transactionJournals()->where('transaction_type_id', $type->id)->count() > 0) {
$flags[] = ':ledger:';
}
diff --git a/config/firefly.php b/config/firefly.php
index 76c440fec8..457da44c28 100644
--- a/config/firefly.php
+++ b/config/firefly.php
@@ -914,9 +914,9 @@ return [
'preselected_accounts' => ['all', 'assets', 'liabilities'],
// allowed sort columns for API's
- 'sorting' => [
+ 'sorting' => [
'allowed' => [
- 'transactions' => ['description','amount'],
+ 'transactions' => ['description', 'amount'],
],
],
];
diff --git a/public/build/assets/create-0e590bfb.js b/public/build/assets/create-0e590bfb.js
new file mode 100644
index 0000000000..b9be846b07
--- /dev/null
+++ b/public/build/assets/create-0e590bfb.js
@@ -0,0 +1 @@
+import{a as m,d as y,f as d}from"./format-money-2cbd3c32.js";import{d as w,c as b}from"./create-empty-split-c1e678fd.js";import{l as v,a as T,b as C,c as P,p as E,d as _,s as L,e as c,f as S,g as D,h as A,i as x,j as k,k as h,m as p}from"./splice-errors-into-transactions-8731db70.js";import{l,i as r,m as B}from"./vendor-47e474ee.js";import"./get-4f3e9dd6.js";class M{post(t){let s="/api/v2/transactions";return m.post(s,t)}}let n=[],u=[];document.addEventListener("location-remove",e=>{u[e.detail.index].remove()});function O(e){let t=0;if(document.querySelector("#form")._x_dataStack[0].$data.entries[t].hasLocation===!1){u[t]=new l.marker(e.latlng,{draggable:!0}),u[t].on("dragend",U),u[t].addTo(n[t]);const o=new CustomEvent("location-set",{detail:{latitude:e.latlng.lat,longitude:e.latlng.lng,index:t,zoomLevel:n[t].getZoom()}});document.dispatchEvent(o)}}function F(e){let t=0;const s=new CustomEvent("location-zoom",{detail:{index:t,zoomLevel:n[t].getZoom()}});document.dispatchEvent(s)}function U(e){let t=e.target,s=t.getLatLng();t.setLatLng(new l.LatLng(s.lat,s.lng),{draggable:"true"});const o=new CustomEvent("location-move",{detail:{latitude:s.lat,longitude:s.lng,index:0}});document.dispatchEvent(o)}function z(e){if(e>0){console.warn("Corwardly refuse to add a map on split #"+(e+1));return}if(typeof n[e]>"u"){let t=document.getElementById("location_map");t&&(n[e]=l.map(t).setView([t.dataset.latitude,t.dataset.longitude],t.dataset.zoomLevel),l.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png",{maxZoom:19,attribution:'© OpenStreetMap'}).addTo(n[e]),n[e].on("click",O),n[e].on("zoomend",F))}}const a=k();let I=function(){return{entries:[],formStates:{loadingCurrencies:!0,loadingBudgets:!0,loadingPiggyBanks:!0,loadingSubscriptions:!0,isSubmitting:!1,returnHereButton:!1,saveAsNewButton:!1,resetButton:!0,rulesButton:!0,webhooksButton:!0},formBehaviour:{formType:"create",foreignCurrencyEnabled:!0},formData:{defaultCurrency:null,enabledCurrencies:[],nativeCurrencies:[],foreignCurrencies:[],budgets:[],piggyBanks:[],subscriptions:[]},groupProperties:{transactionType:"unknown",title:null,id:null,totalAmount:0},notifications:{error:{show:!1,text:"",url:""},success:{show:!1,text:"",url:""},wait:{show:!1,text:""}},filters:{source:[],destination:[]},changedDateTime(e){console.warn("changedDateTime, event is not used")},changedDescription(e){console.warn("changedDescription, event is not used")},changedDestinationAccount(e){this.detectTransactionType()},changedSourceAccount(e){this.detectTransactionType()},detectTransactionType(){const e=this.entries[0].source_account.type??"unknown",t=this.entries[0].destination_account.type??"unknown";if(e==="unknown"&&t==="unknown"){this.groupProperties.transactionType="unknown",console.warn("Cannot infer transaction type from two unknown accounts.");return}if(e===t&&["Asset account","Loan","Debt","Mortgage"].includes(e)){this.groupProperties.transactionType="transfer",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),console.log("filter down currencies for transfer."),this.filterNativeCurrencies(this.entries[0].source_account.currency_code),this.filterForeignCurrencies(this.entries[0].destination_account.currency_code);return}if(e==="Asset account"&&["Expense account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="withdrawal",console.log('[a] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(e==="Asset account"&&t==="unknown"){this.groupProperties.transactionType="withdrawal",console.log('[b] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),console.log(this.entries[0].source_account),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(["Debt","Loan","Mortgage"].includes(e)&&t==="Expense account"){this.groupProperties.transactionType="withdrawal",console.log('[c] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(e==="Revenue account"&&["Asset account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}if(e==="unknown"&&["Asset account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}if(e==="Expense account"&&["Asset account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="deposit",console.warn('FORCE transaction type to be "'+this.groupProperties.transactionType+'".'),this.entries[0].source_account.id=null;return}if(["Debt","Loan","Mortgage"].includes(e)&&t==="Asset account"){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}console.warn('Unknown account combination between "'+e+'" and "'+t+'".')},formattedTotalAmount(){return this.entries.length===0?d(this.groupProperties.totalAmount,"EUR"):d(this.groupProperties.totalAmount,this.entries[0].currency_code??"EUR")},filterForeignCurrencies(e){let t=[],s;for(let o in this.formData.enabledCurrencies)if(this.formData.enabledCurrencies.hasOwnProperty(o)){let i=this.formData.enabledCurrencies[o];i.code===e&&(s=i)}t.push(s),this.formData.foreignCurrencies=t,t.length===1&&t[0].code===this.entries[0].source_account.currency_code&&(console.log("Foreign currency is same as source currency. Disable foreign amount."),this.formBehaviour.foreignCurrencyEnabled=!1),t.length===1&&t[0].code!==this.entries[0].source_account.currency_code&&(console.log("Foreign currency is NOT same as source currency. Enable foreign amount."),this.formBehaviour.foreignCurrencyEnabled=!0);for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].foreign_currency_code=e)},filterNativeCurrencies(e){let t=[],s;for(let o in this.formData.enabledCurrencies)if(this.formData.enabledCurrencies.hasOwnProperty(o)){let i=this.formData.enabledCurrencies[o];i.code===e&&(s=i)}t.push(s),this.formData.nativeCurrencies=t;for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].currency_code=e)},changedAmount(e){const t=parseInt(e.target.dataset.index);this.entries[t].amount=parseFloat(e.target.value),this.groupProperties.totalAmount=0;for(let s in this.entries)this.entries.hasOwnProperty(s)&&(this.groupProperties.totalAmount=this.groupProperties.totalAmount+parseFloat(this.entries[s].amount))},addedSplit(){},processUpload(e){this.showMessageOrRedirectUser()},processUploadError(e){this.notifications.success.show=!1,this.notifications.wait.show=!1,this.notifications.error.show=!0,this.formStates.isSubmitting=!1,this.notifications.error.text=r.t("firefly.errors_upload"),console.error(e)},init(){this.addSplit(),v().then(e=>{this.formStates.loadingCurrencies=!1,this.formData.defaultCurrency=e.defaultCurrency,this.formData.enabledCurrencies=e.enabledCurrencies,this.formData.nativeCurrencies=e.nativeCurrencies,this.formData.foreignCurrencies=e.foreignCurrencies}),T().then(e=>{this.formData.budgets=e,this.formStates.loadingBudgets=!1}),C().then(e=>{this.formData.piggyBanks=e,this.formStates.loadingPiggyBanks=!1}),P().then(e=>{this.formData.subscriptions=e,this.formStates.loadingSubscriptions=!1}),document.addEventListener("upload-success",e=>{this.processUpload(e),document.querySelectorAll("input[type=file]").value=""}),document.addEventListener("upload-error",e=>{this.processUploadError(e)}),document.addEventListener("location-move",e=>{this.entries[e.detail.index].latitude=e.detail.latitude,this.entries[e.detail.index].longitude=e.detail.longitude}),document.addEventListener("location-set",e=>{this.entries[e.detail.index].hasLocation=!0,this.entries[e.detail.index].latitude=e.detail.latitude,this.entries[e.detail.index].longitude=e.detail.longitude,this.entries[e.detail.index].zoomLevel=e.detail.zoomLevel}),document.addEventListener("location-zoom",e=>{this.entries[e.detail.index].hasLocation=!0,this.entries[e.detail.index].zoomLevel=e.detail.zoomLevel}),this.filters.source=["Asset account","Loan","Debt","Mortgage","Revenue account"],this.filters.destination=["Expense account","Loan","Debt","Mortgage","Asset account"]},submitTransaction(){this.notifications.error.show=!1,this.notifications.success.show=!1,this.notifications.wait.show=!1;for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].errors=w());this.formStates.isSubmitting=!0,this.detectTransactionType();let e=E(this.entries,null,this.groupProperties.transactionType),t={group_title:this.groupProperties.title,fire_webhooks:this.formStates.webhooksButton,apply_rules:this.formStates.rulesButton,transactions:e};this.groupProperties.title===null&&e.length>1&&(t.group_title=e[0].description);let s=new M;console.log(t),s.post(t).then(o=>{const i=o.data.data;if(this.groupProperties.id=parseInt(i.id),this.groupProperties.title=i.attributes.group_title??i.attributes.transactions[0].description,_(this.groupProperties.id,i.attributes.transactions)>0){this.notifications.wait.show=!0,this.notifications.wait.text=r.t("firefly.wait_attachments");return}this.showMessageOrRedirectUser()}).catch(o=>{this.submitting=!1,console.log(o),typeof o.response<"u"&&this.parseErrors(o.response.data)})},showMessageOrRedirectUser(){if(this.notifications.error.show=!1,this.notifications.success.show=!1,this.notifications.wait.show=!1,this.formStates.returnHereButton){this.notifications.success.show=!0,this.notifications.success.url="transactions/show/"+this.groupProperties.id,this.notifications.success.text=r.t("firefly.stored_journal_js",{description:this.groupProperties.title}),this.formStates.resetButton&&(this.entries=[],this.addSplit(),this.groupProperties.totalAmount=0);return}window.location="transactions/show/"+this.groupProperties.id+"?transaction_group_id="+this.groupProperties.id+"&message=created"},parseErrors(e){this.notifications.error.show=!0,this.notifications.success.show=!1,this.notifications.wait.show=!1,this.formStates.isSubmitting=!1,this.notifications.error.text=r.t("firefly.errors_submission_v2",{errorMessage:e.message}),e.hasOwnProperty("errors")&&(this.entries=L(e.errors,this.entries))},addSplit(){this.entries.push(b()),setTimeout(()=>{B.init("select.ac-tags",{allowClear:!0,server:a.tag,liveServer:!0,clearEnd:!0,allowNew:!0,notFoundMessage:r.t("firefly.nothing_found"),noCache:!0,fetchOptions:{headers:{"X-CSRF-TOKEN":document.head.querySelector('meta[name="csrf-token"]').content}}});const e=this.entries.length-1;z(e);const t=function(s,o,i){return s.name_with_balance+'
'+r.t("firefly.account_type_"+s.type)+""};c({selector:"input.ac-source",serverUrl:a.account,onChange:S,onSelectItem:D,hiddenValue:this.entries[e].source_account.alpine_name}),c({selector:"input.ac-dest",serverUrl:a.account,filters:this.filters.destination,onRenderItem:t,onChange:A,onSelectItem:x}),c({selector:"input.ac-category",serverUrl:a.category,valueField:"id",labelField:"name",onChange:h,onSelectItem:h}),c({selector:"input.ac-description",serverUrl:a.description,valueField:"id",labelField:"description",onChange:p,onSelectItem:p})},150)},removeSplit(e){this.entries.splice(e,1),document.querySelector("#split-0-tab").click()},clearLocation(e){e.preventDefault();const t=e.currentTarget,s=parseInt(t.attributes["data-index"].value);this.entries[s].hasLocation=!1,this.entries[s].latitude=null,this.entries[s].longitude=null,this.entries[s].zoomLevel=null;const o=new CustomEvent("location-remove",{detail:{index:s}});return document.dispatchEvent(o),!1}}},g={transactions:I,dates:y};function f(){Object.keys(g).forEach(e=>{console.log(`Loading page component "${e}"`);let t=g[e]();Alpine.data(e,()=>t)}),Alpine.start()}document.addEventListener("firefly-iii-bootstrapped",()=>{console.log("Loaded through event listener."),f()});window.bootstrapped&&(console.log("Loaded through window variable."),f());
diff --git a/public/build/assets/create-6dc4ec8c.js b/public/build/assets/create-6dc4ec8c.js
deleted file mode 100644
index b9c41a4df9..0000000000
--- a/public/build/assets/create-6dc4ec8c.js
+++ /dev/null
@@ -1 +0,0 @@
-import{a as m,d as y,f as d}from"./format-money-2cbd3c32.js";import{d as w,c as b}from"./create-empty-split-c1e678fd.js";import{l as v,a as T,b as C,c as P,p as _,d as E,s as L,e as c,f as S,g as D,h as A,i as k,j as x,k as h,m as p}from"./splice-errors-into-transactions-8731db70.js";import{l,i as r,m as B}from"./vendor-47e474ee.js";import"./get-4f3e9dd6.js";class M{post(t){let s="/api/v2/transactions";return m.post(s,t)}}let n=[],u=[];document.addEventListener("location-remove",e=>{u[e.detail.index].remove()});function O(e){let t=0;if(document.querySelector("#form")._x_dataStack[0].$data.entries[t].hasLocation===!1){u[t]=new l.marker(e.latlng,{draggable:!0}),u[t].on("dragend",U),u[t].addTo(n[t]);const o=new CustomEvent("location-set",{detail:{latitude:e.latlng.lat,longitude:e.latlng.lng,index:t,zoomLevel:n[t].getZoom()}});document.dispatchEvent(o)}}function F(e){let t=0;const s=new CustomEvent("location-zoom",{detail:{index:t,zoomLevel:n[t].getZoom()}});document.dispatchEvent(s)}function U(e){let t=e.target,s=t.getLatLng();t.setLatLng(new l.LatLng(s.lat,s.lng),{draggable:"true"});const o=new CustomEvent("location-move",{detail:{latitude:s.lat,longitude:s.lng,index:0}});document.dispatchEvent(o)}function z(e){if(e>0){console.warn("Corwardly refuse to add a map on split #"+(e+1));return}if(typeof n[e]>"u"){let t=document.getElementById("location_map");t&&(n[e]=l.map(t).setView([t.dataset.latitude,t.dataset.longitude],t.dataset.zoomLevel),l.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png",{maxZoom:19,attribution:'© OpenStreetMap'}).addTo(n[e]),n[e].on("click",O),n[e].on("zoomend",F))}}const a=x();let I=function(){return{entries:[],formStates:{loadingCurrencies:!0,loadingBudgets:!0,loadingPiggyBanks:!0,loadingSubscriptions:!0,isSubmitting:!1,returnHereButton:!1,saveAsNewButton:!1,resetButton:!0,rulesButton:!0,webhooksButton:!0},formBehaviour:{formType:"create",foreignCurrencyEnabled:!0},formData:{defaultCurrency:null,enabledCurrencies:[],nativeCurrencies:[],foreignCurrencies:[],budgets:[],piggyBanks:[],subscriptions:[]},groupProperties:{transactionType:"unknown",title:null,id:null,totalAmount:0},notifications:{error:{show:!1,text:"",url:""},success:{show:!1,text:"",url:""},wait:{show:!1,text:""}},filters:{source:[],destination:[]},changedDateTime(e){console.warn("changedDateTime, event is not used")},changedDescription(e){console.warn("changedDescription, event is not used")},changedDestinationAccount(e){this.detectTransactionType()},changedSourceAccount(e){this.detectTransactionType()},detectTransactionType(){const e=this.entries[0].source_account.type??"unknown",t=this.entries[0].destination_account.type??"unknown";if(e==="unknown"&&t==="unknown"){this.groupProperties.transactionType="unknown",console.warn("Cannot infer transaction type from two unknown accounts.");return}if(e===t&&["Asset account","Loan","Debt","Mortgage"].includes(e)){this.groupProperties.transactionType="transfer",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),console.log("filter down currencies for transfer."),this.filterNativeCurrencies(this.entries[0].source_account.currency_code),this.filterForeignCurrencies(this.entries[0].destination_account.currency_code);return}if(e==="Asset account"&&["Expense account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="withdrawal",console.log('[a] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(e==="Asset account"&&t==="unknown"){this.groupProperties.transactionType="withdrawal",console.log('[b] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),console.log(this.entries[0].source_account),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(["Debt","Loan","Mortgage"].includes(e)&&t==="Expense account"){this.groupProperties.transactionType="withdrawal",console.log('[c] Transaction type is detected to be "'+this.groupProperties.transactionType+'".'),this.filterNativeCurrencies(this.entries[0].source_account.currency_code);return}if(e==="Revenue account"&&["Asset account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}if(e==="unknown"&&["Asset account","Debt","Loan","Mortgage"].includes(t)){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}if(["Debt","Loan","Mortgage"].includes(e)&&t==="Asset account"){this.groupProperties.transactionType="deposit",console.log('Transaction type is detected to be "'+this.groupProperties.transactionType+'".');return}console.warn('Unknown account combination between "'+e+'" and "'+t+'".')},formattedTotalAmount(){return this.entries.length===0?d(this.groupProperties.totalAmount,"EUR"):d(this.groupProperties.totalAmount,this.entries[0].currency_code??"EUR")},filterForeignCurrencies(e){let t=[],s;for(let o in this.formData.enabledCurrencies)if(this.formData.enabledCurrencies.hasOwnProperty(o)){let i=this.formData.enabledCurrencies[o];i.code===e&&(s=i)}t.push(s),this.formData.foreignCurrencies=t,t.length===1&&t[0].code===this.entries[0].source_account.currency_code&&(console.log("Foreign currency is same as source currency. Disable foreign amount."),this.formBehaviour.foreignCurrencyEnabled=!1),t.length===1&&t[0].code!==this.entries[0].source_account.currency_code&&(console.log("Foreign currency is NOT same as source currency. Enable foreign amount."),this.formBehaviour.foreignCurrencyEnabled=!0);for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].foreign_currency_code=e)},filterNativeCurrencies(e){let t=[],s;for(let o in this.formData.enabledCurrencies)if(this.formData.enabledCurrencies.hasOwnProperty(o)){let i=this.formData.enabledCurrencies[o];i.code===e&&(s=i)}t.push(s),this.formData.nativeCurrencies=t;for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].currency_code=e)},changedAmount(e){const t=parseInt(e.target.dataset.index);this.entries[t].amount=parseFloat(e.target.value),this.groupProperties.totalAmount=0;for(let s in this.entries)this.entries.hasOwnProperty(s)&&(this.groupProperties.totalAmount=this.groupProperties.totalAmount+parseFloat(this.entries[s].amount))},addedSplit(){},processUpload(e){this.showMessageOrRedirectUser()},processUploadError(e){this.notifications.success.show=!1,this.notifications.wait.show=!1,this.notifications.error.show=!0,this.formStates.isSubmitting=!1,this.notifications.error.text=r.t("firefly.errors_upload"),console.error(e)},init(){this.addSplit(),v().then(e=>{this.formStates.loadingCurrencies=!1,this.formData.defaultCurrency=e.defaultCurrency,this.formData.enabledCurrencies=e.enabledCurrencies,this.formData.nativeCurrencies=e.nativeCurrencies,this.formData.foreignCurrencies=e.foreignCurrencies}),T().then(e=>{this.formData.budgets=e,this.formStates.loadingBudgets=!1}),C().then(e=>{this.formData.piggyBanks=e,this.formStates.loadingPiggyBanks=!1}),P().then(e=>{this.formData.subscriptions=e,this.formStates.loadingSubscriptions=!1}),document.addEventListener("upload-success",e=>{this.processUpload(e),document.querySelectorAll("input[type=file]").value=""}),document.addEventListener("upload-error",e=>{this.processUploadError(e)}),document.addEventListener("location-move",e=>{this.entries[e.detail.index].latitude=e.detail.latitude,this.entries[e.detail.index].longitude=e.detail.longitude}),document.addEventListener("location-set",e=>{this.entries[e.detail.index].hasLocation=!0,this.entries[e.detail.index].latitude=e.detail.latitude,this.entries[e.detail.index].longitude=e.detail.longitude,this.entries[e.detail.index].zoomLevel=e.detail.zoomLevel}),document.addEventListener("location-zoom",e=>{this.entries[e.detail.index].hasLocation=!0,this.entries[e.detail.index].zoomLevel=e.detail.zoomLevel}),this.filters.source=["Asset account","Loan","Debt","Mortgage","Revenue account"],this.filters.destination=["Expense account","Loan","Debt","Mortgage","Asset account"]},submitTransaction(){this.notifications.error.show=!1,this.notifications.success.show=!1,this.notifications.wait.show=!1;for(let o in this.entries)this.entries.hasOwnProperty(o)&&(this.entries[o].errors=w());this.formStates.isSubmitting=!0,this.detectTransactionType();let e=_(this.entries,null,this.groupProperties.transactionType),t={group_title:this.groupProperties.title,fire_webhooks:this.formStates.webhooksButton,apply_rules:this.formStates.rulesButton,transactions:e};this.groupProperties.title===null&&e.length>1&&(t.group_title=e[0].description);let s=new M;console.log(t),s.post(t).then(o=>{const i=o.data.data;if(this.groupProperties.id=parseInt(i.id),this.groupProperties.title=i.attributes.group_title??i.attributes.transactions[0].description,E(this.groupProperties.id,i.attributes.transactions)>0){this.notifications.wait.show=!0,this.notifications.wait.text=r.t("firefly.wait_attachments");return}this.showMessageOrRedirectUser()}).catch(o=>{this.submitting=!1,console.log(o),typeof o.response<"u"&&this.parseErrors(o.response.data)})},showMessageOrRedirectUser(){if(this.notifications.error.show=!1,this.notifications.success.show=!1,this.notifications.wait.show=!1,this.formStates.returnHereButton){this.notifications.success.show=!0,this.notifications.success.url="transactions/show/"+this.groupProperties.id,this.notifications.success.text=r.t("firefly.stored_journal_js",{description:this.groupProperties.title}),this.formStates.resetButton&&(this.entries=[],this.addSplit(),this.groupProperties.totalAmount=0);return}window.location="transactions/show/"+this.groupProperties.id+"?transaction_group_id="+this.groupProperties.id+"&message=created"},parseErrors(e){this.notifications.error.show=!0,this.notifications.success.show=!1,this.notifications.wait.show=!1,this.formStates.isSubmitting=!1,this.notifications.error.text=r.t("firefly.errors_submission_v2",{errorMessage:e.message}),e.hasOwnProperty("errors")&&(this.entries=L(e.errors,this.entries))},addSplit(){this.entries.push(b()),setTimeout(()=>{B.init("select.ac-tags",{allowClear:!0,server:a.tag,liveServer:!0,clearEnd:!0,allowNew:!0,notFoundMessage:r.t("firefly.nothing_found"),noCache:!0,fetchOptions:{headers:{"X-CSRF-TOKEN":document.head.querySelector('meta[name="csrf-token"]').content}}});const e=this.entries.length-1;z(e);const t=function(s,o,i){return s.name_with_balance+'
'+r.t("firefly.account_type_"+s.type)+""};c({selector:"input.ac-source",serverUrl:a.account,onChange:S,onSelectItem:D,hiddenValue:this.entries[e].source_account.alpine_name}),c({selector:"input.ac-dest",serverUrl:a.account,filters:this.filters.destination,onRenderItem:t,onChange:A,onSelectItem:k}),c({selector:"input.ac-category",serverUrl:a.category,valueField:"id",labelField:"name",onChange:h,onSelectItem:h}),c({selector:"input.ac-description",serverUrl:a.description,valueField:"id",labelField:"description",onChange:p,onSelectItem:p})},150)},removeSplit(e){this.entries.splice(e,1),document.querySelector("#split-0-tab").click()},clearLocation(e){e.preventDefault();const t=e.currentTarget,s=parseInt(t.attributes["data-index"].value);this.entries[s].hasLocation=!1,this.entries[s].latitude=null,this.entries[s].longitude=null,this.entries[s].zoomLevel=null;const o=new CustomEvent("location-remove",{detail:{index:s}});return document.dispatchEvent(o),!1}}},g={transactions:I,dates:y};function f(){Object.keys(g).forEach(e=>{console.log(`Loading page component "${e}"`);let t=g[e]();Alpine.data(e,()=>t)}),Alpine.start()}document.addEventListener("firefly-iii-bootstrapped",()=>{console.log("Loaded through event listener."),f()});window.bootstrapped&&(console.log("Loaded through window variable."),f());
diff --git a/public/build/manifest.json b/public/build/manifest.json
index 6bf4c8347c..08e5015460 100644
--- a/public/build/manifest.json
+++ b/public/build/manifest.json
@@ -121,7 +121,7 @@
"integrity": "sha384-ptHLIPXakGRWe8dWim7Qxgub4wolfi5rktBj2EjNw5tyt8hLq+8p+lTsBKZe5Vay"
},
"resources/assets/v2/pages/transactions/create.js": {
- "file": "assets/create-6dc4ec8c.js",
+ "file": "assets/create-0e590bfb.js",
"imports": [
"_format-money-2cbd3c32.js",
"_create-empty-split-c1e678fd.js",
@@ -131,7 +131,7 @@
],
"isEntry": true,
"src": "resources/assets/v2/pages/transactions/create.js",
- "integrity": "sha384-OUiIH870uiZ8Y+/Gl2WLNSLwS8bi6mFgbixL18oCvpeSSN3pLbbmO9M+kzLlXNc9"
+ "integrity": "sha384-E0yymaxo99O2vsNgsuJ2KZD4tBnB+ly/ZlpuS9gJakCJIWWHGxK5z7G1wayhnrK3"
},
"resources/assets/v2/pages/transactions/edit.js": {
"file": "assets/edit-0910e359.js",
diff --git a/resources/assets/v2/pages/transactions/create.js b/resources/assets/v2/pages/transactions/create.js
index cb22a87182..930bd77448 100644
--- a/resources/assets/v2/pages/transactions/create.js
+++ b/resources/assets/v2/pages/transactions/create.js
@@ -180,6 +180,12 @@ let transactions = function () {
console.log('Transaction type is detected to be "' + this.groupProperties.transactionType + '".');
return;
}
+ if ('Expense account' === sourceType && ['Asset account', 'Debt', 'Loan', 'Mortgage'].includes(destType)) {
+ this.groupProperties.transactionType = 'deposit';
+ console.warn('FORCE transaction type to be "' + this.groupProperties.transactionType + '".');
+ this.entries[0].source_account.id = null;
+ return;
+ }
if (['Debt', 'Loan', 'Mortgage'].includes(sourceType) && 'Asset account' === destType) {
this.groupProperties.transactionType = 'deposit';
console.log('Transaction type is detected to be "' + this.groupProperties.transactionType + '".');