Commit Graph

46 Commits

Author SHA1 Message Date
Nabeel Shahzad
67c244240a
postgres fixes 2026-06-01 18:38:58 -05:00
Nabeel Shahzad
612c173dab
Remove is_default and composer update
# Conflicts:
#	composer.lock
2026-05-23 12:05:32 -05:00
Nabeel Shahzad
be1b32c67b
refactor(flight): move dpt_time/arr_time to API resource only
Reverses the modern Attribute-method approach: the Flight model no
longer carries dptTime/arrTime accessors. Instead, the canonical
columns are `departure_time` / `arrival_time` (Carbon, datetime:H:i:s
cast); the legacy `dpt_time` / `arr_time` `Hi`-formatted strings are
projected onto the JSON payload only by FlightResource at API response
time.

Why
- Public Attribute methods on a model are queryable surface and shouldn't
  be hidden behind protected visibility just to satisfy Larastan's
  modelAppends rule. Removing the methods (and the matching `$appends`
  entries) sidesteps the rule entirely.
- Keeps the API contract stable (`dpt_time`/`arr_time` still appear in
  responses, `departure_time`/`arrival_time` stay hidden) while
  internal code paths use the structured columns directly.

Model
- Removed `dptTime()` / `arrTime()` Attribute methods from Flight.
- Removed `dpt_time` / `arr_time` from `$appends`.
- Kept `departure_time` / `arrival_time` in `$hidden` (matches the
  contract locked by FlightResourceTimeFieldsTest).
- Dropped the now-unused `FlightTimeParser` import.

API resource
- FlightResource::toArray() now formats `dpt_time` / `arr_time` from
  the Carbon columns at response time. BidFlightResource inherits the
  projection via parent::toArray().

Form / factory
- FlightForm: TimePicker now binds to `departure_time` / `arrival_time`.
- FlightFactory: default state generates `departure_time` /
  `arrival_time` instead of the legacy keys.

Import / export plumbing
- Filament FlightImporter: kept the `dpt_time` / `arr_time` CSV column
  headers for backward compat; `fillRecordUsing` now parses via
  FlightTimeParser and writes through setAttribute('departure_time'/
  'arrival_time') to satisfy PHPStan's strict property typing.
- Filament FlightExporter: same CSV headers, `state()` callbacks
  format `Hi` from the structured columns.
- Service FlightImporter: transforms legacy keys to structured keys
  in import() before firstOrNew mass-assign.
- Service FlightExporter: overrides the array keys after the column
  loop so CSV columns continue to use the legacy header names with
  Carbon-derived values.
- LegacyImporter (old phpvms import): parses source `deptime`/`arrtime`
  into `departure_time`/`arrival_time` directly.

Tests
- Deleted tests/Unit/Models/FlightTimeAccessorTest.php (covered behavior
  that no longer exists on the model).
- FlightResourceTimeFieldsTest now seeds via `departure_time` /
  `arrival_time` factory state; assertions on the projected
  `dpt_time` / `arr_time` keys remain.
- ImporterTest: end-of-import assertions read
  `$flight->departure_time->format('Hi')` instead of `$flight->dpt_time`.

All four gates green; affected suites: 104 tests pass.
2026-05-23 12:05:09 -05:00
Nabeel Shahzad
2022246fc3
refactor(schema-modernization): apply PR #2215 review feedback
Sweep of CodeRabbit + arthurpar06 review items on PR #2215
(feat/route-bundles).

Bug fixes
- FlightsRelationManager: gate OldExport/OldImport actions on
  !config('phpvms.use_queued_filament_imports') so they don't render
  alongside the queued Filament Import/Export actions.
- FlightTimeBackfiller: move \$parsed++ into each per-field success
  branch. Counters were row-vs-field unit mismatched, making the
  completion log misleading (parsed=rows but failures=fields).
- FlightTimeBackfillerTest: replace Log::shouldReceive('warning')
  ->zeroOrMoreTimes() with ->once()->with(...) and Mockery::on(...)
  payload matcher; the old expectation asserted nothing. Cast id to
  int in the matcher (SQLite returns string IDs).
- FlightListShapeTest: assert both 'enabled' and 'active' keys in
  the API contract structure (resource emits both as backward-compat
  alias; previously only 'active' was locked in).

