how can I also show stock message with there location like "Added %s items to stock with %s location"?

I have a module PartLog witch is used to generate a report from another modules like stock, part and user. I am also using message to store in report description fileds :- look

My PartLog Model:-

class PartLog(models.Model):
    ACTION_ADD = 'Added Part'
    ACTION_REMOVED = 'Removed Part'
    ACTION_DUPLICATED = 'Part Duplicated'
    ACTION_EDITED = 'Part Updated'
    ACTION_ADD_ORDER_TO_PART = 'Added Order to Part'
    ACTION_ADD_STOCK_TO_PART = 'Added %s items to stock'
    ACTION_REMOVE_FROM_STOCK = 'Removed %s items from stock'
    ACTION_CREATED_STOCK = 'Created Stock Item'
    ACTION_DELETED_STOCK = 'Removed Stock Item'
    ACTION_MOVED_TO = 'Stock item moved'
    ACTION_STOCK_EDITED = 'Stock Updated'
    ACTION_STOCK_DUPLICATED = 'Stock Duplicated'
    ACTION_ORDERED_PART = 'Part Ordered'

    ACTION_CHOICES = (
        (ACTION_ADD, ACTION_ADD),
        (ACTION_REMOVED, ACTION_REMOVED),
        (ACTION_DUPLICATED, ACTION_DUPLICATED),
        (ACTION_EDITED, ACTION_EDITED),
        (ACTION_ADD_ORDER_TO_PART, ACTION_ADD_ORDER_TO_PART),
        (ACTION_ADD_STOCK_TO_PART, ACTION_ADD_STOCK_TO_PART),
        (ACTION_REMOVE_FROM_STOCK, ACTION_REMOVE_FROM_STOCK),
        (ACTION_CREATED_STOCK, ACTION_CREATED_STOCK),
        (ACTION_DELETED_STOCK, ACTION_DELETED_STOCK),
        (ACTION_MOVED_TO, ACTION_MOVED_TO),
        (ACTION_STOCK_EDITED, ACTION_STOCK_EDITED),
        (ACTION_STOCK_DUPLICATED, ACTION_STOCK_DUPLICATED),
        (ACTION_ORDERED_PART, ACTION_ORDERED_PART),
    )
    part = models.ForeignKey(to=Part, on_delete=models.SET_NULL, null=True)
    transaction_time = models.DateTimeField('Transaction Time')
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    change_quantity = models.PositiveSmallIntegerField('Change Quantity')
    action = models.CharField(max_length=40, choices=ACTION_CHOICES)

    @property
    def message(self):
        if self.action in [self.ACTION_REMOVE_FROM_STOCK, self.ACTION_ADD_STOCK_TO_PART]:
            return self.action % self.change_quantity
        return self.action

    @staticmethod
    def log(part, user, change_quantity, action):
        PartLog.objects.create(part=part, user=user,
                               change_quantity=change_quantity,
                               action=action, transaction_time=datetime.now())

My Stock Item Create view:-

