def get_context_data(self, **kwargs):

        full_box_url = self.get_box_url_by_filters(product__isnull=False)
        empty_box_url = self.get_box_url_by_filters(product__isnull=True)

        new_box_url = self.get_box_scanned_url(BoxNumber.get_next_box_number())

        # schema http or https
        schema = 'http'
        if settings.DEBUG is False and hasattr(self.request, 'schema'):
            schema = self.request.schema

        protocol_and_host = "{}://{}".format(
            schema, self.request.META.get('HTTP_HOST', ''))

        full_box_url = protocol_and_host + full_box_url
        empty_box_url = protocol_and_host + empty_box_url
        new_box_url = protocol_and_host + new_box_url

        empty_box = Box.objects.filter(product__isnull=True).first()
        full_box = Box.objects.filter(product__isnull=False).first()

        return {
            'full_box_url': full_box_url,
            'empty_box_url': empty_box_url,
            'new_box_url': new_box_url,
            'empty_box': empty_box,
            'full_box': full_box,
            'next_box_number': BoxNumber.get_next_box_number(),
        }
 def test_get_form(self):
     box_number = BoxNumber.format_box_number(15)
     pallet_box = PalletBox(box_number=box_number, )
     form = BoxItemFormView.get_form(pallet_box)
     self.assertIsNotNone(form)
     self.assertIsNone(form.prefix)
     self.assertEqual(box_number, form.initial['box_number'])
    def test_post_box_number_form(self):
        client = self.setup_user_and_client('john', 'doe4')

        box_number = BoxNumber.get_next_box_number()

        response = client.post(
            self.url,
            {
                'mode': ManualMoveBoxView.MODE_ENTER_BOX_NUMBER,
                'box_number': box_number
            },
        )
        self.assertEqual(404, response.status_code)
        self.assertEqual(
            ManualMoveBoxView.MODE_ENTER_BOX_NUMBER,
            response.context['mode'],
        )
        self.assertIsInstance(
            response.context['box_number_form'],
            FilledBoxNumberForm,
        )

        box = Box.objects.create(
            box_number=box_number,
            box_type=BoxType.objects.get(box_type_code='Evans'),
            product=Product.objects.get(prod_name='Canned Potatoes'),
        )
    def test_post_from_location_form__form_valid(self):
        client = self.setup_user_and_client('Jerlene', 'Elder')

        mode = ManualPalletMoveView.MODE_ENTER_FROM_LOCATION

        location = Location.get_location('01', '01', 'B1')

        Box.objects.create(
            box_type=Box.box_type_default(),
            box_number=BoxNumber.format_box_number(42),
            location=location,
        )

        response = client.post(
            self.url,
            {
                'mode': mode,
                'from-loc_row': location.loc_row.pk,
                'from-loc_bin': location.loc_bin.pk,
                'from-loc_tier': location.loc_tier.pk,
            }
        )
        self.assertEqual(
            200,
            response.status_code,
            response.content.decode()
        )
        self.assertEqual(
            ManualPalletMoveView.MODE_ENTER_TO_LOCATION,
            response.context.get('mode'),
        )
        form = response.context.get('to_location_form')
        self.assertIsInstance(form, MoveToLocationForm)
    def post(self, request, *args, **kwargs):
        box_number = kwargs.get('box_number')
        if not box_number:
            return error_page(request, 'missing box_number')

        if not BoxNumber.validate(box_number):
            return error_page(
                request,
                "Invalid box_number '{}'".format(box_number),
            )

        new_box_form = NewBoxForm(
            request.POST,
            initial={'box_number': box_number},
        )

        if not new_box_form.is_valid():
            return render(
                request,
                self.template_name,
                {
                    'form': new_box_form,
                },
            )

        box = new_box_form.save()

        action = request.session.get('action')
        if action == Action.ACTION_BUILD_PALLET:
            return redirect(
                reverse('fpiweb:build_pallet_add_box', args=(box.pk, )))

        return redirect(reverse('fpiweb:box_details', args=(box.pk, )))
    def test_post_box_number_form(self):
        user = User.objects.create_user('jdoe4', '*****@*****.**', 'abc123')

        client = Client()
        client.force_login(user)

        box_number = BoxNumber.get_next_box_number()

        response = client.post(
            self.url,
            {
                'mode': ManualMoveBoxView.MODE_ENTER_BOX_NUMBER,
                'box_number': box_number
            },
        )
        self.assertEqual(404, response.status_code)
        self.assertEqual(
            ManualMoveBoxView.MODE_ENTER_BOX_NUMBER,
            response.context['mode'],
        )
        self.assertIsInstance(
            response.context['box_number_form'],
            FilledBoxNumberForm,
        )

        box = Box.objects.create(
            box_number=box_number,
            box_type=BoxType.objects.get(box_type_code='Evans'),
            product=Product.objects.get(prod_name='Canned Potatoes'),
        )
    def test_prepare_pallet_and_pallet_boxes__duplicate_box_numbers(self):

        pallet = Pallet.objects.create(
            name='duplicate_box_numbers'
        )

        location = Location.get_location('01', '02', 'B1')

        box_number = BoxNumber.get_next_box_number()

        product1, product2 = Product.objects.all()[:2]

        pallet_form = self.get_pallet_form(pallet)
        build_pallet_form = self.get_build_pallet_form(location)

        post_data = management_form_post_data(
            BuildPalletView.formset_prefix,
            2
        )

        post_data.update(
            formset_form_post_data(
                BuildPalletView.formset_prefix,
                0,
                self.get_box_item_form_data(
                    box_number,
                    product1,
                )
            )
        )

        post_data.update(
            formset_form_post_data(
                BuildPalletView.formset_prefix,
                1,
                self.get_box_item_form_data(
                    box_number,
                    product2,
                )
            )
        )

        box_forms = BuildPalletView.BoxFormFactory(
            post_data,
            prefix=BuildPalletView.formset_prefix
        )

        self.assertTrue(pallet_form.is_valid())
        self.assertTrue(build_pallet_form.is_valid())
        self.assertTrue(box_forms.is_valid())

        view = BuildPalletView()
        pattern = f"Duplicate box numbers: {box_number}"
        with self.assertRaisesRegex(BuildPalletError, pattern):
            view.prepare_pallet_and_pallet_boxes(
                pallet_form,
                build_pallet_form,
                box_forms,
            )
