Example #1
0
 def _get_xform(xform_id):
     db = XFormInstance.get_db()
     doc = db.get(xform_id)
     if doc['doc_type'] in doc_types():
         return doc_types()[doc['doc_type']].wrap(doc)
     if doc['doc_type'] == "%s%s" % (XFormInstance.__name__, DELETED_SUFFIX):
         raise UnexpectedDeletedXForm(xform_id)
     raise ResourceNotFound(xform_id)
Example #2
0
def get_forms_by_type(domain, type_, recent_first=False,
                      limit=None):
    assert type_ in doc_types()
    # no production code should be pulling all forms in one go!
    assert limit is not None
    startkey = [domain, type_]
    endkey = startkey + [{}]
    if recent_first:
        startkey, endkey = endkey, startkey
    return XFormInstance.view(
        "couchforms/all_submissions_by_domain",
        startkey=startkey,
        endkey=endkey,
        reduce=False,
        descending=recent_first,
        include_docs=True,
        limit=limit,
        classes=doc_types(),
    ).all()
    def print_stats(self, domain, short=True, diffs_only=False):
        status = get_couch_sql_migration_status(domain)
        print("Couch to SQL migration status for {}: {}".format(domain, status))
        db = get_diff_db(domain)
        try:
            diff_stats = db.get_diff_stats()
        except OperationalError:
            diff_stats = {}

        has_diffs = False
        for doc_type in doc_types():
            form_ids_in_couch = set(get_form_ids_by_type(domain, doc_type))
            form_ids_in_sql = set(FormAccessorSQL.get_form_ids_in_domain_by_type(domain, doc_type))
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            has_diffs |= self._print_status(
                doc_type, form_ids_in_couch, form_ids_in_sql, diff_count, num_docs_with_diffs, short, diffs_only
            )

        form_ids_in_couch = set(get_doc_ids_in_domain_by_type(
            domain, "XFormInstance-Deleted", XFormInstance.get_db())
        )
        form_ids_in_sql = set(FormAccessorSQL.get_deleted_form_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("XFormInstance-Deleted", (0, 0))
        has_diffs |= self._print_status(
            "XFormInstance-Deleted", form_ids_in_couch, form_ids_in_sql,
            diff_count, num_docs_with_diffs, short, diffs_only
        )

        case_ids_in_couch = set(get_case_ids_in_domain(domain))
        case_ids_in_sql = set(CaseAccessorSQL.get_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("CommCareCase", (0, 0))
        has_diffs |= self._print_status(
            'CommCareCase', case_ids_in_couch, case_ids_in_sql, diff_count, num_docs_with_diffs, short, diffs_only
        )

        case_ids_in_couch = set(get_doc_ids_in_domain_by_type(
            domain, "CommCareCase-Deleted", XFormInstance.get_db())
        )
        case_ids_in_sql = set(CaseAccessorSQL.get_deleted_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop("CommCareCase-Deleted", (0, 0))
        has_diffs |= self._print_status(
            'CommCareCase-Deleted', case_ids_in_couch, case_ids_in_sql,
            diff_count, num_docs_with_diffs, short, diffs_only
        )

        if diff_stats:
            for key, counts in diff_stats.items():
                diff_count, num_docs_with_diffs = counts
                has_diffs |= self._print_status(
                    key, set(), set(), diff_count, num_docs_with_diffs, short, diffs_only
                )

        if diffs_only and not has_diffs:
            print(shell_green("No differences found between old and new docs!"))
        return has_diffs
Example #4
0
def get_number_of_forms_by_type(domain, type_):
    assert type_ in doc_types()
    startkey = [domain, type_]
    endkey = startkey + [{}]
    submissions = XFormInstance.view(
        "couchforms/all_submissions_by_domain",
        startkey=startkey,
        endkey=endkey,
        reduce=True,
    ).one()
    return submissions['value'] if submissions else 0
Example #5
0
def get_forms_of_all_types(domain):
    startkey = [domain]
    endkey = startkey + [{}]
    return XFormInstance.view(
        "couchforms/all_submissions_by_domain",
        startkey=startkey,
        endkey=endkey,
        reduce=False,
        include_docs=True,
        classes=doc_types(),
    ).all()
Example #6
0
def _get_form_or_404(id):
    # maybe this should be a more general utility a-la-django's get_object_or_404
    try:
        xform_json = XFormInstance.get_db().get(id)
    except ResourceNotFound:
        raise Http404()

    doc_type = doc_types().get(xform_json.get('doc_type'))
    if not doc_type:
        raise Http404()

    return doc_type.wrap(xform_json)
Example #7
0
def get_number_of_forms_by_type(domain, type_):
    # todo: this is only used to display totals in the "raw forms" report and can probably be removed
    assert type_ in doc_types()
    startkey = [domain, type_]
    endkey = startkey + [{}]
    submissions = XFormInstance.view(
        "couchforms/all_submissions_by_domain",
        startkey=startkey,
        endkey=endkey,
        reduce=True,
        stale=stale_ok(),
    ).one()
    return submissions['value'] if submissions else 0
Example #8
0
 def get_with_attachments(form_id):
     doc = XFormInstance.get_db().get(form_id, attachments=True)
     doc = doc_types()[doc['doc_type']].wrap(doc)
     if doc.external_blobs:
         for name, meta in doc.external_blobs.iteritems():
             with doc.fetch_attachment(name, stream=True) as content:
                 doc.deferred_put_attachment(
                     content,
                     name,
                     content_type=meta.content_type,
                     content_length=meta.content_length,
                 )
     return doc
Example #9
0
    def handle(self, domain, doc_type, **options):
        csv = options.get('csv')
        startdate = options.get('start')
        enddate = options.get('end')

        form_doc_types = doc_types()

        if startdate or enddate:
            if doc_type in CASE_DOC_TYPES or doc_type in form_doc_types:
                if not should_use_sql_backend(domain):
                    raise CommandError("Date filtering not supported for Couch domains")

        if startdate and enddate and enddate <= startdate:
            raise CommandError("enddate must be after startdate")

        handlers = {
            'CommCareCase': compare_cases,
            'CommCareCase-Deleted': compare_cases,
            'CommCareUser': _compare_users,
            'CommCareUser-Deleted': _compare_users,
            'WebUser': _compare_users,
        }
        handlers.update({doc_type: compare_xforms for doc_type in form_doc_types})
        try:
            primary_count, es_count, primary_only, es_only = handlers[doc_type](domain, doc_type, startdate, enddate)
        except KeyError:
            raise CommandError('Unsupported doc type. Use on of: {}'.format(', '.join(handlers)))

        if csv:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([50, 50])

        date_range_output = ''
        if startdate or enddate:
            end = (enddate or datetime.utcnow().date()).strftime(DATE_FORMAT)
            start = startdate.strftime(DATE_FORMAT)
            date_range_output = ' (Between {} and {})'.format(start, end)

        print("\nDoc ID analysis for {}{}\n".format(doc_type, date_range_output))

        print("Primary Count: {}".format(primary_count))
        print("ES Count: {}\n".format(es_count))

        writer = SimpleTableWriter(self.stdout, row_formatter)
        writer.write_table(
            ['Only in Primary', 'Only in ES'],
            zip_longest(primary_only, es_only, fillvalue='')
        )
Example #10
0
 def get_with_attachments(form_id):
     doc = XFormInstance.get_db().get(form_id)
     doc = doc_types()[doc['doc_type']].wrap(doc)
     if doc.external_blobs:
         for name, meta in six.iteritems(doc.external_blobs):
             with doc.fetch_attachment(name, stream=True) as content:
                 doc.deferred_put_attachment(
                     content,
                     name,
                     content_type=meta.content_type,
                     content_length=meta.content_length,
                 )
     else:
         # xforms are expected to at least have the XML attachment
         raise ResourceNotFound("XForm attachment missing: {}".format(form_id))
     return doc
Example #11
0
def _blow_away_migration(domain):
    assert not should_use_sql_backend(domain)
    delete_diff_db(domain)

    for doc_type in doc_types():
        sql_form_ids = FormAccessorSQL.get_form_ids_in_domain_by_type(domain, doc_type)
        FormAccessorSQL.hard_delete_forms(domain, sql_form_ids, delete_attachments=False)

    sql_form_ids = FormAccessorSQL.get_deleted_form_ids_in_domain(domain)
    FormAccessorSQL.hard_delete_forms(domain, sql_form_ids, delete_attachments=False)

    sql_case_ids = CaseAccessorSQL.get_case_ids_in_domain(domain)
    CaseAccessorSQL.hard_delete_cases(domain, sql_case_ids)

    sql_case_ids = CaseAccessorSQL.get_deleted_case_ids_in_domain(domain)
    CaseAccessorSQL.hard_delete_cases(domain, sql_case_ids)
Example #12
0
def get_form_ids_by_type(domain, type_, start=None, end=None):
    assert type_ in doc_types()
    startkey = [domain, type_]
    if end:
        endkey = startkey + end.isoformat()
    else:
        endkey = startkey + [{}]

    if start:
        startkey.append(start.isoformat())

    return [row['id'] for row in XFormInstance.get_db().view(
        "couchforms/all_submissions_by_domain",
        startkey=startkey,
        endkey=endkey,
        reduce=False,
    )]
    def get_diff_stats(self, domain):
        db = get_diff_db(domain)
        diff_stats = db.get_diff_stats()

        stats = {}

        def _update_stats(doc_type, couch_count, sql_count):
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            if diff_count or couch_count != sql_count:
                stats[doc_type] = (couch_count, sql_count, diff_count, num_docs_with_diffs)

        for doc_type in doc_types():
            form_ids_in_couch = len(set(get_form_ids_by_type(domain, doc_type)))
            form_ids_in_sql = len(set(FormAccessorSQL.get_form_ids_in_domain_by_type(domain, doc_type)))
            _update_stats(doc_type, form_ids_in_couch, form_ids_in_sql)

        form_ids_in_couch = len(set(get_doc_ids_in_domain_by_type(
            domain, "XFormInstance-Deleted", XFormInstance.get_db())
        ))
        form_ids_in_sql = len(set(FormAccessorSQL.get_deleted_form_ids_in_domain(domain)))
        _update_stats("XFormInstance-Deleted", form_ids_in_couch, form_ids_in_sql)

        case_ids_in_couch = len(set(get_case_ids_in_domain(domain)))
        case_ids_in_sql = len(set(CaseAccessorSQL.get_case_ids_in_domain(domain)))
        _update_stats("CommCareCase", case_ids_in_couch, case_ids_in_sql)

        if self.strict:
            # only care about these in strict mode
            case_ids_in_couch = len(set(get_doc_ids_in_domain_by_type(
                domain, "CommCareCase-Deleted", XFormInstance.get_db())
            ))
            case_ids_in_sql = len(set(CaseAccessorSQL.get_deleted_case_ids_in_domain(domain)))
            _update_stats("CommCareCase-Deleted", case_ids_in_couch, case_ids_in_sql)

        if diff_stats:
            for key in diff_stats.keys():
                _update_stats(key, 0, 0)

        return stats
Example #14
0
def get_forms_by_id(form_ids):
    forms = iter_docs(XFormInstance.get_db(), form_ids)
    doctypes = doc_types()
    return [doctypes[form['doc_type']].wrap(form) for form in forms if form.get('doc_type') in doctypes]
Example #15
0
 def is_duplicate(cls, xform_id, domain=None):
     if domain:
         try:
             existing_doc = XFormInstance.get_db().get(xform_id)
         except ResourceNotFound:
             return False
         return existing_doc.get('domain') == domain and existing_doc.get('doc_type') in doc_types()
     else:
         return xform_id in XFormInstance.get_db()
Example #16
0
 def test_wrappable(self):
     types = couchforms_models.all_known_formlike_doc_types()
     for key in couchforms_models.doc_types().keys():
         self.assertTrue(key in types)
Example #17
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get("domain") or domain_hint
    doc_type = doc.get("doc_type")
    doc_id = doc.get("_id")
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return doc_type == expected_doc_type or doc_type == ("%s%s" % (expected_doc_type, DELETED_SUFFIX))

    if domain_hint and not (doc.get("domain") == domain_hint or domain_hint in doc.get("domains", ())):
        raise DomainMismatchException("Doc '%s' does not match the domain_hint '%s'" % (doc_id, domain_hint))

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, "Application") or has_doc_type(doc_type, "RemoteApp"):
        if doc.get("copy_of"):
            doc_info = DocInfo(
                display=u"%s (#%s)" % (doc["name"], doc["version"]),
                type_display=_("Application Build"),
                link=reverse("corehq.apps.app_manager.views.download_index", args=[domain, doc_id]),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc["name"],
                type_display=_("Application"),
                link=reverse("corehq.apps.app_manager.views.view_app", args=[domain, doc_id]),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, "CommCareCaseGroup"):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView

        doc_info = DocInfo(
            type_display=_("Case Group"),
            display=doc["name"],
            link=reverse(CaseGroupCaseManagementView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "CommCareCase"):
        doc_info = DocInfo(
            display=doc["name"],
            type_display=_("Case"),
            link=reverse("case_details", args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = DocInfo(
            type_display=_("Form"), link=reverse("render_form_data", args=[domain, doc_id]), is_deleted=generic_delete
        )
    elif doc_type in ("CommCareUser",):
        doc_info = DocInfo(
            display=raw_username(doc["username"]),
            type_display=_("Mobile Worker"),
            link=reverse("edit_commcare_user", args=[domain, doc_id]),
            is_deleted=doc.get("base_doc", "").endswith(DELETED_SUFFIX),
        )
    elif doc_type in ("WebUser",):
        doc_info = DocInfo(
            type_display=_("Web User"),
            display=doc["username"],
            link=reverse("user_account", args=[domain, doc_id]),
            is_deleted=doc.get("base_doc", "").endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, "Group"):
        from corehq.apps.users.views.mobile import EditGroupMembersView

        doc_info = DocInfo(
            type_display=_("Group"),
            display=doc["name"],
            link=reverse(EditGroupMembersView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "Domain"):
        if doc["is_snapshot"] and doc["published"]:
            urlname = "project_info"
        else:
            urlname = "domain_basic_info"
        doc_info = DocInfo(
            type_display=_("Domain"),
            display=doc["name"],
            link=reverse(urlname, kwargs={"domain": doc["name"]}),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, "Location"):
        from corehq.apps.locations.views import EditLocationView

        doc_info = DocInfo(
            type_display=_("Location"),
            display=doc["name"],
            link=reverse(EditLocationView.urlname, args=[domain, doc_id]),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(is_deleted=generic_delete)

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Example #18
0
from corehq.apps.api.resources import v0_1, v0_3, HqBaseResource, DomainSpecificResourceMixin, \
    SimpleSortableResourceMixin
from corehq.apps.api.es import XFormES, CaseES, ESQuerySet, es_search
from corehq.apps.api.fields import ToManyDocumentsField, UseIfRequested, ToManyDictField, ToManyListDictField
from corehq.apps.api.serializers import CommCareCaseSerializer

from no_exceptions.exceptions import Http400

# By the time a test case is running, the resource is already instantiated,
# so as a hack until this can be remedied, there is a global that
# can be set to provide a mock.
MOCK_XFORM_ES = None
MOCK_CASE_ES = None

xform_doc_types = doc_types()


class XFormInstanceResource(SimpleSortableResourceMixin, v0_3.XFormInstanceResource, DomainSpecificResourceMixin):

    # Some fields that were present when just fetching individual docs are
    # not present for e.g. devicelogs and must be allowed blank
    uiversion = fields.CharField(attribute='uiversion', blank=True, null=True)
    metadata = fields.DictField(attribute='metadata', blank=True, null=True)
    domain = fields.CharField(attribute='domain')
    app_id = fields.CharField(attribute='app_id', null=True)
    build_id = fields.CharField(attribute='build_id', null=True)
    initial_processing_complete = fields.BooleanField(
        attribute='initial_processing_complete', null=True)
    problem = fields.CharField(attribute='problem', null=True)
Example #19
0
 def test_wrappable(self):
     types = couchforms_models.all_known_formlike_doc_types()
     for key in couchforms_models.doc_types().keys():
         self.assertTrue(key in types)
Example #20
0
 def is_duplicate(cls, xform_id, domain=None):
     if domain:
         try:
             existing_doc = XFormInstance.get_db().get(xform_id)
         except ResourceNotFound:
             return False
         return existing_doc.get('domain') == domain and existing_doc.get('doc_type') in doc_types()
     else:
         return xform_id in XFormInstance.get_db()
Example #21
0
    def print_stats(self, domain, short=True, diffs_only=False):
        status = get_couch_sql_migration_status(domain)
        print("Couch to SQL migration status for {}: {}".format(
            domain, status))
        db = get_diff_db(domain)
        try:
            diff_stats = db.get_diff_stats()
        except OperationalError:
            diff_stats = {}

        has_diffs = False
        for doc_type in doc_types():
            form_ids_in_couch = set(get_form_ids_by_type(domain, doc_type))
            form_ids_in_sql = set(
                FormAccessorSQL.get_form_ids_in_domain_by_type(
                    domain, doc_type))
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            has_diffs |= self._print_status(doc_type, form_ids_in_couch,
                                            form_ids_in_sql, diff_count,
                                            num_docs_with_diffs, short,
                                            diffs_only)

        form_ids_in_couch = set(
            get_doc_ids_in_domain_by_type(domain, "XFormInstance-Deleted",
                                          XFormInstance.get_db()))
        form_ids_in_sql = set(
            FormAccessorSQL.get_deleted_form_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop(
            "XFormInstance-Deleted", (0, 0))
        has_diffs |= self._print_status("XFormInstance-Deleted",
                                        form_ids_in_couch, form_ids_in_sql,
                                        diff_count, num_docs_with_diffs, short,
                                        diffs_only)

        case_ids_in_couch = set(get_case_ids_in_domain(domain))
        case_ids_in_sql = set(CaseAccessorSQL.get_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop(
            "CommCareCase", (0, 0))
        has_diffs |= self._print_status('CommCareCase', case_ids_in_couch,
                                        case_ids_in_sql, diff_count,
                                        num_docs_with_diffs, short, diffs_only)

        case_ids_in_couch = set(
            get_doc_ids_in_domain_by_type(domain, "CommCareCase-Deleted",
                                          XFormInstance.get_db()))
        case_ids_in_sql = set(
            CaseAccessorSQL.get_deleted_case_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop(
            "CommCareCase-Deleted", (0, 0))
        has_diffs |= self._print_status('CommCareCase-Deleted',
                                        case_ids_in_couch, case_ids_in_sql,
                                        diff_count, num_docs_with_diffs, short,
                                        diffs_only)

        if diff_stats:
            for key, counts in diff_stats.items():
                diff_count, num_docs_with_diffs = counts
                has_diffs |= self._print_status(key, set(), set(), diff_count,
                                                num_docs_with_diffs, short,
                                                diffs_only)

        if diffs_only and not has_diffs:
            print(
                shell_green("No differences found between old and new docs!"))
        return has_diffs
Example #22
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return (doc_type == expected_doc_type or
            doc_type == ('%s%s' % (expected_doc_type, DELETED_SUFFIX)))

    if (
        domain_hint and
        not (
            doc.get('domain') == domain_hint or
            domain_hint in doc.get('domains', ())
        )
    ):
        raise DomainMismatchException("Doc '%s' does not match the domain_hint '%s'" % (doc_id, domain_hint))

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, 'Application') or has_doc_type(doc_type, 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'download_index',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'view_app',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, 'CommCareCaseGroup'):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView
        doc_info = DocInfo(
            type_display=_('Case Group'),
            display=doc['name'],
            link=reverse(
                CaseGroupCaseManagementView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'CommCareCase'):
        doc_info = case_docinfo(domain, doc_id, doc['name'], generic_delete)
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = form_docinfo(domain, doc_id, generic_delete)
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=get_commcareuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=get_webuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, 'Group'):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Domain'):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Location'):
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=_('Location'),
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(
            is_deleted=generic_delete,
        )

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Example #23
0
from corehq.apps.users.util import format_username
from corehq.motech.repeaters.models import Repeater
from corehq.motech.repeaters.utils import get_all_repeater_types
from corehq.util.view_utils import absolute_reverse
from couchforms.models import doc_types
from custom.hope.models import HOPECase, CC_BIHAR_NEWBORN, CC_BIHAR_PREGNANCY
from no_exceptions.exceptions import Http400
import six

# By the time a test case is running, the resource is already instantiated,
# so as a hack until this can be remedied, there is a global that
# can be set to provide a mock.
MOCK_XFORM_ES = None
MOCK_CASE_ES = None

xform_doc_types = doc_types()


class XFormInstanceResource(SimpleSortableResourceMixin, HqBaseResource,
                            DomainSpecificResourceMixin):
    """This version of the form resource is built of Elasticsearch data
    which gets wrapped by ``ESXFormInstance``.
    No type conversion is done e.g. dates and some fields are named differently than in the
    Python models.
    """

    id = fields.CharField(attribute='_id', readonly=True, unique=True)

    domain = fields.CharField(attribute='domain')
    form = fields.DictField(attribute='form_data')
    type = fields.CharField(attribute='type')
Example #24
0
 def should_handle_as_duplicate_or_edit(cls, xform_id, domain):
     existing_doc = XFormInstance.get_db().get(xform_id)
     return existing_doc.get('domain') == domain and existing_doc.get('doc_type') in doc_types()
Example #25
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')

    assert doc.get('domain') == domain or domain in doc.get('domains', ())

    if cache and doc_id in cache:
        return cache[doc_id]

    if doc_type in ('Application', 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display=u'%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'corehq.apps.app_manager.views.download_index',
                    args=[domain, doc_id],
                ),
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'corehq.apps.app_manager.views.view_app',
                    args=[domain, doc_id],
                ),
            )
    elif doc_type in ('CommCareCase',):
        doc_info = DocInfo(
            display=doc['name'],
            type_display=_('Case'),
            link=reverse(
                'case_details',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in (couchforms_models.doc_types().keys()):
        doc_info = DocInfo(
            type_display=_('Form'),
            link=reverse(
                'render_form_data',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=reverse(
                'edit_commcare_user',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=reverse(
                'user_account',
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('Group',):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
        )
    elif doc_type in ('Domain',):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
        )
    elif doc_type == 'Location':
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=doc['location_type'],
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
        )
    else:
        doc_info = DocInfo()

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info
Example #26
0
 def get_with_attachments(form_id):
     doc = XFormInstance.get_db().get(form_id, attachments=True)
     return doc_types()[doc['doc_type']].wrap(doc)
Example #27
0
    def print_stats(self, domain, short=True, diffs_only=False):
        status = get_couch_sql_migration_status(domain)
        print("Couch to SQL migration status for {}: {}".format(
            domain, status))
        db = open_state_db(domain, self.state_dir)
        try:
            diff_stats = db.get_diff_stats()
        except OperationalError:
            diff_stats = {}

        has_diffs = False
        for doc_type in doc_types():
            form_ids_in_couch = set(get_form_ids_by_type(domain, doc_type))
            if doc_type == "XFormInstance":
                form_ids_in_couch.update(
                    get_doc_ids_in_domain_by_type(domain, "HQSubmission",
                                                  XFormInstance.get_db()))
            form_ids_in_sql = set(
                FormAccessorSQL.get_form_ids_in_domain_by_type(
                    domain, doc_type))
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            has_diffs |= self._print_status(doc_type, form_ids_in_couch,
                                            form_ids_in_sql, diff_count,
                                            num_docs_with_diffs, short,
                                            diffs_only)

        form_ids_in_couch = set(
            get_doc_ids_in_domain_by_type(domain, "XFormInstance-Deleted",
                                          XFormInstance.get_db()))
        form_ids_in_sql = set(
            FormAccessorSQL.get_deleted_form_ids_in_domain(domain))
        diff_count, num_docs_with_diffs = diff_stats.pop(
            "XFormInstance-Deleted", (0, 0))
        has_diffs |= self._print_status("XFormInstance-Deleted",
                                        form_ids_in_couch, form_ids_in_sql,
                                        diff_count, num_docs_with_diffs, short,
                                        diffs_only)

        ZERO = Counts(0, 0)
        if db.has_doc_counts():
            doc_counts = db.get_doc_counts()
            couch_missing_cases = doc_counts.get("CommCareCase-couch",
                                                 ZERO).missing
        else:
            doc_counts = None
            couch_missing_cases = 0
        for doc_type in CASE_DOC_TYPES:
            if doc_counts is not None:
                counts = doc_counts.get(doc_type, ZERO)
                case_ids_in_couch = db.get_missing_doc_ids(
                    doc_type) if counts.missing else set()
                case_ids_in_sql = counts
            elif doc_type == "CommCareCase":
                case_ids_in_couch = set(get_case_ids_in_domain(domain))
                case_ids_in_sql = set(
                    CaseAccessorSQL.get_case_ids_in_domain(domain))
            elif doc_type == "CommCareCase-Deleted":
                case_ids_in_couch = set(
                    get_doc_ids_in_domain_by_type(domain,
                                                  "CommCareCase-Deleted",
                                                  XFormInstance.get_db()))
                case_ids_in_sql = set(
                    CaseAccessorSQL.get_deleted_case_ids_in_domain(domain))
            else:
                raise NotImplementedError(doc_type)
            diff_count, num_docs_with_diffs = diff_stats.pop(doc_type, (0, 0))
            has_diffs |= self._print_status(
                doc_type,
                case_ids_in_couch,
                case_ids_in_sql,
                diff_count,
                num_docs_with_diffs,
                short,
                diffs_only,
            )
            if doc_type == "CommCareCase" and couch_missing_cases:
                has_diffs = True
                print(
                    shell_red("%s cases could not be loaded from Couch" %
                              couch_missing_cases))
                if not short:
                    for case_id in db.get_missing_doc_ids(
                            "CommCareCase-couch"):
                        print(case_id)

        if diff_stats:
            for key, counts in diff_stats.items():
                diff_count, num_docs_with_diffs = counts
                has_diffs |= self._print_status(key, set(), set(), diff_count,
                                                num_docs_with_diffs, short,
                                                diffs_only)

        if diffs_only and not has_diffs:
            print(
                shell_green("No differences found between old and new docs!"))
        return has_diffs
Example #28
0
def get_doc_info(doc, domain_hint=None, cache=None):
    """
    cache is just a dictionary that you can keep passing in to speed up info
    retrieval.
    """
    domain = doc.get('domain') or domain_hint
    doc_type = doc.get('doc_type')
    doc_id = doc.get('_id')
    generic_delete = doc_type.endswith(DELETED_SUFFIX)

    def has_doc_type(doc_type, expected_doc_type):
        return (doc_type == expected_doc_type or
            doc_type == ('%s%s' % (expected_doc_type, DELETED_SUFFIX)))

    if (
        domain_hint and
        not (
            doc.get('domain') == domain_hint or
            domain_hint in doc.get('domains', ())
        )
    ):
        raise DomainMismatchException("Doc '%s' does not match the domain_hint '%s'" % (doc_id, domain_hint))

    if cache and doc_id in cache:
        return cache[doc_id]

    if has_doc_type(doc_type, 'Application') or has_doc_type(doc_type, 'RemoteApp'):
        if doc.get('copy_of'):
            doc_info = DocInfo(
                display='%s (#%s)' % (doc['name'], doc['version']),
                type_display=_('Application Build'),
                link=reverse(
                    'download_index',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
        else:
            doc_info = DocInfo(
                display=doc['name'],
                type_display=_('Application'),
                link=reverse(
                    'view_app',
                    args=[domain, doc_id],
                ),
                is_deleted=generic_delete,
            )
    elif has_doc_type(doc_type, 'CommCareCaseGroup'):
        from corehq.apps.data_interfaces.views import CaseGroupCaseManagementView
        doc_info = DocInfo(
            type_display=_('Case Group'),
            display=doc['name'],
            link=reverse(
                CaseGroupCaseManagementView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'CommCareCase'):
        doc_info = case_docinfo(domain, doc_id, doc['name'], generic_delete)
    elif any([has_doc_type(doc_type, d) for d in couchforms_models.doc_types().keys()]):
        doc_info = form_docinfo(domain, doc_id, generic_delete)
    elif doc_type in ('CommCareUser',):
        doc_info = DocInfo(
            display=raw_username(doc['username']),
            type_display=_('Mobile Worker'),
            link=get_commcareuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif doc_type in ('WebUser',):
        doc_info = DocInfo(
            type_display=_('Web User'),
            display=doc['username'],
            link=get_webuser_url(domain, doc_id),
            is_deleted=doc.get('base_doc', '').endswith(DELETED_SUFFIX),
        )
    elif has_doc_type(doc_type, 'Group'):
        from corehq.apps.users.views.mobile import EditGroupMembersView
        doc_info = DocInfo(
            type_display=_('Group'),
            display=doc['name'],
            link=reverse(
                EditGroupMembersView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Domain'):
        if doc['is_snapshot'] and doc['published']:
            urlname = 'project_info'
        else:
            urlname = 'domain_basic_info'
        doc_info = DocInfo(
            type_display=_('Domain'),
            display=doc['name'],
            link=reverse(
                urlname,
                kwargs={'domain' : doc['name']}
            ),
            is_deleted=generic_delete,
        )
    elif has_doc_type(doc_type, 'Location'):
        from corehq.apps.locations.views import EditLocationView
        doc_info = DocInfo(
            type_display=_('Location'),
            display=doc['name'],
            link=reverse(
                EditLocationView.urlname,
                args=[domain, doc_id],
            ),
            is_deleted=generic_delete,
        )
    else:
        doc_info = DocInfo(
            is_deleted=generic_delete,
        )

    doc_info.id = doc_id
    doc_info.domain = domain
    doc_info.type = doc_type

    if cache:
        cache[doc_id] = doc_info

    return doc_info