H1 — native AsEnumCollection for route_types
- Migration ..._add_capability_columns_to_subfleets_table.php: change
  route_types from string(64) to json(). Portable across MySQL,
  PostgreSQL and SQLite. Column is new in this PR so no data
  migration needed.
- Subfleet model: cast switches from custom FlightTypesCast to
  AsEnumCollection::of(FlightType::class).
- Delete app/Casts/FlightTypesCast.php and its unit test.
- Test updates explicitly document the behavior shift: empty selection
  now stored as JSON [] rather than collapsed to null. Custom
  behaviors lost: auto-dedupe, auto-sort, log+drop on invalid token.
  None had consumers; future business logic can decide on the
  null-vs-empty semantic.

H9 — split backfill into data migration
- Schema migration ..._add_time_columns_to_flights_table.php no
  longer runs the backfill inline; just creates the columns.
- New database/migrations_data/2026_05_19_000000_backfill_flight_times.php
  calls FlightTimeBackfiller::run() and is picked up by
  MigrationService::runAllDataMigrations() on next admin update.

H2 — command rename to phpvms: prefix
- PreserveHiddenVisibility signature: flights:preserve-hidden-visibility
  → phpvms:preserve-hidden-visibility for consistency with the rest
  of the namespace (phpvms:dev-install, :importer, :email-test,
  :version).
- Updated refs in console test, docs/UPGRADING.md, and openspec
  change-tracking docs (tasks, design, proposal).

H10 — composer scripts
- Add --parallel flag to 'pint' and 'pint:test' so AGENTS.md's
  'composer pint --test' command uses multi-threading.

H5 — native badge for FlightForm status entry
- Refactor status_badge TextEntry from manual HtmlString + raw <span>
  markup to TextEntry::badge()->color()->state(). Removes the need
  for ->html(), manual e() escaping, and hardcoded Tailwind classes;
  inherits Filament theming and dark-mode automatically.

R2-N — defense in depth
- Wrap :url substitution in e() in parentBundleOwnedDatesMessage().
  FlightBundleResource::getUrl() is safe-by-construction but the
  translation places :url in HTML context.

Collateral
- pint --dirty added an explicit ': array' return type to
  FlightResource::toArray() (it had only @return array in PHPDoc).
  BidFlightResource::toArray() needed the same change for covariance;
  PHPStan would otherwise fail with method.childReturnType.

Prior session items (also included in this commit since not yet
committed):
- FlightTypesCast wrote validation + invalid-token logging.
- FlightsTable bundle-disabled badge with eager-loaded bundle.
- FlightImporter (Filament) added exists:flight_bundles,id rule.
- FlightImporter (Service) memoized default bundle id to avoid N+1.
- FlightForm: minDate as closure that skips for edit; fixed static
  cache leak by using Laravel's container instead.
- SetVisibleFlights: DB::table → Flight::query() for ORM consistency.
- FlightBundle: #[Scope] attribute on visible scope; hasDates() as
  has_dates Attribute accessor.
- FlightBundleTest, SubfleetCapabilityTest, FlightsBulkActionsTest
  updated for new behaviors.
- ShieldSeeder dead-code cleanup.

All four pre-PR gates green: pint --test, phpstan, rector --dry-run,
pest on affected paths (180 tests passed).
2026-05-23 12:05:09 -05:00
Nabeel Shahzad
28f49b97c3
feat(schema-modernization): foundations for RouteForge
Schema, model, Filament, cron, and visibility-semantics foundations
required by the RouteForge change. Four phases delivered as one
coherent change. Verified against four spec files (flight-bundles,
flight-time-storage, subfleet-capability, flight-visibility).

Phase 1.1 \xe2\x80\x94 Flight time columns
- flights.departure_time, flights.arrival_time TIME NULL
- Flight model accessors (Hi-format) + mutators (FlightTimeParser)
- FlightTimeParser supports 9 formats + Z/L/tz suffix stripping
- Migration backfills inline via chunked raw DB::table->update()
- Legacy dpt_time/arr_time VARCHAR columns preserved for one release

Phase 1.2 \xe2\x80\x94 Subfleet capability columns
- subfleets.cruise_speed, max_range_nm, route_types (CSV VARCHAR(64))
- FlightTypesCast splits/sorts/dedupes/logs-on-invalid
- routeforge defaults in config/phpvms.php
- SubfleetForm Operational Capability section