示例#8
0
    def clean(self, value):
        value = super().clean(value)

        if BoxNumber.validate(value):
            return value.upper()

        # Did the user just enter digit?  Try and turn this
        # into a valid box number
        try:
            value = int(value)
        except (TypeError, ValueError):
            raise ValidationError(
                '%(value)s is not a valid box number',
                params={'value': value},
            )

        return BoxNumber.format_box_number(value)
    def test_get_success_url(self):

        # create user for this test (It will only exist briefly in the test
        # database).
        # create an associated profile - just for the test
        user = User.objects.create_user('awesterville',
                                        '*****@*****.**',
                                        'abc123')
        profile = Profile.objects.create(
            title='Test User',
            user=user,
        )

        # Client sends HTTP requests and receives HTTP responses like a user's
        # browser.  It doesn't run any JavaScript, for that you need to use
        # Selenium to control a real browser.
        client = Client()

        # The first time I ran this test, I found that response.url was the
        # login page.  Ooops, forgot to log in.  Call the force_login method
        # to make Django act like we've gone through the login page
        client.force_login(user)

        box_number = BoxNumber.format_box_number(1)
        url = reverse('fpiweb:box_new', args=(box_number, ))

        box_type = BoxType.objects.get(box_type_code='Evans')

        post_data = {
            'box_number': box_number,
            'box_type': box_type.pk,
        }

        response = client.post(url, post_data)

        # Check whether the HTTP status code is 200, if it's not display the
        # text of the page returned.  Sometimes this makes looking for what
        # happened like looking for a needle in a haystack.

        # Unit-testing frameworks like unittest or pytest may discard text
        # sent to the terminal (stdout) unless a test fails.
        # print(dir(response))

        # Here's a handy page to bookmark:
        #     https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
        #
        # Status code 418 is my favorite!
        self.assertEqual(302, response.status_code, str(response.content))

        box = Box.objects.order_by('-pk').first()
        self.assertEqual(reverse('fpiweb:box_details', args=(box.pk, )),
                         response.url)

        box = Box.objects.get(box_number=box_number)

        self.assertEqual(box_type, box.box_type)
        self.assertEqual(box_type.box_type_qty, box.quantity)
