commit 54bc863f5fe589ec0e839ef6b4a9102d732d9221 Author: Artem Darius Weber Date: Tue Jan 7 18:08:34 2025 +0300 init django project and added base invetory models diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ca5a200 Binary files /dev/null and b/.DS_Store differ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/franchise_store.iml b/.idea/franchise_store.iml new file mode 100644 index 0000000..31aca5f --- /dev/null +++ b/.idea/franchise_store.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c83e0bf --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,187 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..9d156b4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..cd27d96 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4777d5d --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +# Define default environment variables +DJANGO_SETTINGS_MODULE ?= dev + +# Default target +.PHONY: help +help: + @echo "Available commands:" + @echo " make run - Run the Django development server" + @echo " make migrate - Apply database migrations" + @echo " make createsuperuser - Create a Django superuser" + +# Run the development server +.PHONY: run +run: + @echo "Running Django server with settings: $(DJANGO_SETTINGS_MODULE)" + DJANGO_SETTINGS_MODULE=$(DJANGO_SETTINGS_MODULE) python manage.py runserver + +# Apply migrations +.PHONY: migrate +migrate: + @echo "Applying migrations with settings: $(DJANGO_SETTINGS_MODULE)" + DJANGO_SETTINGS_MODULE=$(DJANGO_SETTINGS_MODULE) python manage.py migrate + +# Create a superuser +.PHONY: createsuperuser +createsuperuser: + @echo "Creating superuser with settings: $(DJANGO_SETTINGS_MODULE)" + DJANGO_SETTINGS_MODULE=$(DJANGO_SETTINGS_MODULE) python manage.py createsuperuser \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ef343a4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3.8' + +services: + db: + image: postgres:15 + container_name: postgres_db + environment: + POSTGRES_USER: django_user + POSTGRES_PASSWORD: secure_password + POSTGRES_DB: django_db + ports: + - "5433:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - django_network + + adminer: + image: adminer + container_name: adminer + ports: + - "8080:8080" + networks: + - django_network + +volumes: + postgres_data: + +networks: + django_network: + driver: bridge \ No newline at end of file diff --git a/inventory/__init__.py b/inventory/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/inventory/__pycache__/__init__.cpython-310.pyc b/inventory/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..c625c7f Binary files /dev/null and b/inventory/__pycache__/__init__.cpython-310.pyc differ diff --git a/inventory/__pycache__/apps.cpython-310.pyc b/inventory/__pycache__/apps.cpython-310.pyc new file mode 100644 index 0000000..0af6901 Binary files /dev/null and b/inventory/__pycache__/apps.cpython-310.pyc differ diff --git a/inventory/__pycache__/models.cpython-310.pyc b/inventory/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000..8242b78 Binary files /dev/null and b/inventory/__pycache__/models.cpython-310.pyc differ diff --git a/inventory/admin.py b/inventory/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/inventory/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/inventory/apps.py b/inventory/apps.py new file mode 100644 index 0000000..905749f --- /dev/null +++ b/inventory/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InventoryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'inventory' diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py new file mode 100644 index 0000000..d94664b --- /dev/null +++ b/inventory/migrations/0001_initial.py @@ -0,0 +1,72 @@ +# Generated by Django 5.1.4 on 2025-01-07 14:56 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Наименование товара')), + ('manufacturer_name', models.CharField(max_length=255, verbose_name='Производитель')), + ('manufacturer_country', models.CharField(max_length=255, verbose_name='Страна производителя')), + ('manufacturer_code', models.CharField(blank=True, max_length=50, null=True, verbose_name='Код производителя')), + ('dimensions', models.CharField(blank=True, max_length=255, null=True, verbose_name='Размеры')), + ('unit_of_measure', models.CharField(max_length=50, verbose_name='Единица измерения')), + ('shelf_life_days', models.IntegerField(verbose_name='Срок годности (дни)')), + ('barcode', models.CharField(max_length=50, unique=True, verbose_name='Штрихкод')), + ], + ), + migrations.CreateModel( + name='StorageLocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Наименование')), + ('type', models.CharField(choices=[('Store', 'Магазин'), ('Distribution Center', 'Распределительный центр'), ('Office', 'Офис')], max_length=50, verbose_name='Тип места хранения')), + ], + ), + migrations.CreateModel( + name='PriceList', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('price_type', models.CharField(choices=[('Regular', 'Регулярная'), ('Discount', 'Скидочная'), ('Promotional', 'Акционная')], max_length=50, verbose_name='Тип цены')), + ('entry_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Входная цена')), + ('final_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Итоговая цена')), + ('date_effective', models.DateField(verbose_name='Дата вступления в силу')), + ('constraint_percent_limit', models.DecimalField(decimal_places=2, default=1000, max_digits=5, verbose_name='Лимит на наценку (%)')), + ('constraint_price_change', models.DecimalField(decimal_places=2, default=90, max_digits=5, verbose_name='Лимит на изменение цены (%)')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.product', verbose_name='Товар')), + ], + ), + migrations.CreateModel( + name='StockOperation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('operation_type', models.CharField(choices=[('Incoming', 'Приход'), ('Outgoing', 'Расход'), ('Transfer', 'Перемещение')], max_length=50, verbose_name='Тип операции')), + ('quantity', models.IntegerField(verbose_name='Количество')), + ('operation_date', models.DateTimeField(auto_now_add=True, verbose_name='Дата операции')), + ('expiration_date', models.DateField(blank=True, null=True, verbose_name='Срок годности')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.product', verbose_name='Товар')), + ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.storagelocation', verbose_name='Место хранения')), + ], + ), + migrations.CreateModel( + name='Inventory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity', models.IntegerField(verbose_name='Количество')), + ('inventory_date', models.DateField(verbose_name='Дата инвентаризации')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.product', verbose_name='Товар')), + ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.storagelocation', verbose_name='Место хранения')), + ], + ), + ] diff --git a/inventory/migrations/__init__.py b/inventory/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/inventory/migrations/__pycache__/0001_initial.cpython-310.pyc b/inventory/migrations/__pycache__/0001_initial.cpython-310.pyc new file mode 100644 index 0000000..1735705 Binary files /dev/null and b/inventory/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/inventory/migrations/__pycache__/__init__.cpython-310.pyc b/inventory/migrations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..1a2af7b Binary files /dev/null and b/inventory/migrations/__pycache__/__init__.cpython-310.pyc differ diff --git a/inventory/models.py b/inventory/models.py new file mode 100644 index 0000000..9bf6b85 --- /dev/null +++ b/inventory/models.py @@ -0,0 +1,72 @@ +from django.db import models + +class Product(models.Model): + name = models.CharField(max_length=255, verbose_name="Наименование товара") + manufacturer_name = models.CharField(max_length=255, verbose_name="Производитель") + manufacturer_country = models.CharField(max_length=255, verbose_name="Страна производителя") + manufacturer_code = models.CharField(max_length=50, verbose_name="Код производителя", blank=True, null=True) + dimensions = models.CharField(max_length=255, verbose_name="Размеры", blank=True, null=True) + unit_of_measure = models.CharField(max_length=50, verbose_name="Единица измерения") + shelf_life_days = models.IntegerField(verbose_name="Срок годности (дни)") + barcode = models.CharField(max_length=50, unique=True, verbose_name="Штрихкод") + + def __str__(self): + return self.name + + +class StorageLocation(models.Model): + TYPE_CHOICES = [ + ('Store', 'Магазин'), + ('Distribution Center', 'Распределительный центр'), + ('Office', 'Офис'), + ] + name = models.CharField(max_length=255, verbose_name="Наименование") + type = models.CharField(max_length=50, choices=TYPE_CHOICES, verbose_name="Тип места хранения") + + def __str__(self): + return self.name + + +class StockOperation(models.Model): + OPERATION_TYPE_CHOICES = [ + ('Incoming', 'Приход'), + ('Outgoing', 'Расход'), + ('Transfer', 'Перемещение'), + ] + product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") + location = models.ForeignKey(StorageLocation, on_delete=models.CASCADE, verbose_name="Место хранения") + operation_type = models.CharField(max_length=50, choices=OPERATION_TYPE_CHOICES, verbose_name="Тип операции") + quantity = models.IntegerField(verbose_name="Количество") + operation_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата операции") + expiration_date = models.DateField(blank=True, null=True, verbose_name="Срок годности") + + def __str__(self): + return f"{self.operation_type} - {self.product.name}" + + +class PriceList(models.Model): + PRICE_TYPE_CHOICES = [ + ('Regular', 'Регулярная'), + ('Discount', 'Скидочная'), + ('Promotional', 'Акционная'), + ] + product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") + price_type = models.CharField(max_length=50, choices=PRICE_TYPE_CHOICES, verbose_name="Тип цены") + entry_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Входная цена") + final_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена") + date_effective = models.DateField(verbose_name="Дата вступления в силу") + constraint_percent_limit = models.DecimalField(max_digits=5, decimal_places=2, default=1000, verbose_name="Лимит на наценку (%)") + constraint_price_change = models.DecimalField(max_digits=5, decimal_places=2, default=90, verbose_name="Лимит на изменение цены (%)") + + def __str__(self): + return f"{self.price_type} - {self.product.name}" + + +class Inventory(models.Model): + product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар") + location = models.ForeignKey(StorageLocation, on_delete=models.CASCADE, verbose_name="Место хранения") + quantity = models.IntegerField(verbose_name="Количество") + inventory_date = models.DateField(verbose_name="Дата инвентаризации") + + def __str__(self): + return f"Инвентаризация {self.product.name} - {self.location.name}" \ No newline at end of file diff --git a/inventory/tests.py b/inventory/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/inventory/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/inventory/views.py b/inventory/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/inventory/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..a8db909 --- /dev/null +++ b/manage.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + + os.environ.setdefault("DJANGO_SETTINGS_MODULE", f"settings.dev") + + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + + execute_from_command_line(sys.argv) \ No newline at end of file diff --git a/settings/__init__.py b/settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/settings/__pycache__/__init__.cpython-310.pyc b/settings/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..c0f6ea3 Binary files /dev/null and b/settings/__pycache__/__init__.cpython-310.pyc differ diff --git a/settings/__pycache__/base.cpython-310.pyc b/settings/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000..77d06b7 Binary files /dev/null and b/settings/__pycache__/base.cpython-310.pyc differ diff --git a/settings/__pycache__/dev.cpython-310.pyc b/settings/__pycache__/dev.cpython-310.pyc new file mode 100644 index 0000000..7cd880a Binary files /dev/null and b/settings/__pycache__/dev.cpython-310.pyc differ diff --git a/settings/base.py b/settings/base.py new file mode 100644 index 0000000..bf20ec2 --- /dev/null +++ b/settings/base.py @@ -0,0 +1,20 @@ +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'django_db', + 'USER': 'django_user', + 'PASSWORD': 'secure_password', + 'HOST': '127.0.0.1', + 'PORT': '5433', + } +} + +INSTALLED_APPS = [ + # 'django.contrib.admin', + # 'django.contrib.auth', + # 'django.contrib.contenttypes', + # 'django.contrib.sessions', + # 'django.contrib.messages', + # 'django.contrib.staticfiles', + 'inventory', +] \ No newline at end of file diff --git a/settings/dev.py b/settings/dev.py new file mode 100644 index 0000000..a535405 --- /dev/null +++ b/settings/dev.py @@ -0,0 +1,4 @@ +from .base import * + +DEBUG = True +ALLOWED_HOSTS = ["*"] \ No newline at end of file diff --git a/settings/prod.py b/settings/prod.py new file mode 100644 index 0000000..8e979ab --- /dev/null +++ b/settings/prod.py @@ -0,0 +1,15 @@ +from .base import * + +DEBUG = False +ALLOWED_HOSTS = ['store.k-lab.su'] + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'django_db', + 'USER': 'django_user', + 'PASSWORD': 'secure_password', + 'HOST': 'db', + 'PORT': '5433', + } +} \ No newline at end of file