Skip to content

feat: add HXL modules and GIS indicator layers#47

Open
jeremi wants to merge 2 commits into19.0from
feat/gis-indicators-hxl
Open

feat: add HXL modules and GIS indicator layers#47
jeremi wants to merge 2 commits into19.0from
feat/gis-indicators-hxl

Conversation

@jeremi
Copy link
Member

@jeremi jeremi commented Feb 17, 2026

Summary

  • spp_hxl (new): HXL hashtag and attribute management, export profiles, CEL variable integration with Studio
  • spp_hxl_area (new): Area-level HXL indicator import with aggregation rules, batch import pipelines, and area matching services
  • spp_gis_indicators (new): Choropleth map visualization for area-level indicators with configurable color scales and classification methods (quantile, equal interval, manual breaks)

Dependencies

Note

spp_hxl and spp_hxl_area existed in the private repo but were not included in the original OpenSPP2 export. spp_gis_indicators is new, developed on the claude/global-alliance-policy-basket branch.

Test plan

  • spp_hxl installs and tests pass
  • spp_hxl_area installs and tests pass (requires libhxl python dependency)
  • spp_gis_indicators installs and tests pass
  • Color scale classification produces correct break values
  • Indicator layers render feature colors correctly

New modules:
- spp_hxl: HXL hashtag/attribute management and export profiles,
  integrates with CEL variables and Studio
- spp_hxl_area: area-level HXL indicator import, aggregation rules,
  batch import with area matching
- spp_gis_indicators: choropleth visualization for area-level indicators,
  configurable color scales and classification methods (quantile, equal
  interval, manual breaks)
@gemini-code-assist
Copy link

Summary of Changes

Hello @jeremi, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the platform's data management and visualization capabilities by introducing comprehensive support for Humanitarian Exchange Language (HXL). It enables users to seamlessly import, aggregate, and visualize area-level humanitarian data, fostering better data interoperability and informed decision-making. The new modules streamline the process of transforming raw field data into actionable insights on geographical maps.

Highlights

  • HXL Integration Module (spp_hxl): Introduced a new module for Humanitarian Exchange Language (HXL) integration, providing a registry for HXL hashtags and attributes, tools for creating export profiles with HXL tagging, and extending CEL variables with HXL mapping capabilities for data interoperability.
  • HXL Area Integration Module (spp_hxl_area): Added a module for importing HXL-tagged field data and aggregating it to area-level indicators. This includes multiple area matching strategies (P-code, name, GPS, fuzzy), flexible aggregation rules, disaggregation support, and integration with CEL variables.
  • GIS Indicators Module (spp_gis_indicators): Implemented a new module for choropleth map visualization of area-level indicators. It allows mapping indicator values from CEL variables to colors using configurable classification methods (quantile, equal interval, manual breaks) and ColorBrewer-based color scales.
  • CEL Variable Extension: Extended the spp.cel.variable model to include HXL mapping fields, allowing definition of HXL hashtags, attributes, and import/export behavior directly on variables.
  • Data Aggregation and Synchronization: Developed services for aggregating HXL data by geographical area and automatically syncing the generated indicators to spp.data.value for use in CEL expressions and eligibility criteria.
