Skip to content

Added gifts database table#26995

Merged
sagzy merged 1 commit into
mainfrom
add-gifts-table
Apr 6, 2026
Merged

Added gifts database table#26995
sagzy merged 1 commit into
mainfrom
add-gifts-table

Conversation

@sagzy
Copy link
Copy Markdown
Contributor

@sagzy sagzy commented Mar 26, 2026

closes https://linear.app/ghost/issue/BER-3502
ref https://linear.app/ghost/project/gift-subscriptions-b7184e4f8972

Adding a new table in the context of the gift subscriptions project, to store gift data (buyer info, redeemer info, gift amount/currency/duration, etc.)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new persisted gifts table and corresponding migration to store gift purchase records. The schema includes identifiers (id, token), buyer and redeemer member references, tier/product reference, cadence/duration/currency/amount, Stripe fields (stripe_checkout_session_id, stripe_payment_intent_id), lifecycle timestamps and a constrained status plus purchased_at. The gifts table was added to the backup allowlist and exporter tests were updated to include and optionally exclude gifts. The schema integrity test hash was updated to reflect the change.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Added gifts database table' directly and clearly summarizes the main change—adding a new database table for gifts in the schema.
Description check ✅ Passed The description is directly related to the changeset, explaining that it adds a new table to support gift subscriptions and references relevant tracking issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-gifts-table

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the migration [pull request] Includes migration for review label Mar 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 26, 2026

It looks like this PR contains a migration 👀
Here's the checklist for reviewing migrations:

General requirements

  • ⚠️ Tested performance on staging database servers, as performance on local machines is not comparable to a production environment
  • Satisfies idempotency requirement (both up() and down())
  • Does not reference models
  • Filename is in the correct format (and correctly ordered)
  • Targets the next minor version
  • All code paths have appropriate log messages
  • Uses the correct utils
  • Contains a minimal changeset
  • Does not mix DDL/DML operations
  • Tested in MySQL and SQLite

Schema changes

  • Both schema change and related migration have been implemented
  • For index changes: has been performance tested for large tables
  • For new tables/columns: fields use the appropriate predefined field lengths
  • For new tables/columns: field names follow the appropriate conventions
  • Does not drop a non-alpha table outside of a major version

Data changes

  • Mass updates/inserts are batched appropriately
  • Does not loop over large tables/datasets
  • Defends against missing or invalid data
  • For settings updates: follows the appropriate guidelines

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ghost/core/core/server/data/schema/schema.js (1)

1173-1207: Consider adding an updated_at column for tracking modifications.

Most tables in the schema include created_at and updated_at columns (e.g., offers, products, subscriptions). While purchased_at serves as the creation timestamp, there's no column to track subsequent modifications to gift records (e.g., status changes, redemption updates).

If gifts are immutable after purchase, this is fine. Otherwise, consider adding:

        consumed_at: {type: 'dateTime', nullable: true}
+       created_at: {type: 'dateTime', nullable: false},
+       updated_at: {type: 'dateTime', nullable: true}
    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/core/core/server/data/schema/schema.js` around lines 1173 - 1207, The
gifts schema is missing an updated_at column to track modifications; add an
updated_at field to the gifts table definition (alongside the existing
purchased_at, redeemed_at, etc.) with the same type and nullability pattern used
elsewhere (e.g., type 'dateTime', nullable: true) so updates to records such as
status changes or redemption timestamps can be recorded; update any migration or
model logic that expects timestamps to include this new updated_at field where
necessary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ghost/core/core/server/data/schema/schema.js`:
- Around line 1173-1207: The gifts schema is missing an updated_at column to
track modifications; add an updated_at field to the gifts table definition
(alongside the existing purchased_at, redeemed_at, etc.) with the same type and
nullability pattern used elsewhere (e.g., type 'dateTime', nullable: true) so
updates to records such as status changes or redemption timestamps can be
recorded; update any migration or model logic that expects timestamps to include
this new updated_at field where necessary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 861d70a6-a191-4e9a-b974-39298c11f4f9

📥 Commits

Reviewing files that changed from the base of the PR and between f6e7cc8 and 8fed057.

📒 Files selected for processing (3)
  • ghost/core/core/server/data/migrations/versions/6.23/2026-03-26-16-41-06-add-gifts-table.js
  • ghost/core/core/server/data/schema/schema.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js

@sagzy sagzy force-pushed the add-gifts-table branch from 8fed057 to a050218 Compare March 26, 2026 17:17
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
ghost/core/core/server/data/schema/schema.js (2)

1173-1207: Consider adding an updated_at field for consistency and auditability.

