Files
sure/app/controllers/import/uploads_controller.rb
soky srm 560c9fbff3 Family sharing (#1272)
* Initial account sharing changes

* Update schema.rb

* Update schema.rb

* Change sharing UI to modal

* UX fixes and sharing controls

* Scope include in finances better

* Update totals.rb

* Update totals.rb

* Scope reports to finance account scope

* Update impersonation_sessions_controller_test.rb

* Review fixes

* Update schema.rb

* Update show.html.erb

* FIX db validation

* Refine edit permissions

* Review items

* Review

* Review

* Add application level helper

* Critical review

* Address remaining review items

* Fix modals

* more scoping

* linter

* small UI fix

* Fix: Sync broadcasts push unscoped balance sheet to all users

* Update sync_complete_event.rb

 The fix removes the sidebar broadcasts (which rendered unscoped account groups using family.balance_sheet without user context)
  along with the now-unused sidebar_targets, account_group, and family_balance_sheet private methods.

  The sidebar will still update correctly — when the sync completes, Family::SyncCompleteEvent#broadcast fires family.broadcast_refresh, which triggers a
  morph-based page refresh for each user with their own authenticated session, rendering properly scoped sidebar content.
2026-03-25 10:50:23 +01:00

129 lines
3.8 KiB
Ruby

class Import::UploadsController < ApplicationController
layout "imports"
before_action :set_import
def show
end
def sample_csv
send_data @import.csv_template.to_csv,
filename: "#{@import.type.underscore.split('_').first}_sample.csv",
type: "text/csv",
disposition: "attachment"
end
def update
if @import.is_a?(QifImport)
handle_qif_upload
elsif @import.is_a?(SureImport)
update_sure_import_upload
elsif csv_valid?(csv_str)
@import.account = accessible_accounts.find_by(id: import_account_id)
@import.assign_attributes(raw_file_str: csv_str, col_sep: upload_params[:col_sep])
@import.save!(validate: false)
redirect_to import_configuration_path(@import, template_hint: true), notice: t("imports.create.csv_uploaded")
else
flash.now[:alert] = t("import.uploads.show.csv_invalid", default: "Must be valid CSV with headers and at least one row of data")
render :show, status: :unprocessable_entity
end
end
private
def update_sure_import_upload
uploaded = upload_params[:ndjson_file]
unless uploaded.present?
flash.now[:alert] = t("import.uploads.sure_import.ndjson_invalid", default: "Must be valid NDJSON with at least one record")
render :show, status: :unprocessable_entity
return
end
if uploaded.size > SureImport::MAX_NDJSON_SIZE
flash.now[:alert] = t("imports.create.file_too_large", max_size: SureImport::MAX_NDJSON_SIZE / 1.megabyte)
render :show, status: :unprocessable_entity
return
end
content = uploaded.read
uploaded.rewind
if ndjson_valid?(content)
uploaded.rewind
@import.ndjson_file.attach(uploaded)
@import.sync_ndjson_rows_count!
redirect_to import_path(@import), notice: t("imports.create.ndjson_uploaded")
else
flash.now[:alert] = t("import.uploads.sure_import.ndjson_invalid", default: "Must be valid NDJSON with at least one record")
render :show, status: :unprocessable_entity
end
end
def set_import
@import = Current.family.imports.find(params[:import_id])
end
def handle_qif_upload
unless QifParser.valid?(csv_str)
flash.now[:alert] = "Must be a valid QIF file"
render :show, status: :unprocessable_entity and return
end
unless import_account_id.present?
flash.now[:alert] = "Please select an account for the QIF import"
render :show, status: :unprocessable_entity and return
end
ActiveRecord::Base.transaction do
@import.account = accessible_accounts.find(import_account_id)
@import.raw_file_str = QifParser.normalize_encoding(csv_str)
@import.save!(validate: false)
@import.generate_rows_from_csv
@import.sync_mappings
end
redirect_to import_qif_category_selection_path(@import), notice: "QIF file uploaded successfully."
end
def csv_str
@csv_str ||= upload_params[:import_file]&.read || upload_params[:raw_file_str]
end
def csv_valid?(str)
begin
csv = Import.parse_csv_str(str, col_sep: upload_params[:col_sep])
return false if csv.headers.empty?
return false if csv.count == 0
true
rescue CSV::MalformedCSVError
false
end
end
def ndjson_valid?(str)
return false if str.blank?
# Check at least first line is valid NDJSON
first_line = str.lines.first&.strip
return false if first_line.blank?
begin
record = JSON.parse(first_line)
record.key?("type") && record.key?("data")
rescue JSON::ParserError
false
end
end
def upload_params
params.require(:import).permit(:raw_file_str, :import_file, :ndjson_file, :col_sep)
end
def import_account_id
params.require(:import).permit(:account_id)[:account_id]
end
end