Example #1
0
 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})
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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)
Example #5
0
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))
Example #6
0
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))
Example #7
0
 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)
Example #8
0
 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)
Example #9
0
 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)
Example #10
0
 def setUp(self):
     self.form_submission = PackageScanFormSubmission(SUBMISSION_JSON)
Example #11
0
 def test_no_gps(self):
     data = SUBMISSION_JSON.copy()
     data.pop('gps')
     self.form_submission = PackageScanFormSubmission(data)
     self.assertFalse(hasattr(self.form_submission, 'gps'))
Example #12
0
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")
Example #13
0
 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')
Example #14
0
 def setUp(self):
     self.form_submission = PackageScanFormSubmission(VOUCHER_JSON)
Example #15
0
 def test_package_qr_codes(self):
     self.form_submission = PackageScanFormSubmission(PACKAGE_JSON)
     self.assertEqual(set(['test']), self.form_submission.get_qr_codes())
Example #16
0
 def setUp(self):
     self.form_submission = PackageScanFormSubmission(VOUCHER_JSON)
Example #17
0
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")
Example #18
0
 def setUp(self):
     self.form_submission = PackageScanFormSubmission(SUBMISSION_JSON)
Example #19
0
 def test_package_qr_codes(self):
     self.form_submission = PackageScanFormSubmission(PACKAGE_JSON)
     self.assertEqual(set(['test']), self.form_submission.get_qr_codes())
Example #20
0
 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())
Example #21
0
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")
Example #22
0
 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())
Example #23
0
 def test_no_gps(self):
     data = VOUCHER_JSON.copy()
     data.pop('gps')
     self.form_submission = PackageScanFormSubmission(data)
     self.assertFalse(hasattr(self.form_submission, 'gps'))
Example #24
0
 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())