Docs: начальная структура проекта

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-25 14:59:46 +00:00
commit 1669c12182
56 changed files with 2085 additions and 0 deletions

20
app/references/admin.py Normal file
View File

@@ -0,0 +1,20 @@
from django.contrib import admin
from .models import (
Currency,
OrderKind,
Client,
Organization,
Supplier,
Employee,
CashAccount,
Product,
)
admin.site.register(Currency)
admin.site.register(OrderKind)
admin.site.register(Client)
admin.site.register(Organization)
admin.site.register(Supplier)
admin.site.register(Employee)
admin.site.register(CashAccount)
admin.site.register(Product)

7
app/references/apps.py Normal file
View File

@@ -0,0 +1,7 @@
from django.apps import AppConfig
class ReferencesConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "references"
verbose_name = "Справочники"

View File

@@ -0,0 +1,103 @@
# Generated by Django 5.2.11 on 2026-02-25 14:58
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CashAccount',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='Название')),
],
options={
'verbose_name': 'Счёт денежных средств',
'verbose_name_plural': 'Счета денежных средств',
},
),
migrations.CreateModel(
name='Client',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='Название')),
],
options={
'verbose_name': 'Клиент',
'verbose_name_plural': 'Клиенты',
},
),
migrations.CreateModel(
name='Currency',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, verbose_name='Название')),
('code', models.CharField(blank=True, max_length=10, verbose_name='Код')),
],
options={
'verbose_name': 'Валюта',
'verbose_name_plural': 'Валюты',
},
),
migrations.CreateModel(
name='Employee',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='ФИО')),
],
options={
'verbose_name': 'Сотрудник',
'verbose_name_plural': 'Сотрудники',
},
),
migrations.CreateModel(
name='OrderKind',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, verbose_name='Название')),
],
options={
'verbose_name': 'Вид заказа',
'verbose_name_plural': 'Виды заказов',
},
),
migrations.CreateModel(
name='Organization',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='Название')),
],
options={
'verbose_name': 'Организация',
'verbose_name_plural': 'Организации',
},
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='Название')),
],
options={
'verbose_name': 'Товар',
'verbose_name_plural': 'Товары',
},
),
migrations.CreateModel(
name='Supplier',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=300, verbose_name='Название')),
],
options={
'verbose_name': 'Поставщик',
'verbose_name_plural': 'Поставщики',
},
),
]

View File

101
app/references/models.py Normal file
View File

@@ -0,0 +1,101 @@
"""
Справочники ERP WaterSurf.
"""
from django.db import models
class Currency(models.Model):
"""Валюты."""
name = models.CharField("Название", max_length=100)
code = models.CharField("Код", max_length=10, blank=True)
class Meta:
verbose_name = "Валюта"
verbose_name_plural = "Валюты"
def __str__(self):
return self.name or self.code or str(self.pk)
class OrderKind(models.Model):
"""Виды заказов."""
name = models.CharField("Название", max_length=200)
class Meta:
verbose_name = "Вид заказа"
verbose_name_plural = "Виды заказов"
def __str__(self):
return self.name
class Client(models.Model):
"""Клиенты."""
name = models.CharField("Название", max_length=300)
class Meta:
verbose_name = "Клиент"
verbose_name_plural = "Клиенты"
def __str__(self):
return self.name
class Organization(models.Model):
"""Организации."""
name = models.CharField("Название", max_length=300)
class Meta:
verbose_name = "Организация"
verbose_name_plural = "Организации"
def __str__(self):
return self.name
class Supplier(models.Model):
"""Поставщики."""
name = models.CharField("Название", max_length=300)
class Meta:
verbose_name = "Поставщик"
verbose_name_plural = "Поставщики"
def __str__(self):
return self.name
class Employee(models.Model):
"""Сотрудники (для поля Автор в документах)."""
name = models.CharField("ФИО", max_length=300)
class Meta:
verbose_name = "Сотрудник"
verbose_name_plural = "Сотрудники"
def __str__(self):
return self.name
class CashAccount(models.Model):
"""Счета денежных средств."""
name = models.CharField("Название", max_length=300)
class Meta:
verbose_name = "Счёт денежных средств"
verbose_name_plural = "Счета денежных средств"
def __str__(self):
return self.name
class Product(models.Model):
"""Товары."""
name = models.CharField("Название", max_length=300)
class Meta:
verbose_name = "Товар"
verbose_name_plural = "Товары"
def __str__(self):
return self.name