示例#10
0
    def get_context_data(self, **kwargs):

        full_box_url = self.get_box_url_by_filters(product__isnull=False)
        empty_box_url = self.get_box_url_by_filters(product__isnull=True)

        new_box_url = self.get_box_scanned_url(BoxNumber.get_next_box_number())

        empty_box = Box.objects.filter(product__isnull=True).first()
        full_box = Box.objects.filter(product__isnull=False).first()

        return {
            'full_box_url': full_box_url,
            'empty_box_url': empty_box_url,
            'new_box_url': new_box_url,
            'empty_box': empty_box,
            'full_box': full_box,
            'next_box_number': BoxNumber.get_next_box_number()
        }
    def box_new(self, box_number: str, box_type: Union[str, int,
                                                       BoxType]) -> Box:
        """
        Add a new empty box to the inventory system.  If successful it
        adds an activity record for an empty box and returns the box record
        just created.

        Requirements:

        *   Box number is valid, unique, and not previously assigned

        *   Box type is valid

        Exceptions:

            101 - Box number supplied is not in the valid format ('BOXnnnn')

            102 - Box number is not unique

            102 - Box type is not valid

        :param box_number: in the form of 'BOXnnnnn'
        :param box_type: a valid box type code, BoxType record or record id
        :return: the newly created box record
        """

        # box number validation
        if not BoxNumber.validate(box_number):
            raise InvalidValueError(f'101 - Box number of "{box_number}" is '
                                    f'improperly formatted or missing')

        box_exists_qs = Box.objects.filter(box_number=box_number)
        if len(box_exists_qs) > 0:
            raise InvalidActionAttemptedError(
                f'102 - Creating a new box {box_number} failed because it'
                f'already exists')

        # box type validation - either code, id or record
        if type(box_type) == BoxType:
            self.box_type = box_type
        elif type(box_type) == int:
            try:
                self.box_type = BoxType.objects.get(pk=box_type)
            except BoxType.DoesNotExist:
                raise InvalidValueError(
                    f'102 - Box type id of "{box_type}" is invalid')
        else:
            try:
                self.box_type = BoxType.objects.get(box_type_code=box_type)
            except BoxType.DoesNotExist:
                raise InvalidValueError(
                    f'102 - Box type code of "{box_type}" is invalid')
        self._new_box(box_number, self.box_type)
        return self.box
 def build_boxes(number_of_boxes):
     boxes = []
     default_box_type = Box.box_type_default()
     for i in range(number_of_boxes):
         box_number = BoxNumber.get_next_box_number()
         box = Box.objects.create(
             box_number=box_number,
             box_type=default_box_type,
         )
         boxes.append(box)
     return boxes
示例#13
0
    def clean(self, value: str) -> str:
        value = super().clean(value)
        formal_box_number = 'BOX0000'
        raise_error = False
        if BoxNumber.validate(value):
            formal_box_number = value.upper()
        elif value.isdigit():
            # Did the user just enter digit?  Try and turn this
            # into a valid box number
            formal_box_number = BoxNumber.format_box_number(int(value))
            if not BoxNumber.validate(formal_box_number):
                raise_error = True
        else:
            raise_error = True
        if raise_error:
            raise ValidationError(
                '%(value)s is not a valid box number',
                params={'value': value},
            )

        return formal_box_number
示例#14
0
    def get(self, request, **kwargs):
        box_number = kwargs.get('number')
        if box_number is None:
            return error_page(request, "missing kwargs['number']")
        box_number = BoxNumber.format_box_number(box_number)

        try:
            box = Box.objects.get(box_number=box_number)
        except Box.DoesNotExist:
            return redirect('fpiweb:box_new', box_number=box_number)

        if not box.product:
            return redirect('fpiweb:box_edit', pk=box.pk)

        return redirect('fpiweb:box_empty_move', pk=box.pk)
    def get(self, request, *args, **kwargs):
        box_number = kwargs.get('box_number')
        if not box_number:
            return error_page(request, 'missing box_number')

        if not BoxNumber.validate(box_number):
            return error_page(
                request,
                "Invalid box_number '{}'".format(box_number),
            )

        new_box_form = NewBoxForm(initial={'box_number': box_number})
        return render(request, self.template_name, {
            'form': new_box_form,
        })
    def test_expire_months(self):
        """ensure that start month <= end month"""
        post_data = {
            'box_number': BoxNumber.format_box_number(12),
            'product': Product.objects.first().pk,
            'exp_year': 2022,
            'exp_month_start': 5,
            'exp_month_end': 3,
        }

        form = BoxItemForm(post_data)
        self.assertFalse(form.is_valid())
        self.assertIn(
            'Exp month end must be later than or equal to Exp month start',
            form.non_field_errors()
        )
    def get(self, request, **kwargs):
        box_number = kwargs.get('number')
        if box_number is None:
            return error_page(request, "missing kwargs['number']")
        box_number = BoxNumber.format_box_number(box_number)

        action = request.session.get('action')

        if action != Action.ACTION_BUILD_PALLET:
            return error_page(request,
                              "What to do when action is {}?".format(action))

        try:
            box = Box.objects.get(box_number=box_number)
        except Box.DoesNotExist:
            return redirect('fpiweb:box_new', box_number=box_number)

        return redirect('fpiweb:build_pallet_add_box', args=(box.pk, ))
    def test_post_location_form(self):
        user = User.objects.create_user('jdoe5', '*****@*****.**', 'abc123')

        client = Client()
        client.force_login(user)

        box = Box.objects.create(
            box_number=BoxNumber.get_next_box_number(),
            box_type=BoxType.objects.get(box_type_code='Evans'),
            product=Product.objects.get(prod_name='Canned Potatoes'),
            date_filled=timezone.now(),
            exp_year=2022,
            quantity=0,
        )
        self.assertIsNone(box.location)

        location = Location.objects.first()

        response = client.post(
            self.url, {
                'mode': ManualMoveBoxView.MODE_ENTER_LOCATION,
                'loc_row': location.loc_row_id,
                'loc_bin': location.loc_bin_id,
                'loc_tier': location.loc_tier_id,
                'box_pk': box.pk,
            })

        self.assertEqual(200, response.status_code, response.content)

        context_box = response.context.get('box')
        self.assertIsNotNone(context_box)
        self.assertEqual(
            box.pk,
            context_box.pk,
        )
        self.assertEqual(
            location.pk,
            context_box.location.pk,
        )
示例#19
0
    def test_clean(self):

        # ----------------------------------------------------------------
        # super class's clean detects error (i.e. location doesn't exist)
        # ----------------------------------------------------------------
        loc_row = '03'
        loc_bin = '03'
        loc_tier = 'A1'

        location = Location.get_location(loc_row, loc_bin, loc_tier)
        location.delete()

        form = ExistingLocationWithBoxesForm({
            'loc_row': location.loc_row,
            'loc_bin': location.loc_bin,
            'loc_tier': location.loc_tier
        })

        self.assertFalse(form.is_valid())
        self.assertEqual(
            {'__all__': ['Location 03, 03, A1 does not exist.']},
            form.errors,
        )
        self.assertEqual(
            ['Location 03, 03, A1 does not exist.'],
            form.non_field_errors(),
        )

        # ---------------------------
        # Try a location w/out boxes
        # ---------------------------

        location = Location.objects.annotate(
            box_count=Count('box')
        ).filter(
            box_count=0
        ).first()

        form = ExistingLocationWithBoxesForm({
            'loc_row': location.loc_row,
            'loc_bin': location.loc_bin,
            'loc_tier': location.loc_tier,
        })

        self.assertFalse(form.is_valid())
        expected_error = "Location {}, {}, {} doesn't have any boxes".format(
            location.loc_row.loc_row,
            location.loc_bin.loc_bin,
            location.loc_tier.loc_tier,
        )
        self.assertEqual(
            {'__all__': [expected_error]},
            form.errors,
        )
        self.assertEqual(
            [expected_error],
            form.non_field_errors(),
        )

        # ---------------------------------------------
        # Add a box to the location form will validate
        # ---------------------------------------------

        Box.objects.create(
            box_type=Box.box_type_default(),
            box_number=BoxNumber.format_box_number(111),
            location=location,
        )

        form = ExistingLocationWithBoxesForm({
            'loc_row': location.loc_row,
            'loc_bin': location.loc_bin,
            'loc_tier': location.loc_tier,
        })

        self.assertTrue(form.is_valid())
        self.assertEqual(
            location,
            form.cleaned_data['location'],
        )
示例#20
0
def box_number_validator(value) -> None:
    if BoxNumber.validate(value):
        return
    raise ValidationError(f"{value} is not a valid Box Number")
    def test_pallet_finish(self) -> None:
        """
        Test loading and finishing off a pallet.

        Build a new pallet, add some boxes to it, stash the pallet id,
        the pallet box ids, and the box ids associated with them.  Then
        finish the pallet and make sure the pallet and all its pallet boxes
        have been deleted, while the boxes themselves have been preserved.
        Since we are going through the new and fill logic above, we are
        going to assume the activity records have been properly created.

        :return:
        """
        # set some arbitrary values
        pallet_name = 'Hopefully this never matches !@#$%^&*()_+'
        location_code = '0409C2'
        box_type_code = 'Evans'
        starting_box_number = 98765
        number_of_boxes = 40
        ending_box_number = starting_box_number + number_of_boxes
        product_choices = 'Corn', 'Green Beans'
        exp_year_choices = (now().year + 1), (now().year + 2)

        # get corresponding records
        box_type_rec = BoxType.objects.get(box_type_code=box_type_code)
        product1 = Product.objects.get(prod_name=product_choices[0])
        product2 = Product.objects.get(prod_name=product_choices[1])
        product_rec_choices = product1, product2

        bm = BoxManagementClass()

        # build the pallet
        location_rec = Location.objects.get(loc_code=location_code)
        pallet_rec = Pallet.objects.create(
            name=pallet_name,
            location=location_rec,
            pallet_status=Pallet.FILL,
        )
        pallet_rec_id = pallet_rec.id

        # build table of values for later comparison
        pallet_box_info = dict()
        for ndx, box_number in enumerate(
                range(starting_box_number, ending_box_number)):
            ind = ndx % 2
            box_name = BoxNumber.format_box_number(box_number)
            product = product_rec_choices[ind]
            exp_year = exp_year_choices[ind]
            box_rec = bm.box_new(box_number=box_name, box_type=box_type_rec)
            pallet_box_rec = PalletBox.objects.create(pallet=pallet_rec,
                                                      box_number=box_name,
                                                      box=box_rec,
                                                      product=product,
                                                      exp_year=exp_year,
                                                      box_status=PalletBox.NEW)
            pallet_box_info[box_number] = PalletBoxInfo(
                pallet_box_id=pallet_box_rec.id,
                box_id=box_rec.id,
                box_number=box_name,
                product=product,
                exp_year=exp_year)

        # finish (publish) the pallet
        bm.pallet_finish(pallet_rec)

        # validate that worked properly
        for entry in pallet_box_info:
            with raises(PalletBox.DoesNotExist):
                _ = PalletBox.objects.get(
                    pk=pallet_box_info[entry].pallet_box_id)
            box_rec = Box.objects.get(pk=pallet_box_info[entry].box_id)
            assert box_rec.box_number == pallet_box_info[entry].box_number
            assert box_rec.box_type == box_type_rec
            assert box_rec.location == location_rec
            assert box_rec.product == pallet_box_info[entry].product
            assert box_rec.exp_year == pallet_box_info[entry].exp_year
            assert box_rec.exp_month_start == 0
            assert box_rec.exp_month_end == 0
            filled_seconds_ago = (now() - box_rec.date_filled).total_seconds()
            assert filled_seconds_ago < 10
            assert box_rec.quantity == box_type_rec.box_type_qty

        with raises(Pallet.DoesNotExist):
            _ = Pallet.objects.get(pk=pallet_rec_id)
        return
    def test_prepare_pallet_and_pallet_boxes__successful_run(self):

        pallet = Pallet.objects.create(
            name='prepare pallet & boxes'
        )

        location = Location.get_location('01', '02', 'C1')

        pallet_form = self.get_pallet_form(pallet)
        build_pallet_form = self.get_build_pallet_form(location)

        product1, product2 = Product.objects.all()[2:4]

        box_number1 = BoxNumber.get_next_box_number()
        Box.objects.create(
            box_number=box_number1,
            box_type=Box.box_type_default(),
        )
        exp_year1 = timezone.now().year + 1

        box_number2 = BoxNumber.get_next_box_number()
        Box.objects.create(
            box_number=box_number2,
            box_type=Box.box_type_default(),
        )
        exp_year2 = timezone.now().year + 2

        post_data = management_form_post_data(
            BuildPalletView.formset_prefix,
            2
        )

        post_data.update(
            formset_form_post_data(
                BuildPalletView.formset_prefix,
                0,
                self.get_box_item_form_data(
                    box_number1,
                    product1,
                    exp_year=exp_year1,
                )
            )
        )

        post_data.update(
            formset_form_post_data(
                BuildPalletView.formset_prefix,
                1,
                self.get_box_item_form_data(
                    box_number2,
                    product2,
                    exp_year=exp_year2,
                )
            )
        )

        box_forms = BuildPalletView.BoxFormFactory(
            post_data,
            prefix=BuildPalletView.formset_prefix
        )

        self.assertTrue(pallet_form.is_valid())
        self.assertTrue(build_pallet_form.is_valid())
        self.assertTrue(box_forms.is_valid())

        self.assertNotEqual(box_number1, box_number2)

        view = BuildPalletView()
        pallet_out, location_out, boxes_by_box_number = \
            view.prepare_pallet_and_pallet_boxes(
                pallet_form,
                build_pallet_form,
                box_forms,
            )

        self.assertEqual(location, pallet_out.location)
        self.assertEqual(Pallet.FILL, pallet_out.pallet_status)

        self.assertEqual(location, location_out)

        self.assertEqual(
            {box_number1, box_number2},
            boxes_by_box_number.keys(),
        )

        pallet_box1 = boxes_by_box_number[box_number1]
        self.assertEqual(box_number1, pallet_box1.box_number)
        self.assertEqual(pallet, pallet_box1.pallet)
        self.assertEqual(box_number1, pallet_box1.box.box_number)
        self.assertEqual(product1, pallet_box1.product)
        self.assertEqual(exp_year1, pallet_box1.exp_year)

        pallet_box2 = boxes_by_box_number[box_number2]
        self.assertEqual(box_number2, pallet_box2.box_number)
        self.assertEqual(pallet, pallet_box2.pallet)
        self.assertEqual(box_number2, pallet_box2.box.box_number)
        self.assertEqual(product2, pallet_box2.product)
        self.assertEqual(exp_year2, pallet_box2.exp_year)