Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/controllers/import/configurations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def import_params
:number_format,
:signage_convention,
:amount_type_strategy,
:amount_type_identifier_value,
:amount_type_inflow_value,
)
end
Expand Down
42 changes: 42 additions & 0 deletions app/javascript/controllers/import_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default class extends Controller {
"signedAmountFieldset",
"customColumnFieldset",
"amountTypeValue",
"amountTypeInflowValue",
"amountTypeStrategySelect",
];

Expand All @@ -20,6 +21,10 @@ export default class extends Controller {
this.amountTypeColumnKeyValue
) {
this.#showAmountTypeValueTargets(this.amountTypeColumnKeyValue);
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
if (identifierValueSelect && identifierValueSelect.value) {
this.#showAmountTypeInflowValueTargets();
}
}
}

Expand All @@ -31,6 +36,10 @@ export default class extends Controller {

if (this.amountTypeColumnKeyValue) {
this.#showAmountTypeValueTargets(this.amountTypeColumnKeyValue);
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
if (identifierValueSelect && identifierValueSelect.value) {
this.#showAmountTypeInflowValueTargets();
}
}
}

Expand All @@ -45,6 +54,10 @@ export default class extends Controller {
this.#showAmountTypeValueTargets(amountTypeColumnKey);
}

handleAmountTypeIdentifierChange(event) {
this.#showAmountTypeInflowValueTargets();
}

#showAmountTypeValueTargets(amountTypeColumnKey) {
const selectableValues = this.#uniqueValuesForColumn(amountTypeColumnKey);

Expand Down Expand Up @@ -72,6 +85,29 @@ export default class extends Controller {
select.appendChild(fragment);
}

#showAmountTypeInflowValueTargets(amountTypeColumnKey) {
// This should be called when amount_type_identifier_value changes
// We need to update the displayed identifier value in the UI text
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
const selectedValue = identifierValueSelect.value;

if (!selectedValue) {
this.amountTypeInflowValueTarget.classList.add("hidden");
this.amountTypeInflowValueTarget.classList.remove("flex");
return;
}

// Show the inflow value dropdown
this.amountTypeInflowValueTarget.classList.remove("hidden");
this.amountTypeInflowValueTarget.classList.add("flex");

// Update the displayed identifier value in the text
const identifierSpan = this.amountTypeInflowValueTarget.querySelector("span.font-medium");
if (identifierSpan) {
identifierSpan.textContent = selectedValue;
}
}

Copy link

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter amountTypeColumnKey is never used and all invocations pass no argument, which can confuse future readers; remove the unused parameter from the method signature (and its comment if not needed) to clarify intent.

Copilot uses AI. Check for mistakes.
#uniqueValuesForColumn(column) {
const colIdx = this.csvValue[0].indexOf(column);
const values = this.csvValue.slice(1).map((row) => row[colIdx]);
Expand Down Expand Up @@ -101,6 +137,12 @@ export default class extends Controller {
this.customColumnFieldsetTarget.classList.add("hidden");
this.signedAmountFieldsetTarget.classList.remove("hidden");

// Hide the inflow value targets when using signed amount strategy
this.amountTypeValueTarget.classList.add("hidden");
this.amountTypeValueTarget.classList.remove("flex");
this.amountTypeInflowValueTarget.classList.add("hidden");
this.amountTypeInflowValueTarget.classList.remove("flex");

// Remove required from custom column fields
this.customColumnFieldsetTarget
.querySelectorAll("select, input")
Expand Down
9 changes: 5 additions & 4 deletions app/models/import/row.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ def apply_transaction_signage_convention(value)
if import.amount_type_strategy == "signed_amount"
value * (import.signage_convention == "inflows_positive" ? -1 : 1)
elsif import.amount_type_strategy == "custom_column"
inflow_value = import.amount_type_inflow_value
selected_identifier = import.amount_type_identifier_value
inflow_treatment = import.amount_type_inflow_value

if entity_type == inflow_value
value * -1
if entity_type == selected_identifier
value * (inflow_treatment == "inflows_positive" ? -1 : 1)
else
value
value * (inflow_treatment == "inflows_positive" ? 1 : -1)
end
else
raise "Unknown amount type strategy for import: #{import.amount_type_strategy}"
Expand Down
16 changes: 13 additions & 3 deletions app/views/import/configurations/_transaction_import.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,21 @@
<div class="items-center gap-2 text-sm <%= @import.entity_type_col_label.nil? ? "hidden" : "flex" %>" data-import-target="amountTypeValue">
<span class="shrink-0 text-secondary">↪</span>
<span class="text-secondary">Set</span>
<%= form.select :amount_type_inflow_value,
<%= form.select :amount_type_identifier_value,
@import.selectable_amount_type_values,
{ prompt: "Select column", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
{ prompt: "Select value", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
required: @import.amount_type_strategy == "custom_column",
data: { action: "import#handleAmountTypeIdentifierChange" } %>
<span class="text-secondary">as identifier value</span>
</div>

<div class="items-center gap-2 text-sm <%= @import.amount_type_identifier_value.nil? ? "hidden" : "flex" %>" data-import-target="amountTypeInflowValue">
<span class="shrink-0 text-secondary">↪</span>
<span class="text-secondary">Treat "<span class="font-medium"><%= @import.amount_type_identifier_value %></span>" as</span>
<%= form.select :amount_type_inflow_value,
[["Income (inflow)", "inflows_positive"], ["Expense (outflow)", "inflows_negative"]],
{ prompt: "Select type", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
required: @import.amount_type_strategy == "custom_column" %>
<span class="text-secondary">as "income" (inflow) value</span>
</div>
</div>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddAmountTypeIdentifierValueToImports < ActiveRecord::Migration[7.2]
def change
add_column :imports, :amount_type_identifier_value, :string
end
end

Check failure on line 5 in db/migrate/20251002120000_add_amount_type_identifier_value_to_imports.rb

View workflow job for this annotation

GitHub Actions / ci / lint

Layout/TrailingEmptyLines: Final newline missing.
3 changes: 2 additions & 1 deletion test/models/transaction_import_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ class TransactionImportTest < ActiveSupport::TestCase
date_format: "%m/%d/%Y",
amount_col_label: "amount",
entity_type_col_label: "amount_type",
amount_type_inflow_value: "debit",
amount_type_identifier_value: "debit",
amount_type_inflow_value: "inflows_positive",
amount_type_strategy: "custom_column",
signage_convention: nil # Explicitly set to nil to prove this is not needed
)
Expand Down
Loading