Changelog
  • spp_gis_indicators/README.rst
    • Added comprehensive documentation for the GIS Indicators module, detailing its capabilities, models, configuration, and dependencies.
  • spp_gis_indicators/init.py
    • Initialized the spp_gis_indicators Python module.
  • spp_gis_indicators/manifest.py
    • Defined the module's manifest, including its name, summary, version, category, author, website, license, development status, dependencies, and data files.
  • spp_gis_indicators/data/color_scales.xml
    • Added default ColorBrewer-based sequential, diverging, and categorical color scales for GIS visualization.
  • spp_gis_indicators/models/init.py
    • Initialized the models for the spp_gis_indicators module.
  • spp_gis_indicators/models/color_scale.py
    • Implemented the spp.gis.color.scale model to define and manage color schemes for choropleth maps, including validation for JSON color arrays and a method to retrieve colors for specific values.
  • spp_gis_indicators/models/data_layer.py
    • Extended the spp.gis.data.layer model to include a 'choropleth' geographical representation option and a many-to-one field for linking to spp.gis.indicator.layer configurations.
  • spp_gis_indicators/models/indicator_layer.py
    • Implemented the spp.gis.indicator.layer model for configuring how area-level indicators are visualized, including fields for variable, period, incident, color scale, classification method, and computed break values and HTML legend.
  • spp_gis_indicators/pyproject.toml
    • Added build system configuration for the spp_gis_indicators module.
  • spp_gis_indicators/readme/DESCRIPTION.md
    • Provided a detailed Markdown description of the GIS Indicators module's features and capabilities.
  • spp_gis_indicators/security/ir.model.access.csv
    • Defined access control rules for spp.gis.color.scale and spp.gis.indicator.layer models, granting read access to users and full CRUD to administrators.
  • spp_gis_indicators/static/description/index.html
    • Added an HTML description file for the GIS Indicators module.
  • spp_gis_indicators/tests/init.py
    • Initialized the test suite for the spp_gis_indicators module.
  • spp_gis_indicators/tests/test_color_scale.py
    • Added unit tests for the spp.gis.color.scale model, covering creation, validation, and color retrieval logic.
  • spp_gis_indicators/tests/test_data_layer.py
    • Added unit tests for the spp.gis.data.layer extension, verifying the choropleth option and indicator layer field.
  • spp_gis_indicators/tests/test_indicator_layer.py
    • Added unit tests for the spp.gis.indicator.layer model, covering creation, validation, break computation, and feature color retrieval.
  • spp_gis_indicators/views/color_scale_views.xml
    • Defined tree, form, and search views for spp.gis.color.scale, along with an action and menu item.
  • spp_gis_indicators/views/data_layer_views.xml
    • Extended existing GIS data layer form views to include geo_repr and indicator_layer_id fields for choropleth visualization.
  • spp_gis_indicators/views/indicator_layer_views.xml
    • Defined tree, form, and search views for spp.gis.indicator.layer, along with an action and menu item.
  • spp_gis_indicators/views/menu.xml
    • Added a new 'GIS Configuration' parent menu under Settings for managing GIS-related settings.
  • spp_hxl/README.rst
    • Added comprehensive documentation for the HXL Integration module, detailing its capabilities, models, configuration, and dependencies.
  • spp_hxl/init.py
    • Initialized the spp_hxl Python module.
  • spp_hxl/manifest.py
    • Defined the module's manifest, including its name, summary, version, category, author, website, license, development status, dependencies, and data files.
  • spp_hxl/data/hxl_attributes.xml
    • Added predefined HXL attributes, categorized by type (gender, age, population, data, geographic, etc.), with descriptions and standard flags.
  • spp_hxl/data/hxl_hashtags.xml
    • Added predefined HXL hashtags, categorized by type (geographic, population, organization, activity, indicator, etc.), with descriptions and data types.
  • spp_hxl/models/init.py
    • Initialized the models for the spp_hxl module.
  • spp_hxl/models/cel_variable.py
    • Extended the spp.cel.variable model to include HXL mapping fields (hxl_hashtag, hxl_attributes, hxl_tag), and import/export behavior settings.
  • spp_hxl/models/hxl_attribute.py
    • Implemented the spp.hxl.attribute model for managing HXL attributes, including code format validation and uniqueness constraints.
  • spp_hxl/models/hxl_export_profile.py
    • Implemented spp.hxl.export.profile and spp.hxl.export.profile.column models for defining HXL export templates, including model selection, column mappings, and HXL tag composition.
  • spp_hxl/models/hxl_tag.py
    • Implemented the spp.hxl.tag model for managing HXL hashtags, including hashtag format validation and uniqueness constraints.
  • spp_hxl/pyproject.toml
    • Added build system configuration for the spp_hxl module.
  • spp_hxl/readme/DESCRIPTION.md
    • Provided a detailed Markdown description of the HXL Integration module's features and capabilities.
  • spp_hxl/security/ir.model.access.csv
    • Defined access control rules for HXL tag, attribute, and export profile models, granting read access to users and full CRUD to administrators.
  • spp_hxl/static/description/index.html
    • Added an HTML description file for the HXL Integration module.
  • spp_hxl/tests/init.py
    • Initialized the test suite for the spp_hxl module.
  • spp_hxl/tests/test_hxl_attribute.py
    • Added unit tests for the spp.hxl.attribute model, covering creation, uniqueness, and format validation.
  • spp_hxl/tests/test_hxl_export_profile.py
    • Added unit tests for the HXL export profile models, covering creation, uniqueness, column definitions, and tag computation.
  • spp_hxl/tests/test_hxl_tag.py
    • Added unit tests for the spp.hxl.tag model, covering creation, uniqueness, and format validation.
  • spp_hxl/tests/test_hxl_variable.py
    • Added unit tests for the spp.cel.variable HXL extension, covering HXL tag computation and import/export behavior.
  • spp_hxl/tests/test_security.py
    • Added security tests for the HXL module to verify access control for different user roles.
  • spp_hxl/views/cel_variable_views.xml
    • Extended the CEL variable form view to include a new 'HXL Mapping' tab with fields for HXL hashtag, attributes, and import/export behavior.
  • spp_hxl/views/hxl_attribute_views.xml
    • Defined tree, form, and search views for spp.hxl.attribute, along with an action.
  • spp_hxl/views/hxl_export_profile_views.xml
    • Defined tree, form, and search views for spp.hxl.export.profile and its columns, along with an action.
  • spp_hxl/views/hxl_tag_views.xml
    • Defined tree, form, and search views for spp.hxl.tag, along with an action.
  • spp_hxl/views/menus.xml
    • Added main menu items for HXL, including configuration for hashtags, attributes, and export profiles.
  • spp_hxl_area/QUICKSTART.md
    • Added a quick start guide for the HXL Area module, covering setup, data preparation, import steps, and common use cases.
  • spp_hxl_area/README.md
    • Provided a detailed Markdown README for the HXL Area module, outlining its overview, features, architecture, key models, usage, and troubleshooting.
  • spp_hxl_area/README.rst
    • Added a reStructuredText README for the HXL Area module, detailing its capabilities, models, configuration, and dependencies.
  • spp_hxl_area/init.py
    • Initialized the spp_hxl_area Python module, importing models, wizards, and services.
  • spp_hxl_area/manifest.py
    • Defined the module's manifest, including its name, summary, version, category, author, website, license, development status, dependencies, external Python dependencies (libhxl), and data files.
  • spp_hxl_area/data/hxl_import_profiles.xml
    • Added predefined HXL import profiles for common scenarios like Sri Lanka Damage Assessment, Philippines Beneficiary Coverage, OCHA 3W Import, Generic P-code Import, and GPS Survey Import.
  • spp_hxl_area/models/init.py
    • Initialized the models for the spp_hxl_area module.
  • spp_hxl_area/models/hxl_aggregation_rule.py
    • Implemented the spp.hxl.aggregation.rule model to define how HXL data is aggregated into area indicators, including aggregation type, source column, filter expressions, and disaggregation options.
  • spp_hxl_area/models/hxl_area_indicator.py
    • Implemented the spp.hxl.area.indicator model to store aggregated area-level indicator values, with fields for area, variable, period, incident, value, count, disaggregation JSON, and automatic synchronization to spp.data.value.
  • spp_hxl_area/models/hxl_import_batch.py
    • Implemented the spp.hxl.import.batch model to track individual HXL import executions, including file data, context, state, statistics, column mappings, and error logs, with asynchronous processing via queue jobs.
  • spp_hxl_area/models/hxl_import_mapping.py
    • Implemented the spp.hxl.import.mapping model for column mapping within an import batch, storing source column, detected HXL tag, mapping type, and confidence score.
  • spp_hxl_area/models/hxl_import_profile.py
    • Implemented the spp.hxl.import.profile model for configuring HXL data imports, defining area matching strategies, area column tags, target admin levels, and aggregation rules.
  • spp_hxl_area/pyproject.toml
    • Added build system configuration for the spp_hxl_area module.
  • spp_hxl_area/readme/DESCRIPTION.md
    • Provided a detailed Markdown description of the HXL Area module's features and capabilities.
  • spp_hxl_area/security/ir.model.access.csv
    • Defined access control rules for HXL Area models, including import profiles, aggregation rules, batches, mappings, and indicators, granting appropriate permissions to users and administrators.
  • spp_hxl_area/services/init.py
    • Initialized the services for the spp_hxl_area module.
  • spp_hxl_area/services/aggregation_engine.py
    • Implemented the AggregationEngine service to process HXL rows, apply aggregation rules, and generate area-level indicators, including handling filter expressions and disaggregation.
  • spp_hxl_area/services/area_matcher.py
    • Implemented the AreaMatcher service to match HXL area values to spp.area records using various strategies (P-code, name, GPS, fuzzy) and caching results.
  • spp_hxl_area/static/description/index.html
    • Added an HTML description file for the HXL Area module.
  • spp_hxl_area/tests/init.py
    • Initialized the test suite for the spp_hxl_area module.
  • spp_hxl_area/tests/test_aggregation_engine.py
    • Added unit tests for the AggregationEngine service, covering various aggregation types, filter expressions, and disaggregation logic.
  • spp_hxl_area/tests/test_area_matcher.py
    • Added unit tests for the AreaMatcher service, covering different matching strategies (P-code, name, fuzzy) and caching behavior.
  • spp_hxl_area/tests/test_hxl_aggregation_rule.py
    • Added unit tests for the spp.hxl.aggregation.rule model, covering creation, validation, and default values.
  • spp_hxl_area/tests/test_hxl_area_indicator.py
    • Added unit tests for the spp.hxl.area.indicator model, covering creation, unique constraints, and automatic synchronization to data values.
  • spp_hxl_area/tests/test_hxl_import_batch.py
    • Added unit tests for the spp.hxl.import.batch model, covering creation, state transitions, column detection, and result viewing.
  • spp_hxl_area/tests/test_hxl_import_mapping.py
    • Added unit tests for the spp.hxl.import.mapping model, covering creation, default values, and name display.
  • spp_hxl_area/tests/test_hxl_import_profile.py
    • Added unit tests for the spp.hxl.import.profile model, covering creation, uniqueness, and configuration validation.
  • spp_hxl_area/views/hxl_aggregation_rule_views.xml
    • Defined form views for spp.hxl.aggregation.rule.
  • spp_hxl_area/views/hxl_area_indicator_views.xml
    • Defined tree, form, and search views for spp.hxl.area.indicator, along with an action.
  • spp_hxl_area/views/hxl_import_batch_views.xml
    • Defined tree, form, and search views for spp.hxl.import.batch, including status bar, action buttons, and statistical information.
  • spp_hxl_area/views/hxl_import_profile_views.xml
    • Defined tree, form, and search views for spp.hxl.import.profile, including area matching strategy, aggregation rules, and batch count.
  • spp_hxl_area/views/menus.xml
    • Added main menu items for 'HXL Area', including 'Import HXL Data' wizard, 'Import Batches', 'Area Indicators', and a 'Configuration' submenu for import profiles.
  • spp_hxl_area/wizards/init.py
    • Initialized the wizards for the spp_hxl_area module.
  • spp_hxl_area/wizards/hxl_area_import_wizard.py
    • Implemented the HxlAreaImportWizard transient model for a multi-step HXL data import process, including file parsing, data preview, and area matching preview.
  • spp_hxl_area/wizards/hxl_area_import_wizard_views.xml
    • Defined the form view for the HXL Area Import Wizard, providing an educational header, fields for profile, file upload, context, and data/matching previews.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces new modules (spp_hxl, spp_hxl_area, spp_gis_indicators) to enhance HXL data integration and GIS-based indicator visualization. However, it contains critical security vulnerabilities, specifically a confirmed Cross-Site Scripting (XSS) in the HXL import wizard's data preview and a high risk of insecure code evaluation in the aggregation engine. Additionally, the review suggests modernizing SQL constraint definitions and clarifying a misleading code comment to improve maintainability.

