diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..2eebe8d --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,17 @@ +name: Deploy MES Core +on: + push: + branches: [ main ] + +jobs: + deploy: + runs-on: debian-my # Или твой self-hosted раннер + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Deploy to Production + run: | + docker compose up -d --build + docker compose exec -T web python manage.py migrate + docker compose exec -T web python manage.py collectstatic --noinput \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..74fbcdb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.12-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY . . +CMD ["gunicorn", "--bind", "0.0.0.0:8000", "core.wsgi:application"] \ No newline at end of file diff --git a/core/settings.py b/core/settings.py index 46f3d40..a364313 100644 --- a/core/settings.py +++ b/core/settings.py @@ -11,6 +11,12 @@ https://docs.djangoproject.com/en/6.0/ref/settings/ """ from pathlib import Path +import environ + + +env = environ.Env() +environ.Env.read_env() # Читаем файл .env + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -37,6 +43,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'shiftflow', # Вот это допиши обязательно! ] MIDDLEWARE = [ @@ -73,10 +80,7 @@ WSGI_APPLICATION = 'core.wsgi.application' # https://docs.djangoproject.com/en/6.0/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', - } + 'default': env.db('DATABASE_URL', default='sqlite:///db.sqlite3') } @@ -102,9 +106,9 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/6.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' +# Язык и время +LANGUAGE_CODE = 'ru-ru' +TIME_ZONE = 'Europe/Moscow' USE_I18N = True diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ad525a4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +services: + web: + build: . + container_name: mes_core_web + volumes: + - .:/app + ports: + - "8000:8000" + env_file: + - .env + restart: always \ No newline at end of file diff --git a/shiftflow/admin.py b/shiftflow/admin.py index 8c38f3f..b3a99f5 100644 --- a/shiftflow/admin.py +++ b/shiftflow/admin.py @@ -1,3 +1,12 @@ from django.contrib import admin +from .models import Machine, Item -# Register your models here. +@admin.register(Machine) +class MachineAdmin(admin.ModelAdmin): + list_display = ('name',) + +@admin.register(Item) +class ItemAdmin(admin.ModelAdmin): + list_display = ('date', 'machine', 'deal', 'drawing_name', 'quantity_plan', 'quantity_fact', 'status') + list_filter = ('date', 'machine', 'status') + search_fields = ('deal', 'drawing_name') \ No newline at end of file diff --git a/shiftflow/migrations/0001_initial.py b/shiftflow/migrations/0001_initial.py new file mode 100644 index 0000000..f3a11dd --- /dev/null +++ b/shiftflow/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 6.0.3 on 2026-03-27 14:24 + +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Machine', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, verbose_name='Станок')), + ], + options={ + 'verbose_name': 'Станок', + 'verbose_name_plural': 'Станки', + }, + ), + migrations.CreateModel( + name='Item', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField(default=django.utils.timezone.now, verbose_name='Дата')), + ('deal', models.CharField(max_length=100, verbose_name='№ Сделки')), + ('drawing_name', models.CharField(max_length=255, verbose_name='Чертеж / Деталь')), + ('material', models.CharField(max_length=255, verbose_name='Материал')), + ('dim_value', models.FloatField(help_text='Длина реза или толщина листа', verbose_name='Размер (мм)')), + ('quantity_plan', models.PositiveIntegerField(verbose_name='План, шт')), + ('quantity_fact', models.PositiveIntegerField(default=0, verbose_name='Факт, шт')), + ('priority', models.PositiveIntegerField(default=10, verbose_name='Приоритет')), + ('status', models.CharField(choices=[('new', 'В задании'), ('work', 'В работе'), ('done', 'Выполнено')], default='new', max_length=10, verbose_name='Статус')), + ('machine', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='shiftflow.machine', verbose_name='Станок')), + ], + options={ + 'verbose_name': 'Позиция', + 'verbose_name_plural': 'Сменное задание', + 'ordering': ['-date', 'priority'], + }, + ), + ]