O
O
Oleksandr Shovkoviy2017-09-27 22:29:31
Django
Oleksandr Shovkoviy, 2017-09-27 22:29:31

Any ideas how to implement the creation/storage of an incoming/outgoing invoice in Django?

I am writing an application (Django+MySQL) for warehouse management.
The main task of the application is to manage the product range and mutual settlements with contractors. The moment of posting and issuing goods with the formation of invoices + with the possibility of their subsequent viewing and editing is important (by analogy in 1C) .
I'm at a dead end, I can not solve two questions:

  • how to implement adding and storing a "standard invoice"
  • how to implement the form for adding goods to the invoice (the number of goods in the invoice may vary)

PS Do not judge strictly, I have been working with Python3 for a little over a year (I mainly used network hardware and linux for administration) , I wrote mostly interactive console utilities, served MySQL database , Django - I have been studying djangobook for a little over a month

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
neatsoft, 2017-09-28
@xand3r_si1k

Documents should be stored in one table, the rows of the tabular part (of all documents) should be stored in the second.
models.py:

from django.db import models
from django.db.models import Max, Sum
from django.utils.translation import ugettext_lazy as _


class Product(models.Model):
    name = models.CharField(
        _('Name'),
        max_length=200,
        db_index=True,
    )

    def __str__(self):
        return self.name


class Document(models.Model):
    INVOICE = 'I'
    WAYBILL = 'W'
    TYPE_CHOICES = (
        (INVOICE, _('Invoice')),
        (WAYBILL, _('Waybill')),
    )
    type = models.CharField(
        _('Type'),
        max_length=1,
        choices=TYPE_CHOICES,
    )
    number = models.CharField(
        _('Number'),
        blank=True,
        max_length=50,
    )
    created_at = models.DateTimeField(
        _('Created'),
        auto_now_add=True,
        db_index=True,
    )

    @property
    def total(self):
        return self.items.aggregate(sum=Sum('total'))['sum']

    class Meta:
        ordering = ['-created_at']


class DocumentItem(models.Model):
    document = models.ForeignKey(
        Document,
        models.CASCADE,
        related_name='items',
    )
    position = models.PositiveIntegerField(
        verbose_name=_('Position'),
        editable=False,
        db_index=True,
    )
    product = models.ForeignKey(
        Product,
        models.PROTECT,
    )
    price = models.DecimalField(
        _('Price'),
        max_digits=12,
        decimal_places=2,
    )
    quantity = models.DecimalField(
        _('Quantity'),
        max_digits=10,
        decimal_places=3,
    )
    total = models.DecimalField(
        _('Total'),
        max_digits=12,
        decimal_places=2,
    )

    def save(self, *args, **kwargs):
        if not self.position:
            position = self.document.items.aggregate(Max('position'))['position__max'] or 0
            self.position = position + 1
        super(DocumentItem, self).save(*args, **kwargs)

admin.py:
from django.contrib import admin

from .models import Product, Document, DocumentItem


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    pass


class DocumentItemInline(admin.TabularInline):
    model = DocumentItem
    fields = (
        'position',
        'product',
        'price',
        'quantity',
        'total',
    )
    readonly_fields = (
        'position',
    )
    ordering = ['position']


@admin.register(Document)
class DocumentAdmin(admin.ModelAdmin):
    inlines = [
        DocumentItemInline,
    ]
    list_display = (
        'type',
        'number',
        'created_at',
        'total',
    )
    list_filter = (
        'type',
    )
    search_fields = (
        '=number',
    )

The standard admin panel is just an example, it is not for this at all (it should not be available to ordinary users). But real forms are built on the same principle.
The code was thrown right here, I did not check it, so minor errors are possible.

E
Exploding, 2017-09-28
@Exploding

I didn’t quite understand, the emphasis on how to organize data storage in a muscle or something that specifically concerns janga?
If the first - I would divide the documents into types: one more field in the table of documents, which would determine the type of the document (enum "sale", "order", etc.). And knowing the type of the document, you can "on the fly" form the same balances in the warehouse, without worrying about the integrity of the data. And as unique identifiers for delivery items and using them to track what was sold from the warehouse - use, for example, md5 hash:
product_id + order_price ("plus" here is considered as a cantonation of parameters).
Another question is what will happen later after a lot of time ... such an option for calculating the warehouse "on the fly" will sooner or later increase the load on the subd, but this is already an individual question for everyone. If this is not 100,500 sales per day, then this scheme may well exist and successfully resolve for a long time. And you'll see :)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question