def setUp(self): super(ShipmentPackageMapViewTest, self).setUp() self.package = PackageFactory(shipment=self.shipment, code=QR_CODE) form_data = PackageScanFormSubmission(json.loads(PACKAGE_DATA)) FormSubmission.from_ona_form_data(form_data) self.url = reverse('shipments_package_map', kwargs={'pk': self.package.pk})
def test_record_package_location_no_package(self, mock_logging): """No matching package with the supplied QR code is found""" PackageFactory(code='not-found') self.assertFalse(PackageScan.objects.all()) form_data = PackageScanFormSubmission(json.loads(PACKAGE_DATA)) FormSubmission.from_ona_form_data(form_data) self.assertFalse(PackageScan.objects.all()) self.assertTrue(mock_logging.exception.called)
def test_record_package_location_invalid_status(self, mock_logging): """Invalid current_location ingested""" PackageFactory(code=QR_CODE) self.assertFalse(PackageScan.objects.all()) data = json.loads(PACKAGE_DATA) data["current_location"] = "FOOBAR-Zero_Point" form_data = PackageScanFormSubmission(data) FormSubmission.from_ona_form_data(form_data) self.assertTrue(mock_logging.error.called)
def test_record_package_location_malformed_uuid(self, mock_logging): """Bad UUID""" PackageFactory(code=QR_CODE) self.assertFalse(PackageScan.objects.all()) data = json.loads(PACKAGE_DATA) data['_uuid'] = 'foobar' form_data = PackageScanFormSubmission(data) FormSubmission.from_ona_form_data(form_data) self.assertFalse(PackageScan.objects.all()) self.assertTrue(mock_logging.exception.called)
class ProductTestCase(unittest.TestCase): """Basic test for Product object.""" def setUp(self): self.form_submission = PackageScanFormSubmission(VOUCHER_JSON) def test_voucher_qr_codes(self): self.assertEqual(['test'], self.form_submission.get_qr_codes()) def test_package_qr_codes(self): self.form_submission = PackageScanFormSubmission(PACKAGE_JSON) self.assertEqual(set(['test']), self.form_submission.get_qr_codes()) def test_gps(self): self.assertEqual(VOUCHER_JSON['gps'], self.form_submission.gps) def test_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertFalse(hasattr(self.form_submission, 'gps')) def test_submission_time(self): self.assertEqual( VOUCHER_JSON['_submission_time'], self.form_submission._submission_time.strftime(SUBMITTED_AT_FORMAT)) def test_get_latitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[0]) self.assertEqual(value, self.form_submission.get_lat()) def test_get_latitude_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertIsNone(self.form_submission.get_lat()) def test_get_longitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[1]) self.assertEqual(value, self.form_submission.get_lng()) def test_get_altitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[2]) self.assertEqual(value, self.form_submission.get_altitude()) def test_get_accuracy(self): value = float(VOUCHER_JSON['gps'].split(' ')[3]) self.assertEqual(value, self.form_submission.get_accuracy()) def test_get_gps_data_out_of_range(self): self.assertIsNone(self.form_submission.get_gps_data(100))
class ProductTestCase(unittest.TestCase): """Basic test for Product object.""" def setUp(self): self.form_submission = PackageScanFormSubmission(VOUCHER_JSON) def test_voucher_qr_codes(self): self.assertEqual(['test'], self.form_submission.get_qr_codes()) def test_package_qr_codes(self): self.form_submission = PackageScanFormSubmission(PACKAGE_JSON) self.assertEqual(set(['test']), self.form_submission.get_qr_codes()) def test_gps(self): self.assertEqual(VOUCHER_JSON['gps'], self.form_submission.gps) def test_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertFalse(hasattr(self.form_submission, 'gps')) def test_submission_time(self): self.assertEqual( VOUCHER_JSON['_submission_time'], self.form_submission._submission_time.strftime( SUBMITTED_AT_FORMAT)) def test_get_latitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[0]) self.assertEqual(value, self.form_submission.get_lat()) def test_get_latitude_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertIsNone(self.form_submission.get_lat()) def test_get_longitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[1]) self.assertEqual(value, self.form_submission.get_lng()) def test_get_altitude(self): value = float(VOUCHER_JSON['gps'].split(' ')[2]) self.assertEqual(value, self.form_submission.get_altitude()) def test_get_accuracy(self): value = float(VOUCHER_JSON['gps'].split(' ')[3]) self.assertEqual(value, self.form_submission.get_accuracy()) def test_get_gps_data_out_of_range(self): self.assertIsNone(self.form_submission.get_gps_data(100))
def test_record_package_scan_no_gps(self): # A scan with no GPS data still updates the package status pkg = PackageFactory(code=QR_CODE, status=Shipment.STATUS_IN_PROGRESS) self.assertFalse(PackageScan.objects.all()) data = json.loads(PACKAGE_DATA) data.pop('gps') form_data = PackageScanFormSubmission(data) FormSubmission.from_ona_form_data(form_data) # Yes, we have a scan self.assertTrue(PackageScan.objects.all()) self.assertEqual(Shipment.STATUS_IN_TRANSIT, PackageDBView.objects.get(pk=pkg.pk).status)
def test_record_package_location_valid_status_in_transit( self, mock_logging): """Valid current_location ingested""" date_picked_up = now() PackageFactory(code=QR_CODE, date_picked_up=date_picked_up) self.assertFalse(PackageScan.objects.all()) data = json.loads(PACKAGE_DATA) form_data = PackageScanFormSubmission(data) FormSubmission.from_ona_form_data(form_data) self.assertFalse(mock_logging.error.called) scan = PackageScan.objects.all()[0] self.assertEqual(scan.package.status, Shipment.STATUS_IN_TRANSIT) self.assertEqual(scan.package.shipment.status, Shipment.STATUS_IN_TRANSIT) self.assertEqual(scan.package.date_picked_up, date_picked_up) self.assertEqual(scan.package.date_in_transit, form_data._submission_time) self.assertEqual(scan.package.date_received, None)
def test_record_package_location_valid_status_picked_up( self, mock_logging): """Valid current_location ingested""" PackageFactory(code=QR_CODE) self.assertFalse(PackageScan.objects.all()) data = json.loads(PACKAGE_DATA) data['current_location'] = "STATUS_PICKED_UP-something" form_data = PackageScanFormSubmission(data) FormSubmission.from_ona_form_data(form_data) self.assertFalse(mock_logging.error.called) scan = PackageScan.objects.all()[0] self.assertEqual(scan.package.status, Shipment.STATUS_PICKED_UP) self.assertEqual(scan.package.shipment.status, Shipment.STATUS_PICKED_UP) self.assertEqual(scan.package.date_picked_up, form_data._submission_time) self.assertEqual(scan.package.date_in_transit, None) self.assertEqual(scan.package.date_received, None)
def setUp(self): self.form_submission = PackageScanFormSubmission(SUBMISSION_JSON)
def test_no_gps(self): data = SUBMISSION_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertFalse(hasattr(self.form_submission, 'gps'))
def record_package_location(sender, instance, **kwargs): # Only record package locations for package tracking forms try: logger.debug("record_package_location...") form_id = int(settings.ONA_PACKAGE_FORM_ID) if kwargs.get('created', False) and int( instance.data['form_id']) == form_id: submission = PackageScanFormSubmission(instance.data) logger.debug("New formsubmission. %d QR codes", len(submission.get_qr_codes())) for code in submission.get_qr_codes(): logger.debug("QR code: %s" % code) try: pkg = Package.objects.get(code=code) except Package.DoesNotExist: logger.exception("Scanned Package with code %s not found" % code) else: scan_status_label = submission.get_current_packagescan_label( ) PackageScan.objects.create( package=pkg, longitude=submission.get_lng(), latitude=submission.get_lat(), altitude=submission.get_altitude(), accuracy=submission.get_accuracy(), when=submission._submission_time, status_label=scan_status_label) logger.debug("created location") # Update Package and Shipment Status based on selected current_location value # Values should look similar to the following samples, defined by the # Ona XLSFOrm: # STATUS_IN_TRANSIT-Zero_Point # STATUS_IN_TRANSIT-Partner_Warehouse # STATUS_IN_TRANSIT-Pre-Distribution_Point # STATUS_RECEIVED-Distribution Point # STATUS_RECEIVED-Post-Distribution Point # The prefix part (before the first -) is one of the predefined status # names that are attributes of the Shipment model. status = submission.current_location.split('-', 1)[0] logger.debug("status=%r" % status) if not hasattr(Shipment, status): # If no match is found, log the invalid package status as it is # indicative of the app and Ona being out of sync msg = "FormSubmission with form id of %s has invalid package status: %s" \ % (instance.form_id, status) logger.error(msg) continue status = getattr(Shipment, status, None) if status: update_fields = ['last_scan_status_label'] pkg.last_scan_status_label = scan_status_label if pkg.status != status: update_fields.append('status') pkg.status = status if status == Shipment.STATUS_RECEIVED and not pkg.date_received: update_fields.append('date_received') pkg.date_received = submission._submission_time elif status == Shipment.STATUS_PICKED_UP and not pkg.date_picked_up: update_fields.append('date_picked_up') pkg.date_picked_up = submission._submission_time elif status == Shipment.STATUS_IN_TRANSIT and not pkg.date_in_transit: update_fields.append('date_in_transit') pkg.date_in_transit = submission._submission_time pkg.save(update_fields=update_fields) pkg.shipment.status = status pkg.shipment.last_scan_status_label = scan_status_label pkg.shipment.save( update_fields=['status', 'last_scan_status_label']) logger.debug("set status to %s" % pkg.get_status_display()) else: logger.debug( "Ignoring this FormSubmission. kwargs[created]=%s, form_id=%s," " form_id=%s" % (kwargs.get( 'created', False), int(instance.data['form_id']), form_id)) except Exception: logger.exception("Something blew up in record_package_location")
def setUp(self): super(ShipmentDashboardViewTest, self).setUp() self.package = PackageFactory(shipment=self.shipment, code=QR_CODE) form_data = PackageScanFormSubmission(json.loads(PACKAGE_DATA)) FormSubmission.from_ona_form_data(form_data) self.url = reverse('shipments_dashboard')
def setUp(self): self.form_submission = PackageScanFormSubmission(VOUCHER_JSON)
def test_package_qr_codes(self): self.form_submission = PackageScanFormSubmission(PACKAGE_JSON) self.assertEqual(set(['test']), self.form_submission.get_qr_codes())
def record_package_location(sender, instance, **kwargs): # Only record package locations for package tracking forms try: logger.debug("record_package_location...") form_ids = [int(x) for x in settings.ONA_FORM_IDS] if kwargs.get('created', False) and int(instance.data['form_id']) in form_ids: submission = PackageScanFormSubmission(instance.data) logger.debug("New formsubmission. %d QR codes", len(submission.get_qr_codes())) for code in submission.get_qr_codes(): logger.debug("QR code: %s" % code) try: pkg = Package.objects.get(code=code) except Package.DoesNotExist: logger.exception("Scanned Package with code %s not found" % code) else: scan_status_label = submission.get_current_packagescan_label() PackageScan.objects.create( package=pkg, longitude=submission.get_lng(), latitude=submission.get_lat(), altitude=submission.get_altitude(), accuracy=submission.get_accuracy(), when=submission._submission_time, status_label=scan_status_label ) logger.debug("created location") # Update Package and Shipment Status based on selected current_location value # Values should look similar to the following samples, defined by the # Ona XLSFOrm: # STATUS_IN_TRANSIT-Zero_Point # STATUS_IN_TRANSIT-Partner_Warehouse # STATUS_IN_TRANSIT-Pre-Distribution_Point # STATUS_RECEIVED-Distribution Point # STATUS_RECEIVED-Post-Distribution Point # The prefix part (before the first -) is one of the predefined status # names that are attributes of the Shipment model. if submission.is_voucher(): status = Shipment.STATUS_RECEIVED else: status = submission.current_location.split('-', 1)[0] logger.debug("status=%r" % status) if not hasattr(Shipment, status): # If no match is found, log the invalid package status as it is # indicative of the app and Ona being out of sync msg = "FormSubmission with form id of %s has invalid package status: %s" \ % (instance.form_id, status) logger.error(msg) continue status = getattr(Shipment, status, None) if status: update_fields = ['last_scan_status_label'] pkg.last_scan_status_label = scan_status_label if pkg.status != status: update_fields.append('status') pkg.status = status if status == Shipment.STATUS_RECEIVED and not pkg.date_received: update_fields.append('date_received') pkg.date_received = submission._submission_time elif status == Shipment.STATUS_PICKED_UP and not pkg.date_picked_up: update_fields.append('date_picked_up') pkg.date_picked_up = submission._submission_time elif status == Shipment.STATUS_IN_TRANSIT and not pkg.date_in_transit: update_fields.append('date_in_transit') pkg.date_in_transit = submission._submission_time pkg.save(update_fields=update_fields) pkg.shipment.status = status pkg.shipment.last_scan_status_label = scan_status_label pkg.shipment.save(update_fields=['status', 'last_scan_status_label']) logger.debug("set status to %s" % pkg.get_status_display()) else: logger.debug("Ignoring this FormSubmission. kwargs[created]=%s, form_id=%s," " form_ids=%s" % (kwargs.get('created', False), int(instance.data['form_id']), form_ids)) except Exception: logger.exception("Something blew up in record_package_location")
def test_get_latitude_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertIsNone(self.form_submission.get_lat())
def process_new_package_scans(): """Updates the local database with new package tracking form submissions""" logger.debug("process_new_package_scans task starting...") try: form_id = int(settings.ONA_PACKAGE_FORM_ID) if form_id in bad_form_ids: return client = OnaApiClient() form_def = client.get_form_definition(form_id) if not form_def: # Logging an error should result in an email to the admins so they # know to fix this. logger.error("Bad ONA_PACKAGE_FORM_ID: %s" % form_id) # Let's not keep trying for the bad form ID. We'll have to change the # settings and restart to fix it. bad_form_ids.add(form_id) return # What's the last submission we got (if any) most_recent_submission = FormSubmission.objects.filter(form_id=form_id)\ .order_by('-submission_time').first() if most_recent_submission: # Don't re-fetch the last form since = most_recent_submission.submission_time logger.debug("Getting forms since %s" % since) else: logger.debug("No form submissions yet for %r" % form_id) since = None try: submissions = client.get_form_submissions(form_id, since=since) except Http404: logger.error( "Got 404 getting submissions for ONA_PACKAGE_FORM_ID = %s" % form_id) return except OnaApiClientException as e: if e.status_code != 404: raise logger.error( "Got 404 getting submissions for ONA_PACKAGE_FORM_ID = %s" % form_id) return logger.debug( "process_new_package_scans downloaded %d submitted forms" % len(submissions)) # add the form definition JSON to each submission for data in submissions: data.update({'form_id': form_id}) data.update({'form_definition': form_def}) # create a list of API repr objects and ensure they are sorted by submission date objects = [PackageScanFormSubmission(x) for x in submissions] objects.sort(key=lambda x: x._submission_time) logger.debug("There are %d objects to look at" % len(objects)) for submission in objects: existing = FormSubmission.objects.filter( uuid=submission._uuid).first() if not existing: logger.debug("Got new form, creating new record") try: FormSubmission.from_ona_form_data(submission) except Exception: logger.exception( "HEY got exception creating new FormSubmission") else: logger.debug("Form %s (%r, %s) already existed" % (submission._uuid, submission.form_id, existing.submission_time)) except ConnectionError: logger.exception("Error connecting to Ona server") except Exception: logger.exception("Something blew up in process_new_package_scans") logger.debug("process_new_package_scans task done")
def test_record_voucher_location(self): PackageFactory(code=QR_CODE) self.assertFalse(PackageScan.objects.all()) form_data = PackageScanFormSubmission(json.loads(VOUCHER_DATA)) FormSubmission.from_ona_form_data(form_data) self.assertTrue(PackageScan.objects.all())
def test_no_gps(self): data = VOUCHER_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertFalse(hasattr(self.form_submission, 'gps'))
def test_get_latitude_no_gps(self): data = SUBMISSION_JSON.copy() data.pop('gps') self.form_submission = PackageScanFormSubmission(data) self.assertIsNone(self.form_submission.get_lat())