39
app/references/urls.py Normal file
View File

@@ -0,0 +1,39 @@
from django.urls import path
from . import views
app_name = "references"
urlpatterns = [
path("currencies/", views.CurrencyList.as_view(), name="currency_list"),
path("currencies/create/", views.CurrencyCreate.as_view(), name="currency_create"),
path("currencies/<int:pk>/edit/", views.CurrencyUpdate.as_view(), name="currency_update"),
path("currencies/<int:pk>/delete/", views.CurrencyDelete.as_view(), name="currency_delete"),
path("order-kinds/", views.OrderKindList.as_view(), name="orderkind_list"),
path("order-kinds/create/", views.OrderKindCreate.as_view(), name="orderkind_create"),
path("order-kinds/<int:pk>/edit/", views.OrderKindUpdate.as_view(), name="orderkind_update"),
path("order-kinds/<int:pk>/delete/", views.OrderKindDelete.as_view(), name="orderkind_delete"),
path("clients/", views.ClientList.as_view(), name="client_list"),
path("clients/create/", views.ClientCreate.as_view(), name="client_create"),
path("clients/<int:pk>/edit/", views.ClientUpdate.as_view(), name="client_update"),
path("clients/<int:pk>/delete/", views.ClientDelete.as_view(), name="client_delete"),
path("organizations/", views.OrganizationList.as_view(), name="organization_list"),
path("organizations/create/", views.OrganizationCreate.as_view(), name="organization_create"),
path("organizations/<int:pk>/edit/", views.OrganizationUpdate.as_view(), name="organization_update"),
path("organizations/<int:pk>/delete/", views.OrganizationDelete.as_view(), name="organization_delete"),
path("suppliers/", views.SupplierList.as_view(), name="supplier_list"),
path("suppliers/create/", views.SupplierCreate.as_view(), name="supplier_create"),
path("suppliers/<int:pk>/edit/", views.SupplierUpdate.as_view(), name="supplier_update"),
path("suppliers/<int:pk>/delete/", views.SupplierDelete.as_view(), name="supplier_delete"),
path("employees/", views.EmployeeList.as_view(), name="employee_list"),
path("employees/create/", views.EmployeeCreate.as_view(), name="employee_create"),
path("employees/<int:pk>/edit/", views.EmployeeUpdate.as_view(), name="employee_update"),
path("employees/<int:pk>/delete/", views.EmployeeDelete.as_view(), name="employee_delete"),
path("cash-accounts/", views.CashAccountList.as_view(), name="cashaccount_list"),
path("cash-accounts/create/", views.CashAccountCreate.as_view(), name="cashaccount_create"),
path("cash-accounts/<int:pk>/edit/", views.CashAccountUpdate.as_view(), name="cashaccount_update"),
path("cash-accounts/<int:pk>/delete/", views.CashAccountDelete.as_view(), name="cashaccount_delete"),
path("products/", views.ProductList.as_view(), name="product_list"),
path("products/create/", views.ProductCreate.as_view(), name="product_create"),
path("products/<int:pk>/edit/", views.ProductUpdate.as_view(), name="product_update"),
path("products/<int:pk>/delete/", views.ProductDelete.as_view(), name="product_delete"),
]

131
app/references/views.py Normal file
View File

