openimis/openimis-be-api_fhir_py

View on GitHub
api_fhir/converters/claimResponseConverter.py

Summary

Maintainability
A
0 mins
Test Coverage
from claim.models import Feedback, ClaimItem, ClaimService
from django.db.models import Subquery
from medical.models import Item, Service

from api_fhir.configurations import Stu3ClaimConfig
from api_fhir.converters import BaseFHIRConverter, CommunicationRequestConverter
from api_fhir.converters.claimConverter import ClaimConverter
from api_fhir.exceptions import FHIRRequestProcessException
from api_fhir.models import ClaimResponse, Money, ClaimResponsePayment, ClaimResponseError, ClaimResponseItem, Claim, \
    ClaimResponseItemAdjudication, ClaimResponseProcessNote, ClaimResponseAddItem
from api_fhir.utils import TimeUtils, FhirUtils


class ClaimResponseConverter(BaseFHIRConverter):

    @classmethod
    def to_fhir_obj(cls, imis_claim):
        fhir_claim_response = ClaimResponse()
        fhir_claim_response.created = TimeUtils.date().isoformat()
        fhir_claim_response.request = ClaimConverter.build_fhir_resource_reference(imis_claim)
        cls.build_fhir_pk(fhir_claim_response, imis_claim.uuid)
        ClaimConverter.build_fhir_identifiers(fhir_claim_response, imis_claim)
        cls.build_fhir_outcome(fhir_claim_response, imis_claim)
        cls.build_fhir_payment(fhir_claim_response, imis_claim)
        cls.build_fhir_total_benefit(fhir_claim_response, imis_claim)
        cls.build_fhir_errors(fhir_claim_response, imis_claim)
        cls.build_fhir_communication_request_reference(fhir_claim_response, imis_claim)
        cls.build_fhir_items(fhir_claim_response, imis_claim)
        return fhir_claim_response

    @classmethod
    def build_fhir_outcome(cls, fhir_claim_response, imis_claim):
        code = imis_claim.status
        if code is not None:
            display = cls.get_status_display_by_code(code)
            fhir_claim_response.outcome = cls.build_codeable_concept(str(code), system=None, text=display)

    @classmethod
    def get_status_display_by_code(cls, code):
        display = None
        if code == 1:
            display = Stu3ClaimConfig.get_fhir_claim_status_rejected_code()
        elif code == 2:
            display = Stu3ClaimConfig.get_fhir_claim_status_entered_code()
        elif code == 4:
            display = Stu3ClaimConfig.get_fhir_claim_status_checked_code()
        elif code == 8:
            display = Stu3ClaimConfig.get_fhir_claim_status_processed_code()
        elif code == 16:
            display = Stu3ClaimConfig.get_fhir_claim_status_valuated_code()
        return display

    @classmethod
    def build_fhir_payment(cls, fhir_claim_response, imis_claim):
        fhir_payment = ClaimResponsePayment()
        fhir_payment.adjustmentReason = cls.build_simple_codeable_concept(imis_claim.adjustment)
        date_processed = imis_claim.date_processed
        if date_processed:
            fhir_payment.date = date_processed.isoformat()
        fhir_claim_response.payment = fhir_payment

    @classmethod
    def build_fhir_total_benefit(cls, fhir_claim_response, imis_claim):
        total_approved = Money()
        total_approved.value = imis_claim.approved
        fhir_claim_response.totalBenefit = total_approved

    @classmethod
    def build_fhir_errors(cls, fhir_claim_response, imis_claim):
        rejection_reason = imis_claim.rejection_reason
        if rejection_reason:
            fhir_error = ClaimResponseError()
            fhir_error.code = cls.build_codeable_concept(str(rejection_reason))
            fhir_claim_response.error = [fhir_error]

    @classmethod
    def build_fhir_communication_request_reference(cls, fhir_claim_response, imis_claim):
        feedback = cls.get_imis_claim_feedback(imis_claim)
        if feedback:
            reference = CommunicationRequestConverter.build_fhir_resource_reference(feedback)
            fhir_claim_response.communicationRequest = [reference]

    @classmethod
    def get_imis_claim_feedback(cls, imis_claim):
        try:
            feedback = imis_claim.feedback
        except Feedback.DoesNotExist:
            feedback = None
        return feedback

    @classmethod
    def build_fhir_items(cls, fhir_claim_response, imis_claim):
        for claim_item in cls.generate_fhir_claim_items(imis_claim):
            type = claim_item.category.text
            code = claim_item.service.text

            if type == Stu3ClaimConfig.get_fhir_claim_item_code():
                serviced = cls.get_imis_claim_item_by_code(code, imis_claim.id)
            elif  type == Stu3ClaimConfig.get_fhir_claim_service_code():
                serviced = cls.get_service_claim_item_by_code(code, imis_claim.id)
            else:
                raise FHIRRequestProcessException(['Could not assign category {} for claim_item: {}'
                                                  .format(type, claim_item)])

            cls._build_response_items(fhir_claim_response, claim_item, serviced, serviced.rejection_reason)

    @classmethod
    def _build_response_items(cls, fhir_claim_response, claim_item, imis_service, rejected_reason):
        cls.build_fhir_item(fhir_claim_response, claim_item, imis_service,
                            rejected_reason=rejected_reason)
        cls.build_fhir_claim_add_item(fhir_claim_response, claim_item)

    @classmethod
    def generate_fhir_claim_items(cls, imis_claim):
        claim = Claim()
        ClaimConverter.build_fhir_items(claim, imis_claim)
        return claim.item

    @classmethod
    def get_imis_claim_item_by_code(cls, code, imis_claim_id):
        item_code_qs = Item.objects.filter(code=code)
        result = ClaimItem.objects.filter(item_id__in=Subquery(item_code_qs.values('id')), claim_id=imis_claim_id)
        return result[0] if len(result) > 0 else None

    @classmethod
    def build_fhir_claim_add_item(cls, fhir_claim_response, claim_item):
        add_item = ClaimResponseAddItem()
        item_code = claim_item.service.text
        add_item.sequenceLinkId.append(claim_item.sequence)
        add_item.service = cls.build_codeable_concept(code=item_code)
        fhir_claim_response.addItem.append(add_item)

    @classmethod
    def get_service_claim_item_by_code(cls, code, imis_claim_id):
        service_code_qs = Service.objects.filter(code=code)
        result = ClaimService.objects.filter(service_id__in=Subquery(service_code_qs.values('id')),
                                             claim_id=imis_claim_id)
        return result[0] if len(result) > 0 else None

    @classmethod
    def build_fhir_item(cls, fhir_claim_response, claim_item, item, rejected_reason=None):
        claim_response_item = ClaimResponseItem()
        claim_response_item.sequenceLinkId = claim_item.sequence
        cls.build_fhir_item_general_adjudication(claim_response_item, item)
        if rejected_reason:
            cls.build_fhir_item_rejected_reason_adjudication(claim_response_item, rejected_reason)
        note = cls.build_process_note(fhir_claim_response, item.justification)
        if note:
            claim_response_item.noteNumber = [note.number]
        fhir_claim_response.item.append(claim_response_item)

    @classmethod
    def build_fhir_item_general_adjudication(cls, claim_response_item, item):
        item_adjudication = ClaimResponseItemAdjudication()
        item_adjudication.category = \
            cls.build_simple_codeable_concept(Stu3ClaimConfig.get_fhir_claim_item_general_adjudication_code())
        item_adjudication.reason = cls.build_fhir_adjudication_reason(item)
        item_adjudication.value = item.qty_approved
        limitation_value = Money()
        limitation_value.value = item.limitation_value
        item_adjudication.amount = limitation_value
        claim_response_item.adjudication.append(item_adjudication)

    @classmethod
    def build_fhir_item_rejected_reason_adjudication(cls, claim_response_item, rejection_reason):
        item_adjudication = ClaimResponseItemAdjudication()
        item_adjudication.category = \
            cls.build_simple_codeable_concept(Stu3ClaimConfig.get_fhir_claim_item_rejected_reason_adjudication_code())
        item_adjudication.reason = cls.build_codeable_concept(rejection_reason)
        claim_response_item.adjudication.append(item_adjudication)

    @classmethod
    def build_fhir_adjudication_reason(cls, item):
        status = item.status
        text_code = None
        if status == 1:
            text_code = Stu3ClaimConfig.get_fhir_claim_item_status_passed_code()
        elif status == 2:
            text_code = Stu3ClaimConfig.get_fhir_claim_item_status_rejected_code()
        return cls.build_codeable_concept(status, text=text_code)

    @classmethod
    def build_process_note(cls, fhir_claim_response, string_value):
        result = None
        if string_value:
            note = ClaimResponseProcessNote()
            note.number = FhirUtils.get_next_array_sequential_id(fhir_claim_response.processNote)
            note.text = string_value
            fhir_claim_response.processNote.append(note)
            result = note
        return result