def send_notifications(xform, cases): # TODO: fix circular imports from corehq.apps.commtrack.requisitions import get_notification_recipients from corehq.apps.commtrack.requisitions import get_notification_message # for now the only notifications are for requisitions that were touched. # todo: if we wanted to include previously requested items we could do so # by either polling for other open requisitions here, or by ensuring that # they get touched by the commtrack case processing. requisitions = [RequisitionCase.wrap(case._doc) for case in cases if case.type == const.REQUISITION_CASE_TYPE] if requisitions: by_status = defaultdict(list) for r in requisitions: by_status[r.requisition_status].append(r) req_config = CommtrackConfig.for_domain(requisitions[0].domain).requisition_config # since each state transition might trigger a different person to be notified for s, reqs in by_status.items(): next_action = req_config.get_next_action(RequisitionStatus.to_action_type(s)) if next_action: # we could make this even more customizable by specifying it per requisition # but that would get even messier in terms of constructing the messages # so we'll just compose one message per status type now, and then send # it to everyone who should be notified. to_notify = filter( create_unique_filter(lambda u: u._id), itertools.chain(*(get_notification_recipients(next_action, r) for r in reqs)), ) msg = get_notification_message(next_action, reqs) for u in to_notify: phone = u.get_verified_number() if phone: send_sms_to_verified_number(phone, msg)
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 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')
for s, reqs in by_status.items(): next_action = req_config.get_next_action( RequisitionStatus.to_action_type(s)) if next_action: # we could make this even more customizable by specifying it per requisition # but that would get even messier in terms of constructing the messages # so we'll just compose one message per status type now, and then send # it to everyone who should be notified. to_notify = filter( create_unique_filter(lambda u: u._id), itertools.chain( *(get_notification_recipients(next_action, r) for r in reqs))) msg = get_notification_message(next_action, reqs) for u in to_notify: phone = u.get_verified_number() if phone: send_sms_to_verified_number(phone, msg) def raise_events(xform, cases): requisition_cases = [ RequisitionCase.wrap(c._doc) for c in cases if c.type == const.REQUISITION_CASE_TYPE ] if requisition_cases and requisition_cases[ 0].requisition_status == RequisitionStatus.APPROVED: requisition_approved.send(sender=None, requisitions=requisition_cases) if requisition_cases and requisition_cases[