def handle(self, *args, **options): domain = 'care-bihar' root_types = ('cc_bihar_pregnancy', 'cc_bihar_newborn') TASK_TYPE = 'task' # loop through all mother cases, then all child cases # for each case get all associated tasks # if any duplicates found, clean up / print them with open('bihar-duplicate-tasks.csv', 'wb') as f: writer = csv.writer(f, dialect=csv.excel) _dump_headings(writer) for case_type in root_types: for parent_case in get_cases_in_domain(domain, case_type): try: tasks = filter( lambda subcase: subcase.type == TASK_TYPE, parent_case.get_subcases()) if tasks: types = [_task_id(t) for t in tasks] unique_types = set(types) if len(unique_types) != len(tasks): for type_being_checked in unique_types: matching_cases = [ t for t in tasks if _task_id(t) == type_being_checked ] if len(matching_cases) > 1: for row, case in _get_rows( parent_case, matching_cases): keep = row[-1] writer.writerow(row) if options['cleanup'] and not keep: _purge(case) except Exception, e: print 'error with case %s (%s)' % (parent_case._id, e)
def handle(self, *args, **options): domain = 'care-bihar' root_types = ('cc_bihar_pregnancy', 'cc_bihar_newborn') TASK_TYPE = 'task' # loop through all mother cases, then all child cases # for each case get all associated tasks # if any duplicates found, clean up / print them with open('bihar-duplicate-tasks.csv', 'wb') as f: writer = csv.writer(f, dialect=csv.excel) _dump_headings(writer) for case_type in root_types: for parent_case in get_cases_in_domain(domain, case_type): try: tasks = filter(lambda subcase: subcase.type == TASK_TYPE, parent_case.get_subcases()) if tasks: types = [_task_id(t) for t in tasks] unique_types = set(types) if len(unique_types) != len(tasks): for type_being_checked in unique_types: matching_cases = [t for t in tasks if _task_id(t) == type_being_checked] if len(matching_cases) > 1: for row, case in _get_rows(parent_case, matching_cases): keep = row[-1] writer.writerow(row) if options['cleanup'] and not keep: _purge(case) except Exception, e: print 'error with case %s (%s)' % (parent_case._id, e)
def new_update_case_properties(): _domain = Domain.get_by_name(DOMAINS[0]) if _domain is None: return time_zone = _domain.default_timezone time_zone = pytz.timezone(time_zone) past_21_date = past_x_date(time_zone, 21) past_42_date = past_x_date(time_zone, 42) for domain in DOMAINS: update_groups_index(domain) case_list = get_cases_in_domain(domain, type=TYPE) cases_to_modify = [] for case in case_list: if case.closed: continue if not get_none_or_value( case, "owner_id") or not get_none_or_value( case, "date_admission") or not get_none_or_value( case, "facility_id"): continue curr_assignment = get_none_or_value(case, "current_assignment") next_assignment = get_none_or_value(case, "next_assignment") facility_id = get_none_or_value(case, "facility_id") fida_group = get_group_id(domain, "fida", facility_id) cati_owner_username = get_owner_username(domain, "cati", facility_id) ## Assignment Directly from Registration ## # Assign Cases to Call Center if case.date_admission >= past_21_date and ( not curr_assignment) and (not next_assignment): owner_id = get_group_id(domain, "cati", facility_id) if not owner_id: continue update = {"owner_id": owner_id, "current_assignment": "cati"} cases_to_modify.append({ "case_id": case._id, "update": update, "close": False, }) # Assign Cases Directly To Field elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and ( not curr_assignment) and (not next_assignment): if not fida_group: continue update = { "current_assignment": "fida", "owner_id": fida_group, "cati_status": 'skipped', } cases_to_modify.append({ "case_id": case._id, "update": update, "close": False, })
def indexed_facilities(): facility_index = {} for domain in DOMAINS: current_domain_index = {} facilities = get_cases_in_domain(domain, type="facility") for facility in facilities: current_domain_index[facility.facility_id] = { "cati": facility.cati_user, "fida": facility.fida_user } facility_index[domain] = current_domain_index return facility_index
def test_simple(self): caseblock = CaseBlock( create=True, case_id=uuid.uuid4().hex, user_id=self.user_id, owner_id=self.user_id, case_type='exploder-type', version=V2 ).as_string() submit_case_blocks([caseblock], self.domain.name) self.assertEqual(1, len(get_case_ids_in_domain(self.domain.name))) explode_cases(self.user_id, self.domain.name, 10) cases_back = list(get_cases_in_domain(self.domain.name)) self.assertEqual(10, len(cases_back)) for case in cases_back: self.assertEqual(self.user_id, case.owner_id)
def indexed_facilities(): facility_index = {} for domain in DOMAINS: current_domain_index = {} facilities = get_cases_in_domain(domain, type="facility") for facility in facilities: case_sharing_group = GROUPS_BY_ID[domain].get(facility.owner_id, None) if case_sharing_group is None: continue cati_user = case_sharing_group.metadata.get('cati_user', None) fida_user = case_sharing_group.metadata.get('fida_user', None) current_domain_index[facility.facility_id] = { "cati": cati_user, "fida": fida_user } facility_index[domain] = current_domain_index return facility_index
def indexed_facilities(): facility_index = {} for domain in DOMAINS: current_domain_index = {} facilities = get_cases_in_domain(domain, type="facility") for facility in facilities: case_sharing_group = GROUPS_BY_ID[domain].get( facility.owner_id, None) if case_sharing_group is None: continue cati_user = case_sharing_group.metadata.get('cati_user', None) fida_user = case_sharing_group.metadata.get('fida_user', None) current_domain_index[facility.facility_id] = { "cati": cati_user, "fida": fida_user } facility_index[domain] = current_domain_index return facility_index
def testImportBasic(self): config = self._config(self.default_headers) file = MockExcelFile(header_columns=self.default_headers, num_rows=5) res = do_import(file, config, self.domain) self.assertEqual(5, res['created_count']) self.assertEqual(0, res['match_count']) self.assertFalse(res['errors']) self.assertEqual(1, res['num_chunks']) cases = list(get_cases_in_domain(self.domain)) self.assertEqual(5, len(cases)) properties_seen = set() for case in cases: self.assertEqual(self.couch_user._id, case.user_id) self.assertEqual(self.couch_user._id, case.owner_id) self.assertEqual(self.default_case_type, case.type) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop)) self.assertFalse(case.get_case_property(prop) in properties_seen) properties_seen.add(case.get_case_property(prop))
def test_create_and_fulfill_requisition(self): amounts = [(p._id, 50.0 + float(i*10)) for i, p in enumerate(self.products)] self.submit_xml_form(create_requisition_xml(amounts)) req_cases = list(get_cases_in_domain(self.domain.name, type=const.REQUISITION_CASE_TYPE)) self.assertEqual(1, len(req_cases)) req = req_cases[0] [index] = req.indices self.assertEqual(const.SUPPLY_POINT_CASE_TYPE, index.referenced_type) self.assertEqual(self.sp._id, index.referenced_id) self.assertEqual('parent_id', index.identifier) for product, amt in amounts: self.check_stock_models(req, product, amt, 0, 'stock') self.submit_xml_form(create_fulfillment_xml(req, amounts)) for product, amt in amounts: self.check_stock_models(req, product, 0, -amt, 'stock') for product, amt in amounts: self.check_product_stock(self.sp, product, amt, amt, 'stock')
def testImportBasic(self): config = self._config(self.default_headers) file = MockExcelFile(header_columns=self.default_headers, num_rows=5) res = do_import(file, config, self.domain) self.assertEqual(5, res['created_count']) self.assertEqual(0, res['match_count']) self.assertEqual(0, res['errors']) self.assertEqual(1, res['num_chunks']) cases = list(get_cases_in_domain(self.domain)) self.assertEqual(5, len(cases)) properties_seen = set() for case in cases: self.assertEqual(self.couch_user._id, case.user_id) self.assertEqual(self.couch_user._id, case.owner_id) self.assertEqual(self.default_case_type, case.type) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop)) self.assertFalse( case.get_case_property(prop) in properties_seen) properties_seen.add(case.get_case_property(prop))
def testExternalIdChunking(self): # bootstrap a stub case external_id = 'importer-test-external-id' headers = ['external_id', 'age', 'sex', 'location'] config = self._config(headers, search_field='external_id') file = MockExcelFile(header_columns=headers, num_rows=3, row_generator=id_match_generator(external_id)) # the first one should create the case, and the remaining two should update it res = do_import(file, config, self.domain) self.assertEqual(1, res['created_count']) self.assertEqual(2, res['match_count']) self.assertFalse(res['errors']) self.assertEqual(2, res['num_chunks']) # the lookup causes an extra chunk # should just create the one case self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) [case] = get_cases_in_domain(self.domain) self.assertEqual(external_id, case.external_id) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop))
def testCaseIdMatching(self): # bootstrap a stub case case = CommCareCase(domain=self.domain, type=self.default_case_type) case.importer_test_prop = 'foo' case.save() self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) config = self._config(self.default_headers) file = MockExcelFile(header_columns=self.default_headers, num_rows=3, row_generator=id_match_generator(case._id)) res = do_import(file, config, self.domain) self.assertEqual(0, res['created_count']) self.assertEqual(3, res['match_count']) self.assertFalse(res['errors']) # shouldn't create any more cases, just the one self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) [case] = get_cases_in_domain(self.domain) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop)) # shouldn't touch existing properties self.assertEqual('foo', case.importer_test_prop)
def test_parent_child(self): parent_id = uuid.uuid4().hex parent_type = 'exploder-parent-type' parent_block = CaseBlock( create=True, case_id=parent_id, user_id=self.user_id, owner_id=self.user_id, case_type=parent_type, version=V2 ).as_string() child_id = uuid.uuid4().hex child_block = CaseBlock( create=True, case_id=child_id, user_id=self.user_id, owner_id=self.user_id, case_type='exploder-child-type', index={'parent': (parent_type, parent_id)}, version=V2 ).as_string() submit_case_blocks([parent_block, child_block], self.domain.name) self.assertEqual(2, len(get_case_ids_in_domain(self.domain.name))) explode_cases(self.user_id, self.domain.name, 5) cases_back = list(get_cases_in_domain(self.domain.name)) self.assertEqual(10, len(cases_back)) parent_cases = {p._id: p for p in filter(lambda case: case.type == parent_type, cases_back)} self.assertEqual(5, len(parent_cases)) child_cases = filter(lambda case: case.type == 'exploder-child-type', cases_back) self.assertEqual(5, len(child_cases)) child_indices = [child.indices[0].referenced_id for child in child_cases] # make sure they're different self.assertEqual(len(child_cases), len(set(child_indices))) for child in child_cases: self.assertEqual(1, len(child.indices)) self.assertTrue(child.indices[0].referenced_id in parent_cases)
def handle(self, *args, **options): domain = 'care-bihar' # forward all cases that were last modified between these dates def should_forward_case(case): min_date = datetime(2013, 9, 10) max_date = datetime(2013, 11, 7) return (case.server_modified_on and min_date < case.server_modified_on < max_date) prod_repeater = CaseRepeater.get('a478a5a3d8964338cb3124de77e3ec58') success_count = 0 fail_count = 0 for case in get_cases_in_domain(domain): try: if should_forward_case(case): prod_repeater.register(case) success_count += 1 except Exception: fail_count += 1 logging.exception('problem creating repeater stub for case %s' % case._id) print 'successfully forwarded %s cases. %s were not processed' % (success_count, fail_count)
def testExternalIdChunking(self): # bootstrap a stub case external_id = 'importer-test-external-id' headers = ['external_id', 'age', 'sex', 'location'] config = self._config(headers, search_field='external_id') file = MockExcelFile(header_columns=headers, num_rows=3, row_generator=id_match_generator(external_id)) # the first one should create the case, and the remaining two should update it res = do_import(file, config, self.domain) self.assertEqual(1, res['created_count']) self.assertEqual(2, res['match_count']) self.assertEqual(0, res['errors']) self.assertEqual(2, res['num_chunks']) # the lookup causes an extra chunk # should just create the one case self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) [case] = get_cases_in_domain(self.domain) self.assertEqual(external_id, case.external_id) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop))
def test_create_fulfill_and_receive_requisition(self): amounts = [(p._id, 50.0 + float(i*10)) for i, p in enumerate(self.products)] # ---------------- # Create a request # ---------------- self.submit_xml_form(create_requisition_xml(amounts)) req_cases = list(get_cases_in_domain(self.domain.name, type=const.REQUISITION_CASE_TYPE)) self.assertEqual(1, len(req_cases)) req = RequisitionCase.get(req_cases[0]._id) [index] = req.indices self.assertEqual(req.requisition_status, 'requested') self.assertEqual(const.SUPPLY_POINT_CASE_TYPE, index.referenced_type) self.assertEqual(self.sp._id, index.referenced_id) self.assertEqual('parent_id', index.identifier) # TODO: these types of tests probably belong elsewhere self.assertEqual(req.get_next_action().keyword, 'fulfill') self.assertEqual(req.get_location()._id, self.sp.location._id) self.assertEqual(len(RequisitionCase.open_for_location( self.domain.name, self.sp.location._id )), 1) self.assertEqual( get_notification_message( req.get_next_action(), [req] ), self.expected_notification_message(req, amounts) ) for product, amt in amounts: self.check_stock_models(req, product, amt, 0, 'ct-requested') # ---------------- # Mark it fulfilled # ----------------- self.submit_xml_form(create_fulfillment_xml(req, amounts)) req = RequisitionCase.get(req._id) self.assertEqual(req.requisition_status, 'fulfilled') self.assertEqual(req.get_next_action().keyword, 'rec') self.assertEqual( get_notification_message( req.get_next_action(), [req] ), self.expected_notification_message(req, amounts) ) for product, amt in amounts: # we are expecting two separate blocks to have come with the same # values self.check_stock_models(req, product, amt, amt, 'stock') self.check_stock_models(req, product, amt, 0, 'ct-fulfilled') # ---------------- # Mark it received # ---------------- self.submit_xml_form(create_received_xml(req, amounts)) req = RequisitionCase.get(req._id) self.assertEqual(req.requisition_status, 'received') self.assertIsNone(req.get_next_action()) self.assertEqual(len(RequisitionCase.open_for_location( self.domain.name, self.sp.location._id )), 0) for product, amt in amounts: self.check_stock_models(req, product, 0, -amt, 'stock') self.check_stock_models(self.sp, product, amt, amt, 'stock')
def new_update_case_properties(): _domain = Domain.get_by_name(DOMAINS[0]) if _domain is None: return time_zone = _domain.default_timezone time_zone = pytz.timezone(time_zone) past_21_date = past_x_date(time_zone, 21) past_42_date = past_x_date(time_zone, 42) for domain in DOMAINS: update_groups_index(domain) case_list = get_cases_in_domain(domain, type=TYPE) cases_to_modify = [] for case in case_list: if case.closed: continue if not get_none_or_value(case, "owner_id") or not get_none_or_value(case, "date_admission") or not get_none_or_value(case, "site_id"): continue curr_assignment = get_none_or_value(case, "current_assignment") next_assignment = get_none_or_value(case, "next_assignment") site_id = case.site_id fida_group = get_group_id(domain, "fida", site_id) cati_owner_username = get_owner_username(domain, "cati", site_id) ## Assignment Directly from Registration ## # Assign Cases to Call Center if case.date_admission >= past_21_date and (not curr_assignment) and (not next_assignment): owner_id = get_group_id(domain, "cati", site_id) if not owner_id: continue update = { "owner_id": owner_id, "current_assignment": "cati" } cases_to_modify.append({ "case_id": case._id, "update": update, "close": False, }) # Assign Cases Directly To Field elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (not curr_assignment) and (not next_assignment): if not fida_group: continue update = { "current_assignment": "fida", "owner_id": fida_group, "cati_status": 'skipped', } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, } ) # Assign Cases Directly to Lost to Follow Up elif case.date_admission < past_42_date and (not curr_assignment) and (not next_assignment): update = { "cati_status": 'skipped', "last_assignment": '', "closed_status": "timed_out_lost_to_follow_up", } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) ## Assignment from Call Center ## # Assign Cases to Field (manually by call center) elif (case.date_admission >= past_42_date) and next_assignment == "fida": if not cati_owner_username or not fida_group: continue update = { "last_cati_user": cati_owner_username, "current_assignment": "fida", "next_assignment": '', "owner_id": fida_group, "cati_status": 'manually_assigned_to_field' } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, } ) # Assign cases to field (automatically) elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (curr_assignment == "cati" or curr_assignment == "cati_tl"): if not cati_owner_username or not fida_group: continue update = { "last_cati_assignment": curr_assignment, "last_cati_user": cati_owner_username, "cati_status": 'timed_out', "current_assignment": "fida", "next_assignment": '', "owner_id": fida_group } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, } ) # Assign Cases to Lost to Follow Up elif case.date_admission < past_42_date and (curr_assignment == "cati" or curr_assignment == "cati_tl"): if not get_owner_username(domain, curr_assignment, site_id) or not cati_owner_username: continue update = { "last_cati_assignment": curr_assignment, "last_cati_user": cati_owner_username, "last_user": get_owner_username(domain, curr_assignment, site_id), "cati_status": 'timed_out', "last_assignment": curr_assignment, "current_assignment": '', "closed_status": "timed_out_lost_to_follow_up", "next_assignment": '' } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) ## Assignment from Field ## # Assign Cases to Lost to Follow Up elif case.date_admission < past_42_date and (curr_assignment == "fida" or curr_assignment == "fida_tl"): if not get_owner_username(domain, curr_assignment, site_id): continue update = { "last_user": get_owner_username(domain, curr_assignment, site_id), "last_assignment": curr_assignment, "current_assignment": '', "closed_status": "timed_out_lost_to_follow_up", "next_assignment": '', } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) case_blocks = [ElementTree.tostring(CaseBlock( create=False, case_id=case["case_id"], update=case["update"], close=case["close"], version=V2, ).as_xml()) for case in cases_to_modify ] submit_case_blocks(case_blocks, domain)
def test_create_fulfill_and_receive_requisition(self): amounts = [(p._id, 50.0 + float(i * 10)) for i, p in enumerate(self.products)] # ---------------- # Create a request # ---------------- self.submit_xml_form(create_requisition_xml(amounts)) req_cases = list( get_cases_in_domain(self.domain.name, type=const.REQUISITION_CASE_TYPE)) self.assertEqual(1, len(req_cases)) req = RequisitionCase.get(req_cases[0]._id) [index] = req.indices self.assertEqual(req.requisition_status, 'requested') self.assertEqual(const.SUPPLY_POINT_CASE_TYPE, index.referenced_type) self.assertEqual(self.sp._id, index.referenced_id) self.assertEqual('parent_id', index.identifier) # TODO: these types of tests probably belong elsewhere self.assertEqual(req.get_next_action().keyword, 'fulfill') self.assertEqual(req.get_location()._id, self.sp.location._id) self.assertEqual( len( RequisitionCase.open_for_location(self.domain.name, self.sp.location._id)), 1) self.assertEqual( get_notification_message(req.get_next_action(), [req]), self.expected_notification_message(req, amounts)) for product, amt in amounts: self.check_stock_models(req, product, amt, 0, 'ct-requested') # ---------------- # Mark it fulfilled # ----------------- self.submit_xml_form(create_fulfillment_xml(req, amounts)) req = RequisitionCase.get(req._id) self.assertEqual(req.requisition_status, 'fulfilled') self.assertEqual(req.get_next_action().keyword, 'rec') self.assertEqual( get_notification_message(req.get_next_action(), [req]), self.expected_notification_message(req, amounts)) for product, amt in amounts: # we are expecting two separate blocks to have come with the same # values self.check_stock_models(req, product, amt, amt, 'stock') self.check_stock_models(req, product, amt, 0, 'ct-fulfilled') # ---------------- # Mark it received # ---------------- self.submit_xml_form(create_received_xml(req, amounts)) req = RequisitionCase.get(req._id) self.assertEqual(req.requisition_status, 'received') self.assertIsNone(req.get_next_action()) self.assertEqual( len( RequisitionCase.open_for_location(self.domain.name, self.sp.location._id)), 0) for product, amt in amounts: self.check_stock_models(req, product, 0, -amt, 'stock') self.check_stock_models(self.sp, product, amt, amt, 'stock')
def new_update_case_properties(): _domain = Domain.get_by_name(DOMAINS[0]) if _domain is None: return time_zone = _domain.default_timezone time_zone = pytz.timezone(time_zone) past_21_date = past_x_date(time_zone, 21) past_42_date = past_x_date(time_zone, 42) setup_indices() for domain in DOMAINS: case_list = list(get_cases_in_domain(domain, type=BIRTH_TYPE)) case_list = case_list + list(get_cases_in_domain(domain, type=CATI_FIDA_CHECK_TYPE)) cases_to_modify = [] for case in case_list: if case.closed: continue if not get_none_or_value(case, "owner_id") or not get_none_or_value(case, "date_admission") or not get_none_or_value(case, "facility_id"): continue curr_assignment = get_none_or_value(case, "current_assignment") next_assignment = get_none_or_value(case, "next_assignment") facility_id = get_none_or_value(case, "facility_id") fida_group = get_group_id(domain, "fida", facility_id) cati_owner_username = get_owner_username(domain, "cati", facility_id) ## Assignment Directly from Registration ## # Assign Cases to Call Center if case.date_admission >= past_21_date and (not curr_assignment) and (not next_assignment): owner_id = get_group_id(domain, "cati", facility_id) if not owner_id: continue owner_group = GROUPS_BY_ID[domain].get(owner_id, None) cati_name = owner_group.metadata.get('name', None) if owner_group else None update = { "current_assignment": "cati", "cati_name": cati_name } cases_to_modify.append({ "case_id": case._id, "update": update, "close": False, "owner_id": owner_id, }) # Assign Cases Directly To Field elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (not curr_assignment) and (not next_assignment): if not fida_group: continue update = { "current_assignment": "fida", "cati_status": 'skipped', } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, "owner_id": fida_group, } ) # Assign Cases Directly to Lost to Follow Up elif case.date_admission < past_42_date and (not curr_assignment) and (not next_assignment): update = { "cati_status": 'skipped', "last_assignment": '', "closed_status": "timed_out_lost_to_follow_up", } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) ## Assignment from Call Center ## # Assign Cases to Field (manually by call center) elif (case.date_admission >= past_42_date) and next_assignment == "fida": if not cati_owner_username or not fida_group: continue update = { "last_cati_user": cati_owner_username, "current_assignment": "fida", "next_assignment": '', "cati_status": 'manually_assigned_to_field' } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, "owner_id": fida_group, } ) # Assign cases to field (automatically) elif (case.date_admission >= past_42_date) and (case.date_admission < past_21_date) and (curr_assignment == "cati" or curr_assignment == "cati_tl"): if not cati_owner_username or not fida_group: continue update = { "last_cati_assignment": curr_assignment, "last_cati_user": cati_owner_username, "cati_status": 'timed_out', "current_assignment": "fida", "next_assignment": '', } cases_to_modify.append( { "case_id": case._id, "update": update, "close": False, "owner_id": fida_group, } ) # Assign Cases to Lost to Follow Up elif case.date_admission < past_42_date and (curr_assignment == "cati" or curr_assignment == "cati_tl"): if not get_owner_username(domain, curr_assignment, facility_id) or not cati_owner_username: continue update = { "last_cati_assignment": curr_assignment, "last_cati_user": cati_owner_username, "last_user": get_owner_username(domain, curr_assignment, facility_id), "cati_status": 'timed_out', "last_assignment": curr_assignment, "current_assignment": '', "closed_status": "timed_out_lost_to_follow_up", "next_assignment": '' } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) ## Assignment from Field ## # Assign Cases to Lost to Follow Up elif case.date_admission < past_42_date and (curr_assignment == "fida" or curr_assignment == "fida_tl"): if not get_owner_username(domain, curr_assignment, facility_id): continue update = { "last_user": get_owner_username(domain, curr_assignment, facility_id), "last_assignment": curr_assignment, "current_assignment": '', "closed_status": "timed_out_lost_to_follow_up", "next_assignment": '', } cases_to_modify.append( { "case_id": case._id, "update": update, "close": True, } ) case_blocks = [] for case in cases_to_modify: kwargs = { "create": False, "case_id": case["case_id"], "update": case["update"], "close": case["close"], "version": V2, } if case.get("owner_id", None): kwargs["owner_id"] = case["owner_id"] case_blocks.append(ElementTree.tostring(CaseBlock(**kwargs).as_xml())) submit_case_blocks(case_blocks, domain)
class ImporterTest(TestCase): def setUp(self): self.domain = create_domain("importer-test").name self.default_case_type = 'importer-test-casetype' self.default_headers = ['case_id', 'age', 'sex', 'location'] self.couch_user = WebUser.create(None, "test", "foobar") self.couch_user.add_domain_membership(self.domain, is_admin=True) self.couch_user.save() delete_all_cases() def tearDown(self): self.couch_user.delete() def _config(self, col_names=None, search_column=None, case_type=None, search_field='case_id', named_columns=False, create_new_cases=True): col_names = col_names or self.default_headers case_type = case_type or self.default_case_type search_column = search_column or col_names[0] return ImporterConfig( couch_user_id=self.couch_user._id, case_type=case_type, excel_fields=col_names, case_fields=[''] * len(col_names), custom_fields=col_names, type_fields=['plain'] * len(col_names), search_column=search_column, search_field=search_field, named_columns=named_columns, create_new_cases=create_new_cases, key_column='', value_column='', ) def testImportNone(self): res = do_import(None, self._config(), self.domain) self.assertEqual('EXPIRED', res['error']) self.assertEqual(0, len(get_case_ids_in_domain(self.domain))) def testImporterErrors(self): res = do_import(MockExcelFile(has_errors=True), self._config(), self.domain) self.assertEqual('HAS_ERRORS', res['error']) self.assertEqual(0, len(get_case_ids_in_domain(self.domain))) def testImportBasic(self): config = self._config(self.default_headers) file = MockExcelFile(header_columns=self.default_headers, num_rows=5) res = do_import(file, config, self.domain) self.assertEqual(5, res['created_count']) self.assertEqual(0, res['match_count']) self.assertEqual(0, res['errors']) self.assertEqual(1, res['num_chunks']) cases = list(get_cases_in_domain(self.domain)) self.assertEqual(5, len(cases)) properties_seen = set() for case in cases: self.assertEqual(self.couch_user._id, case.user_id) self.assertEqual(self.couch_user._id, case.owner_id) self.assertEqual(self.default_case_type, case.type) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop)) self.assertFalse( case.get_case_property(prop) in properties_seen) properties_seen.add(case.get_case_property(prop)) def testImportNamedColumns(self): config = self._config(self.default_headers, named_columns=True) file = MockExcelFile(header_columns=self.default_headers, num_rows=5) res = do_import(file, config, self.domain) # we create 1 less since we knock off the header column self.assertEqual(4, res['created_count']) self.assertEqual(4, len(get_case_ids_in_domain(self.domain))) def testCaseIdMatching(self): # bootstrap a stub case case = CommCareCase(domain=self.domain, type=self.default_case_type) case.importer_test_prop = 'foo' case.save() self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) config = self._config(self.default_headers) file = MockExcelFile(header_columns=self.default_headers, num_rows=3, row_generator=id_match_generator(case._id)) res = do_import(file, config, self.domain) self.assertEqual(0, res['created_count']) self.assertEqual(3, res['match_count']) self.assertEqual(0, res['errors']) # shouldn't create any more cases, just the one self.assertEqual(1, len(get_case_ids_in_domain(self.domain))) [case] = get_cases_in_domain(self.domain) for prop in self.default_headers[1:]: self.assertTrue(prop in case.get_case_property(prop)) # shouldn't touch existing properties self.assertEqual('foo', case.importer_test_prop)