Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration with Commcare #7

Merged
merged 5 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions spp_commcare/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "15.0.0.0.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/openspp/openspp-commcare",
"website": "https://github.com/openspp/openspp-registry",
"license": "LGPL-3",
"development_status": "Alpha",
"maintainers": ["jeremi", "gonzalesedwin1123"],
Expand All @@ -20,8 +20,13 @@
"auth_api_key",
],
"external_dependencies": {"python": []},
'data': [
'security/ir.model.access.csv',
"data": [
"security/ir.model.access.csv",
"views/main_view.xml",
"views/commcare_form_views.xml",
"views/commcare_form_metadata_views.xml",
"views/commcare_case_views.xml",
"views/commcare_field_map_views.xml",
],
"assets": {},
"demo": [],
Expand Down
27 changes: 15 additions & 12 deletions spp_commcare/controllers/commcare_form.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
from odoo import http
import json
import logging

from odoo import http

from odoo.http import request
_logger = logging.getLogger(__name__)

print('Hello world! CommCareController')
_logger.info("Hello world! CommCareController")


class CommCareController(http.Controller):

# @http.route('/commcare/form/', methods=['GET'], type='http', auth='api_key')
@http.route('/commcare/form/', methods=['GET'], type='http', auth='api_key')
@http.route("/commcare/form/", methods=["GET"], type="http", auth="api_key")
def get_sample(self, **kwargs):
return json.dumps({'success': True})
return json.dumps({"success": True})

@http.route('/commcare/form/', auth='api_key', methods=['POST'], csrf=False, type='json')
@http.route(
"/commcare/form/", auth="api_key", methods=["POST"], csrf=False, type="json"
)
def create_form(self, **kwargs):
print('Hello world! CommCareController create_form')
CommCareForm = http.request.env['spp.commcare.form']
_logger.info("Hello world! CommCareController create_form")
CommCareForm = http.request.env["spp.commcare.form"]
form_data = http.request.jsonrequest

if not form_data:
return {'error': 'No valid data received'}
return {"error": "No valid data received"}

new_form = CommCareForm.create_form_from_json(form_data)

if new_form:
return {'success': True, 'form_id': new_form.id}
return {"success": True, "form_id": new_form.id}
else:
return {'error': 'Form could not be created'}

return {"error": "Form could not be created"}
2 changes: 1 addition & 1 deletion spp_commcare/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from . import commcare_case
from . import commcare_form
from . import field_mapping
from . import ir_http
from . import xform_to_odoo

108 changes: 59 additions & 49 deletions spp_commcare/models/commcare_case.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import json
import logging
from datetime import datetime

from odoo import models, fields, api
from odoo import api, fields, models
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from datetime import datetime


class CommCareCase(models.Model):
_name = 'spp.commcare.case'
_description = 'CommCare Cases'
_name = "spp.commcare.case"
_description = "CommCare Cases"
_rec_name = "case_id"
_order = "id desc"

# Fixed fields
domain = fields.Char(string='Domain', required=True)
case_id = fields.Char(string='Case ID', required=True, index=True)
case_type = fields.Char(string='Case Type')
user_id = fields.Char(string='User ID', required=True)
closed = fields.Boolean(string='Closed', default=False)
xform_ids = fields.Char(string='XForm IDs') # Assuming IDs can be stored as comma-separated values
date_closed = fields.Datetime(string='Date Closed')
date_modified = fields.Datetime(string='Date Modified')
server_date_modified = fields.Datetime(string='Server Date Modified')
domain = fields.Char(required=True)
case_id = fields.Char(string="Case ID", required=True, index=True)
case_type = fields.Char()
user_id = fields.Char(string="User ID", required=True)
closed = fields.Boolean(default=False)
xform_ids = fields.Char(
string="XForm IDs"
) # Assuming IDs can be stored as comma-separated values
date_closed = fields.Datetime()
date_modified = fields.Datetime()
server_date_modified = fields.Datetime()

# Flexible field for form-specific properties
properties = fields.Text(string='Properties')
properties = fields.Text()

# Parent-Child Relationship
parent_id = fields.Many2one('spp.commcare.case', string='Parent Case')
parent_id = fields.Many2one("spp.commcare.case", string="Parent Case")

# Link to the res.partner model
partner_id = fields.Many2one('res.partner', string='Associated Partner')
partner_id = fields.Many2one("res.partner", string="Associated Partner")

is_partial = fields.Boolean(string="Is Partially filled", default=False)

Expand All @@ -38,62 +42,65 @@ def link_case_to_partner(self, partner=None):
properties_dict = json.loads(self.properties)

# Step 2: Extract group_id
group_id = properties_dict.get('group_id')
group_id = properties_dict.get("group_id")
if not group_id:
logging.warning(f"No group_id found for case_id {self.case_id}")
return # or log a warning

# Step 2: Extract group_id
case_type = properties_dict.get('case_type')
case_type = properties_dict.get("case_type")
if not case_type:
return # or log a warning
# Step 3: Search for the matching partner
criteria = [('name', '=', group_id)]
if case_type == 'group':
criteria.append(('is_group', '=', True))
criteria = [("name", "=", group_id)]
if case_type == "group":
criteria.append(("is_group", "=", True))
else:
criteria.append(('is_group', '=', False))
criteria.append(("is_group", "=", False))

matching_partner = self.env['res.partner'].search(criteria, limit=1)
matching_partner = self.env["res.partner"].search(criteria, limit=1)

# Step 4: Link the case to the partner if found
if matching_partner:
self.partner_id = matching_partner.id
else:
logging.warning(f"No matching partner found for group_id {group_id}")


@api.model
def create_case_from_json(self, case_json):
# Serialize the properties dictionary to a JSON-formatted string
properties_str = json.dumps(case_json.get('properties', {}))
properties_str = json.dumps(case_json.get("properties", {}))

# Prepare a data dictionary to hold the new case's data
case_data = {
'domain': case_json.get('domain'),
'case_id': case_json.get('case_id'),
'user_id': case_json.get('user_id'),
'closed': case_json.get('closed', False),
'xform_ids': ','.join(case_json.get('xform_ids', [])),
'date_closed': case_json.get('date_closed'),
'date_modified': case_json.get('date_modified'),
'server_date_modified': case_json.get('server_date_modified'),
'properties': properties_str,
'case_type': case_json.get('properties', {}).get('case_type')
"domain": case_json.get("domain"),
"case_id": case_json.get("case_id"),
"user_id": case_json.get("user_id"),
"closed": case_json.get("closed", False),
"xform_ids": ",".join(case_json.get("xform_ids", [])),
"date_closed": case_json.get("date_closed"),
"date_modified": case_json.get("date_modified"),
"server_date_modified": case_json.get("server_date_modified"),
"properties": properties_str,
"case_type": case_json.get("properties", {}).get("case_type"),
}

# Search for an existing case with the same case_id
existing_case = self.env['spp.commcare.case'].search([('case_id', '=', case_data['case_id'])],
order='create_date desc', limit=1)
existing_case = self.env["spp.commcare.case"].search(
[("case_id", "=", case_data["case_id"])], order="create_date desc", limit=1
)

# If a case exists, decide whether to update it
if existing_case and not existing_case.is_partial:
existing_date_str = existing_case.date_modified
new_date_str = case_data['date_modified']
new_date_str = case_data["date_modified"]

# Convert both dates to datetime objects for comparison
existing_date = datetime.strptime(existing_date_str,
DEFAULT_SERVER_DATETIME_FORMAT) if existing_date_str else datetime.min
existing_date = (
datetime.strptime(existing_date_str, DEFAULT_SERVER_DATETIME_FORMAT)
if existing_date_str
else datetime.min
)
new_date = datetime.strptime(new_date_str, DEFAULT_SERVER_DATETIME_FORMAT)

# Update only if the new record is more recent
Expand All @@ -104,29 +111,32 @@ def create_case_from_json(self, case_json):
else:
# Create a new case if none exists with the same case_id
# Handle parent-child relationships, if applicable
indices = case_json.get('indices', {})
parent_info = indices.get('parent')
indices = case_json.get("indices", {})
parent_info = indices.get("parent")
if parent_info:
parent_case_id = parent_info.get('case_id')
parent_case = self.env['spp.commcare.case'].search([('case_id', '=', parent_case_id)],
order='create_date desc', limit=1)
parent_case_id = parent_info.get("case_id")
parent_case = self.env["spp.commcare.case"].search(
[("case_id", "=", parent_case_id)],
order="create_date desc",
limit=1,
)

# Create parent case if not found
if not parent_case:
parent_case_data = {
'case_id': parent_case_id,
"case_id": parent_case_id,
# Add any other default or inferred fields for parent case here
}
parent_case = self.env['spp.commcare.case'].create(parent_case_data)
parent_case = self.env["spp.commcare.case"].create(parent_case_data)

case_data['parent_id'] = parent_case.id
case_data["parent_id"] = parent_case.id

if existing_case:
existing_case.write(case_data)
return existing_case
else:
# Create the new case record in Odoo and return it
new_case = self.env['spp.commcare.case'].create(case_data)
new_case = self.env["spp.commcare.case"].create(case_data)

# Link case to partner after creation
new_case.link_case_to_partner()
Expand Down
Loading
Loading