Skip to content

Commit dbe68ab

Browse files
Add amount_type_identifier_value to import configuration
Introduces a new field, amount_type_identifier_value, to the import configuration and database schema. Updates controller, model logic, JavaScript, and view to support selecting and treating a specific identifier value for custom column amount type strategy. Adjusts tests to use the new field.
1 parent cbc653a commit dbe68ab

File tree

6 files changed

+68
-8
lines changed

6 files changed

+68
-8
lines changed

app/controllers/import/configurations_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def import_params
3838
:number_format,
3939
:signage_convention,
4040
:amount_type_strategy,
41+
:amount_type_identifier_value,
4142
:amount_type_inflow_value,
4243
)
4344
end

app/javascript/controllers/import_controller.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default class extends Controller {
1111
"signedAmountFieldset",
1212
"customColumnFieldset",
1313
"amountTypeValue",
14+
"amountTypeInflowValue",
1415
"amountTypeStrategySelect",
1516
];
1617

@@ -20,6 +21,10 @@ export default class extends Controller {
2021
this.amountTypeColumnKeyValue
2122
) {
2223
this.#showAmountTypeValueTargets(this.amountTypeColumnKeyValue);
24+
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
25+
if (identifierValueSelect && identifierValueSelect.value) {
26+
this.#showAmountTypeInflowValueTargets();
27+
}
2328
}
2429
}
2530

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

3237
if (this.amountTypeColumnKeyValue) {
3338
this.#showAmountTypeValueTargets(this.amountTypeColumnKeyValue);
39+
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
40+
if (identifierValueSelect && identifierValueSelect.value) {
41+
this.#showAmountTypeInflowValueTargets();
42+
}
3443
}
3544
}
3645

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

57+
handleAmountTypeIdentifierChange(event) {
58+
this.#showAmountTypeInflowValueTargets();
59+
}
60+
4861
#showAmountTypeValueTargets(amountTypeColumnKey) {
4962
const selectableValues = this.#uniqueValuesForColumn(amountTypeColumnKey);
5063

@@ -72,6 +85,29 @@ export default class extends Controller {
7285
select.appendChild(fragment);
7386
}
7487

88+
#showAmountTypeInflowValueTargets(amountTypeColumnKey) {
89+
// This should be called when amount_type_identifier_value changes
90+
// We need to update the displayed identifier value in the UI text
91+
const identifierValueSelect = this.amountTypeValueTarget.querySelector("select");
92+
const selectedValue = identifierValueSelect.value;
93+
94+
if (!selectedValue) {
95+
this.amountTypeInflowValueTarget.classList.add("hidden");
96+
this.amountTypeInflowValueTarget.classList.remove("flex");
97+
return;
98+
}
99+
100+
// Show the inflow value dropdown
101+
this.amountTypeInflowValueTarget.classList.remove("hidden");
102+
this.amountTypeInflowValueTarget.classList.add("flex");
103+
104+
// Update the displayed identifier value in the text
105+
const identifierSpan = this.amountTypeInflowValueTarget.querySelector("span.font-medium");
106+
if (identifierSpan) {
107+
identifierSpan.textContent = selectedValue;
108+
}
109+
}
110+
75111
#uniqueValuesForColumn(column) {
76112
const colIdx = this.csvValue[0].indexOf(column);
77113
const values = this.csvValue.slice(1).map((row) => row[colIdx]);
@@ -101,6 +137,12 @@ export default class extends Controller {
101137
this.customColumnFieldsetTarget.classList.add("hidden");
102138
this.signedAmountFieldsetTarget.classList.remove("hidden");
103139

140+
// Hide the inflow value targets when using signed amount strategy
141+
this.amountTypeValueTarget.classList.add("hidden");
142+
this.amountTypeValueTarget.classList.remove("flex");
143+
this.amountTypeInflowValueTarget.classList.add("hidden");
144+
this.amountTypeInflowValueTarget.classList.remove("flex");
145+
104146
// Remove required from custom column fields
105147
this.customColumnFieldsetTarget
106148
.querySelectorAll("select, input")

app/models/import/row.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ def apply_transaction_signage_convention(value)
4747
if import.amount_type_strategy == "signed_amount"
4848
value * (import.signage_convention == "inflows_positive" ? -1 : 1)
4949
elsif import.amount_type_strategy == "custom_column"
50-
inflow_value = import.amount_type_inflow_value
50+
selected_identifier = import.amount_type_identifier_value
51+
inflow_treatment = import.amount_type_inflow_value
5152

52-
if entity_type == inflow_value
53-
value * -1
53+
if entity_type == selected_identifier
54+
value * (inflow_treatment == "inflows_positive" ? -1 : 1)
5455
else
55-
value
56+
value * (inflow_treatment == "inflows_positive" ? 1 : -1)
5657
end
5758
else
5859
raise "Unknown amount type strategy for import: #{import.amount_type_strategy}"

app/views/import/configurations/_transaction_import.html.erb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,21 @@
7878
<div class="items-center gap-2 text-sm <%= @import.entity_type_col_label.nil? ? "hidden" : "flex" %>" data-import-target="amountTypeValue">
7979
<span class="shrink-0 text-secondary"></span>
8080
<span class="text-secondary">Set</span>
81-
<%= form.select :amount_type_inflow_value,
81+
<%= form.select :amount_type_identifier_value,
8282
@import.selectable_amount_type_values,
83-
{ prompt: "Select column", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
83+
{ prompt: "Select value", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
84+
required: @import.amount_type_strategy == "custom_column",
85+
data: { action: "import#handleAmountTypeIdentifierChange" } %>
86+
<span class="text-secondary">as identifier value</span>
87+
</div>
88+
89+
<div class="items-center gap-2 text-sm <%= @import.amount_type_identifier_value.nil? ? "hidden" : "flex" %>" data-import-target="amountTypeInflowValue">
90+
<span class="shrink-0 text-secondary"></span>
91+
<span class="text-secondary">Treat "<span class="font-medium"><%= @import.amount_type_identifier_value %></span>" as</span>
92+
<%= form.select :amount_type_inflow_value,
93+
[["Income (inflow)", "inflows_positive"], ["Expense (outflow)", "inflows_negative"]],
94+
{ prompt: "Select type", container_class: "w-48 px-3 py-1.5 border border-secondary rounded-md" },
8495
required: @import.amount_type_strategy == "custom_column" %>
85-
<span class="text-secondary">as "income" (inflow) value</span>
8696
</div>
8797
</div>
8898
<% end %>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddAmountTypeIdentifierValueToImports < ActiveRecord::Migration[7.2]
2+
def change
3+
add_column :imports, :amount_type_identifier_value, :string
4+
end
5+
end

test/models/transaction_import_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ class TransactionImportTest < ActiveSupport::TestCase
8484
date_format: "%m/%d/%Y",
8585
amount_col_label: "amount",
8686
entity_type_col_label: "amount_type",
87-
amount_type_inflow_value: "debit",
87+
amount_type_identifier_value: "debit",
88+
amount_type_inflow_value: "inflows_positive",
8889
amount_type_strategy: "custom_column",
8990
signage_convention: nil # Explicitly set to nil to prove this is not needed
9091
)

0 commit comments

Comments
 (0)