Most tables in this schema include an updated_at: {type: 'dateTime', nullable: true} field to track when records are modified. The gifts table will likely have status transitions (purchased → redeemed → consumed, or purchased → expired, etc.), and having updated_at helps track when these changes occur for debugging and auditing purposes.

Proposed fix
         refunded_at: {type: 'dateTime', nullable: true},
-        consumed_at: {type: 'dateTime', nullable: true}
+        consumed_at: {type: 'dateTime', nullable: true},
+        updated_at: {type: 'dateTime', nullable: true}
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/core/core/server/data/schema/schema.js` around lines 1173 - 1207, Add
an updated_at column to the gifts table schema to match other tables and record
modification timestamps: inside the gifts schema object (adjacent to fields like
purchased_at, redeemed_at, status), add an updated_at: {type: 'dateTime',
nullable: true} entry so updates to status
(purchased/redeemed/consumed/expired/refunded) and other changes are auditable
and consistent with existing tables.

1197-1206: Consider adding indexes for common query patterns.

Depending on expected query patterns, you may want to add indexes on frequently queried columns like status, buyer_member_id, redeemer_member_id, or tier_id. This can be deferred until actual usage patterns are known.

Example index definition
'@@INDEXES@@': [
    ['status'],
    ['buyer_member_id'],
    ['tier_id']
]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/core/core/server/data/schema/schema.js` around lines 1197 - 1206, The
schema for the vouchers table lacks indexes for columns likely used in filters
(e.g., status, buyer_member_id, redeemer_member_id, tier_id); add an
'@@INDEXES@@' entry to the schema definition (near the fields status,
purchased_at, redeemed_at, etc.) listing arrays for the columns you expect to
query frequently (for example ['status'], ['buyer_member_id'], ['tier_id'], and
optionally ['redeemer_member_id']) so the ORM/DB will create those indexes; keep
index names/defaults consistent with existing schema conventions when adding the
'@@INDEXES@@' block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ghost/core/core/server/data/schema/schema.js`:
- Around line 1173-1207: Add an updated_at column to the gifts table schema to
match other tables and record modification timestamps: inside the gifts schema
object (adjacent to fields like purchased_at, redeemed_at, status), add an
updated_at: {type: 'dateTime', nullable: true} entry so updates to status
(purchased/redeemed/consumed/expired/refunded) and other changes are auditable
and consistent with existing tables.
- Around line 1197-1206: The schema for the vouchers table lacks indexes for
columns likely used in filters (e.g., status, buyer_member_id,
redeemer_member_id, tier_id); add an '@@INDEXES@@' entry to the schema
definition (near the fields status, purchased_at, redeemed_at, etc.) listing
arrays for the columns you expect to query frequently (for example ['status'],
['buyer_member_id'], ['tier_id'], and optionally ['redeemer_member_id']) so the
ORM/DB will create those indexes; keep index names/defaults consistent with
existing schema conventions when adding the '@@INDEXES@@' block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e1cabf00-5cee-48d3-a893-52e032394b50

📥 Commits

Reviewing files that changed from the base of the PR and between 8fed057 and a050218.

📒 Files selected for processing (4)
  • ghost/core/core/server/data/exporter/table-lists.js
  • ghost/core/core/server/data/migrations/versions/6.23/2026-03-26-16-41-06-add-gifts-table.js
  • ghost/core/core/server/data/schema/schema.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js
✅ Files skipped from review due to trivial changes (3)
  • ghost/core/core/server/data/exporter/table-lists.js
  • ghost/core/core/server/data/migrations/versions/6.23/2026-03-26-16-41-06-add-gifts-table.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js

@sagzy sagzy changed the title Added gifts database table Added gifts database table Mar 26, 2026
@sagzy sagzy force-pushed the add-gifts-table branch 2 times, most recently from 50635b0 to 931d238 Compare March 31, 2026 21:34
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
ghost/core/core/server/data/schema/schema.js (2)

1198-1233: Consider adding indexes for common query patterns.

The table lacks explicit indexes beyond unique constraints. Depending on expected query patterns, consider adding indexes for:

  • status and expires_at (for expiration batch jobs)
  • buyer_member_id / redeemer_member_id (for member lookups)

This can be deferred and added via migration once query patterns are established in production.

📊 Example index definition
         refunded_at: {type: 'dateTime', nullable: true}
+        '@@INDEXES@@': [
+            ['status', 'expires_at'],
+            ['buyer_member_id'],
+            ['redeemer_member_id']
+        ]
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/core/core/server/data/schema/schema.js` around lines 1198 - 1233, The
gifts schema (object "gifts" in schema.js) currently only has unique constraints
but no non-unique indexes; add non-unique indexes for common query patterns by
creating a migration (or updating the schema index definitions) that adds
indexes on status, expires_at, buyer_member_id and redeemer_member_id (and
consider a composite index like (status, expires_at) for expiration batch
queries) so lookups by member and expiration scans are efficient in production.

