Docs: начальная структура проекта
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
20
app/references/admin.py
Normal file
20
app/references/admin.py
Normal 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
7
app/references/apps.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ReferencesConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "references"
|
||||
verbose_name = "Справочники"
|
||||
103
app/references/migrations/0001_initial.py
Normal file
103
app/references/migrations/0001_initial.py
Normal 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': 'Поставщики',
|
||||
},
|
||||
),
|
||||
]
|
||||
0
app/references/migrations/__init__.py
Normal file
0
app/references/migrations/__init__.py
Normal file
101
app/references/models.py
Normal file
101
app/references/models.py
Normal 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
39
app/references/urls.py
Normal 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
131
app/references/views.py
Normal 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",
|
||||
"Товары", "Товар",
|
||||
)
|
||||
Reference in New Issue
Block a user