From 4e68a74ef5a40f60079a8b412691593d135c5636 Mon Sep 17 00:00:00 2001 From: Sergei Poljanski Date: Tue, 26 May 2026 19:08:55 +0300 Subject: [PATCH] db: issuer_profiles + clients migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit issuer_profiles is one row per user with all the legal-entity fields that previously lived in the ISSUER constant — legal name, tax id, reg number, bank details — plus per-user defaults (invoice prefix, currency, due days, notes). On invoice creation these get snapshotted onto the invoice row so historical PDFs render unchanged when the user later edits their profile. clients is per-user, case-insensitive unique on (owner_id, email). Partial index on active clients for the dropdown. Soft-archive only; ON DELETE RESTRICT to honor the indefinite-retention rule. --- .../003_issuer_profiles_and_clients.rb | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 db/migrations/003_issuer_profiles_and_clients.rb diff --git a/db/migrations/003_issuer_profiles_and_clients.rb b/db/migrations/003_issuer_profiles_and_clients.rb new file mode 100644 index 0000000..711a02d --- /dev/null +++ b/db/migrations/003_issuer_profiles_and_clients.rb @@ -0,0 +1,41 @@ +Sequel.migration do + change do + create_table(:issuer_profiles) do + foreign_key :user_id, :users, type: :Bignum, primary_key: true, + on_delete: :restrict + String :legal_name + String :legal_name_local + String :tax_id + String :reg_number + Date :registered_on + String :address, text: true + String :contact_email + String :contact_phone + String :bank_name + String :bank_iban + String :bank_swift + String :invoice_prefix, null: false, default: 'INV' + String :default_currency, null: false, default: 'USD', size: 3 + Integer :default_due_days, null: false, default: 14 + String :default_notes, text: true + DateTime :updated_at, null: false + end + + create_table(:clients) do + primary_key :id, type: :Bignum + foreign_key :owner_id, :users, type: :Bignum, null: false, + on_delete: :restrict + String :name, null: false + String :email, null: false + String :address, text: true + String :default_currency, size: 3 + Integer :default_due_days + String :default_notes, text: true + DateTime :archived_at + DateTime :created_at, null: false + end + + run "CREATE UNIQUE INDEX clients_owner_email_idx ON clients (owner_id, lower(email))" + run "CREATE INDEX clients_owner_active_idx ON clients (owner_id) WHERE archived_at IS NULL" + end +end