Phase 1.3 \xe2\x80\x94 Flight Bundles
- flight_bundles table + flights.bundle_id NOT NULL FK
- Default bundle seeded inline; existing flights backfilled
- FlightBundle model + factory + BundleObserver (queued recompute)
- FlightBundleResource as sole Flights nav entry (slug=flights,
  icon=OutlinedMap, sort=2)
- Nested FlightResource under FlightBundleResource (slug=flight,
  parentResource, create+edit only, no nav entry)
- FlightsRelationManager with relatedResource for full-page row actions
- FlightForm: bundle selector removed (route-bound), date inputs
  hidden when parent bundle owns dates, XSS-safe placeholder link
- Date columns stored as TIMESTAMP UTC, UI converts to local tz
- Soft-deleting a bundle leaves children non-deleted; visibility
  recompute sets visible=false (no cascade delete)
- Spatie Shield permissions: flight_bundle.* seeded

Phase 1.4 \xe2\x80\x94 Visibility semantics
- flights.active renamed to flights.enabled (admin source of truth)
- flights.visible is cron-managed combined state
- SetActiveFlights cron deleted; SetVisibleFlights cron added
- Two-pass bulk SQL UPDATE scoped by bundle, chunks of 500
- RecomputeBundleVisibility queued job dispatched on bundle save/restore
- Flight::scopeVisible added; scopeActive retained as plain alias
- Pilot-facing read sites use ->visible() (AirportController fix)
- FlightResource JSON + FlightExporter CSV expose both enabled+active
- Four-state status badge (Disabled / Disabled by Bundle / Enabled
  Out of Window / Enabled & In Window) replaces Visible toggle
- 5 visibility indexes added

Verification
- 469 Pest tests passed (2058 assertions)
- phpstan level 5 clean (646 files)
- pint --test clean
- rector --dry-run clean
- All four spec files PASS (28 requirements + 36 scenarios verified
  by kimi-spec-reviewer)