Comment on lines +139 to +140
# WARNING: eval() is dangerous - in production use a safe expression evaluator
if self._eval_filter(row, rule.filter_expression):

Choose a reason for hiding this comment

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

security-high high

There is a high risk of insecure code evaluation in the aggregation engine. The developer's own comments and documentation explicitly warn that eval() is used and that it poses a security risk if expressions are user-provided (e.g., in spp.hxl.aggregation.rule). Although the code currently calls spp.cel.service.evaluate_expression, the presence of these warnings suggests that the underlying implementation may be insecure or that the transition to a safe evaluator is incomplete. The comment on line 139 is misleading as _eval_filter uses spp.cel.service for evaluation, not eval(). To remediate the overall risk, ensure the expression evaluation service uses a strictly sandboxed environment and does not rely on Python's eval(). If the implementation is already safe, remove all misleading warning comments and update the documentation to reflect the security of the system.

Comment on lines +176 to +185
html.append(f"<th>{col}</th>")
html.append("</tr></thead>")

# Rows
html.append("<tbody>")
for row in rows:
html.append("<tr>")
for col in columns:
value = row.get(col, "")
html.append(f"<td>{value}</td>")

Choose a reason for hiding this comment

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

security-high high

The _generate_preview_html method is vulnerable to Cross-Site Scripting (XSS). It constructs an HTML table by directly concatenating strings with untrusted data from the uploaded HXL file (both headers and cell values). This HTML is then rendered in the wizard's preview tab. An attacker can craft a malicious HXL file containing JavaScript which will execute in the context of the user's session when they preview the data.

