diff --git a/CLAUDE.md b/CLAUDE.md index d10aff4..9c8af8c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,7 +78,7 @@ This is the backend API for Ashes.live, a fan-developed deckbuilder and communit 2. Rebuild the container: `make build` ### Database Migrations -1. Create the migration: `make migration-new ARGS='DESCRIPTION HERE'` +1. Create the migration: `make migrate-new ARGS='DESCRIPTION HERE'` 2. Review generated migration file to ensure no unexpected changes 3. Execute the migration: `make migrate` diff --git a/api/schemas/cards.py b/api/schemas/cards.py index 33bf597..a172719 100644 --- a/api/schemas/cards.py +++ b/api/schemas/cards.py @@ -141,6 +141,7 @@ class CardOut(BaseModel): copies: int | None = None effectRepeats: bool | None = None is_legacy: bool | None = None + chained: bool | None = None class CardUpdate(BaseModel): @@ -171,6 +172,7 @@ class CardUpdate(BaseModel): recover: Annotated[str | int | None, BeforeValidator(str_or_int)] = None spellboard: int | None = None copies: int | None = None + chained: bool | None = False class CardUsageCounts(BaseModel): diff --git a/api/views/cards.py b/api/views/cards.py index 5cd2c3f..71290c6 100644 --- a/api/views/cards.py +++ b/api/views/cards.py @@ -490,10 +490,10 @@ def update_card( card.alt_dice_flags = 0 del json_data["altDice"] # Update JSON-only data that doesn't need parsing - for prop in ("magicCost", "effectMagicCost", "effectRepeats"): + for prop in ("magicCost", "effectMagicCost", "effectRepeats", "chained"): update_value = getattr(data, prop) if update_value is not None and update_value != json_data.get(prop): - if update_value: + if update_value or update_value == 0: json_data[prop] = update_value elif prop in json_data: del json_data[prop] @@ -501,7 +501,7 @@ def update_card( for prop in ("attack", "life", "recover", "battlefield", "spellboard"): update_value = getattr(data, prop) if update_value is not None and update_value != json_data.get(prop): - if update_value: + if update_value or update_value == 0: json_data[prop] = str_or_int(update_value) elif prop in json_data: del json_data[prop] diff --git a/migrations/versions/2025-08-24_add_card_chains_489f5ba99de2.py b/migrations/versions/2025-08-24_add_card_chains_489f5ba99de2.py new file mode 100644 index 0000000..d18ab2e --- /dev/null +++ b/migrations/versions/2025-08-24_add_card_chains_489f5ba99de2.py @@ -0,0 +1,49 @@ +"""Add card chains + +Revision ID: 489f5ba99de2 +Revises: b5e78986c4b6 +Create Date: 2025-08-24 15:46:54.114706+00:00 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "489f5ba99de2" +down_revision = "b5e78986c4b6" +branch_labels = None +depends_on = None + + +def upgrade(): + # Update all cards with default chain status + op.execute( + """ + UPDATE card SET "json" = "json" || '{"chained": false}'::jsonb + WHERE is_legacy = FALSE + """ + ) + op.execute( + """ + UPDATE card SET "json" = "json" || '{"chained": true}'::jsonb + WHERE is_legacy = FALSE AND stub IN ( + 'explosive-growth', + 'golden-veil', + 'hypnotize', + 'psychic-vampire', + 'river-skald', + 'summon-shining-hydra', + 'meteor' + ) + """ + ) + + +def downgrade(): + op.execute( + """ + UPDATE card SET "json" = "json" - 'chained' + WHERE is_legacy = FALSE + """ + )