feat(api): support idempotent valuation writes (#1637)

* feat(api): support idempotent valuation writes

* fix(api): clarify valuation upsert status

* docs(api): document nested valuation upserts

* docs(api): clarify valuation upsert semantics

* docs(api): clarify valuation upsert signaling
This commit is contained in:
ghost
2026-05-04 10:51:48 -06:00
committed by GitHub
parent ddaf42c96c
commit 05ef8bd9e7
4 changed files with 133 additions and 2 deletions

View File

@@ -143,6 +143,81 @@ class Api::V1::ValuationsControllerTest < ActionDispatch::IntegrationTest
assert_equal @account.id, response_data["account"]["id"]
end
test "should upsert valuation for same account and date when requested" do
existing_entry = @valuation.entry
valuation_params = {
upsert: "true",
valuation: {
account_id: existing_entry.account.id,
amount: 12_345.67,
date: existing_entry.date,
notes: "API correction"
}
}
assert_no_difference("@family.entries.valuations.count") do
post api_v1_valuations_url,
params: valuation_params,
headers: api_headers(@api_key)
end
assert_response :ok
response_data = JSON.parse(response.body)
assert_equal existing_entry.id, response_data["id"]
assert_equal existing_entry.date.to_s, response_data["date"]
assert_equal "API correction", response_data["notes"]
assert_equal BigDecimal("12345.67"), existing_entry.reload.amount
end
test "should create valuation when upsert is requested without an existing same-date valuation" do
valuation_date = Date.current + 3.days
valuation_params = {
upsert: "true",
valuation: {
account_id: @account.id,
amount: 9876.54,
date: valuation_date,
notes: "New API valuation"
}
}
assert_difference("@family.entries.valuations.count", 1) do
post api_v1_valuations_url,
params: valuation_params,
headers: api_headers(@api_key)
end
assert_response :created
response_data = JSON.parse(response.body)
assert_equal valuation_date.to_s, response_data["date"]
assert_equal "New API valuation", response_data["notes"]
end
test "should accept nested upsert flag for same-date valuation writes" do
existing_entry = @valuation.entry
valuation_params = {
valuation: {
account_id: existing_entry.account.id,
amount: 22_222.22,
date: existing_entry.date,
notes: "Nested upsert correction",
upsert: "true"
}
}
assert_no_difference("@family.entries.valuations.count") do
post api_v1_valuations_url,
params: valuation_params,
headers: api_headers(@api_key)
end
assert_response :ok
response_data = JSON.parse(response.body)
assert_equal existing_entry.id, response_data["id"]
assert_equal "Nested upsert correction", response_data["notes"]
assert_equal BigDecimal("22222.22"), existing_entry.reload.amount
end
test "should reject create with read-only API key" do
valuation_params = {
valuation: {