To remediate this, ensure all untrusted data is properly escaped before being inserted into the HTML string. You can use Odoo's html_escape utility.

from odoo.tools import html_escape
# ...
html.append(f"<th>{html_escape(col)}</th>")
# ...
html.append(f"<td>{html_escape(str(value))}</td>")

is_standard = fields.Boolean(default=True, help="True if part of HXL 1.1 standard specification")
active = fields.Boolean(default=True)

_code_unique = models.Constraint("unique(code)", "HXL attribute code must be unique!")

Choose a reason for hiding this comment

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

medium

The use of models.Constraint is a deprecated way of defining SQL constraints in Odoo. It's recommended to use the _sql_constraints attribute instead for better maintainability and adherence to modern Odoo development practices.

Suggested change
_code_unique = models.Constraint("unique(code)", "HXL attribute code must be unique!")
_sql_constraints = [
("code_unique", "unique(code)", "HXL attribute code must be unique!"),
]


active = fields.Boolean(default=True)

_code_unique = models.Constraint("unique(code)", "Export profile code must be unique!")

Choose a reason for hiding this comment

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

medium

The use of models.Constraint is a deprecated way of defining SQL constraints in Odoo. It's recommended to use the _sql_constraints attribute instead for better maintainability and adherence to modern Odoo development practices.

Suggested change
_code_unique = models.Constraint("unique(code)", "Export profile code must be unique!")
_sql_constraints = [
("code_unique", "unique(code)", "Export profile code must be unique!"),
]

)
active = fields.Boolean(default=True)

_hashtag_unique = models.Constraint("unique(hashtag)", "HXL hashtag must be unique!")

Choose a reason for hiding this comment

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

medium

The use of models.Constraint is a deprecated way of defining SQL constraints in Odoo. It's recommended to use the _sql_constraints attribute instead for better maintainability and adherence to modern Odoo development practices.

Suggested change
_hashtag_unique = models.Constraint("unique(hashtag)", "HXL hashtag must be unique!")
_sql_constraints = [
("hashtag_unique", "unique(hashtag)", "HXL hashtag must be unique!"),
]

Comment on lines +104 to +107
_unique_indicator = models.Constraint(
"UNIQUE(area_id, variable_id, period_key, incident_id, batch_id)",
"Indicator must be unique per area/variable/period/incident/batch",
)

Choose a reason for hiding this comment

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

medium

The use of models.Constraint is a deprecated way of defining SQL constraints in Odoo. It's recommended to use the _sql_constraints attribute instead for better maintainability and adherence to modern Odoo development practices.

    _sql_constraints = [
        (
            "unique_indicator",
            "UNIQUE(area_id, variable_id, period_key, incident_id, batch_id)",
            "Indicator must be unique per area/variable/period/incident/batch",
        ),
    ]

help="Number of imports using this profile",
)

_code_unique = models.Constraint("UNIQUE(code)", "Profile code must be unique")

Choose a reason for hiding this comment

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

medium

The use of models.Constraint is a deprecated way of defining SQL constraints in Odoo. It's recommended to use the _sql_constraints attribute instead for better maintainability and adherence to modern Odoo development practices.

Suggested change
_code_unique = models.Constraint("UNIQUE(code)", "Profile code must be unique")
_sql_constraints = [("code_unique", "UNIQUE(code)", "Profile code must be unique")]

…UI fixes

- Promote both modules to Beta status
- Fix mode="tree" to mode="list" (Odoo 19 compat)
- Add missing list view for aggregation rules
- Make import batch fields readonly when completed/failed
- Remove redundant header buttons
- Fix PII in log messages
- Improve form layouts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant