def handle(self, **options): dry_run = options['check'] # 1. Find domains with locations domains_having_locations = ( SQLLocation.objects.order_by('domain').distinct('domain') .values_list('domain', flat=True) ) print("Domain having locations(%s): %s" % (len(domains_having_locations), domains_having_locations)) # 2. Find domains on flat fixture domain_with_flat_fixture_enabled = find_domains_with_flat_fixture_enabled() print("Domain with flat fixture enabled(%s): %s" % (len(domain_with_flat_fixture_enabled), domain_with_flat_fixture_enabled)) # 3. Find domains to stay on legacy fixture domains_to_stay_on_hierarchical_fixture = (set(domains_having_locations) - set(domain_with_flat_fixture_enabled)) print("Domain to stay on hierarchical fixture(%s): %s" % (len(domains_to_stay_on_hierarchical_fixture), domains_to_stay_on_hierarchical_fixture)) # 4. Update domains that need to stay on hierarchical with enabled legacy toggle to be able to access conf # and update their location configuration to use hierarchical fixture for now for domain in domains_to_stay_on_hierarchical_fixture: if not dry_run: print(u"Setting HIERARCHICAL_LOCATION_FIXTURE toggle for domain: %s" % domain) HIERARCHICAL_LOCATION_FIXTURE.set(domain, True, NAMESPACE_DOMAIN) else: print(u"HIERARCHICAL_LOCATION_FIXTURE toggle would be set for domain: %s" % domain) if not dry_run: print(u"Enabling legacy fixture for domain: %s" % domain) location_configuration = LocationFixtureConfiguration.for_domain(domain) print("Current Configuration, Persisted: %s, Use Flat fixture: %s, Use Hierarchical fixture %s" % ( not location_configuration._state.adding, location_configuration.sync_hierarchical_fixture, location_configuration.sync_flat_fixture)) enable_legacy_fixture_for_domain(domain) else: print(u"Legacy fixture to be enabled for domain: %s" % domain) location_configuration = LocationFixtureConfiguration.for_domain(domain) print("Current Configuration, Persisted: %s, Use Flat fixture: %s, Use Hierarchical fixture %s" % ( not location_configuration._state.adding, location_configuration.sync_hierarchical_fixture, location_configuration.sync_flat_fixture)) # 5. Domains that need to stay on flat fixture need not worry about any change since they would # default to flat fixture but must ensure if they don't have conf set for using hierarchical fixture for domain in domain_with_flat_fixture_enabled: # For domains with flat fixture enabled and have configuration defined to use hierarchical fixture # Notify them to make their state clear location_conf_for_domain = LocationFixtureConfiguration.for_domain(domain) if not location_conf_for_domain._state.adding and location_conf_for_domain.sync_hierarchical_fixture: # Can use the following to update them # location_conf_for_domain.sync_flat_fixture = True # location_conf_for_domain.sync_hierarchical_fixture = False # location_conf_for_domain.save() print("Domain that needs attention since its not in a definite state: %s" % domain)
def copy_locations(self, types_only=False): from corehq.apps.locations.models import LocationType, SQLLocation from corehq.apps.locations.views import LocationFieldsView self._copy_custom_data(LocationFieldsView.field_type) location_types = LocationType.objects.by_domain(self.existing_domain) location_types_map = {} for location_type in location_types: if location_type.parent_type_id: location_type.parent_type_id = location_types_map[location_type.parent_type_id] old_id, new_id = self.save_sql_copy(location_type, self.new_domain) location_types_map[old_id] = new_id if not types_only: # MPTT sorts this queryset so we can just save in the same order new_loc_pks_by_code = {} for loc in SQLLocation.active_objects.filter(domain=self.existing_domain): # start with a new location so we don't inadvertently copy over a bunch of foreign keys new_loc = SQLLocation() for field in ["name", "site_code", "external_id", "metadata", "is_archived", "latitude", "longitude"]: setattr(new_loc, field, getattr(loc, field, None)) new_loc.domain = self.new_domain new_loc.parent_id = new_loc_pks_by_code[loc.parent.site_code] if loc.parent_id else None new_loc.location_type_id = location_types_map[loc.location_type_id] _, new_pk = self.save_sql_copy(new_loc, self.new_domain) new_loc_pks_by_code[new_loc.site_code] = new_pk existing_fixture_config = LocationFixtureConfiguration.for_domain(self.existing_domain) self.save_sql_copy(existing_fixture_config, self.new_domain)
def should_sync_flat_fixture(project): # Sync flat fixture for domains with conf for flat fixture enabled # This does not check for toggle for migration to allow domains those domains to migrate to flat fixture return ( project.uses_locations and LocationFixtureConfiguration.for_domain(project.name).sync_flat_fixture )
def copy_locations(self, types_only=False): from corehq.apps.locations.models import LocationType, SQLLocation from corehq.apps.locations.views import LocationFieldsView self._copy_custom_data(LocationFieldsView.field_type) location_types = LocationType.objects.by_domain(self.existing_domain) location_types_map = {} for location_type in location_types: if location_type.parent_type_id: location_type.parent_type_id = location_types_map[location_type.parent_type_id] old_id, new_id = self.save_sql_copy(location_type, self.new_domain) location_types_map[old_id] = new_id if not types_only: # use get_descendants, which sorts locations hierarchically, # so we can save in the same order locs = SQLLocation.objects.get_queryset_descendants( Q(domain=self.existing_domain, parent_id__isnull=True) ).filter(is_archived=False) new_loc_pks_by_code = {} for loc in locs: # start with a new location so we don't inadvertently copy over a bunch of foreign keys new_loc = SQLLocation() for field in ["name", "site_code", "external_id", "metadata", "is_archived", "latitude", "longitude"]: setattr(new_loc, field, getattr(loc, field, None)) new_loc.domain = self.new_domain new_loc.parent_id = new_loc_pks_by_code[loc.parent.site_code] if loc.parent_id else None new_loc.location_type_id = location_types_map[loc.location_type_id] _, new_pk = self.save_sql_copy(new_loc, self.new_domain) new_loc_pks_by_code[new_loc.site_code] = new_pk existing_fixture_config = LocationFixtureConfiguration.for_domain(self.existing_domain) self.save_sql_copy(existing_fixture_config, self.new_domain)
def should_sync_hierarchical_fixture(project): # Sync hierarchical fixture for domains with fixture toggle enabled for migration and # configuration set to use hierarchical fixture # Even if both fixtures are set up, this one takes priority for domains with toggle enabled return (project.uses_locations and toggles.HIERARCHICAL_LOCATION_FIXTURE.enabled(project.name) and LocationFixtureConfiguration.for_domain( project.name).sync_hierarchical_fixture)
def post(self, request, *args, **kwargs): location_settings = LocationFixtureConfiguration.for_domain(self.domain) form = LocationFixtureForm(request.POST, instance=location_settings) if form.is_valid(): form.save() messages.success(request, _("Location configuration updated successfully")) return self.get(request, *args, **kwargs)
def location_fixture_instances(domain, instance_name): from corehq.apps.locations.models import LocationFixtureConfiguration if (toggles.HIERARCHICAL_LOCATION_FIXTURE.enabled(domain) and not LocationFixtureConfiguration.for_domain( domain).sync_flat_fixture): return Instance(id=instance_name, src='jr://fixture/commtrack:{}'.format(instance_name)) return Instance(id=instance_name, src='jr://fixture/{}'.format(instance_name))
def should_sync_flat_fixture(project, app): if not project.uses_locations: return False if app and app.location_fixture_restore in SYNC_FLAT_FIXTURES: return True if app and app.location_fixture_restore != DEFAULT_LOCATION_FIXTURE_OPTION: return False return LocationFixtureConfiguration.for_domain(project.name).sync_flat_fixture
def should_sync_hierarchical_fixture(project, app): if (not project.uses_locations or not toggles.HIERARCHICAL_LOCATION_FIXTURE.enabled(project.name)): return False if app and app.location_fixture_restore in SYNC_HIERARCHICAL_FIXTURE: return True if app and app.location_fixture_restore != DEFAULT_LOCATION_FIXTURE_OPTION: return False return LocationFixtureConfiguration.for_domain(project.name).sync_hierarchical_fixture
def should_sync_flat_fixture(domain): return ( toggles.FLAT_LOCATION_FIXTURE.enabled(domain) and LocationFixtureConfiguration.for_domain(domain).sync_flat_fixture )
def page_context(self): location_settings = LocationFixtureConfiguration.for_domain( self.domain) form = LocationFixtureForm(instance=location_settings) return {'form': form}
def location_fixture_instances(domain, instance_name): from corehq.apps.locations.models import LocationFixtureConfiguration if (toggles.HIERARCHICAL_LOCATION_FIXTURE.enabled(domain) and not LocationFixtureConfiguration.for_domain(domain).sync_flat_fixture): return Instance(id=instance_name, src='jr://fixture/commtrack:{}'.format(instance_name)) return Instance(id=instance_name, src='jr://fixture/{}'.format(instance_name))
def enable_legacy_fixture_for_domain(domain): location_configuration = LocationFixtureConfiguration.for_domain(domain) location_configuration.sync_hierarchical_fixture = True location_configuration.sync_flat_fixture = False location_configuration.save()
def should_sync_hierarchical_fixture(project): return (project.uses_locations and LocationFixtureConfiguration.for_domain( project.name).sync_hierarchical_fixture)
def should_sync_flat_fixture(domain): return (toggles.FLAT_LOCATION_FIXTURE.enabled(domain) and LocationFixtureConfiguration.for_domain(domain).sync_flat_fixture)
def should_sync_hierarchical_fixture(project): return ( project.uses_locations and LocationFixtureConfiguration.for_domain(project.name).sync_hierarchical_fixture )