Django-приложение для управления небольшим инвентарным списком

Я создал очень маленькое Django-приложение для управления очень маленьким инвентарным списком.

Мой models.py код таков:

class Inventory(models.Model):
    account = models.ForeignKey(
        "accounts.Account", on_delete=models.DO_NOTHING, null=False, blank=False
    )


class InventoryProduct(models.Model):
    inventory = models.ForeignKey("Inventory", on_delete=models.CASCADE)
    sku = models.ForeignKey(
        "products.SKU", on_delete=models.DO_NOTHING, null=False, blank=False
    )
    quantity = models.PositiveIntegerField(
        default=0
    ) 


class Transaction(models.Model):
    IN = 1
    OUT = 0
    TYPE_CHOICES = (
        (IN, "Incoming"),  # Carico / Entrata
        (OUT, "Outgoing"),  # Scarico / Uscita
    )
    inventory = models.ForeignKey("Inventory", on_delete=models.CASCADE)
    transferred_to = models.ForeignKey(
        "Inventory", on_delete=models.CASCADE, blank=True, null=True
    )
    code = models.UUIDField(default=uuid.uuid4)
    transaction_type = models.PositiveSmallIntegerField(
        choices=TYPE_CHOICES, default=IN
    )
    transaction_date = models.DateTimeField(auto_now_add=True)
    notes = models.TextField(null=True, blank=True)


class TransactionItem(models.Model):
    transaction = models.ForeignKey("Transaction", on_delete=models.CASCADE)
    item = models.ForeignKey("InventoryProduct", on_delete=models.CASCADE)
    quantity = models.IntegerField()

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self.item.quantity += self.quantity
        self.item.save()

Код достаточно понятен, в основном у меня есть Inventory на аккаунт и Inventory имеет продукты, которые я добавляю в связанную модель InventoryItem. Каждый товар в InventoryItem имеет количество, которое будет обновляться во время Transaction.

Транзакция имеет тип IN/OUT, чтобы понять, нужно ли мне добавить или удалить товары из инвентаря. Наконец, как вы, конечно, понимаете, TransactionItem содержит все элементы с количеством (для добавления или удаления) внутри транзакции.

Все просто, я очень ценю ваше мнение, если я могу как-то улучшить моделирование.

Мои вопросы:

  1. Добавьте способ передачи товаров из одного инвентаря в другой (я думаю, мне нужна операция OUT, а затем IN), но как я могу отслеживать это "движение" из одного инвентаря в другой? Я хотел бы сохранять, из какого инвентаря поступают продукты.

  2. Этот вопрос также связан с первым. Продукты могут быть добавлены в инвентарь из Заказа или путем переноса из другого инвентаря. Как я могу также включить Order в "концепцию"?

  3. <<<13>>

    >

    1. Отслеживание перемещений между запасами

    Чтобы отслеживать, откуда поступают товары, можно добавить поле transferred_from. Это позволит вам создать прямую связь между исходным и конечным инвентарем для каждого перемещения.

    class Transaction(models.Model):
        # Existing fields...
        transferred_from = models.ForeignKey(
            "Inventory", related_name="transferred_from_transactions", on_delete=models.CASCADE, blank=True, null=True
        )
        transferred_to = models.ForeignKey(
            "Inventory", related_name="transferred_to_transactions", on_delete=models.CASCADE, blank=True, null=True
        )
    

    Пример запроса:

    # Assuming 'last_transaction' is a Transaction instance
    last_transaction = Transaction.objects.last()
    
    # To find out where the product came from
    if last_transaction.transferred_from:
        source_inventory = last_transaction.transferred_from
        print(f"Product came from Inventory ID: {source_inventory.id}")
    else:
        print("This product did not come from another inventory.")
    

    2. Включая концепцию заказа

    Добавьте новую модель: Модели Order и OrderItem

    class Order(models.Model):
        order_code = models.UUIDField(default=uuid.uuid4, editable=False)
        order_date = models.DateTimeField(auto_now_add=True)
        # Additional fields as needed
    
    class OrderItem(models.Model):
        order = models.ForeignKey(Order, on_delete=models.CASCADE)
        sku = models.ForeignKey("products.SKU", on_delete=models.CASCADE)
        quantity = models.PositiveIntegerField(default=0)
    

    Далее добавьте ссылку на заказ в модель транзакций:

    class Transaction(models.Model):
        # Existing fields...
        order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True, related_name="transactions")
    

    Пример использования:

    # Assuming 'some_transaction' is a Transaction instance
    some_transaction = Transaction.objects.select_related('order', 'transferred_from').last()
    
    # Check if the transaction is linked to an order
    if some_transaction.order:
        print(f"Transaction linked to Order ID: {some_transaction.order.id}")
    
    # Check where the products came from
    if some_transaction.transferred_from:
        print(f"Products transferred from Inventory ID: {some_transaction.transferred_from.id}")
    else:
        print("Products were not transferred from another inventory.")
    

    Надеюсь, это поможет.

    Я бы удалил 'transaction_type', а 'inventory' и 'transfer_to' переименовал в что-то вроде 'source_inventory' и 'target_inventory'. Таким образом, передача из одного инвентаря в другой будет одной транзакцией. Транзакции IN для данного инвентаря - это те, в которых данный инвентарь является целевым_инвентарем для транзакции, а транзакции OUT - это те, в которых он является исходным_инвентарем.

    AWS-ориентированное решение, но я бы использовал AWS Chalice для работы с веб-фронт-эндом; https://aws.github.io/chalice/quickstart.html

    Я бы рассмотрел dynamodb или даже s3 для быстрого и грязного хранилища данных для инвентаризации. У этого парня есть куча python для dynamo, даже если вам не нравится идея chalice. https://www.tecracer.com/blog/2021/03/modelling-a-product-catalog-in-dynamodb.html. Chalice позволяет легко сделать веб-маршрут, так что вы можете вставить свой код инвентаризации в маршруты.

    @app.route('/add/{value}', methods=['GET'])
    def add(value):
       # add to dynamo code here
    @app.route('/sub/{value}', methods=['GET'])
    def sub(value):
       # remove from dynamo here
    
    Вернуться на верх