Migration path documented in docs/UPGRADING.md and openspec/changes/
schema-modernization-for-routeforge/.
2026-05-23 12:05:09 -05:00
Arthur Parienté
7490e72523
[8.x] refactor: use native php enum instead of class (#2210)
* wip

* refactor: update enum handling and improve type hints across models

* refactor: deprecate labels and select methods in HasSelect trait for better separation of concerns

* copilot suggestions
2026-05-12 16:29:41 -05:00
Arthur Parienté
992b6d343a
[8.x] feature: upgrade to Laravel 13 (#2204)
* upgrade to laravel 13

* phpstan

* rollback to symfony 7.4

* fix: ModuleService merge

* refactor: new rector rules
2026-05-06 11:27:21 -05:00
Nabeel S.
d601b1f9e2
Phase 5 of prettus repository removal. (#2195)
* test(setting): characterization tests for setting() helper + API shape

* refactor(setting,expense): add #[Scope] + #[ObservedBy] + casts() + drop dead $rules

* feat(services): add SettingService with cache-aware store/retrieve

* feat(finance): add FinanceService::getExpensesForType

* refactor(setting): migrate setting()/setting_save() helpers to SettingService

* refactor(setting): migrate Api controller, Filament page, importer, test helper to SettingService

* refactor(expense): migrate PirepFinanceService, ExportAction, FinanceTest to FinanceService::getExpensesForType

* refactor(setting,expense): delete SettingRepository and ExpenseRepository

* test(setting): use Setting::byKey scope in characterization test

* refactor(setting): drop redundant Cache::forget in Maintenance page

SettingService::store() now invalidates the per-key cache slot internally
(introduced in d9c94195). Manual Cache::forget calls after setting_save()
became dead code in this branch, mirroring the same cleanup applied to
Filament/Pages/Settings.php in 31aa55da. Drops the now-unused Cache import
as well — caught by deep review.

* fix(setting): increment count in SettingsImporter run

Pre-existing bug. $count was declared but never incremented, so the
import log always read 'Imported 0 settings' regardless of how many
settings the legacy importer actually wrote.

Found during Phase 5 deep review.

* refactor(filament): wrap settings save in DB::transaction

The Filament Settings page writes N setting rows in a foreach loop,
then calls FinanceService::changeJournalCurrencies() which rewrites
journal + journal_transaction rows to a (potentially) new currency.
A throw mid-loop or mid-currency-migration left the DB with half-saved
settings or a half-migrated journal.

Wrap both halves in a single DB::transaction() so a partial failure
rolls back all writes atomically.

Found during Phase 5 deep review.

* refactor(services): declare strict_types=1 across app/Services/

Phase 5 introduced declare(strict_types=1); in SettingService.php only.
This commit applies the same declaration to the remaining 65 service
files for consistency.

65 files migrated. 6 files required minimal signature/cast adjustments
to handle existing caller patterns where strict mode exposed implicit
type coercion at runtime or in phpstan:

- FareService::recalculateFares cast $pivot->capacity to (float)
  before floor() (DB returns string).
- Finance/RecurringFinanceService::processExpenses cast
  $expense->ref_model to (string) before explode() (nullable column).
- AirportLookup/VaCentralLookup, GeoService: pass $e->getMessage()
  to Log::error() instead of the Exception object.
- DatabaseService::time() cast Carbon to (string) (return type contract).
- ModuleService::installModule pass $file->getRealPath() to PharData
  and Madzipper::make() (UploadedFile -> string path).

No files reverted. No tests modified.

Found during Phase 5 deep review (convention drift).

* style(setting): align match arms for pint 1.29.1

Pint 1.29.1 aligns => arrows in match expressions under
binary_operator_spaces (with align_single_space_minimal). 1.29.0 did
not. CI installs latest globally and fails on the un-aligned form.

Bumped composer.lock so local matches CI.

* Update app/Services/Finance/RecurringFinanceService.php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* refactor(installer): add strict types to LoggerTrait

LoggerTrait declared strict_types=1 but methods had no parameter or
return types. Added: comment(string $text): void, info(string $text):
void, error(string $text): void.

FlightImporter:59 was passing a Throwable to error() — switched to
$e->getMessage() to match the new contract. Same pattern applied in
5b2133a8 to VaCentralLookup and GeoService.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-27 15:21:27 -05:00
Abimael Carrasquillo
8fdd34d2ea
Add callsign attribute to flight importer (#2132) 2025-12-19 10:35:34 -06:00
Arthur Parienté
a715ddf486
feat(admin): upgrade to Filament v4 (#2062)
* remove filament-clusters

* upgrade livewire

* remove coolsam modules and resolve modules providers before filament

* update dependencies

* run upgrade script

* refactor: module links plugin

* refactor: version widget

* refactor: admin panel

* refactor: create custom theme to use tailwindcss classes

* feat: add language switcher plugin

* refactor: migrate ActivityLogResource

* refactor: migrate SimBriefAirframes

* refactor: migrate AirlineResource

* refactor: translate FilesRelationManager

* refactor: migrate AirportResource

* refactor: translate FilesRelationManager

* refactor: translate ExpensesRelationManager

* refactor: migrate AwardResource

* refactor: migrate ExpenseResource

* refactor: migrate FareResource

* refactor: migrate FlightResource

* refactor: migrate InviteResource

* refactor: migrate ModuleResource

* refactor: migrate PageResource

* refactor: migrate PirepFieldResource

* refactor: migrate PirepResource

* refactor: some translations in the FlightResource

* refactor: migrate RankResource

* refactor: migrate SubfleetResource

* refactor: migrate AircraftResource

* refactor: migrate TyperatingResource

* refactor: migrate UserFieldResource

* refactor: migrate UserResource

* refactor: remove the emptyStateActions

* refactor: migrate Finances

* fix: SimBriefAirframe

* refactor: migrate Maintenance

* refactor: migrate Settings

* refactor: remove old pages views

* refactor: NavigationGroups

* feat: upgrade SystemPanel, Update page and add streamed response to migrations

* fix: canAccess in Updater

* feat: upgrade the whole SystemPanel

* remove tests migrations (oops)

* refactor: remove system theme

* chore: update filament

* fix: role system and custom permission generator

* fix: airport translation

* feat: translate dashboard widgets

* fix: version major number

* refactor: update IconColumn boolean

* chore: upgrade to vite v7 and fix some CVEs

* feat: run pint in parallel and add rector to pre-commit

* chore: downgrade openspout to support php 82

* feat(admin): add prefetching

* fix(pre-commit): run pint only on staged files

* fix(seeds): in_progress.yml seeds

* refactor: add full type coverage to admin

* fix: permissions in PirepFieldsAction and UserFieldsAction

* refactor: translation for PIREPs Fields

---------

Co-authored-by: Nabeel S. <99736+nabeelio@users.noreply.github.com>
2025-08-13 10:20:23 -05:00
Nabeel Shahzad
00c6942e73
Merge remote-tracking branch 'origin/feature/8.0'
# Conflicts:
#	.github/version.yml
#	app/Console/Commands/Version.php
#	app/Database/seeds/permissions.yml
#	app/Http/Controllers/Admin/UserController.php
#	app/Models/UserOAuthToken.php
#	app/Providers/AuthServiceProvider.php
#	composer.json
#	composer.lock
#	config/version.yml
#	modules/Sample/Providers/SampleServiceProvider.php
#	resources/views/admin/menu.blade.php
#	resources/views/layouts/seven/nav.blade.php
#	version.json
2025-05-05 11:14:06 -05:00
Arthur Parienté
28e2d33b88
[8.x] Add RectorPHP (#1986)
* Add rector

* Remove cache

* Run rector again

* Run pint

* Run Rector in CI

* Update composer.lock
2025-03-14 11:38:16 -05:00
B.Fatih KOZ
658cba569e
Update FlightImporter.php (#1983)
* Fix module menu icon

* Update FlightImporter.php

Closes #1982 

Use `0` instead of `null` to follow the `setDays()` function and have a proper match for `firstorNew()`

---------

Co-authored-by: Nabeel S. <99736+nabeelio@users.noreply.github.com>
2025-02-04 14:52:45 -06:00
Nabeel S.
273cb86bc5
Add Laravel Pint linting (#1933)
* Run linter

* Run Pint in github action

* Run the linter verbose
2025-01-11 17:03:03 -06:00
B.Fatih KOZ
a367267fce
Update FlightImporter.php (#1861)
Consider days during flight matching for update / new flight decision.

Co-authored-by: Nabeel S. <nabeelio@users.noreply.github.com>
2024-09-10 09:21:35 -05:00
B.Fatih KOZ
7c696b834b
Update Flight Importer (#1859)
* Update FlightImporter.php

* StyleCI Fix
2024-09-09 14:32:11 -05:00
B.Fatih KOZ
7b1b9e5c31
Update FlightImporter.php (#1671) 2023-11-13 10:20:20 -06:00
B.Fatih KOZ
54574c0071
Fix Flight Importer/Exporter and Aircraft Importer (#1649)
* Row fixes

* Fix FIN field

* Fix test files

* fix files again for typo

* Again !

* Fix distance calculation

* Attempt to fix FirstOrNew

---------

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2023-10-30 12:43:28 -05:00
Nabeel S
fce71e96d9
Importer fixes for dirty fields (#1623)
* Importer fixes for dirty fields

* Code cleanup
2023-10-03 19:00:24 -04:00
B.Fatih KOZ
d96d936e09
Background improvements for events (#1506)
* events

- Event model and database table
- event_id field for flights and pireps (for relationships)
- user_id field for flights (for relationships)
- Flight export/import updates to follow model changes

* StlyCI Fixes

* Another StyleCI Fix :)

* Update 2022_12_27_192218_create_events.php

* Update 2022_12_27_192218_create_events.php

* Update 2022_12_27_192218_create_events.php

use `primary` instead of `increments` as requested

* Update 2022_12_27_192218_create_events.php

---------

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2023-02-06 12:00:17 -06:00
Nabeel S
41bd325f9a
Revert "Bug fix #1414 (#1487)" (#1492)
This reverts commit b4311b861f.
2022-10-30 22:58:26 -04:00
Yash Govekar
b4311b861f
Bug fix #1414 (#1487)
* Update module migrate command to avoid errors.

* Fixed issue #1414
2022-10-24 11:11:00 -04:00
B.Fatih KOZ
7fabd57e13
Fix flight and subfleet import with edited fares (#1379)
* Fix fare import

* StyleFix
2022-01-11 08:17:32 -05:00
B.Fatih KOZ
f3b032e56b
Add airline_id to created subfleet/subfleets during flight import. (#1320)
Add airline_id to created subfleet/subfleets during flight import.
2021-09-28 20:17:12 -04:00
lesmar54
90d1708aab
Fixes to CSV import Exports (#1299)
* Update SubfleetImporter.php

Correction to the import to include Simbrief Code

* Update SubfleetImporter.php

Added in the missing fields HUB-ID and SIMBrief as these are input on the main screen

* Update AircraftImporter.php

Part of the missing data fields in csv import export

* Update FlightImporter.php

Part of the missing fields in csv import and export

* Update AircraftImporter.php

* Update FlightImporter.php

* Update aircraft.csv

Test data amended as part of the missing csv fields

* Update subfleets.csv

Part of the fix for missing fields in csv files used for import/export

* Update flights.csv

* Update FlightImporter.php

* Update subfleets.csv

Removed unused fields

* Update FlightImporter.php

* Update FlightImporter.php

* Update FlightImporter.php

* amended for new csv file layouts
2021-09-08 09:50:34 -04:00
Nabeel S
88a8ffe48a
Check for blank values on import and omit them (#1266)
* Check for blank values on import and omit them

* Add paused status to the pirep changed
2021-07-22 15:56:03 -04:00
B.Fatih KOZ
68a6ed24cb
Fix Flight Importer (#1202)
* Handle Route and Level fields too during import.
* Also removed the check for `visible => true` from `firstorNew` 'cause va admin may be importing to update not visible flights too.
  (by default all new flights are visible, so no affect on new flights)

Closes #1201
2021-05-24 15:19:06 -04:00
exciler
be6332936f
When importing flights, set subfleet name only if subfleet has been created (#1095)
* when importing flights, set subfleet name only if subfleet has been created, do not update existing subfleets

* add tests for flights import regarding subfleets

Co-authored-by: Andreas Palm <ap@ewsp.de>
2021-03-23 08:50:19 -04:00
Nabeel Shahzad
c5ab0978db Force visible flag to true for imports #818 2020-09-11 09:18:27 -04:00
Nabeel S
9f3ddd5dbd
Add fixed pilot pay for a flight #487 (#622) 2020-03-06 11:36:02 -05:00
Nabeel S
16c977c769
Add load_factor and load_factor_variance to flights #352 (#620) 2020-03-05 20:19:12 -05:00
Nabeel S
c2f7c5e421
Properly create/update rows importing #486 (#503) 2020-01-16 10:40:42 -05:00
Nabeel S
831b72fb2b
Set a default model value for airports on PIREP (#500)
* Set a default model value for airports on PIREP

* Fix airport icao reference

* Default airport models
2020-01-15 13:00:58 -05:00
Nabeel S
4f4d0c266a
Allow nullable field and calculate distance if nulled for flight import #478 (#482) 2019-12-25 17:16:34 +05:00
Nabeel S
7a34756188
Issue fixes (#413)
* Auto lookup missing airports closes #404

* Ensure flight ICAOs are capitalized closes #404

* Update htaccess in root closes #412

* Update htaccess in root closes #412

* StyleCI fix
2019-10-23 12:01:31 -04:00
Nabeel Shahzad
a720f12e0b Rename Interfaces to Contracts to better match Laravel conventions 2019-07-15 15:44:31 -04:00
Nabeel Shahzad
9596d88b48 Apply fixes from StyleCI 2018-08-26 16:40:04 +00:00
Nabeel Shahzad
89f067807b comment out the flight dupe check on import 2018-04-25 12:05:12 -05:00
Nabeel Shahzad
531e86f5e7 Fix flight duplicate detection in add/edit/import; fix active checkbox 2018-04-25 11:53:32 -05:00
Nabeel Shahzad
63544088cd Add validation to importers to fix invalid/empty columns #222 2018-03-30 17:27:29 -05:00
Nabeel Shahzad
0bf1286c3a Fix error in flight importer 2018-03-29 11:47:37 -05:00
Nabeel Shahzad
1161106d9c Fix airport field row being inserted and check against airport ID 2018-03-23 12:27:28 -05:00
Nabeel Shahzad
7105e82922 Add days of week to flights table; add to import/export for flights 2018-03-22 21:21:35 -05:00
Nabeel Shahzad
8b53ca2fdc Fix types and codes import 2018-03-22 19:59:35 -05:00
Nabeel Shahzad
a44204b185 Import/export expenses #194 2018-03-22 17:17:37 -05:00
Nabeel Shahzad
fbfd71adcf Cleanup Exporter; use firstOrCreate for any missing data we can infer/setup defaults for 2018-03-22 12:43:58 -05:00