Backend
API contract, database changes, business logic orchestration, and integration points for the Reflex Management backend in crelio-app.
File References
API Layer
-
File:
report/views/reflex_test_config.py -
Description: Contains API views for:
- Creating, updating, deleting configurations
- Enabling / disabling reflex rules
- Manual trigger and evaluation endpoints
-
GitHub:
https://github.com/CrelioHealth/crelio-app/blob/main/report/views/reflex_test_config.py
Model Layer
-
File:
report/models/reflex_test_config.py -
Description: Core business logic including:
- Payload validation
- Rule evaluation engine
- Reflex trigger determination
- Database operations (CRUD + rules handling)
-
GitHub:
https://github.com/CrelioHealth/crelio-app/blob/main/report/models/reflex_test_config.py
Reflex Test Configuration APIs
This section documents all backend endpoints related to:
- Reflex Test Configuration (CRUD + enable/disable)
- Manual Reflex Triggering
- Trigger Evaluation
Base Path
/reflex-test/
## API
```http
POST /api-v3/finance/bill/<lab_bill_id>/update/Configuration APIs
1. Create Configuration
- Endpoint:
POST /reflex-test/new - View:
ReflexTestConfigurationView
Description
Creates a new reflex test configuration.
Flow
- Validates payload →
validate_payload() - Saves configuration →
save_reflex_test_config() - Creates parameter rules
- Returns serialized response
2. Fetch All Configurations
- Endpoint:
GET /reflex-test/ - View:
FetchReflexTestConfigurationView
Description
Fetches all reflex configurations for the logged-in lab.
Response
- Total configurations
- List of configurations with parameter rules
3. Fetch Single Configuration
- Endpoint:
GET /reflex-test/{reflex_test_id}
Description
Fetches a specific reflex test configuration.
4. Update Configuration
- Endpoint:
PUT /reflex-test/{reflex_test_id}/update
Flow
- Validates payload
- Updates core fields
- Deletes old parameter rules
- Recreates rules
5. Delete Configuration
- Endpoint:
DELETE /reflex-test/{reflex_test_id}/delete
Description
Deletes a reflex configuration and logs activity.
6. Enable Configuration
- Endpoint:
PATCH /reflex-test/{reflex_test_id}/enable
7. Disable Configuration
- Endpoint:
PATCH /reflex-test/{reflex_test_id}/disable
Description
Toggles configuration status using:
enable_or_disable()method- Activity logging
Manual Reflex APIs
Base Path
/reflex-test/manual/
1. Check Trigger Conditions
- Endpoint:
GET /reflex-test/manual/check-triggers/{lab_report_id} - View:
DetermineTriggerForReflexTests
Description
Evaluates whether reflex tests should be triggered based on:
- Report values
- Configured rules
- Parameter types
Flow
- Fetch report
- Fetch applicable configurations
- Evaluate rules →
fetch_triggered_tests() - Return triggered tests along with metadata
2. Trigger Reflex Tests Manually
- Endpoint:
POST /reflex-test/manual/trigger-reflex - View:
ManuallyTriggerReflexTests
Description
Manually triggers reflex tests for a given report.
Required Payload
{
"labReportId": number,
"triggeredIndexes": { "index": "value" },
"triggeringTestsId": number
}Flow
- Validates payload
- Calls
enqueue_reflex_trigger() - Sends job to async processing (Fusion webhook)
3. Get Configured Reflex Tests
- Endpoint:
GET /reflex-test/manual/get-configured-tests?testIds[]=1&testIds[]=2 - View:
GetConfiguredReflexTests
Description
Returns list of tests that have reflex configurations.
Internal Processing Flow
Validation Layer
validate_payload()- Checks required fields
- Validates parameter types
- Validates rules (range/list/descriptive)
- Prevents conflicts and duplicates
Rule Evaluation
Handled via:
- Range →
get_range_parameter_trigger_test_ids() - List/Descriptive →
get_list_descriptive_parameter_trigger_test_ids() - Multi-value →
evaluate_multi_value_trigger()
Trigger Execution
fetch_triggered_tests()→ determines eligible testsfetch_related_details()→ enriches test metadataenqueue_reflex_trigger()→ sends async job
Models Used in Reflex Management
ReflexTestConfiguration
class ReflexTestConfiguration(BaseModel):
category_id_mapper: dict[int, str] = {
"created": 628,
"updated": 629,
"triggered": 630,
"deleted": 634,
"enabled": 644,
"disabled": 645,
}
id = models.AutoField(auto_created=True, primary_key=True) # noqa A003
lab = models.ForeignKey(
"account.Labs",
on_delete=models.CASCADE,
null=True,
default=None,
db_default=None,
)
test = models.ForeignKey(
"masters.AllTests",
on_delete=models.CASCADE,
null=True,
default=None,
db_default=None,
)
trigger_index = models.PositiveSmallIntegerField(
null=True, default=None, db_default=None
)
trigger_type = models.CharField(
choices=TRIGGER_TYPE_CHOICES,
max_length=50,
default="NORMAL_RANGE",
db_default="NORMAL_RANGE",
)
lower_range = models.FloatField(default=0.0, null=True)
upper_range = models.FloatField(default=0.0, null=True)
new_tests = models.TextField(null=True, default="[]")
create_new_bill = models.BooleanField(default=False, db_default=False)
is_enabled = models.BooleanField(default=True)
parameter_type = models.CharField(
choices=PARAMETER_TYPE_CHOICES,
max_length=50,
default="RANGE",
db_default="RANGE",
)
trigger_value = models.TextField(max_length=500, null=True)
manual_reflex = models.BooleanField(default=False, db_default=False)
interfacing_reflex = models.BooleanField(default=False, db_default=False)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
created_by = models.ForeignKey(
"account.LabUser",
on_delete=models.SET_NULL,
related_name="reflex_test_config_created_by",
null=True,
default=None,
db_default=None,
)
updated_by = models.ForeignKey(
"account.LabUser",
on_delete=models.SET_NULL,
related_name="reflex_test_config_updated_by",
null=True,
default=None,
db_default=None,
)
def __repr__(self):
return (
f"ReflexTestConfiguration(id={self.id}, test={self.test}, lab={self.lab})"
)
class Meta:
db_table = "ReflexTestConfiguration"
unique_together = ("test", "trigger_index")This model is used to store reflex test configurations.
Each configuration defines:
- Which test + parameter to monitor
- What conditions should trigger reflex tests
- Which tests should be added
- How they should be billed and executed
Key Fields
-
test → Primary test for which reflex logic is defined
-
trigger_index → Parameter index used for evaluation
-
trigger_type → Type of trigger (NORMAL_RANGE / CRITICAL / CUSTOM / etc.)
-
parameter_type → Determines rule type:
- RANGE
- LIST
- DESCRIPTIVE
-
lower_range / upper_range → Used for numeric range-based conditions
-
trigger_value → Stores value for list/descriptive conditions
-
new_tests → JSON string containing reflex test IDs
-
create_new_bill → Controls billing behavior
-
manual_reflex / interfacing_reflex → Determines trigger mode
-
is_enabled → Enables/disables configuration
ReflexTestDetails
class ReflexTestDetails(BaseModel):
bill = models.ForeignKey("finance.billing", on_delete=models.CASCADE)
report = models.ForeignKey("masters.AllTests", on_delete=models.CASCADE)
lab_report = models.ForeignKey("report.LabReportRelation", on_delete=models.CASCADE)
is_triggered = models.BooleanField(default=False, db_default=False)
triggering_method = models.CharField(max_length=100, null=True)
parameters_triggered = models.TextField(default="[]")
stop_auto_trigger = models.BooleanField(default=True, db_default=False)
triggered_by_user = models.ForeignKey(
"account.LabUser", null=True, on_delete=models.SET_NULL
)
triggered_time = models.DateTimeField(auto_now_add=True)
reports_triggered = models.TextField(default="[]")
extra_data = models.TextField(default="{}")
class Meta:
db_table = "ReflexTestDetails"This model stores runtime data of triggered reflex tests.
It acts as an audit + tracking layer.
Key Fields
-
bill → Bill where reflex tests were added
-
lab_report → Associated lab report
-
report → Primary test
-
is_triggered → Whether reflex was triggered
-
triggering_method → manual / interfacing
-
parameters_triggered → Indexes that caused trigger (JSON)
-
reports_triggered → Reflex test IDs triggered (JSON)
-
triggered_by_user → User who triggered reflex
-
triggered_time → Timestamp of trigger
Reflex Triggering Flow
Handled via:
TriggerReflexTestInBillAPI view
Overview
This API is responsible for:
- Evaluating trigger conditions
- Determining eligible reflex tests
- Adding tests to bill
- Logging activity
- Saving trigger details
Trigger Flow (Step-by-Step)
1. Payload Validation
-
Validates required fields:
lab_report_relation_idtests_mappedtriggered_indexes
-
Ensures:
- Device ID exists (for interfacing)
- Report exists
- Primary test exists
2. Duplicate Trigger Check
- Checks if reflex already triggered:
- Prevents duplicate execution
- Logs activity
3. Determine Eligible Reflex Tests
Handled via:
get_trigger_eligible_tests_data()
Logic
- Fetch configurations:
- Based on test + trigger index
- For each config:
- Identify parameter type
- Evaluate condition
4. Rule Evaluation
Range Parameters
-
Handled by:
get_range_parameter_trigger_test_ids()
-
Logic:
- Fetch parameter rules
- Determine range (custom / normal / critical)
- Compare value
- Collect matching reflex tests
List / Descriptive Parameters
-
Handled by:
get_list_descriptive_parameter_trigger_test_ids()
-
Supported conditions:
- IS_NOT
- CONTAINS
- EXACT_MATCHES
- DOES_NOT_CONTAIN
- CONTAINS_MULTIPLE_VALUES
Multi-value Logic
- Handled by:
evaluate_multi_value_trigger()
Example Structure
{
"condition": "AND",
"contains": ["Positive"],
"does_not_contains": ["Negative"]
}Evaluation Logic
-
AND
→ All conditions must match -
OR
→ Any condition must match
5. Add Reflex Tests to Bill
Handled via:
add_tests_against_bill()
Flow
-
Separate tests:
- Existing bill
- New bill
-
Prepare payload:
prepare_payload_for_adding_to_bill()
-
Call billing controller:
commonBillAddTestController()
6. Validation Before Adding Tests
Handled via:
validate_addition_of_test_for_patient()
Ensures
- No duplicate test addition
- No circular dependencies
- Bill is not locked
7. Activity Logging
Handled via:
save_success_activity()
Logs
- Triggered tests
- Trigger type (manual/interfacing)
- Patient
- Bill
- Parameter
8. Save Trigger Details
Handled via:
save_reflex_details_instance()
Stores
- Triggered tests
- Triggering indexes
- Trigger method
- User + timestamp