From e38bfbcb5bc69ff010227639ab620b46c2791ea3 Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 17:19:21 -0400 Subject: [PATCH 01/10] Start: show and edit FileMaker codes on payments, workshops, resources Co-Authored-By: Claude Opus 5.5 (1M context) From 675c1c39493d087ee800a65fbbbccb876765dd3e Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 17:21:12 -0400 Subject: [PATCH 02/10] Let admins see and fix FileMaker codes on payments, workshops, and resources These tables carry a filemaker_code column but no page showed it, so a wrong or missing code could only be fixed in the console. Payments and workshops also get the admin-mode archive links people and organizations have; resources have no FileMaker archive table to link to. Co-Authored-By: Claude Opus 5.5 (1M context) --- app/controllers/payments_controller.rb | 2 +- app/controllers/workshops_controller.rb | 2 +- app/models/payment.rb | 1 + app/models/workshop.rb | 1 + app/views/payments/edit.html.erb | 12 ++++++++++ app/views/resources/_form.html.erb | 5 ++++ app/views/workshops/_form.html.erb | 11 +++++++++ config/features.yml | 12 ++++++++++ spec/requests/payments_spec.rb | 31 +++++++++++++++++++++++++ spec/requests/resources_spec.rb | 14 +++++++++++ spec/requests/workshops_spec.rb | 30 ++++++++++++++++++++++++ 11 files changed, 119 insertions(+), 2 deletions(-) diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index 69652f4910..c53ea16c58 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -252,7 +252,7 @@ def calculate_allocation_amount(payment, allocatable) end def edit_payment_params - params.require(:payment).permit(:person_id, :organization_id, :form_submission_id, :payer_sgid, :additional_designation_sgid) + params.require(:payment).permit(:person_id, :organization_id, :form_submission_id, :payer_sgid, :additional_designation_sgid, :filemaker_code) end def redirect_path_for(allocatable) diff --git a/app/controllers/workshops_controller.rb b/app/controllers/workshops_controller.rb index 18b900a952..698cb92d75 100644 --- a/app/controllers/workshops_controller.rb +++ b/app/controllers/workshops_controller.rb @@ -207,7 +207,7 @@ def workshop_params params.require(:workshop).permit( :title, :featured, :published, :full_name, :author_id, :windows_type_id, :workshop_idea_id, :author_credit_preference, - :month, :year, + :month, :year, :filemaker_code, :publicly_visible, :publicly_featured, diff --git a/app/models/payment.rb b/app/models/payment.rb index a7e0e30661..d4f3e66839 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -1,4 +1,5 @@ class Payment < ApplicationRecord + include FilemakerCoded has_paper_trail PAYER_TYPES = %w[Person Organization].freeze diff --git a/app/models/workshop.rb b/app/models/workshop.rb index 11932ea209..d1aa49581b 100644 --- a/app/models/workshop.rb +++ b/app/models/workshop.rb @@ -3,6 +3,7 @@ class Workshop < ApplicationRecord credits_to_org include Featureable, Publishable, RemoteSearchable, TagFilterable, Trendable, WindowsTypeFilterable, RichTextSearchable include Communicable + include FilemakerCoded include PunctuationStrippable include Rails.application.routes.url_helpers include ActionText::Attachable diff --git a/app/views/payments/edit.html.erb b/app/views/payments/edit.html.erb index ac644b9778..2ec5ff9b27 100644 --- a/app/views/payments/edit.html.erb +++ b/app/views/payments/edit.html.erb @@ -40,6 +40,18 @@ <%= f.input :form_submission_id, input_html: { class: "bg-white" }, label: "Form Submission ID" %> + +
+ <%= f.input :filemaker_code, + input_html: { class: "bg-white" }, + label: "FileMaker code" %> + <%- if params[:admin] == "true" %> +

+ <%= filemaker_code_links(f.object, archive: FmPayment, table: "payments", label: "View archive", + link_class: "text-blue-600 hover:text-blue-800 underline") %> +

+ <% end %> +
<%= link_to "Cancel", payment_path(@payment), class: button_classes(:secondary_outline) %> diff --git a/app/views/resources/_form.html.erb b/app/views/resources/_form.html.erb index 0a394342ee..7aa6c26cb7 100644 --- a/app/views/resources/_form.html.erb +++ b/app/views/resources/_form.html.erb @@ -51,6 +51,11 @@ <%= visibility_flag_input f, :publicly_featured %> <%= visibility_flag_input f, :hidden_from_search %>
+ <%= f.input :filemaker_code, + label: "FileMaker code", + wrapper_html: { class: "mt-4" }, + input_html: { class: "w-full rounded border-gray-300" }, + label_html: { class: "font-medium mb-1 block" } %> <% end %> diff --git a/app/views/workshops/_form.html.erb b/app/views/workshops/_form.html.erb index deab563095..9ea741fe30 100644 --- a/app/views/workshops/_form.html.erb +++ b/app/views/workshops/_form.html.erb @@ -103,6 +103,17 @@ } %> +
+ <%= f.input :filemaker_code, + label: "FileMaker code", + input_html: { class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" } %> + <%- if params[:admin] == "true" %> +

+ <%= filemaker_code_links(f.object, archive: FmWorkshop, table: "workshops", label: "View archive", + link_class: "text-blue-600 hover:text-blue-800 underline") %> +

+ <% end %> +
<%= render "shared/visibility_info", flags: %i[published featured publicly_visible publicly_featured] %> diff --git a/config/features.yml b/config/features.yml index f1cf79f513..5f466b2217 100644 --- a/config/features.yml +++ b/config/features.yml @@ -4261,3 +4261,15 @@ the archive record links back to the affiliation. pro_tips: - "An affiliation's code is usually its program's FileMaker project ID (like P2775), and occasionally a personnel ID (like PS9999)." + +- name: "FileMaker codes on payments, workshops, and resources" + area: content + display_status: admin_facing + released_on: 2026-10-12 + pr_number: 2656 + summary: >- + The payment, workshop, and resource editors now show each record's FileMaker + code so admins can see and fix it, the same way people and organizations do. + pro_tips: + - "Separate several codes with commas — a record can answer to more than one." + - "With admin mode on, payment and workshop codes link to their row in the FileMaker archive." diff --git a/spec/requests/payments_spec.rb b/spec/requests/payments_spec.rb index 958afeb0b7..12a6e85523 100644 --- a/spec/requests/payments_spec.rb +++ b/spec/requests/payments_spec.rb @@ -172,9 +172,40 @@ end end + describe "GET /payments/:id/edit FileMaker code" do + it "renders the FileMaker code field" do + payment = create(:payment, person:) + + get edit_payment_path(payment) + + expect(response.body).to include("payment[filemaker_code]") + end + + it "links each archived code to the FileMaker payments archive in admin mode" do + FmPayment.create!(fm_id: "D29186", data: {}) + payment = create(:payment, person:, filemaker_code: "D29186, D99999") + + get edit_payment_path(payment, admin: "true") + + expect(response.body).to include(fm_archive_path("D29186", table: "payments")) + expect(response.body).to include("View archive D99999") + expect(response.body).not_to include(fm_archive_path("D99999", table: "payments")) + end + end + describe "PATCH /payments/:id" do let(:organization) { create(:organization) } + it "updates the FileMaker code" do + payment = create(:payment, person:) + + patch payment_path(payment), params: { + payment: { payer_sgid: person.to_sgid.to_s, filemaker_code: "D29186" } + } + + expect(payment.reload.filemaker_code).to eq("D29186") + end + it "updates payer and designation via sgids" do payment = create(:payment, person:, organization: nil) diff --git a/spec/requests/resources_spec.rb b/spec/requests/resources_spec.rb index 839a99d224..9969dc6012 100644 --- a/spec/requests/resources_spec.rb +++ b/spec/requests/resources_spec.rb @@ -139,6 +139,13 @@ expect(response.body).to include('name="resource[publicly_visible]"') expect(response.body).to include(VisibilityFlagsHelper::FLAG_DEFINITIONS[:hidden_from_search][:description]) end + + it "renders the FileMaker code field" do + resource = Resource.create! valid_attributes + get edit_resource_url(resource) + + expect(response.body).to include('name="resource[filemaker_code]"') + end end describe "POST /create" do @@ -200,6 +207,13 @@ expect(resource.title).to eq("Updated Resource Title") end + it "updates the FileMaker code" do + resource = Resource.create! valid_attributes + patch resource_url(resource), params: { resource: new_attributes.merge(filemaker_code: "R42") } + + expect(resource.reload.filemaker_code).to eq("R42") + end + it "redirects to the updated resource" do resource = Resource.create! valid_attributes patch resource_url(resource), params: { resource: new_attributes } diff --git a/spec/requests/workshops_spec.rb b/spec/requests/workshops_spec.rb index 3dca2646b4..f208f46fda 100644 --- a/spec/requests/workshops_spec.rb +++ b/spec/requests/workshops_spec.rb @@ -52,6 +52,36 @@ end end + describe "FileMaker code" do + let(:admin) { create(:user, :admin) } + let(:workshop) { create(:workshop) } + + before { sign_in admin } + + it "renders the FileMaker code field on edit" do + get edit_workshop_url(workshop) + + expect(response.body).to include("workshop[filemaker_code]") + end + + it "links an archived code to the FileMaker workshops archive in admin mode" do + FmWorkshop.create!(fm_id: "W123", data: {}) + workshop.update!(filemaker_code: "W123") + + get edit_workshop_url(workshop, admin: "true") + + expect(response.body).to include(fm_archive_path("W123", table: "workshops")) + end + + it "updates the FileMaker code" do + patch workshop_url(workshop), params: { + workshop: { title: workshop.title, category_ids: [ "" ], filemaker_code: "W123" } + } + + expect(workshop.reload.filemaker_code).to eq("W123") + end + end + # --- STORIES THAT USE THIS WORKSHOP ---------------------------------------- describe "GET /show stories section" do let(:user) { create(:user) } From 774ecfa0288775e05a8feee4436423d825c157dd Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 17:54:43 -0400 Subject: [PATCH 03/10] Put the payment FileMaker code in the blue admin box like people and orgs Co-Authored-By: Claude Opus 5.5 (1M context) --- app/views/payments/edit.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/payments/edit.html.erb b/app/views/payments/edit.html.erb index 2ec5ff9b27..e8eb28881d 100644 --- a/app/views/payments/edit.html.erb +++ b/app/views/payments/edit.html.erb @@ -41,7 +41,7 @@ input_html: { class: "bg-white" }, label: "Form Submission ID" %> -
+
<%= f.input :filemaker_code, input_html: { class: "bg-white" }, label: "FileMaker code" %> From 87d361c18222f073648520037f1f182137dbef39 Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 17:55:53 -0400 Subject: [PATCH 04/10] Pair the payment FileMaker code with the form submission ID on one row Co-Authored-By: Claude Opus 5.5 (1M context) --- app/views/payments/edit.html.erb | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/app/views/payments/edit.html.erb b/app/views/payments/edit.html.erb index e8eb28881d..b039550b4a 100644 --- a/app/views/payments/edit.html.erb +++ b/app/views/payments/edit.html.erb @@ -37,20 +37,24 @@ prompt: "Search people and organizations", label: "Additional designation" %> - <%= f.input :form_submission_id, - input_html: { class: "bg-white" }, - label: "Form Submission ID" %> +
+
+ <%= f.input :form_submission_id, + input_html: { class: "bg-white" }, + label: "Form Submission ID" %> +
-
- <%= f.input :filemaker_code, - input_html: { class: "bg-white" }, - label: "FileMaker code" %> - <%- if params[:admin] == "true" %> -

- <%= filemaker_code_links(f.object, archive: FmPayment, table: "payments", label: "View archive", - link_class: "text-blue-600 hover:text-blue-800 underline") %> -

- <% end %> +
+ <%= f.input :filemaker_code, + input_html: { class: "bg-white" }, + label: "FileMaker code" %> + <%- if params[:admin] == "true" %> +

+ <%= filemaker_code_links(f.object, archive: FmPayment, table: "payments", label: "View archive", + link_class: "text-blue-600 hover:text-blue-800 underline") %> +

+ <% end %> +
From 396104dfd48e7e6f54c339a71bf61f11ec019361 Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 17:58:08 -0400 Subject: [PATCH 05/10] Put the resource FileMaker code on the audience/display-order row Co-Authored-By: Claude Opus 5.5 (1M context) --- app/views/resources/_form.html.erb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/views/resources/_form.html.erb b/app/views/resources/_form.html.erb index 7aa6c26cb7..1738c9cc92 100644 --- a/app/views/resources/_form.html.erb +++ b/app/views/resources/_form.html.erb @@ -37,6 +37,15 @@ input_html: { class: "w-24 rounded border-gray-300 px-2 py-1", min: 1, step: 1 }, label_html: { class: "font-medium mb-1 block" } %>
+ + <% if allowed_to?(:manage?, @resource) %> +
+ <%= f.input :filemaker_code, + label: "FileMaker code", + input_html: { class: "w-full rounded border-gray-300" }, + label_html: { class: "font-medium mb-1 block" } %> +
+ <% end %>
@@ -51,11 +60,6 @@ <%= visibility_flag_input f, :publicly_featured %> <%= visibility_flag_input f, :hidden_from_search %>
- <%= f.input :filemaker_code, - label: "FileMaker code", - wrapper_html: { class: "mt-4" }, - input_html: { class: "w-full rounded border-gray-300" }, - label_html: { class: "font-medium mb-1 block" } %> <% end %> From 4c61f332b514f6b5b6ac01d0d382a7e304c6d30e Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 19:25:33 -0400 Subject: [PATCH 06/10] Record the new payment/workshop archive links in ADR-0005 Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/adr/0005-filemaker-code-archive-mapping.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/adr/0005-filemaker-code-archive-mapping.md b/docs/adr/0005-filemaker-code-archive-mapping.md index 76e70c197e..8e25f38515 100644 --- a/docs/adr/0005-filemaker-code-archive-mapping.md +++ b/docs/adr/0005-filemaker-code-archive-mapping.md @@ -26,9 +26,9 @@ drive the archive pages' links. | `people.filemaker_code` | `fm_rolodexes` | `ID`, e.g. `00006` | `filemaker_code_links` on person edit + admin details | | `organizations.filemaker_code` | `fm_projects`, then `fm_organizations` | `ProjectID`, e.g. `P2775`; `OrgID`, e.g. `ORG07206` | `filemaker_code_links` on org form; `filemaker_project_links` / `filemaker_organization_links` on org edit | | `affiliations.filemaker_code` | `fm_projects`, then `fm_personnels` | `ProjectID`, e.g. `P2775`; rarely `PrsnlRecID`, e.g. `PS9999` | `filemaker_code_links` on affiliation edit | -| `payments.filemaker_code` | `fm_payments` | `RecordID`, e.g. `D29186` | dev seed (no UI link yet) | -| `workshops.filemaker_code` | `fm_workshops` | `WorkshopID` | dev seed (no UI link yet) | -| `resources.filemaker_code` | `fm_quotations` | `RecordID`, e.g. `Q10215` | no UI link yet | +| `payments.filemaker_code` | `fm_payments` | `RecordID`, e.g. `D29186` | `filemaker_code_hint` on payment edit | +| `workshops.filemaker_code` | `fm_workshops` | `WorkshopID` | `filemaker_code_hint` on workshop form | +| `resources.filemaker_code` | `fm_quotations` | `RecordID`, e.g. `Q10215` | `filemaker_code_hint` on resource form | - **Organization → Project, or → Organization.** An app `Organization` is usually one art program site, which is a FileMaker *Project*. FileMaker's own Organization row is @@ -173,6 +173,6 @@ Production, 2026-10-12: 84 records (41 organizations, 16 affiliations, 14 worksh ## Consequences -A UI link for payments, workshops, or resources includes `FilemakerCoded` on the +A UI link for a new FileMaker-coded column includes `FilemakerCoded` on the model and declares the archive table above (e.g. `filemaker_archived_in FmPersonnel`); `filemaker_code_links` reads it from there. From f09bdfca49e0adad13f8561ae5a11ef767078b2d Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 19:30:32 -0400 Subject: [PATCH 07/10] Drop the admin-mode archive tip from the FileMaker codes feature entry Co-Authored-By: Claude Opus 5.5 (1M context) --- config/features.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/features.yml b/config/features.yml index 5f466b2217..c04c30b0ef 100644 --- a/config/features.yml +++ b/config/features.yml @@ -4272,4 +4272,3 @@ code so admins can see and fix it, the same way people and organizations do. pro_tips: - "Separate several codes with commas — a record can answer to more than one." - - "With admin mode on, payment and workshop codes link to their row in the FileMaker archive." From f5d1d8f38c29b97f91b22879adbf1a73d503b1b7 Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 21:27:05 -0400 Subject: [PATCH 08/10] Link payment, workshop, and resource codes through the archive declaration Main moved archive links onto each model's filemaker_archived_in, shown in the code field's hint for anyone the archive policy allows, so these forms follow suit. Resources now map to quotations per ADR-0005, so they get links too. Co-Authored-By: Claude Opus 5.5 (1M context) --- AGENTS.md | 2 +- app/models/payment.rb | 1 + app/models/resource.rb | 2 ++ app/models/workshop.rb | 1 + app/views/payments/edit.html.erb | 9 ++------- app/views/resources/_form.html.erb | 1 + app/views/workshops/_form.html.erb | 15 ++++----------- spec/requests/payments_spec.rb | 6 +++--- spec/requests/resources_spec.rb | 8 ++++++++ spec/requests/workshops_spec.rb | 4 ++-- 10 files changed, 25 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index db37359ab7..5e959012f4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -146,7 +146,7 @@ This codebase (Rails 8.1) | `Communicable` | Gives a record the `notifications` association, nested attributes, a default `communications_scope`, and a `before_validation` addressing a hand-logged communication to the record's `communications_email`. Included by every model whose form renders `shared/_comments_and_communications` | | `AuthorCreditable` | Author attribution. Credits are formatted by the credited **person's profile** (`Person#display_name_preference`), not by the record. The record's `author_credit_preference` is the consent snapshot taken at create time and is human-editable only on the author credit divergences page. Anonymity is a one-way latch: the profile or the record can set it, neither can strip it from the other. `credits_to_org` flips the unattributed label to "AWBW Staff"; `credits_creator` (idea models, workshop logs) credits the submitting account's person when no author is named | | `Featureable` | `featured`, `publicly_featured` scopes | -| `FilemakerCoded` | Reads `filemaker_code` as the trimmed, comma-separated **list** it is (Person, Organization, Affiliation): `#filemaker_codes` for the set a record answers to, `.join_filemaker_codes` to combine any mix of strings/lists into one normalized column value (both dedupers union the codes on merge). `filemaker_archived_in` names the `Fm*` archive table(s) a model's codes point into (`.filemaker_archives`), and `.with_filemaker_code(code)` finds records carrying a code. Nothing should compare the whole column against a single code — `FilemakerHelper#filemaker_code_links` renders one archive link per code, and `fm_archives#show` links back to the portal records carrying its code | +| `FilemakerCoded` | Reads `filemaker_code` as the trimmed, comma-separated **list** it is (Person, Organization, Affiliation, Payment, Workshop, Resource): `#filemaker_codes` for the set a record answers to, `.join_filemaker_codes` to combine any mix of strings/lists into one normalized column value (both dedupers union the codes on merge). `filemaker_archived_in` names the `Fm*` archive table(s) a model's codes point into (`.filemaker_archives`), and `.with_filemaker_code(code)` finds records carrying a code. Nothing should compare the whole column against a single code — `FilemakerHelper#filemaker_code_links` renders one archive link per code, and `fm_archives#show` links back to the portal records carrying its code | | `Mentioner` | ActionText @mention extraction and grouping | | `NameFilterable` | Name-based filtering | | `PayChargeExtensions` | Included into `Pay::Charge` (via `config/initializers/pay.rb`): turns a Stripe charge into an AWBW `Payment` + `Allocation`, resolving the membership invoice it pays | diff --git a/app/models/payment.rb b/app/models/payment.rb index d4f3e66839..4f6f4b67e5 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -1,5 +1,6 @@ class Payment < ApplicationRecord include FilemakerCoded + filemaker_archived_in FmPayment has_paper_trail PAYER_TYPES = %w[Person Organization].freeze diff --git a/app/models/resource.rb b/app/models/resource.rb index b593611d19..adca59174e 100644 --- a/app/models/resource.rb +++ b/app/models/resource.rb @@ -5,6 +5,8 @@ class Resource < ApplicationRecord include Rails.application.routes.url_helpers include ActionText::Attachable include Mentionable + include FilemakerCoded + filemaker_archived_in FmQuotation # Define rich text fields for mentions functionality def self.mentionable_rich_text_fields diff --git a/app/models/workshop.rb b/app/models/workshop.rb index d1aa49581b..5001ee05f3 100644 --- a/app/models/workshop.rb +++ b/app/models/workshop.rb @@ -4,6 +4,7 @@ class Workshop < ApplicationRecord include Featureable, Publishable, RemoteSearchable, TagFilterable, Trendable, WindowsTypeFilterable, RichTextSearchable include Communicable include FilemakerCoded + filemaker_archived_in FmWorkshop include PunctuationStrippable include Rails.application.routes.url_helpers include ActionText::Attachable diff --git a/app/views/payments/edit.html.erb b/app/views/payments/edit.html.erb index b039550b4a..68af01c8e0 100644 --- a/app/views/payments/edit.html.erb +++ b/app/views/payments/edit.html.erb @@ -47,13 +47,8 @@
<%= f.input :filemaker_code, input_html: { class: "bg-white" }, - label: "FileMaker code" %> - <%- if params[:admin] == "true" %> -

- <%= filemaker_code_links(f.object, archive: FmPayment, table: "payments", label: "View archive", - link_class: "text-blue-600 hover:text-blue-800 underline") %> -

- <% end %> + label: "FileMaker code", + hint: filemaker_code_hint(f.object) %>
diff --git a/app/views/resources/_form.html.erb b/app/views/resources/_form.html.erb index 1738c9cc92..4826dbf639 100644 --- a/app/views/resources/_form.html.erb +++ b/app/views/resources/_form.html.erb @@ -42,6 +42,7 @@
<%= f.input :filemaker_code, label: "FileMaker code", + hint: filemaker_code_hint(f.object), input_html: { class: "w-full rounded border-gray-300" }, label_html: { class: "font-medium mb-1 block" } %>
diff --git a/app/views/workshops/_form.html.erb b/app/views/workshops/_form.html.erb index 9ea741fe30..83bec3b2e9 100644 --- a/app/views/workshops/_form.html.erb +++ b/app/views/workshops/_form.html.erb @@ -103,17 +103,10 @@ } %> -
- <%= f.input :filemaker_code, - label: "FileMaker code", - input_html: { class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" } %> - <%- if params[:admin] == "true" %> -

- <%= filemaker_code_links(f.object, archive: FmWorkshop, table: "workshops", label: "View archive", - link_class: "text-blue-600 hover:text-blue-800 underline") %> -

- <% end %> -
+ <%= f.input :filemaker_code, + label: "FileMaker code", + hint: filemaker_code_hint(f.object), + input_html: { class: "block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" } %>
<%= render "shared/visibility_info", flags: %i[published featured publicly_visible publicly_featured] %> diff --git a/spec/requests/payments_spec.rb b/spec/requests/payments_spec.rb index 12a6e85523..bd0b5a286a 100644 --- a/spec/requests/payments_spec.rb +++ b/spec/requests/payments_spec.rb @@ -181,14 +181,14 @@ expect(response.body).to include("payment[filemaker_code]") end - it "links each archived code to the FileMaker payments archive in admin mode" do + it "links each archived code to the FileMaker payments archive" do FmPayment.create!(fm_id: "D29186", data: {}) payment = create(:payment, person:, filemaker_code: "D29186, D99999") - get edit_payment_path(payment, admin: "true") + get edit_payment_path(payment) expect(response.body).to include(fm_archive_path("D29186", table: "payments")) - expect(response.body).to include("View archive D99999") + expect(response.body).to include("No FileMaker archive record for D99999") expect(response.body).not_to include(fm_archive_path("D99999", table: "payments")) end end diff --git a/spec/requests/resources_spec.rb b/spec/requests/resources_spec.rb index 9969dc6012..981f5f1916 100644 --- a/spec/requests/resources_spec.rb +++ b/spec/requests/resources_spec.rb @@ -146,6 +146,14 @@ expect(response.body).to include('name="resource[filemaker_code]"') end + + it "links an archived code to the FileMaker quotations archive" do + FmQuotation.create!(fm_id: "Q10215", data: {}) + resource = Resource.create! valid_attributes.merge(filemaker_code: "Q10215") + get edit_resource_url(resource) + + expect(response.body).to include(fm_archive_path("Q10215", table: "quotations")) + end end describe "POST /create" do diff --git a/spec/requests/workshops_spec.rb b/spec/requests/workshops_spec.rb index f208f46fda..1ca40e066a 100644 --- a/spec/requests/workshops_spec.rb +++ b/spec/requests/workshops_spec.rb @@ -64,11 +64,11 @@ expect(response.body).to include("workshop[filemaker_code]") end - it "links an archived code to the FileMaker workshops archive in admin mode" do + it "links an archived code to the FileMaker workshops archive" do FmWorkshop.create!(fm_id: "W123", data: {}) workshop.update!(filemaker_code: "W123") - get edit_workshop_url(workshop, admin: "true") + get edit_workshop_url(workshop) expect(response.body).to include(fm_archive_path("W123", table: "workshops")) end From 7c2b24f8b4232bfcdc1a4bc4c8de753f61648f8a Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 21:50:41 -0400 Subject: [PATCH 09/10] Link FileMaker archive records back to their payment, workshop, or resource An archive record only listed the people, orgs, and affiliations carrying its code, so a payment, workshop, or quotation row was a dead end back to the portal. Co-Authored-By: Claude Opus 5.5 (1M context) --- app/controllers/fm_archives_controller.rb | 2 +- app/helpers/filemaker_helper.rb | 3 +++ config/features.yml | 1 + spec/requests/fm_archives_spec.rb | 31 +++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/app/controllers/fm_archives_controller.rb b/app/controllers/fm_archives_controller.rb index 48891710c9..8e837b6910 100644 --- a/app/controllers/fm_archives_controller.rb +++ b/app/controllers/fm_archives_controller.rb @@ -63,7 +63,7 @@ class FmArchivesController < ApplicationController { label: "Other", icon: "📎", tables: %w[notes] } ] - PORTAL_MODELS = [ Person, Organization, Affiliation ].freeze + PORTAL_MODELS = [ Person, Organization, Affiliation, Payment, Workshop, Resource ].freeze def index authorize! :fm_archive diff --git a/app/helpers/filemaker_helper.rb b/app/helpers/filemaker_helper.rb index c646c1f070..04b6014b0d 100644 --- a/app/helpers/filemaker_helper.rb +++ b/app/helpers/filemaker_helper.rb @@ -34,6 +34,9 @@ def filemaker_portal_link(record) when Person then [ record.full_name, person_path(record) ] when Organization then [ record.name, organization_path(record) ] when Affiliation then [ "#{record.person&.full_name} at #{record.organization&.name}", edit_affiliation_path(record) ] + when Payment then [ [ dollars_from_cents(record.amount_cents), record.payer&.name ].compact.join(" from "), payment_path(record) ] + when Workshop then [ record.title, workshop_path(record) ] + when Resource then [ record.title, resource_path(record, no_redirect: true) ] end link_to text, path, class: button_classes(:primary_outline, size: :sm) diff --git a/config/features.yml b/config/features.yml index c04c30b0ef..062a94c22d 100644 --- a/config/features.yml +++ b/config/features.yml @@ -4272,3 +4272,4 @@ code so admins can see and fix it, the same way people and organizations do. pro_tips: - "Separate several codes with commas — a record can answer to more than one." + - "Each code links to its FileMaker archive record, and that record links back to the payment, workshop, or resource." diff --git a/spec/requests/fm_archives_spec.rb b/spec/requests/fm_archives_spec.rb index 128c65b9fd..b0d3d04813 100644 --- a/spec/requests/fm_archives_spec.rb +++ b/spec/requests/fm_archives_spec.rb @@ -84,6 +84,37 @@ expect(response.body).to include(ERB::Util.html_escape("#{affiliation.person.full_name} at #{affiliation.organization.name}")) end + it "links an archived payment back to its portal payment" do + FmPayment.create!(fm_id: "D29186") + person = create(:person) + payment = create(:payment, person:, amount_cents: 15_000, filemaker_code: "D29186") + + get fm_archive_path("D29186", table: "payments") + + expect(response.body).to include(payment_path(payment)) + expect(response.body).to include("$150 from #{ERB::Util.html_escape(person.name)}") + end + + it "links an archived workshop back to its portal workshop" do + FmWorkshop.create!(fm_id: "W0123") + workshop = create(:workshop, filemaker_code: "W0123") + + get fm_archive_path("W0123", table: "workshops") + + expect(response.body).to include(workshop_path(workshop)) + expect(response.body).to include(ERB::Util.html_escape(workshop.title)) + end + + it "links an archived quotation back to its portal resource" do + FmQuotation.create!(fm_id: "Q10215") + resource = create(:resource, filemaker_code: "Q10215") + + get fm_archive_path("Q10215", table: "quotations") + + expect(response.body).to include(ERB::Util.html_escape(resource_path(resource, no_redirect: true))) + expect(response.body).to include(ERB::Util.html_escape(resource.title)) + end + it "omits the portal section when nothing carries the code" do FmRolodex.create!(fm_id: "00006") From 823f98005c75ff98809f27ad7e51da4dbb3eb712 Mon Sep 17 00:00:00 2001 From: Mae Beale Date: Mon, 12 Oct 2026 22:12:50 -0400 Subject: [PATCH 10/10] Treat resource FileMaker codes as not in the archive A Leader spotlight's code names the FileMaker quotation its text came from, but the resource is its own portal record and quotations belong with the portal's quotes, so the code stays editable without archive links either way. Co-Authored-By: Claude Opus 5.5 (1M context) --- app/controllers/fm_archives_controller.rb | 2 +- app/helpers/filemaker_helper.rb | 1 - app/models/resource.rb | 1 - app/views/resources/_form.html.erb | 1 - config/features.yml | 2 +- docs/adr/0005-filemaker-code-archive-mapping.md | 13 +++++++------ spec/requests/fm_archives_spec.rb | 10 ---------- spec/requests/resources_spec.rb | 5 +++-- 8 files changed, 12 insertions(+), 23 deletions(-) diff --git a/app/controllers/fm_archives_controller.rb b/app/controllers/fm_archives_controller.rb index 8e837b6910..2ce09502b6 100644 --- a/app/controllers/fm_archives_controller.rb +++ b/app/controllers/fm_archives_controller.rb @@ -63,7 +63,7 @@ class FmArchivesController < ApplicationController { label: "Other", icon: "📎", tables: %w[notes] } ] - PORTAL_MODELS = [ Person, Organization, Affiliation, Payment, Workshop, Resource ].freeze + PORTAL_MODELS = [ Person, Organization, Affiliation, Payment, Workshop ].freeze def index authorize! :fm_archive diff --git a/app/helpers/filemaker_helper.rb b/app/helpers/filemaker_helper.rb index 04b6014b0d..349b083da5 100644 --- a/app/helpers/filemaker_helper.rb +++ b/app/helpers/filemaker_helper.rb @@ -36,7 +36,6 @@ def filemaker_portal_link(record) when Affiliation then [ "#{record.person&.full_name} at #{record.organization&.name}", edit_affiliation_path(record) ] when Payment then [ [ dollars_from_cents(record.amount_cents), record.payer&.name ].compact.join(" from "), payment_path(record) ] when Workshop then [ record.title, workshop_path(record) ] - when Resource then [ record.title, resource_path(record, no_redirect: true) ] end link_to text, path, class: button_classes(:primary_outline, size: :sm) diff --git a/app/models/resource.rb b/app/models/resource.rb index adca59174e..0f4e99af9b 100644 --- a/app/models/resource.rb +++ b/app/models/resource.rb @@ -6,7 +6,6 @@ class Resource < ApplicationRecord include ActionText::Attachable include Mentionable include FilemakerCoded - filemaker_archived_in FmQuotation # Define rich text fields for mentions functionality def self.mentionable_rich_text_fields diff --git a/app/views/resources/_form.html.erb b/app/views/resources/_form.html.erb index 4826dbf639..1738c9cc92 100644 --- a/app/views/resources/_form.html.erb +++ b/app/views/resources/_form.html.erb @@ -42,7 +42,6 @@
<%= f.input :filemaker_code, label: "FileMaker code", - hint: filemaker_code_hint(f.object), input_html: { class: "w-full rounded border-gray-300" }, label_html: { class: "font-medium mb-1 block" } %>
diff --git a/config/features.yml b/config/features.yml index 062a94c22d..981ec2c8c5 100644 --- a/config/features.yml +++ b/config/features.yml @@ -4272,4 +4272,4 @@ code so admins can see and fix it, the same way people and organizations do. pro_tips: - "Separate several codes with commas — a record can answer to more than one." - - "Each code links to its FileMaker archive record, and that record links back to the payment, workshop, or resource." + - "Each code links to its FileMaker archive record, and that record links back to the payment or workshop." diff --git a/docs/adr/0005-filemaker-code-archive-mapping.md b/docs/adr/0005-filemaker-code-archive-mapping.md index 8e25f38515..8f5ea1b3b5 100644 --- a/docs/adr/0005-filemaker-code-archive-mapping.md +++ b/docs/adr/0005-filemaker-code-archive-mapping.md @@ -28,7 +28,7 @@ drive the archive pages' links. | `affiliations.filemaker_code` | `fm_projects`, then `fm_personnels` | `ProjectID`, e.g. `P2775`; rarely `PrsnlRecID`, e.g. `PS9999` | `filemaker_code_links` on affiliation edit | | `payments.filemaker_code` | `fm_payments` | `RecordID`, e.g. `D29186` | `filemaker_code_hint` on payment edit | | `workshops.filemaker_code` | `fm_workshops` | `WorkshopID` | `filemaker_code_hint` on workshop form | -| `resources.filemaker_code` | `fm_quotations` | `RecordID`, e.g. `Q10215` | `filemaker_code_hint` on resource form | +| `resources.filemaker_code` | none | `RecordID` of the source quotation, e.g. `Q10215` | resource form (editable, no archive link) | - **Organization → Project, or → Organization.** An app `Organization` is usually one art program site, which is a FileMaker *Project*. FileMaker's own Organization row is @@ -47,11 +47,12 @@ drive the archive pages' links. never its org. One affiliation carries a real `PS` Personnel id, so Personnel stays as the second table. The 13 that differ from the org's code are worth a look: the affiliation may sit on the wrong org, or the org may be missing that code. -- **Resource → Quotation.** In production, 116 of 128 resource codes are quotation ids - (`Q…`), 115 of them on Leader spotlight resources and one on a Story; 115 of the 116 - exist in `fm_quotations` (quotes and testimonials, with a `WorkShopLeader` field). - Form Letters are mail-merge templates, not resources. The dev seed still leaves - `resources.filemaker_code` blank. +- **Resource → none.** In production, 116 of 128 resource codes are quotation ids + (`Q…`), 115 of them on Leader spotlight resources and one on a Story: each spotlight's + body is the text of the FileMaker quotation it was built from. A resource is still its + own portal record, not an archive row, and quotations belong with the portal's quotes, + so resource codes stay editable but don't link into the archive or back. The dev seed + leaves `resources.filemaker_code` blank. ## Archive id patterns diff --git a/spec/requests/fm_archives_spec.rb b/spec/requests/fm_archives_spec.rb index b0d3d04813..e182b87d9b 100644 --- a/spec/requests/fm_archives_spec.rb +++ b/spec/requests/fm_archives_spec.rb @@ -105,16 +105,6 @@ expect(response.body).to include(ERB::Util.html_escape(workshop.title)) end - it "links an archived quotation back to its portal resource" do - FmQuotation.create!(fm_id: "Q10215") - resource = create(:resource, filemaker_code: "Q10215") - - get fm_archive_path("Q10215", table: "quotations") - - expect(response.body).to include(ERB::Util.html_escape(resource_path(resource, no_redirect: true))) - expect(response.body).to include(ERB::Util.html_escape(resource.title)) - end - it "omits the portal section when nothing carries the code" do FmRolodex.create!(fm_id: "00006") diff --git a/spec/requests/resources_spec.rb b/spec/requests/resources_spec.rb index 981f5f1916..77b65bf814 100644 --- a/spec/requests/resources_spec.rb +++ b/spec/requests/resources_spec.rb @@ -147,12 +147,13 @@ expect(response.body).to include('name="resource[filemaker_code]"') end - it "links an archived code to the FileMaker quotations archive" do + it "shows the FileMaker code without an archive link" do FmQuotation.create!(fm_id: "Q10215", data: {}) resource = Resource.create! valid_attributes.merge(filemaker_code: "Q10215") get edit_resource_url(resource) - expect(response.body).to include(fm_archive_path("Q10215", table: "quotations")) + expect(response.body).to include('value="Q10215"') + expect(response.body).not_to include("table=quotations") end end