class StockItemCreate(PermissionRequiredMixin, AjaxCreateView):
    """
    View for creating a new StockItem
    Parameters can be pre-filled by passing query items:
    - part: The part of which the new StockItem is an instance
    - location: The location of the new StockItem

    If the parent part is a "tracked" part, provide an option to create uniquely serialized items
    rather than a bulk quantity of stock items
    """
    permission_required = ('users.add_stocks',)
    model = StockItem
    form_class = CreateStockItemForm
    context_object_name = 'item'
    ajax_template_name = 'modal_form.html'
    ajax_form_title = _('Create new Stock Item')

    def get_form(self):
        """ Get form for StockItem creation.
        Overrides the default get_form() method to intelligently limit
        ForeignKey choices based on other selections
        """

        form = super().get_form()

        # If the user has selected a Part, limit choices for SupplierPart
        if form['part'].value():
            part_id = form['part'].value()

            try:
                part = Part.objects.get(id=part_id)

                # Hide the 'part' field (as a valid part is selected)
                form.fields['part'].widget = HiddenInput()

                # trackable parts get special consideration
                if part.trackable:
                    form.fields['delete_on_deplete'].widget = HiddenInput()
                    form.fields['delete_on_deplete'].initial = False
                else:
                    form.fields.pop('serial_numbers')

                # If the part is NOT purchaseable, hide the supplier_part field
                if not part.purchaseable:
                    form.fields['supplier_part'].widget = HiddenInput()
                else:
                    # Pre-select the allowable SupplierPart options
                    parts = form.fields['supplier_part'].queryset
                    parts = parts.filter(part=part.id)

                    form.fields['supplier_part'].queryset = parts

                    # If there is one (and only one) supplier part available, pre-select it
                    all_parts = parts.all()
                    if len(all_parts) == 1:

                        # TODO - This does NOT work for some reason? Ref build.views.BuildItemCreate
                        form.fields['supplier_part'].initial = all_parts[0].id

            except Part.DoesNotExist:
                pass

        # Otherwise if the user has selected a SupplierPart, we know what Part they meant!
        elif form['supplier_part'].value() is not None:
            pass

        return form

    def get_initial(self):
        """ Provide initial data to create a new StockItem object
        """

        # Is the client attempting to copy an existing stock item?
        item_to_copy = self.request.GET.get('copy', None)

        if item_to_copy:
            try:
                original = StockItem.objects.get(pk=item_to_copy)
                initials = model_to_dict(original)
                self.ajax_form_title = _("Copy Stock Item")
            except StockItem.DoesNotExist:
                initials = super(StockItemCreate, self).get_initial().copy()

        else:
            initials = super(StockItemCreate, self).get_initial().copy()

        part_id = self.request.GET.get('part', None)
        loc_id = self.request.GET.get('location', None)

        # Part field has been specified
        if part_id:
            try:
                part = Part.objects.get(pk=part_id)
                initials['part'] = part
                initials['location'] = part.get_default_location()
                initials['supplier_part'] = part.default_supplier
            except Part.DoesNotExist:
                pass

        # Location has been specified
        if loc_id:
            try:
                initials['location'] = StockLocation.objects.get(pk=loc_id)
            except StockLocation.DoesNotExist:
                pass

        return initials

    def post(self, request, *args, **kwargs):
        """ Handle POST of StockItemCreate form.

        - Manage serial-number valdiation for tracked parts
        """

        form = self.get_form()

        data = {}

        valid = form.is_valid()

        if valid:
            part_id = form['part'].value()
            try:
                part = Part.objects.get(id=part_id)
                quantity = Decimal(form['quantity'].value())
            except (Part.DoesNotExist, ValueError, InvalidOperation):
                part = None
                quantity = 1
                valid = False
                form.errors['quantity'] = [_('Invalid quantity')]

            if part is None:
                form.errors['part'] = [_('Invalid part selection')]
            else:
                # A trackable part must provide serial numbesr
                if part.trackable:
                    sn = request.POST.get('serial_numbers', '')

                    sn = str(sn).strip()

                    # If user has specified a range of serial numbers
                    if len(sn) > 0:
                        try:
                            serials = ExtractSerialNumbers(sn, quantity)

                            existing = []

                            for serial in serials:
                                if not StockItem.check_serial_number(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

                            # At this point we have a list of serial numbers which we know are valid,
                            # and do not currently exist
                            form.clean()

                            data = form.cleaned_data

                            for serial in serials:
                                # Create a new stock item for each serial number
                                item = StockItem(
                                    part=part,
                                    quantity=1,
                                    serial=serial,
                                    supplier_part=data.get('supplier_part'),
                                    location=data.get('location'),
                                    batch=data.get('batch'),
                                    delete_on_deplete=False,
                                    status=data.get('status'),
                                    notes=data.get('notes'),
                                    URL=data.get('URL'),
                                )

                                item.save(user=request.user)

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

                else:
                    # For non-serialized items, simply save the form.
                    # We need to call _post_clean() here because it is prevented in the form implementation
                    form.clean()
                    form._post_clean()

                    item = form.save(commit=False)
                    item.save(user=request.user)

                    PartLog.log(
                        part=part, change_quantity=form.cleaned_data.get('quantity', 0),
                        action=PartLog.ACTION_ADD_STOCK_TO_PART, user=request.user
                    )

                    data['pk'] = item.pk
                    data['url'] = item.get_absolute_url()
                    data['success'] = _("Created new stock item")

        data['form_valid'] = valid

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

Need to show message in description like " Added %S items to stock with %S location "
Location is just we select at the time of Stock item creation.

Please help me understand what the issue is here.

What I think the situation is:

  • You have a page (the image displayed at the top)
    • Some button or widget that brings up a form to enter data
    • Uses AJAX to submit that form
    • The server returns a JSON response
  • You want that JSON response to have the data that updates the displayed page

If I’m not correct, please describe what the situation is.

And, I’m not sure where your question lies then - is it that you don’t know how to create that message? Or is it that you don’t know how to update the page with that message?

1 Like

Thanks for the reply, I have resolved this issue