@@ -0,0 +1,131 @@
"""
CRUD для справочников (списки и формы).
"""
import logging
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.contrib import messages
from django.utils.translation import gettext_lazy as _
from .models import (
Currency,
OrderKind,
Client,
Organization,
Supplier,
Employee,
CashAccount,
Product,
)
logger = logging.getLogger(__name__)
def _ref_view(model_class, list_url_name, create_url_name, update_url_name, delete_url_name, list_title, form_title):
"""Фабрика представлений для одного справочника."""
class List(LoginRequiredMixin, ListView):
model = model_class
template_name = "references/reference_list.html"
context_object_name = "items"
extra_context = {
"title": list_title,
"create_url_name": create_url_name,
"update_url_name": update_url_name,
"delete_url_name": delete_url_name,
}
class Create(LoginRequiredMixin, CreateView):
model = model_class
fields = "__all__"
template_name = "references/reference_form.html"
success_url = reverse_lazy(list_url_name)
extra_context = {"title": form_title, "cancel_url": reverse_lazy(list_url_name)}
def form_valid(self, form):
messages.success(self.request, _("Запись создана."))
logger.info("Справочник %s: создана запись %s", model_class.__name__, form.instance)
return super().form_valid(form)
class Update(LoginRequiredMixin, UpdateView):
model = model_class
fields = "__all__"
template_name = "references/reference_form.html"
success_url = reverse_lazy(list_url_name)
context_object_name = "object"
extra_context = {"title": form_title, "cancel_url": reverse_lazy(list_url_name)}
def form_valid(self, form):
messages.success(self.request, _("Запись сохранена."))
logger.info("Справочник %s: обновлена запись %s", model_class.__name__, form.instance)
return super().form_valid(form)
class Delete(LoginRequiredMixin, DeleteView):
model = model_class
template_name = "references/reference_confirm_delete.html"
success_url = reverse_lazy(list_url_name)
context_object_name = "object"
extra_context = {"cancel_url": reverse_lazy(list_url_name)}
def form_valid(self, form):
messages.success(self.request, _("Запись удалена."))
logger.info("Справочник %s: удалена запись %s", model_class.__name__, self.object)
return super().form_valid(form)
return List, Create, Update, Delete
# Валюты
CurrencyList, CurrencyCreate, CurrencyUpdate, CurrencyDelete = _ref_view(
Currency, "references:currency_list", "references:currency_create",
"references:currency_update", "references:currency_delete",
"Валюты", "Валюта",
)
# Виды заказов
OrderKindList, OrderKindCreate, OrderKindUpdate, OrderKindDelete = _ref_view(
OrderKind, "references:orderkind_list", "references:orderkind_create",
"references:orderkind_update", "references:orderkind_delete",
"Виды заказов", "Вид заказа",
)
# Клиенты
ClientList, ClientCreate, ClientUpdate, ClientDelete = _ref_view(
Client, "references:client_list", "references:client_create",
"references:client_update", "references:client_delete",
"Клиенты", "Клиент",
)
# Организации
OrganizationList, OrganizationCreate, OrganizationUpdate, OrganizationDelete = _ref_view(
Organization, "references:organization_list", "references:organization_create",
"references:organization_update", "references:organization_delete",
"Организации", "Организация",
)
# Поставщики
SupplierList, SupplierCreate, SupplierUpdate, SupplierDelete = _ref_view(
Supplier, "references:supplier_list", "references:supplier_create",
"references:supplier_update", "references:supplier_delete",
"Поставщики", "Поставщик",
)
# Сотрудники
EmployeeList, EmployeeCreate, EmployeeUpdate, EmployeeDelete = _ref_view(
Employee, "references:employee_list", "references:employee_create",
"references:employee_update", "references:employee_delete",
"Сотрудники", "Сотрудник",
)
# Счета денежных средств
CashAccountList, CashAccountCreate, CashAccountUpdate, CashAccountDelete = _ref_view(
CashAccount, "references:cashaccount_list", "references:cashaccount_create",
"references:cashaccount_update", "references:cashaccount_delete",
"Счета денежных средств", "Счёт денежных средств",
)
# Товары
ProductList, ProductCreate, ProductUpdate, ProductDelete = _ref_view(
Product, "references:product_list", "references:product_create",
"references:product_update", "references:product_delete",
"Товары", "Товар",
)