diff --git a/app/Api/V2/Request/Model/Transaction/StoreRequest.php b/app/Api/V2/Request/Model/Transaction/StoreRequest.php index 3cb6b3c292..3bc6dd1eb4 100644 --- a/app/Api/V2/Request/Model/Transaction/StoreRequest.php +++ b/app/Api/V2/Request/Model/Transaction/StoreRequest.php @@ -28,6 +28,7 @@ use FireflyIII\Models\UserGroup; use FireflyIII\Rules\BelongsUserGroup; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsDateOrTime; +use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\NullArrayObject; use FireflyIII\Support\Request\AppendsLocationData; use FireflyIII\Support\Request\ChecksLogin; @@ -74,7 +75,6 @@ class StoreRequest extends FormRequest 'fire_webhooks' => $this->boolean('fire_webhooks', true), 'transactions' => $this->getTransactionData(), ]; - // TODO include location and ability to process it. } /** @@ -107,8 +107,8 @@ class StoreRequest extends FormRequest 'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable', // amount - 'transactions.*.amount' => 'required|numeric|gt:0|max:1000000000', - 'transactions.*.foreign_amount' => 'numeric|gt:0|max:1000000000', + 'transactions.*.amount' => ['required', new IsValidPositiveAmount()], + 'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()], // description 'transactions.*.description' => 'nullable|between:1,1000', @@ -140,7 +140,8 @@ class StoreRequest extends FormRequest // other interesting fields 'transactions.*.reconciled' => [new IsBoolean()], 'transactions.*.notes' => 'min:1|max:50000|nullable', - 'transactions.*.tags' => 'between:0,255', + 'transactions.*.tags' => 'between:0,1024', + 'transactions.*.tags*' => 'between:0,1024', // meta info fields 'transactions.*.internal_reference' => 'min:1|max:255|nullable', @@ -166,6 +167,9 @@ class StoreRequest extends FormRequest 'transactions.*.due_date' => 'date|nullable', 'transactions.*.payment_date' => 'date|nullable', 'transactions.*.invoice_date' => 'date|nullable', + + // TODO include location and ability to process it. + ]; } @@ -222,7 +226,7 @@ class StoreRequest extends FormRequest */ foreach ($this->get('transactions') as $transaction) { $object = new NullArrayObject($transaction); - $return[] = [ + $result= [ 'type' => $this->clearString($object['type']), 'date' => $this->dateFromValue($object['date']), 'order' => $this->integerFromValue((string)$object['order']), @@ -300,6 +304,8 @@ class StoreRequest extends FormRequest 'payment_date' => $this->dateFromValue($object['payment_date']), 'invoice_date' => $this->dateFromValue($object['invoice_date']), ]; + $result = $this->addFromromTransactionStore($transaction, $result); + $return[] = $result; } return $return; diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index 5e72939f3b..71541b21e6 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -28,6 +28,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; +use FireflyIII\Models\Location; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; @@ -96,7 +97,7 @@ class TransactionJournalFactory { app('log')->debug('Now in TransactionJournalFactory::create()'); // convert to special object. - $dataObject = new NullArrayObject($data); + $dataObject = new NullArrayObject($data); app('log')->debug('Start of TransactionJournalFactory::create()'); $collection = new Collection(); @@ -163,7 +164,7 @@ class TransactionJournalFactory protected function storeMeta(TransactionJournal $journal, NullArrayObject $data, string $field): void { - $set = [ + $set = [ 'journal' => $journal, 'name' => $field, 'data' => (string) ($data[$field] ?? ''), @@ -197,14 +198,14 @@ class TransactionJournalFactory $this->errorIfDuplicate($row['import_hash_v2']); /** Some basic fields */ - $type = $this->typeRepository->findTransactionType(null, $row['type']); - $carbon = $row['date'] ?? today(config('app.timezone')); - $order = $row['order'] ?? 0; - $currency = $this->currencyRepository->findCurrency((int) $row['currency_id'], $row['currency_code']); - $foreignCurrency = $this->currencyRepository->findCurrencyNull($row['foreign_currency_id'], $row['foreign_currency_code']); - $bill = $this->billRepository->findBill((int) $row['bill_id'], $row['bill_name']); - $billId = TransactionType::WITHDRAWAL === $type->type && null !== $bill ? $bill->id : null; - $description = (string) $row['description']; + $type = $this->typeRepository->findTransactionType(null, $row['type']); + $carbon = $row['date'] ?? today(config('app.timezone')); + $order = $row['order'] ?? 0; + $currency = $this->currencyRepository->findCurrency((int) $row['currency_id'], $row['currency_code']); + $foreignCurrency = $this->currencyRepository->findCurrencyNull($row['foreign_currency_id'], $row['foreign_currency_code']); + $bill = $this->billRepository->findBill((int) $row['bill_id'], $row['bill_name']); + $billId = TransactionType::WITHDRAWAL === $type->type && null !== $bill ? $bill->id : null; + $description = (string) $row['description']; // Manipulate basic fields $carbon->setTimezone(config('app.timezone')); @@ -220,7 +221,7 @@ class TransactionJournalFactory } /** create or get source and destination accounts */ - $sourceInfo = [ + $sourceInfo = [ 'id' => $row['source_id'], 'name' => $row['source_name'], 'iban' => $row['source_iban'], @@ -229,7 +230,7 @@ class TransactionJournalFactory 'currency_id' => $currency->id, ]; - $destInfo = [ + $destInfo = [ 'id' => $row['destination_id'], 'name' => $row['destination_name'], 'iban' => $row['destination_iban'], @@ -239,8 +240,8 @@ class TransactionJournalFactory ]; app('log')->debug('Source info:', $sourceInfo); app('log')->debug('Destination info:', $destInfo); - $sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo); - $destinationAccount = $this->getAccount($type->type, 'destination', $destInfo); + $sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo); + $destinationAccount = $this->getAccount($type->type, 'destination', $destInfo); app('log')->debug('Done with getAccount(2x)'); // this is the moment for a reconciliation sanity check (again). @@ -248,15 +249,15 @@ class TransactionJournalFactory [$sourceAccount, $destinationAccount] = $this->reconciliationSanityCheck($sourceAccount, $destinationAccount); } - $currency = $this->getCurrencyByAccount($type->type, $currency, $sourceAccount, $destinationAccount); - $foreignCurrency = $this->compareCurrencies($currency, $foreignCurrency); - $foreignCurrency = $this->getForeignByAccount($type->type, $foreignCurrency, $destinationAccount); - $description = $this->getDescription($description); + $currency = $this->getCurrencyByAccount($type->type, $currency, $sourceAccount, $destinationAccount); + $foreignCurrency = $this->compareCurrencies($currency, $foreignCurrency); + $foreignCurrency = $this->getForeignByAccount($type->type, $foreignCurrency, $destinationAccount); + $description = $this->getDescription($description); app('log')->debug(sprintf('Date: %s (%s)', $carbon->toW3cString(), $carbon->getTimezone()->getName())); /** Create a basic journal. */ - $journal = TransactionJournal::create( + $journal = TransactionJournal::create( [ 'user_id' => $this->user->id, 'user_group_id' => $this->user->user_group_id, @@ -273,7 +274,7 @@ class TransactionJournalFactory app('log')->debug(sprintf('Created new journal #%d: "%s"', $journal->id, $journal->description)); /** Create two transactions. */ - $transactionFactory = app(TransactionFactory::class); + $transactionFactory = app(TransactionFactory::class); $transactionFactory->setUser($this->user); $transactionFactory->setJournal($journal); $transactionFactory->setAccount($sourceAccount); @@ -292,7 +293,7 @@ class TransactionJournalFactory } /** @var TransactionFactory $transactionFactory */ - $transactionFactory = app(TransactionFactory::class); + $transactionFactory = app(TransactionFactory::class); $transactionFactory->setUser($this->user); $transactionFactory->setJournal($journal); $transactionFactory->setAccount($destinationAccount); @@ -310,7 +311,7 @@ class TransactionJournalFactory throw new FireflyException($e->getMessage(), 0, $e); } - $journal->completed = true; + $journal->completed = true; $journal->save(); $this->storeBudget($journal, $row); $this->storeCategory($journal, $row); @@ -318,10 +319,23 @@ class TransactionJournalFactory $this->storePiggyEvent($journal, $row); $this->storeTags($journal, $row['tags']); $this->storeMetaFields($journal, $row); + $this->storeLocation($journal, $row); return $journal; } + private function storeLocation(TransactionJournal $journal, NullArrayObject $data): void + { + if (true === $data['store_location']) { + $location = new Location(); + $location->longitude = $data['longitude']; + $location->latitude = $data['latitude']; + $location->zoom_level = $data['zoom_level']; + $location->locatable()->associate($journal); + $location->save(); + } + } + private function hashArray(NullArrayObject $row): string { $dataRow = $row->getArrayCopy(); @@ -334,7 +348,7 @@ class TransactionJournalFactory app('log')->error(sprintf('Could not encode dataRow: %s', $e->getMessage())); $json = microtime(); } - $hash = hash('sha256', $json); + $hash = hash('sha256', $json); app('log')->debug(sprintf('The hash is: %s', $hash), $dataRow); return $hash; @@ -355,21 +369,17 @@ class TransactionJournalFactory /** @var null|TransactionJournalMeta $result */ $result = TransactionJournalMeta::withTrashed() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') - ->whereNotNull('transaction_journals.id') - ->where('transaction_journals.user_id', $this->user->id) - ->where('data', json_encode($hash, JSON_THROW_ON_ERROR)) - ->with(['transactionJournal', 'transactionJournal.transactionGroup']) - ->first() - ; + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->whereNotNull('transaction_journals.id') + ->where('transaction_journals.user_id', $this->user->id) + ->where('data', json_encode($hash, JSON_THROW_ON_ERROR)) + ->with(['transactionJournal', 'transactionJournal.transactionGroup']) + ->first(['journal_meta.*']); if (null !== $result) { app('log')->warning(sprintf('Found a duplicate in errorIfDuplicate because hash %s is not unique!', $hash)); $journal = $result->transactionJournal()->withTrashed()->first(); $group = $journal?->transactionGroup()->withTrashed()->first(); - $groupId = $group?->id; - if (null === $group) { - $groupId = 0; - } + $groupId = (int) $group?->id; throw new DuplicateTransactionException(sprintf('Duplicate of transaction #%d.', $groupId)); } @@ -381,18 +391,18 @@ class TransactionJournalFactory private function validateAccounts(NullArrayObject $data): void { app('log')->debug(sprintf('Now in %s', __METHOD__)); - $transactionType = $data['type'] ?? 'invalid'; + $transactionType = $data['type'] ?? 'invalid'; $this->accountValidator->setUser($this->user); $this->accountValidator->setTransactionType($transactionType); // validate source account. - $array = [ + $array = [ 'id' => null !== $data['source_id'] ? (int) $data['source_id'] : null, 'name' => null !== $data['source_name'] ? (string) $data['source_name'] : null, 'iban' => null !== $data['source_iban'] ? (string) $data['source_iban'] : null, 'number' => null !== $data['source_number'] ? (string) $data['source_number'] : null, ]; - $validSource = $this->accountValidator->validateSource($array); + $validSource = $this->accountValidator->validateSource($array); // do something with result: if (false === $validSource) { @@ -401,7 +411,7 @@ class TransactionJournalFactory app('log')->debug('Source seems valid.'); // validate destination account - $array = [ + $array = [ 'id' => null !== $data['destination_id'] ? (int) $data['destination_id'] : null, 'name' => null !== $data['destination_name'] ? (string) $data['destination_name'] : null, 'iban' => null !== $data['destination_iban'] ? (string) $data['destination_iban'] : null, @@ -469,7 +479,7 @@ class TransactionJournalFactory // return user's default: return app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup); } - $result = $preference ?? $currency; + $result = $preference ?? $currency; app('log')->debug(sprintf('Currency is now #%d (%s) because of account #%d (%s)', $result->id, $result->code, $account->id, $account->name)); return $result; diff --git a/app/Models/Location.php b/app/Models/Location.php index c7e1a7358f..0eeca7e125 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -93,12 +93,14 @@ class Location extends Model return $rules; } - /** - * Get all the accounts. - */ public function accounts(): MorphMany { - return $this->morphMany(Account::class, 'noteable'); + return $this->morphMany(Account::class, 'locatable'); + } + + public function transactionJournals(): MorphMany + { + return $this->morphMany(TransactionJournal::class, 'locatable'); } /** diff --git a/app/Support/Request/AppendsLocationData.php b/app/Support/Request/AppendsLocationData.php index cb84c513ae..86e99adca5 100644 --- a/app/Support/Request/AppendsLocationData.php +++ b/app/Support/Request/AppendsLocationData.php @@ -78,12 +78,12 @@ trait AppendsLocationData $data['latitude'] = null; $data['zoom_level'] = null; - $longitudeKey = $this->getLocationKey($prefix, 'longitude'); - $latitudeKey = $this->getLocationKey($prefix, 'latitude'); - $zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level'); - $isValidPOST = $this->isValidPost($prefix); - $isValidPUT = $this->isValidPUT($prefix); - $isValidEmptyPUT = $this->isValidEmptyPUT($prefix); + $longitudeKey = $this->getLocationKey($prefix, 'longitude'); + $latitudeKey = $this->getLocationKey($prefix, 'latitude'); + $zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level'); + $isValidPOST = $this->isValidPost($prefix); + $isValidPUT = $this->isValidPUT($prefix); + $isValidEmptyPUT = $this->isValidEmptyPUT($prefix); // for a POST (store), all fields must be present and not NULL. if ($isValidPOST) { @@ -119,6 +119,40 @@ trait AppendsLocationData return $data; } + /** + * @param array $information + * @param array $return + * + * @return array + */ + public function addFromromTransactionStore(array $information, array $return): array + { + $return['store_location'] = false; + if (true === $information['store_location']) { + $long = array_key_exists('longitude', $information) ? $information['longitude'] : null; + $lat = array_key_exists('latitude', $information) ? $information['latitude'] : null; + if (null !== $long && null !== $lat && $this->validLongitude($long) && $this->validLatitude($lat)) { + $return['store_location'] = true; + $return['longitude'] = $information['longitude']; + $return['latitude'] = $information['latitude']; + $return['zoom_level'] = $information['zoom_level']; + } + } + return $return; + } + + private function validLongitude(string $longitude): bool + { + $number = (float) $longitude; + return $number >= -180 && $number <= 180; + } + + private function validLatitude(string $latitude): bool + { + $number = (float) $latitude; + return $number >= -90 && $number <= 90; + } + private function getLocationKey(?string $prefix, string $key): string { if (null === $prefix) { @@ -213,9 +247,9 @@ trait AppendsLocationData $zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level'); return ( - null === $this->get($longitudeKey) - && null === $this->get($latitudeKey) - && null === $this->get($zoomLevelKey)) + null === $this->get($longitudeKey) + && null === $this->get($latitudeKey) + && null === $this->get($zoomLevelKey)) && ( 'PUT' === $this->method() || ('POST' === $this->method() && $this->routeIs('*.update')) diff --git a/app/Transformers/V2/TransactionGroupTransformer.php b/app/Transformers/V2/TransactionGroupTransformer.php index e0c4fb6563..5516ad277c 100644 --- a/app/Transformers/V2/TransactionGroupTransformer.php +++ b/app/Transformers/V2/TransactionGroupTransformer.php @@ -26,6 +26,7 @@ namespace FireflyIII\Transformers\V2; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Location; use FireflyIII\Models\Note; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; @@ -47,18 +48,18 @@ class TransactionGroupTransformer extends AbstractTransformer private TransactionCurrency $default; private array $meta; private array $notes; + private array $locations; private array $tags; public function collectMetaData(Collection $objects): void { - // start with currencies: - $currencies = []; - $journals = []; + $currencies = []; + $journals = []; /** @var array $object */ foreach ($objects as $object) { foreach ($object['sums'] as $sum) { - $id = (int) $sum['currency_id']; + $id = (int) $sum['currency_id']; $currencies[$id] ??= TransactionCurrency::find($sum['currency_id']); } @@ -72,7 +73,7 @@ class TransactionGroupTransformer extends AbstractTransformer $this->default = app('amount')->getDefaultCurrency(); // grab meta for all journals: - $meta = TransactionJournalMeta::whereIn('transaction_journal_id', array_keys($journals))->get(); + $meta = TransactionJournalMeta::whereIn('transaction_journal_id', array_keys($journals))->get(); /** @var TransactionJournalMeta $entry */ foreach ($meta as $entry) { @@ -81,7 +82,7 @@ class TransactionGroupTransformer extends AbstractTransformer } // grab all notes for all journals: - $notes = Note::whereNoteableType(TransactionJournal::class)->whereIn('noteable_id', array_keys($journals))->get(); + $notes = Note::whereNoteableType(TransactionJournal::class)->whereIn('noteable_id', array_keys($journals))->get(); /** @var Note $note */ foreach ($notes as $note) { @@ -89,12 +90,20 @@ class TransactionGroupTransformer extends AbstractTransformer $this->notes[$id] = $note; } + // grab all locations for all journals: + $locations = Location::whereLocatableType(TransactionJournal::class)->whereIn('locatable_id', array_keys($journals))->get(); + + /** @var Location $location */ + foreach ($locations as $location) { + $id = $location->locatable_id; + $this->locations[$id] = $location; + } + // grab all tags for all journals: - $tags = DB::table('tag_transaction_journal') - ->leftJoin('tags', 'tags.id', 'tag_transaction_journal.tag_id') - ->whereIn('tag_transaction_journal.transaction_journal_id', array_keys($journals)) - ->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag']) - ; + $tags = DB::table('tag_transaction_journal') + ->leftJoin('tags', 'tags.id', 'tag_transaction_journal.tag_id') + ->whereIn('tag_transaction_journal.transaction_journal_id', array_keys($journals)) + ->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag']); /** @var \stdClass $tag */ foreach ($tags as $tag) { @@ -104,7 +113,7 @@ class TransactionGroupTransformer extends AbstractTransformer // create converter Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__)); - $this->converter = new ExchangeRateConverter(); + $this->converter = new ExchangeRateConverter(); } public function transform(array $group): array @@ -147,10 +156,10 @@ class TransactionGroupTransformer extends AbstractTransformer */ private function transformTransaction(array $transaction): array { - $transaction = new NullArrayObject($transaction); - $type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionType::WITHDRAWAL); - $journalId = (int) $transaction['transaction_journal_id']; - $meta = new NullArrayObject($this->meta[$journalId] ?? []); + $transaction = new NullArrayObject($transaction); + $type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionType::WITHDRAWAL); + $journalId = (int) $transaction['transaction_journal_id']; + $meta = new NullArrayObject($this->meta[$journalId] ?? []); /** * Convert and use amount: @@ -167,6 +176,17 @@ class TransactionGroupTransformer extends AbstractTransformer } $this->converter->summarize(); + $longitude = null; + $latitude = null; + $zoomLevel = null; + if (array_key_exists($journalId, $this->locations)) { + /** @var Location $location */ + $location = $this->locations[$journalId]; + $latitude = (string) $location->latitude; + $longitude = (string) $location->longitude; + $zoomLevel = $location->zoom_level; + } + return [ 'user' => (string) $transaction['user_id'], 'user_group' => (string) $transaction['user_group_id'], @@ -241,9 +261,9 @@ class TransactionGroupTransformer extends AbstractTransformer 'invoice_date' => $this->date($meta['invoice_date']), // location data - // 'longitude' => $longitude, - // 'latitude' => $latitude, - // 'zoom_level' => $zoomLevel, + 'longitude' => $longitude, + 'latitude' => $latitude, + 'zoom_level' => $zoomLevel, // // 'has_attachments' => $this->hasAttachments((int) $row['transaction_journal_id']), ]; diff --git a/resources/assets/v2/api/v1/preferences/index.js b/resources/assets/v2/api/v1/preferences/index.js index e037b9101a..83d4499c09 100644 --- a/resources/assets/v2/api/v1/preferences/index.js +++ b/resources/assets/v2/api/v1/preferences/index.js @@ -25,6 +25,8 @@ export default class Preferences { return api.get('/api/v1/preferences/' + name); } + + getByNameNow(name) { return api.get('/api/v1/preferences/' + name); } diff --git a/resources/assets/v2/pages/transactions/create.js b/resources/assets/v2/pages/transactions/create.js index 58c56d8eff..822a8f66e9 100644 --- a/resources/assets/v2/pages/transactions/create.js +++ b/resources/assets/v2/pages/transactions/create.js @@ -40,6 +40,10 @@ import L from "leaflet"; import 'leaflet/dist/leaflet.css'; +// TODO upload attachments to other file +// TODO fix two maps, perhaps disconnect from entries entirely. +// TODO group title +// TODO map location from preferences let i18n; @@ -186,7 +190,7 @@ let transactions = function () { budgets: [], piggyBanks: {}, subscriptions: [], - dateFields: ['interest_date','book_date','process_date','due_date','payment_date','invoice_date'], + dateFields: ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'], foreignAmountEnabled: true, filters: { @@ -754,19 +758,41 @@ let transactions = function () { let fieldName; // todo add 'was-validated' to form. - + console.log('Now processing errors.'); for (const key in data.errors) { if (data.errors.hasOwnProperty(key)) { if (key === 'group_title') { + console.log('Handling group title error.'); // todo handle group errors. //this.group_title_errors = errors.errors[key]; } if (key !== 'group_title') { + console.log('Handling errors for ' + key); // lol, the dumbest way to explode "transactions.0.something" ever. transactionIndex = parseInt(key.split('.')[1]); fieldName = key.split('.')[2]; + console.log('Transaction index: ' + transactionIndex); + console.log('Field name: ' + fieldName); + console.log('Errors'); + console.log(data.errors[key]); // set error in this object thing. switch (fieldName) { + case 'currency_code': + case 'foreign_currency_code': + case 'category_name': + case 'piggy_bank_id': + case 'notes': + case 'internal_reference': + case 'external_url': + case 'latitude': + case 'longitude': + case 'zoom_level': + case 'interest_date': + case 'book_date': + case 'process_date': + case 'due_date': + case 'payment_date': + case 'invoice_date': case 'amount': case 'date': case 'budget_id': @@ -779,6 +805,10 @@ let transactions = function () { case 'source_id': this.entries[transactionIndex].errors.source_account = this.entries[transactionIndex].errors.source_account.concat(data.errors[key]); break; + case 'type': + // put the error in the description: + this.entries[transactionIndex].errors.description = this.entries[transactionIndex].errors.source_account.concat(data.errors[key]); + break; case 'destination_name': case 'destination_id': this.entries[transactionIndex].errors.destination_account = this.entries[transactionIndex].errors.destination_account.concat(data.errors[key]); @@ -810,6 +840,7 @@ let transactions = function () { server: urls.tag, liveServer: true, clearEnd: true, + allowNew: true, notFoundMessage: '(nothing found)', noCache: true, fetchOptions: { @@ -819,14 +850,28 @@ let transactions = function () { } }); const count = this.entries.length - 1; - this.entries[count].map = L.map('mappie').setView([this.latitude, this.longitude], this.zoomLevel); + //let map = L.map('location_map_' + count).setView([this.latitude, this.longitude], this.zoomLevel); - L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { - maxZoom: 19, - attribution: '© OpenStreetMap' - }).addTo(this.entries[count].map); - this.entries[count].map.on('click', this.addPointToMap); - this.entries[count].map.on('zoomend', this.saveZoomOfMap); + // L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + // maxZoom: 19, + // attribution: '© OpenStreetMap '+count+'' + // }).addTo(map); + // map.on('click', this.addPointToMap); + // map.on('zoomend', this.saveZoomOfMap); + + const id = 'location_map_' + count; + const map = () => { + const el = document.getElementById(id), + map = L.map(id).setView([this.latitude, this.longitude], this.zoomLevel) + L.tileLayer( + 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + {attribution: '© OpenStreetMap '+count+''} + ).addTo(map) + map.on('click', this.addPointToMap); + map.on('zoomend', this.saveZoomOfMap); + return map + } + this.entries[count].map = map(); }, 250); @@ -878,13 +923,6 @@ let transactions = function () { document.querySelector('#form')._x_dataStack[0].$data.entries[index].longitude = e.latlng.lng; document.querySelector('#form')._x_dataStack[0].$data.entries[index].zoomLevel = map.getZoom(); } - //this.entries[index].hasLocation = true; - // map.on('click', function (e) { - // if (false === this.hasLocation) { - // let marker = new L.marker(e.latlng).addTo(map); - // this.hasLocation = true; - // } - // }); } } } diff --git a/resources/assets/v2/pages/transactions/shared/create-empty-split.js b/resources/assets/v2/pages/transactions/shared/create-empty-split.js index fade56ec0f..a4f8d97780 100644 --- a/resources/assets/v2/pages/transactions/shared/create-empty-split.js +++ b/resources/assets/v2/pages/transactions/shared/create-empty-split.js @@ -76,11 +76,43 @@ export function createEmptySplit() { invoice_date: '', errors: { - 'amount': [], - 'foreign_amount': [], - 'budget_id': [], - 'category_name': [], - 'piggy_bank_id': [], + description: [], + + // amount information: + amount: [], + currency_code: [], + foreign_amount: [], + foreign_currency_code: [], + + // source and destination + source_account: [], + destination_account: [], + + // meta data information: + budget_id: [], + category_name: [], + piggy_bank_id: [], + bill_id: [], + tags: [], + notes: [], + + // other meta fields: + internal_reference: [], + external_url: [], + + // map + latitude: [], + longitude: [], + zoom_level: [], + + // date and time + date: [], + interest_date: [], + book_date: [], + process_date: [], + due_date: [], + payment_date: [], + invoice_date: [], }, }; } diff --git a/resources/assets/v2/pages/transactions/shared/parse-from-entries.js b/resources/assets/v2/pages/transactions/shared/parse-from-entries.js index f71265eba2..e03bedd308 100644 --- a/resources/assets/v2/pages/transactions/shared/parse-from-entries.js +++ b/resources/assets/v2/pages/transactions/shared/parse-from-entries.js @@ -55,14 +55,24 @@ export function parseFromEntries(entries, transactionType) { current.category_name = entry.category_name; current.piggy_bank_id = entry.piggy_bank_id; current.bill_id = entry.bill_id; + current.tags = entry.tags; + current.notes = entry.notes; + + // more meta + current.internal_reference = entry.internal_reference; + current.external_url = entry.external_url; // location + current.store_location = false; if (entry.hasLocation) { + current.store_location = true; current.longitude = entry.longitude.toString(); current.latitude = entry.latitude.toString(); current.zoom_level = entry.zoomLevel; } + + // if foreign amount currency code is set: if (typeof entry.foreign_currency_code !== 'undefined' && '' !== entry.foreign_currency_code.toString()) { current.foreign_currency_code = entry.foreign_currency_code; diff --git a/resources/views/v2/transactions/create.blade.php b/resources/views/v2/transactions/create.blade.php index 00aa39b448..02b4e6b86f 100644 --- a/resources/views/v2/transactions/create.blade.php +++ b/resources/views/v2/transactions/create.blade.php @@ -343,6 +343,7 @@ + :class="{'is-invalid': transaction.errors.external_url.length > 0, 'form-control': true}" + placeholder="{{ __('firefly.external_url') }}" /> +
@@ -420,7 +428,7 @@
-
+