Skip to content

Instantly share code, notes, and snippets.

@hbruno
Last active April 23, 2026 11:59
Show Gist options
  • Select an option

  • Save hbruno/78443416ae0f25ca24685ab5bfd0812c to your computer and use it in GitHub Desktop.

Select an option

Save hbruno/78443416ae0f25ca24685ab5bfd0812c to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""
Script to update all filters that are supported by VOICE.
For a filter to be supported by VOICE:
1. The filter's field_name must exist in the FeedbackRequest model within the respondent_mapped_fields or subject_mapped_fields JSON fields.
2. Consider the specific filters for each organization (org_id).
3. Consider the filter's entity field.
4. Consider available_modules (must include FilterModule.VOICE or be None).
"""
import warnings
from sqlalchemy.exc import SAWarning
warnings.filterwarnings('ignore', category=SAWarning, message='.*relationship.*will copy column.*')
from sqlalchemy import or_, select
from libs.db import db
from libs.crosschq_importer.models import ImportType
from libs.filters.models import Filter, FilterModule
from libs.orgs.models import Organization
from libs.survey_answers_analytics.helpers import FILTER_MAPPING_VOICE
from libs.survey_answers_analytics.models import FeedbackRequest, FeedbackSettings
def get_last_object(entity: str, org_id: str | None) -> FeedbackRequest:
"""Get the last object of the given entity"""
print("\tget_last_object")
feedback_query = (
select(FeedbackRequest)
.join(FeedbackSettings, FeedbackRequest.feedback_settings_id == FeedbackSettings.id)
.where(FeedbackRequest.subject_type == entity)
.where(FeedbackSettings.feedback_origin == 'voice')
.order_by(FeedbackRequest.created_on.desc())
.limit(1)
)
if org_id:
feedback_query = feedback_query.where(FeedbackRequest.org_id == org_id)
result = db.session.execute(feedback_query)
return result.scalars().first()
def get_filters_for_org(entity: str, org_id: str | None) -> list[Filter]:
print(f"\tget_filters_for_org {entity}, {org_id}")
filters_query = select(Filter).where(Filter.is_active.is_(True), Filter.entity == entity, or_(Filter.is_deleted.is_(False), Filter.is_deleted.is_(None)))
if org_id:
filters_query = filters_query.where(Filter.org_id == org_id)
else:
filters_query = filters_query.where(Filter.org_id.is_(None))
result = db.session.execute(filters_query)
return list(result.scalars().all())
def is_filter_supported_by_voice(filter_item: Filter, sample_object: FeedbackRequest) -> bool:
if filter_item.field_name in FILTER_MAPPING_VOICE:
return True
subject_fields = sample_object.subject_mapped_fields or {}
respondent_fields = sample_object.respondent_mapped_fields or {}
return filter_item.field_name in subject_fields or filter_item.field_name in respondent_fields
def update_filter_available_modules(filter_item: Filter, is_supported: bool) -> bool:
print("\tupdate_filter_available_modules")
current_modules = filter_item.available_modules or []
has_voice = FilterModule.VOICE in current_modules
modified = False
if is_supported and not has_voice:
if current_modules:
filter_item.available_modules = list(current_modules) + [FilterModule.VOICE]
else:
pass
modified = True
elif not is_supported and has_voice:
new_modules = [m for m in current_modules if m != FilterModule.VOICE]
filter_item.available_modules = new_modules if new_modules else None
modified = True
elif not is_supported and not current_modules:
all_modules_except_voice = [m for m in FilterModule if m != FilterModule.VOICE]
filter_item.available_modules = all_modules_except_voice
modified = True
return modified
def check_filter_by_entity(entity: str, org_id: str | None):
print("\tcheck_filter_by_entity")
sample_object = get_last_object(entity, org_id)
if not sample_object:
print(f"\t\tNo sample object found for entity {entity} and org_id {org_id}")
return
filters = get_filters_for_org(entity, org_id)
modified_count = 0
for filter_item in filters:
is_supported = is_filter_supported_by_voice(filter_item, sample_object)
if update_filter_available_modules(filter_item, is_supported):
modified_count += 1
print("\tUpdated filter %s (codename=%s): VOICE supported=%s", filter_item.id, filter_item.codename, is_supported)
if modified_count > 0:
db.session.commit()
def get_orgs_with_voice() -> list[str]:
return Organization.objects(is_voice_enable=True).values_list('org_id')
def count_filters_with_modules():
from sqlalchemy import TEXT, VARCHAR, Boolean, Column, Enum, ForeignKey, desc, func, or_, select, sql, text
filter_count = select(func.count()).select_from(Filter).where(Filter.is_active.is_(True), Filter.available_modules.isnot(None))
res = db.session.execute(filter_count)
return res.scalar()
def main():
all_orgs = [None] + list(get_orgs_with_voice())
all_orgs = [
None,
"68024e2a-7a5c-4847-b4fa-f69ced866094",
"46c35c85-2469-4de9-bf2b-6553899ed348",
"3119feab-d369-4435-91fa-1d081f85ec39",
"21e8d75e-cfe0-4634-a1b7-c4c3dbd76dd3",
"b877fc16-afac-4ce9-8290-c8fbbf3a29bb",
"91600e74-01d8-4c1a-8439-37d5657655ea",
"c1030490-c58e-47b3-89b9-a159e617aeb5",
"daa62f8b-85de-4dd3-b578-8767fe918dd1",
"f623ef10-24fb-4e60-a2de-1b54dc8db2c9",
"a82f026d-ad20-437f-b1c8-b0f0159f6cb5",
"59b0a5af-adf4-46be-86b4-10e7220543c5",
"5af71862-5928-42f0-8b7b-b674efc09221",
"2b6cf6d2-4b00-448e-977a-641b2a6df34b",
"90dd6811-83c5-420e-856e-9b1046165d1f",
"f5d72bd4-4f78-49e7-a97c-f64e31d4e797",
"1ec7c5e7-c87a-4aea-98f2-6292f3be8fee",
"5186f003-fd95-4f72-a8df-d9494d10c5d4",
"c309dc81-7508-4306-8f85-0e4b633db204",
"a713b5ac-ee86-4328-b37f-3fd878d1a873",
"4be56648-e938-4521-861a-d2cda2e51942",
"220a7c7a-575e-4dd2-82d0-6c175eb46ca8",
"cc527f96-2515-46c8-adba-fcf3f722645c",
"a85a4644-dea5-49dc-9006-191ea686fa04",
"6fe12dda-b185-405a-9fbc-ca0d42f5920e",
"32b7431e-961b-45d3-82d4-c877dbd02e5a",
"826f2aaa-69bc-42da-8496-6a3d2aa6781d",
"1ee2ed33-b498-4caa-9dd9-f2189b3e238c",
"bbb7eb45-f7e2-480d-8900-1cd8a9b47417",
"81b50461-0d5b-487d-9e67-3c529923c598",
"a0645a08-e0d7-40bc-ba64-75ddb6e38452",
"3f5e5ef8-3dc8-4b93-b7a7-2761e7a5892a",
"3b8bbd67-b2d8-46b6-8b20-1d5be70bc432",
"f7843e1b-11a7-455f-8c9a-a5a56fdb62e3",
"bb9f3448-b019-46be-82df-7d51e187a888",
"299cbf31-0dd0-4ab0-b892-00f55a3015a5",
"db474f6c-87d0-4ab8-9a69-d8562233d797",
"01d912b7-23ba-426f-80b7-b9042fd75f7f",
"aa4e8f74-7d2d-476e-943c-bc688c0d7ae6",
"83788f1a-9fcf-45e7-bdde-3942705d1f40",
"ffff9cbb-5d4c-45eb-acb2-a5717b56c79d",
"f1ae888a-9819-422f-9d57-eb0f3ac71b28",
"d85c8005-937f-4828-9519-b86efb499346",
"30015fab-a7ea-4571-bb67-39169f004bd1",
"cdc7bf5e-7b1b-4e34-83b0-660e85d6d220",
"acfced87-fdfd-4fbe-a5ba-7305f896e3e4",
"ac6338cc-c36c-4525-b8c5-1ecc22834f9f",
"40a27799-1097-488c-be4f-1190d62f11dc",
"390c120c-85bf-4acd-822d-9d7ff1d3d84c",
"a6026b73-808d-471d-aec0-b21d3bea2f10",
"e175ae19-4913-4215-8b59-fd00395329dc",
"c8f72693-5eb8-41ec-a570-e9a413cd2e24",
"a65aaaaf-6147-4b47-ad65-c58e3bd577e5",
"34841aa8-31f1-4d77-ac3b-697548fec2c1",
"9b0c8286-9ec9-494c-8b18-1ca19e1cad89",
"5cab4e49-f20f-4ca7-9ecb-ec7fce946dce",
"b0d0482c-ed02-4e8d-a0bf-58a6fc80116a",
"f9775b39-5720-4fc9-8530-5b861d0af1d0",
"410fd465-7af5-4d93-b7cf-ebe11c07c5f4",
"9efde923-95d2-4b39-a69f-b41997274e16",
"eb9cfc94-057d-4a19-b521-43659ec6521d",
"474289cf-1bfd-421c-9c09-6ba51af1df86",
"4f1c4f42-ed8f-45c8-a9ac-e7d94ef90b70",
"52f9a9c3-2d27-44bc-8a3b-88ffe2729eb8",
"5d215673-84e9-4d8b-b4d0-7c5abf46a3da",
"e533b985-6308-4735-9cf9-4bb4a9526aeb",
"8fc7e503-51da-44c1-9c7e-8601f3deec83",
"5ead77e9-8266-4bd6-9ea8-8f4e3a3ccb5d",
"5de8adc0-2b98-4da8-aa2b-dc0edb7612c1",
"c19a0168-d326-4fe0-ae17-56052b1997de",
"b1015433-eaff-4a87-acf4-9a9355f2ceb3",
"4b24601b-c303-4c46-a4a7-e126e0db9a82",
"5fa5a084-5f72-42e7-9a1f-7d499acbcf35",
"2f382192-2657-4a51-8f14-a286ba8a07ac",
"aa46ae5a-9405-4181-8415-7e283da39b52"
]
for org_id in all_orgs:
print(org_id)
check_filter_by_entity('candidate', org_id)
check_filter_by_entity('employee', org_id)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment