Skip to content

Conversation

@maatinito
Copy link
Collaborator

Summary

• Add new formula field type to support calculated values in forms
• Formula fields can perform mathematical calculations and text concatenation
• Automatic recalculation when dependent fields change
• Support for field references using {Field Name} syntax

Technical Implementation

• Add FormuleChamp and FormuleTypeDeChamp models
• Configure formule type in TypeDeChamp constants
• Add French translations for the new field type
• Include comprehensive test suite with factories
• Foundation for Dentaku integration (gem to be added)

Test Plan

  • Run existing test suite to ensure no regressions
  • Verify new formula champ models are working
  • Test validation of formula expressions
  • Verify factory generation works correctly
  • Check French translations are loading properly

Next Steps

  • Integration with Dentaku gem for formula evaluation
  • Admin interface for formula configuration
  • Dynamic recalculation in user interface
  • Complete formula evaluation logic

@maatinito maatinito force-pushed the feature/champ_formule branch 7 times, most recently from 7739c9a to 88693a7 Compare June 26, 2025 20:42
@maatinito maatinito force-pushed the feature/champ_formule branch 2 times, most recently from d8b8f9f to ec2684e Compare July 2, 2025 19:15
@maatinito maatinito force-pushed the feature/champ_formule branch from ec2684e to 3ccad52 Compare August 25, 2025 07:27
@claude
Copy link

claude bot commented Aug 27, 2025

Code Review: Formula Field Feature (Champ Formule)

Overall Assessment

This is a well-structured implementation of a formula field feature that follows the project's architecture patterns. The code quality is high and demonstrates good understanding of the mes-demarches codebase structure.

✅ Strengths

Architecture & Design:

  • Follows the established champ architecture pattern with proper model inheritance (Champs::FormuleChamp inherits from Champ)
  • Correctly implements the type system with TypesDeChamp::FormuleTypeDeChamp
  • Proper GraphQL integration with descriptor types
  • Smart hybrid approach using labels for UI and stable_ids for storage
  • Good separation of concerns with dedicated service classes

Code Quality:

  • Clean, readable code with appropriate method decomposition
  • Good error handling and validation
  • Proper use of Rails conventions (callbacks, validations, delegations)
  • Comprehensive test coverage with factories and specs
  • Follows Ruby style guidelines

Security & Data Integrity:

  • Uses stable_ids for field references, making formulas resilient to field renaming
  • Proper validation of formula expressions
  • Circular reference detection in formula calculations
  • Sanitized output formatting for URLs and other data types

🔍 Areas for Improvement

Performance Considerations:

  1. Formula recalculation efficiency (app/models/champ.rb:285-305):
    The refresh_dependent_formulas method could benefit from batching when multiple fields change to avoid N+1 queries.

  2. Dependency tracking could be optimized with caching for large forms with many formula fields.

Code Structure:

  1. Long method in FormulaCalculationService - The main calculation method could benefit from further decomposition.

  2. Missing order validation - As mentioned in the spec, formula fields that reference fields appearing later in the form order should be validated.

UI/UX:

  1. Client-side validation in formula_editor_controller.ts is good, but the 300ms debounce might feel sluggish for real-time feedback.

🔧 Technical Issues

GraphQL Schema:

  • The schema updates look correct and follow existing patterns
  • Proper implementation of descriptor types

Database:

  • No migrations needed for this implementation (uses existing JSON options column)
  • Good use of existing infrastructure

Testing:

  • Comprehensive test coverage
  • Good use of factories for different scenarios
  • Tests cover edge cases and error conditions

🛡️ Security Review

  • Input validation: Proper validation of formula expressions ✅
  • XSS prevention: Formula outputs are properly escaped ✅
  • Access control: Formulas only reference fields within the same procedure ✅
  • Feature flag: Properly gated behind feature flag for controlled rollout ✅

📝 Minor Suggestions

  1. Error messages: Consider making error messages more user-friendly, especially for non-technical users.

  2. Documentation: The inline help text is good, but consider adding examples for complex functions.

  3. Accessibility: The formula display component has good ARIA attributes, well done.

🎯 Compliance with Project Standards

  • ✅ Follows the established champ architecture from CLAUDE.md
  • ✅ Uses proper Rails conventions
  • ✅ Implements GraphQL integration correctly
  • ✅ Maintains compatibility with fork-specific features (INSTANCE_* constants)
  • ✅ Includes proper French translations
  • ✅ Feature flag implementation for controlled rollout

🚀 Recommendation

APPROVE with minor optimizations to consider for future iterations. This is a solid implementation that adds significant value while maintaining code quality and following established patterns.

The formula field feature is ready for deployment with the current implementation. The identified performance optimizations can be addressed in future iterations based on real-world usage patterns.

@claude
Copy link

claude bot commented Aug 29, 2025

Pull Request Review: Formula Field Feature (Champ Formule)

Summary

This PR implements a comprehensive formula field feature that allows administrators to create calculated fields in forms. The implementation follows the project's established patterns and includes proper test coverage.

Code Quality ✅

Strengths:

  • Follows project conventions: Proper inheritance from base classes, consistent naming patterns
  • Good separation of concerns: Logic split between models, services, and components
  • Comprehensive test coverage: Tests for models, services, and edge cases
  • Proper error handling: Graceful degradation with user-friendly error messages
  • Internationalization: French translations and locale-specific function names
  • TypeScript integration: Well-typed JavaScript controller with proper interfaces

Architecture Assessment ✅

Model Design:

  • FormuleChamp properly extends Champ base class
  • FormuleTypeDeChamp follows the established pattern
  • Proper GraphQL integration with descriptor types
  • Correct stable_id usage for field references

Service Layer:

  • FormulaCalculationService is well-structured with clear error handling
  • Supports both label-based and stable_id-based field references (good backward compatibility)
  • Proper circular reference detection

Security Considerations ✅

Formula Evaluation Security:

  • Uses Dentaku gem for safe expression evaluation (sandbox approach)
  • No eval() usage - expressions are parsed and evaluated safely
  • Field references are validated before resolution
  • Input validation prevents extremely long expressions (1000 char limit)

Input Sanitization:

  • Field references are properly validated against available champs
  • Stable ID resolution prevents injection attacks
  • Error messages don't expose sensitive information

Performance Considerations ⚠️

Potential Issues:

  • N+1 Query Risk: dependent_formula_champs could trigger multiple queries in refresh_dependent_formulas
  • Recalculation Performance: Formula recalculation happens on every dependent field save, which could be expensive with complex formulas or many dependencies
  • Recursive Formula Performance: Deep formula chains could cause performance issues

Bug Prevention ✅

Edge Case Handling:

  • Proper handling of blank/nil expressions
  • Error messages for invalid field references
  • Circular reference detection
  • Type coercion for different field types

Validation:

  • Expression length validation
  • Field reference validation
  • Basic syntax validation

Test Coverage ✅

Comprehensive Testing:

  • Unit tests for all major components
  • Integration tests for formula calculation
  • Error case testing
  • Edge case coverage (blank expressions, invalid references)
  • French function testing

Potential Issues & Recommendations

  1. Performance Monitoring: Consider adding metrics for formula calculation time

  2. Expression Complexity: Consider limiting expression complexity beyond just length

  3. Caching: For expensive formulas, consider caching computed values with proper invalidation

  4. Documentation: The inline documentation is good, but consider adding examples of supported functions in the admin UI

  5. Future Enhancement: The TODO for Dentaku validation should be prioritized for production readiness

Minor Code Suggestions

  1. app/models/champ.rb:285 - Consider preloading to avoid N+1 queries in dependent_formula_champs method

  2. JavaScript Controller: Good debouncing implementation, but consider adding loading states for better UX

Conclusion

This is a well-implemented feature that follows the project's patterns and maintains high code quality standards. The security considerations are properly addressed, and the test coverage is comprehensive.

Recommendation: ✅ APPROVE with minor performance optimizations to be considered post-merge.

The feature is ready for production deployment with proper monitoring of formula calculation performance.

@maatinito maatinito force-pushed the feature/champ_formule branch from be177c5 to 464a052 Compare August 29, 2025 17:36
@claude
Copy link

claude bot commented Aug 29, 2025

Code Review - Formula Field Feature (Champ Formule)

🎯 Overall Assessment

This is a well-implemented feature that adds formula calculation capabilities to the form system. The implementation follows the established patterns in the codebase and includes comprehensive testing. However, there are several areas that need attention before deployment.

🚨 Security & Performance Concerns

1. Formula Expression Injection Risk

  • Issue: While Dentaku provides some safety, the formula expressions aren't fully sandboxed
  • Risk: Potential for complex expressions that could cause performance issues or unexpected behavior
  • Recommendation: Consider implementing expression complexity limits and validation depth

2. Circular Reference Detection

  • ✅ Good: Circular reference detection is implemented in FormulaCalculationService
  • ⚠️ Concern: Detection uses recursion which could cause stack overflow with deep dependencies
  • Recommendation: Consider iterative approach or maximum depth limit

3. Performance Impact

  • Issue: Formula recalculation happens on every field change via refresh_dependent_formulas
  • Risk: O(n²) performance with many interdependent formulas
  • Recommendation: Batch formula recalculations or implement change tracking

🐛 Potential Bugs

1. Value Overriding in FormuleChamp
The value method always recomputes instead of using stored values:

  • Issue: This bypasses the stored value attribute completely
  • Problem: Could cause inconsistency between what's stored in DB vs displayed
  • Fix: Check if stored value exists first, only recompute if needed

2. Missing Validation in Controller

  • Issue: No server-side validation of formula expressions on form submission
  • Risk: Invalid expressions could be saved and cause runtime errors
  • Fix: Add validation before saving

3. JavaScript Error Handling

  • Issue: error.message in TypeScript could be undefined in some browsers
  • Fix: Add null checks for better error handling

🏗️ Code Quality Issues

1. Inconsistent Error Messages

  • French messages mixed with English in some places
  • Some error messages not internationalized
  • Fix: Standardize all messages and use I18n consistently

2. Missing Edge Case Handling
The get_champ_numeric_value method lacks fallbacks for unknown field types

  • Issue: Unknown field types default to text extraction which might not be appropriate
  • Fix: Add explicit handling for all possible field types

3. Code Duplication

  • Label ↔ stable_id conversion logic exists in both frontend and backend
  • Recommendation: Centralize this logic in a service class

🧪 Test Coverage Analysis

✅ Strengths:

  • Comprehensive unit tests for FormuleChamp
  • Good coverage of FormulaCalculationService
  • Tests include error scenarios
  • Factory patterns follow established conventions

⚠️ Gaps:

  • Missing integration tests for formula dependency updates
  • No tests for concurrent formula calculation scenarios
  • GraphQL integration tests could be more comprehensive
  • Missing tests for edge cases in FormulaValueDisplayComponent

🎨 Best Practices & Style

✅ Good Practices:

  • Follows Rails conventions and patterns
  • Proper use of callbacks and validations
  • Feature flag implementation for controlled rollout
  • Accessible UI components with ARIA attributes

🔧 Improvements Needed:

  • Some methods are quite long (e.g., FormulaCalculationService#get_champ_numeric_value)
  • Magic numbers should be constants (24 * 3600 for date conversion)
  • Some complex conditions could be extracted to meaningful method names

🚀 Performance Considerations

Current Issues:

  1. Formula recalculation on every field change (not batched)
  2. Recursive dependency resolution could be expensive
  3. No caching of formula results

Recommendations:

  1. Implement change tracking to only recalculate when dependencies change
  2. Add result caching with cache invalidation
  3. Consider background processing for complex formulas

🔒 Security Assessment

Low Risk Items:

  • No direct user input in formula execution (uses stable IDs)
  • Dentaku library provides basic expression safety
  • No file system or network operations in formulas

Medium Risk Items:

  • Complex expressions could cause performance issues
  • Error messages might reveal internal structure

📋 Action Items Before Merge

Critical (Must Fix):

  1. Fix the value method in FormuleChamp to use stored values appropriately
  2. Add server-side validation for formula expressions
  3. Implement expression complexity limits

Important (Should Fix):

  1. Add batch formula recalculation to prevent performance issues
  2. Improve error handling in JavaScript controller
  3. Add integration tests for formula dependencies

Nice to Have:

  1. Centralize label/stable_id conversion logic
  2. Add result caching for performance
  3. Extract large methods into smaller, focused ones

🎯 Recommendations

  1. Phased Rollout: The feature flag is excellent - use it to gradually roll out to avoid performance issues
  2. Monitoring: Add logging/metrics for formula calculation performance
  3. Documentation: Consider adding admin documentation for formula syntax
  4. Validation: Implement more robust server-side validation before enabling feature

📊 Final Score: 7.5/10

This is a solid implementation that shows good understanding of the codebase architecture. The comprehensive testing and thoughtful UI design are commendable. However, the performance and validation concerns need to be addressed before production deployment.

The feature flag approach shows good judgment for a complex feature like this. I'd recommend addressing the critical issues, then using the feature flag for a gradual rollout while monitoring performance impact.

maatinito and others added 15 commits September 14, 2025 16:21
This specification document outlines the implementation of a new
formula field type that allows automatic calculation of values
based on other fields in the form.

Key features:
- Support for both numeric and text formulas using Dentaku
- Mustache syntax {Field Label} for field references
- Automatic text-to-numeric conversion for calculations
- Always returns text output (simplified approach)
- Uses INSTANCE_* constants for fork compatibility
- Real-time recalculation when dependent fields change

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Introduces FormuleChamp and FormuleTypeDeChamp classes to support
formula-based calculations in form fields.
- Add formule to TYPE_CHAMPS enum
- Configure formule as STANDARD category
- Add formule_expression to INSTANCE_OPTIONS
Add translations for formule type and validation error messages.
Add factories for FormuleChamp and FormuleTypeDeChamp with various
test scenarios including field references and text formulas.
Include tests for formula expression validation, calculation logic,
field references, and error handling scenarios.
- Add EditableChamp::FormuleComponent for formula field display
- Add FormulaValueDisplayComponent with smart value formatting (URLs, dates, numbers)
- Add GraphQL FormuleChampDescriptorType and schema integration
- Add _show template for formula field rendering
- Include DSFR styling and accessibility features
- Add French/English translations for formula components
…port

- Add FormulaCalculationService with comprehensive formula evaluation
- Support French Excel functions (SOMME, MOYENNE, SI, MIN, MAX, ABS, ARRONDI)
- Implement field reference resolution using field labels {Field Name}
- Add circular reference detection and error handling
- Create intelligent value formatting components with URL/date/number detection
- Add comprehensive test coverage for all calculation scenarios
- Ensure DSFR styling and accessibility compliance
- Add formula expression field to type_de_champ editor form
- Include help text for field reference syntax and French functions
- Add proper HTML attributes for accessibility (DSFR styling)
- Add formule_expression parameter to controller whitelist
- Update formule_champ_spec tests to match Dentaku implementation
- Add formula editor component tests for UI validation
- Fix validation by using standard 'value' attribute instead of computed_value
- Fix number/date display confusion in FormulaValueDisplayComponent
- Simplify formula field UI component (remove flashy callout)
- Clean up redundant test mocks for better maintainability
- Ensure decimal results without fractional part display as integers
Replace delegation to type_de_champ with direct type_champ comparisons for visa?, te_fenua?, lexpol?, formule? methods to avoid expensive lookup operations.
- Add dependent_stable_ids to track field dependencies in formulas
- Add formule_user_expression methods for user-friendly display
- Auto-refresh dependent formula fields when referenced fields change
- Add FormulaExpressionService for stable_id/libelle conversion
- Fix factory to use value instead of deprecated computed_value
- Add comprehensive tests for dependent formula champs functionality
- Update GraphQL schema with formula field changes
Conditionally enable formule field based on procedure feature flag to control rollout of this new field type.
maatinito and others added 9 commits September 14, 2025 16:21
- Remove duplicate used_by_routing_rules? method that was causing rubocop error
- Fix validation method name from validate_champ_value_or_prefill? to validate_champ_value?
The TypeDeChamp model doesn't have a revision attribute directly,
it gets it through associations. The test was incorrectly trying to
pass revision to the factory.
The table_id method from TypeDeChamp was not accessible from Champ instances,
causing failures in TableRowSelectorComponent. Add table_id to the explicit
delegation alongside accredited_user_list.
Add the formule feature to the list of features initialized by Flipper.
This allows the formula field type to be controlled via feature flags.
- Add Stimulus controller to convert labels to stable_ids in real-time
- Store formulas with stable_ids for robust dependency tracking
- Show user-friendly labels in UI, convert to stable_ids before save
- Add validation feedback for invalid field references
- Add automatic refresh of dependent formulas when values change
- Add .worktrees to gitignore

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Server-side validation now detects unresolved variables ({Variable} patterns)
- Client keeps original expression when conversion fails (preserves user work)
- Clear error messages showing which fields are unknown
- Fix SI function to treat 0 as false for Excel-like behavior

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Remove formule_user_expression= setter as conversion is handled client-side
- Remove formule_user_expression from controller permitted params
- Update specs to use revisions array instead of single revision mock
- Fix rubocop offenses (trailing whitespace)

The formula field conversion from labels to stable IDs is now exclusively
handled by the JavaScript controller, making the server-side setter redundant.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
…state

- Document completed implementation (MVP functional with Dentaku)
- Add hybrid labels/stable_ids architecture documentation
- Define order constraints and public/private context rules
- Update roadmap based on existing implementation
- Prioritize critical missing features (order validation)
- Clarify stable_ids are essential for robustness (field renaming immunity)
- Move formula field configuration section after description field
- Maintain consistency with integer and date fields ordering
- Follow standard pattern: name, description, specific parameters

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@maatinito maatinito force-pushed the feature/champ_formule branch from 464a052 to 0202c0c Compare September 15, 2025 02:22
@maatinito maatinito force-pushed the devpf branch 5 times, most recently from d67fd3d to 770f813 Compare September 16, 2025 01:48
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.

2 participants