fix: disabling last store/group no longer resets all to enabled
Added store_filters_seeded / group_filters_seeded flags to SyncConfig. _enabled_*_ids now returns None (all enabled) only before first toggle, not when the filter table is empty due to all being disabled. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
"""Add store_filters_seeded and group_filters_seeded to sync_configs."""
|
||||
revision = "0011"
|
||||
down_revision = "0010"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column("sync_configs", sa.Column("store_filters_seeded", sa.Boolean(), nullable=False, server_default="0"))
|
||||
op.add_column("sync_configs", sa.Column("group_filters_seeded", sa.Boolean(), nullable=False, server_default="0"))
|
||||
|
||||
# Mark existing rows as seeded if they already have filters
|
||||
op.execute("""
|
||||
UPDATE sync_configs sc
|
||||
SET store_filters_seeded = 1
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM sync_filters sf
|
||||
WHERE sf.sync_config_id = sc.id AND sf.entity_type = 'store'
|
||||
)
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE sync_configs sc
|
||||
SET group_filters_seeded = 1
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM sync_filters sf
|
||||
WHERE sf.sync_config_id = sc.id AND sf.entity_type = 'group'
|
||||
)
|
||||
""")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column("sync_configs", "group_filters_seeded")
|
||||
op.drop_column("sync_configs", "store_filters_seeded")
|
||||
@@ -59,6 +59,8 @@ class SyncConfig(Base):
|
||||
is_enabled = Column(Boolean, nullable=False, default=False)
|
||||
evo_mirror_enabled = Column(Boolean, nullable=False, default=False)
|
||||
vk_mirror_enabled = Column(Boolean, nullable=False, default=False)
|
||||
store_filters_seeded = Column(Boolean, nullable=False, default=False)
|
||||
group_filters_seeded = Column(Boolean, nullable=False, default=False)
|
||||
confirmed_at = Column(DateTime, nullable=True)
|
||||
price_multiplier = Column(Numeric(10, 4), nullable=False, default=1.0)
|
||||
created_at = Column(DateTime, nullable=False, server_default=func.now())
|
||||
|
||||
@@ -24,29 +24,25 @@ def _get_or_create_sync_config(db: Session, user_id: int) -> SyncConfig:
|
||||
|
||||
|
||||
def _enabled_store_ids(db: Session, user_id: int) -> set[str] | None:
|
||||
"""Return set of enabled store evotor_ids, or None if no filters set (all enabled)."""
|
||||
"""Return set of enabled store evotor_ids, or None if filters not yet seeded (all enabled)."""
|
||||
cfg = db.query(SyncConfig).filter_by(user_id=user_id).first()
|
||||
if not cfg:
|
||||
if not cfg or not cfg.store_filters_seeded:
|
||||
return None
|
||||
filters = db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="store", filter_mode="include"
|
||||
).all()
|
||||
if not filters:
|
||||
return None
|
||||
return {f.entity_id for f in filters}
|
||||
|
||||
|
||||
def _enabled_group_ids(db: Session, user_id: int, store_evotor_id: str) -> set[str] | None:
|
||||
"""Return set of enabled group evotor_ids for a store, or None if all enabled."""
|
||||
"""Return set of enabled group evotor_ids for a store, or None if filters not yet seeded (all enabled)."""
|
||||
cfg = db.query(SyncConfig).filter_by(user_id=user_id).first()
|
||||
if not cfg:
|
||||
if not cfg or not cfg.group_filters_seeded:
|
||||
return None
|
||||
filters = db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="group", filter_mode="include",
|
||||
parent_entity_id=store_evotor_id,
|
||||
).all()
|
||||
if not filters:
|
||||
return None
|
||||
return {f.entity_id for f in filters}
|
||||
|
||||
|
||||
@@ -166,37 +162,20 @@ async def catalog_store_toggle(store_evotor_id: str, request: Request, db: Sessi
|
||||
|
||||
cfg = _get_or_create_sync_config(db, user.id)
|
||||
|
||||
# If no filters exist yet, that means all stores are implicitly enabled.
|
||||
# Toggling one store OFF means we create include-filters for all OTHER stores.
|
||||
existing = db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="store", filter_mode="include"
|
||||
).all()
|
||||
existing_ids = {f.entity_id for f in existing}
|
||||
|
||||
if store_evotor_id in existing_ids:
|
||||
# Currently enabled → disable: remove its filter
|
||||
db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="store",
|
||||
entity_id=store_evotor_id, filter_mode="include",
|
||||
).delete()
|
||||
else:
|
||||
if not existing_ids:
|
||||
# First toggle: seed include-filters for all OTHER stores
|
||||
all_stores = db.query(CachedStore).filter_by(user_id=user.id).all()
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
for s in all_stores:
|
||||
if s.evotor_id == store_evotor_id:
|
||||
continue
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
entity_type="store",
|
||||
entity_id=s.evotor_id,
|
||||
entity_name=s.name,
|
||||
filter_mode="include",
|
||||
created_at=now,
|
||||
))
|
||||
if cfg.store_filters_seeded:
|
||||
if store_evotor_id in existing_ids:
|
||||
# Currently enabled → disable: remove its filter
|
||||
db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="store",
|
||||
entity_id=store_evotor_id, filter_mode="include",
|
||||
).delete()
|
||||
else:
|
||||
# Re-enable: add its filter back
|
||||
# Currently disabled → re-enable: add its filter back
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
entity_type="store",
|
||||
@@ -204,6 +183,22 @@ async def catalog_store_toggle(store_evotor_id: str, request: Request, db: Sessi
|
||||
filter_mode="include",
|
||||
created_at=datetime.now(timezone.utc).replace(tzinfo=None),
|
||||
))
|
||||
else:
|
||||
# First toggle ever: seed include-filters for all OTHER stores, mark seeded
|
||||
all_stores = db.query(CachedStore).filter_by(user_id=user.id).all()
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
for s in all_stores:
|
||||
if s.evotor_id == store_evotor_id:
|
||||
continue
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
entity_type="store",
|
||||
entity_id=s.evotor_id,
|
||||
entity_name=s.name,
|
||||
filter_mode="include",
|
||||
created_at=now,
|
||||
))
|
||||
cfg.store_filters_seeded = True
|
||||
|
||||
db.commit()
|
||||
return RedirectResponse("/catalog/stores", 303)
|
||||
@@ -227,30 +222,12 @@ async def catalog_group_toggle(
|
||||
).all()
|
||||
existing_ids = {f.entity_id for f in existing}
|
||||
|
||||
if group_evotor_id in existing_ids:
|
||||
db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="group",
|
||||
entity_id=group_evotor_id, filter_mode="include",
|
||||
).delete()
|
||||
else:
|
||||
if not existing_ids:
|
||||
# First toggle: seed include-filters for all OTHER groups in this store
|
||||
all_groups = db.query(CachedGroup).filter_by(
|
||||
user_id=user.id, store_evotor_id=store_evotor_id,
|
||||
).all()
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
for g in all_groups:
|
||||
if g.evotor_id == group_evotor_id:
|
||||
continue
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
entity_type="group",
|
||||
entity_id=g.evotor_id,
|
||||
entity_name=g.name,
|
||||
filter_mode="include",
|
||||
parent_entity_id=store_evotor_id,
|
||||
created_at=now,
|
||||
))
|
||||
if cfg.group_filters_seeded:
|
||||
if group_evotor_id in existing_ids:
|
||||
db.query(SyncFilter).filter_by(
|
||||
sync_config_id=cfg.id, entity_type="group",
|
||||
entity_id=group_evotor_id, filter_mode="include",
|
||||
).delete()
|
||||
else:
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
@@ -260,6 +237,25 @@ async def catalog_group_toggle(
|
||||
parent_entity_id=store_evotor_id,
|
||||
created_at=datetime.now(timezone.utc).replace(tzinfo=None),
|
||||
))
|
||||
else:
|
||||
# First toggle ever: seed include-filters for all OTHER groups in this store, mark seeded
|
||||
all_groups = db.query(CachedGroup).filter_by(
|
||||
user_id=user.id, store_evotor_id=store_evotor_id,
|
||||
).all()
|
||||
now = datetime.now(timezone.utc).replace(tzinfo=None)
|
||||
for g in all_groups:
|
||||
if g.evotor_id == group_evotor_id:
|
||||
continue
|
||||
db.add(SyncFilter(
|
||||
sync_config_id=cfg.id,
|
||||
entity_type="group",
|
||||
entity_id=g.evotor_id,
|
||||
entity_name=g.name,
|
||||
filter_mode="include",
|
||||
parent_entity_id=store_evotor_id,
|
||||
created_at=now,
|
||||
))
|
||||
cfg.group_filters_seeded = True
|
||||
|
||||
db.commit()
|
||||
return RedirectResponse(f"/catalog/stores/{store_evotor_id}/groups", 303)
|
||||
|
||||
Reference in New Issue
Block a user