1224-1228: Consider adding a default value for status.

The status field lacks a defaultTo value. Since gifts are created upon purchase, defaulting to 'purchased' would provide a safety net if any code path fails to explicitly set the status.

💡 Suggested change
         status: {
-            type: 'string', maxlength: 50, nullable: false, validations: {
+            type: 'string', maxlength: 50, nullable: false, defaultTo: 'purchased', validations: {
                 isIn: [['purchased', 'redeemed', 'consumed', 'expired', 'refunded']]
             }
         },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/core/core/server/data/schema/schema.js` around lines 1224 - 1228, The
status column in the gifts schema currently has type, maxlength, nullable, and
isIn validations but no default; update the status definition in schema.js (the
status field with validations isIn: [['purchased', 'redeemed', 'consumed',
'expired', 'refunded']]) to include a defaultTo of 'purchased' so new gift
records default to 'purchased' when not explicitly set; ensure the added default
aligns with the existing type/validation and does not break nullable:false
constraint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ghost/core/core/server/data/schema/schema.js`:
- Line 1207: The schema field definition for tier_id (tier_id: {type: 'string',
maxlength: 24, nullable: false, unique: false, references: 'products.id'}) is
missing an explicit cascadeDelete behavior; update the tier_id column definition
in schema.js to include the appropriate cascade policy (either cascadeDelete:
true or cascadeDelete: false) to match the intended behavior for product/tier
deletions, mirroring the pattern used by other product foreign keys (see
subscriptions.tier_id and the product foreign keys that include cascadeDelete)
so the migration/schema is consistent and explicit.

---

Nitpick comments:
In `@ghost/core/core/server/data/schema/schema.js`:
- Around line 1198-1233: The gifts schema (object "gifts" in schema.js)
currently only has unique constraints but no non-unique indexes; add non-unique
indexes for common query patterns by creating a migration (or updating the
schema index definitions) that adds indexes on status, expires_at,
buyer_member_id and redeemer_member_id (and consider a composite index like
(status, expires_at) for expiration batch queries) so lookups by member and
expiration scans are efficient in production.
- Around line 1224-1228: The status column in the gifts schema currently has
type, maxlength, nullable, and isIn validations but no default; update the
status definition in schema.js (the status field with validations isIn:
[['purchased', 'redeemed', 'consumed', 'expired', 'refunded']]) to include a
defaultTo of 'purchased' so new gift records default to 'purchased' when not
explicitly set; ensure the added default aligns with the existing
type/validation and does not break nullable:false constraint.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 045168dd-44df-445f-a0db-4012a6a798f2

📥 Commits

Reviewing files that changed from the base of the PR and between 50635b0 and 931d238.

📒 Files selected for processing (5)
  • ghost/core/core/server/data/exporter/table-lists.js
  • ghost/core/core/server/data/migrations/versions/6.25/2026-03-31-09-46-30-add-gifts-table.js
  • ghost/core/core/server/data/schema/schema.js
  • ghost/core/test/integration/exporter/exporter.test.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js
✅ Files skipped from review due to trivial changes (2)
  • ghost/core/test/unit/server/data/schema/integrity.test.js
  • ghost/core/core/server/data/migrations/versions/6.25/2026-03-31-09-46-30-add-gifts-table.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • ghost/core/test/integration/exporter/exporter.test.js

Comment thread ghost/core/core/server/data/schema/schema.js
@sagzy sagzy force-pushed the add-gifts-table branch 6 times, most recently from cc2791e to 8221f3f Compare April 6, 2026 09:07
closes https://linear.app/ghost/issue/BER-3502
ref https://linear.app/ghost/project/gift-subscriptions-b7184e4f8972

Adds a new table in the context of the gift subscriptions project, to store gift data (buyer info, redeemer info, gift amount/currency/duration, etc.)
@sagzy sagzy force-pushed the add-gifts-table branch from 8221f3f to 27d92ae Compare April 6, 2026 09:13
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 6, 2026

@sagzy sagzy enabled auto-merge (squash) April 6, 2026 09:32
@sagzy sagzy merged commit 7a6c220 into main Apr 6, 2026
39 checks passed
@sagzy sagzy deleted the add-gifts-table branch April 6, 2026 09:41
franky19 pushed a commit to franky19/Ghost that referenced this pull request Apr 18, 2026
closes https://linear.app/ghost/issue/BER-3502
ref https://linear.app/ghost/project/gift-subscriptions-b7184e4f8972

Adding a new table in the context of the gift subscriptions project, to
store gift data (buyer info, redeemer info, gift
amount/currency/duration, etc.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

migration [pull request] Includes migration for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants