Esempio n. 1
0
    def receive_line_item(self, line, location, quantity, user):
        """ Receive a line item (or partial line item) against this PO
        """

        if not self.status == OrderStatus.PLACED:
            raise ValidationError({
                "status":
                _("Lines can only be received against an order marked as 'Placed'"
                  )
            })

        try:
            quantity = int(quantity)
            if quantity <= 0:
                raise ValidationError(
                    {"quantity": _("Quantity must be greater than zero")})
        except ValueError:
            raise ValidationError({"quantity": _("Invalid quantity provided")})

        # Create a new stock item
        if line.part:
            stock = StockItem(part=line.part.part,
                              supplier_part=line.part,
                              location=location,
                              quantity=quantity,
                              purchase_order=self)

            stock.save()

            # Add a new transaction note to the newly created stock item
            stock.addTransactionNote(
                "Received items", user,
                "Received {q} items against order '{po}'".format(q=quantity,
                                                                 po=str(self)))

        # Update the number of parts received against the particular line item
        line.received += quantity
        line.save()

        # Has this order been completed?
        if len(self.pending_line_items()) == 0:

            self.received_by = user
            self.complete_order()  # This will save the model
Esempio n. 2
0
    def done(self, form_list, **kwargs):
        """Create items."""
        items = self.get_clean_items()

        import_done = 0
        import_error = []

        # Create Part instances
        for part_data in items.values():

            # set related parts
            optional_matches = {}
            for idx in self.file_manager.OPTIONAL_MATCH_HEADERS:
                if idx.lower() in part_data:
                    try:
                        optional_matches[idx] = self.allowed_items[idx].get(
                            pk=int(part_data[idx.lower()]))
                    except (ValueError,
                            self.allowed_items[idx].model.DoesNotExist, self.
                            allowed_items[idx].model.MultipleObjectsReturned):
                        optional_matches[idx] = None
                else:
                    optional_matches[idx] = None

            # add part
            new_part = Part(
                name=part_data.get('name', ''),
                description=part_data.get('description', ''),
                keywords=part_data.get('keywords', None),
                IPN=part_data.get('ipn', None),
                revision=part_data.get('revision', None),
                link=part_data.get('link', None),
                default_expiry=part_data.get('default_expiry', 0),
                minimum_stock=part_data.get('minimum_stock', 0),
                units=part_data.get('units', None),
                notes=part_data.get('notes', None),
                category=optional_matches['Category'],
                default_location=optional_matches['default_location'],
                default_supplier=optional_matches['default_supplier'],
                variant_of=optional_matches['variant_of'],
                active=str2bool(part_data.get('active', True)),
                base_cost=part_data.get('base_cost', 0),
                multiple=part_data.get('multiple', 1),
                assembly=str2bool(
                    part_data.get('assembly',
                                  part_settings.part_assembly_default())),
                component=str2bool(
                    part_data.get('component',
                                  part_settings.part_component_default())),
                is_template=str2bool(
                    part_data.get('is_template',
                                  part_settings.part_template_default())),
                purchaseable=str2bool(
                    part_data.get('purchaseable',
                                  part_settings.part_purchaseable_default())),
                salable=str2bool(
                    part_data.get('salable',
                                  part_settings.part_salable_default())),
                trackable=str2bool(
                    part_data.get('trackable',
                                  part_settings.part_trackable_default())),
                virtual=str2bool(
                    part_data.get('virtual',
                                  part_settings.part_virtual_default())),
            )
            try:
                new_part.save()

                # add stock item if set
                if part_data.get('stock', None):
                    stock = StockItem(
                        part=new_part,
                        location=new_part.default_location,
                        quantity=int(part_data.get('stock', 1)),
                    )
                    stock.save()
                import_done += 1
            except ValidationError as _e:
                import_error.append(', '.join(set(_e.messages)))

        # Set alerts
        if import_done:
            alert = f"<strong>{_('Part-Import')}</strong><br>{_('Imported {n} parts').format(n=import_done)}"
            messages.success(self.request, alert)
        if import_error:
            error_text = '\n'.join([
                f'<li><strong>x{import_error.count(a)}</strong>: {a}</li>'
                for a in set(import_error)
            ])
            messages.error(
                self.request,
                f"<strong>{_('Some errors occured:')}</strong><br><ul>{error_text}</ul>"
            )

        return HttpResponseRedirect(reverse('part-index'))
Esempio n. 3
0
    def post(self, request, *args, **kwargs):
        """ Handle POST request. Mark the build as COMPLETE
        
        - If the form validation passes, the Build objects completeBuild() method is called
        - Otherwise, the form is passed back to the client
        """

        build = self.get_object()

        form = self.get_form()

        confirm = str2bool(request.POST.get('confirm', False))

        loc_id = request.POST.get('location', None)

        valid = False

        if confirm is False:
            form.errors['confirm'] = [
                'Confirm completion of build',
            ]
        else:
            try:
                location = StockLocation.objects.get(id=loc_id)
                valid = True
            except StockLocation.DoesNotExist:
                form.errors['location'] = ['Invalid location selected']

            serials = []

            if build.part.trackable:
                # A build for a trackable part must specify serial numbers

                sn = request.POST.get('serial_numbers', '')

                sn = str(sn).strip()

                # If the user has specified serial numbers, check they are valid
                if len(sn) > 0:
                    try:
                        # Exctract a list of provided serial numbers
                        serials = ExtractSerialNumbers(sn, build.quantity)

                        existing = []

                        for serial in serials:
                            if not StockItem.check_serial_number(
                                    build.part, serial):
                                existing.append(serial)

                        if len(existing) > 0:
                            exists = ",".join([str(x) for x in existing])
                            form.errors['serial_numbers'] = [
                                _('The following serial numbers already exist: ({sn})'
                                  .format(sn=exists))
                            ]
                            valid = False

                    except ValidationError as e:
                        form.errors['serial_numbers'] = e.messages
                        valid = False

            if valid:
                build.completeBuild(location, serials, request.user)

        data = {
            'form_valid': valid,
        }

        return self.renderJsonResponse(request,
                                       form,
                                       data,
                                       context=self.get_context_data())