This commit is contained in:
2026-04-06 23:50:24 +03:30
parent a67236d45c
commit ff464cb4a5
140 changed files with 2061 additions and 2702 deletions
+88
View File
@@ -0,0 +1,88 @@
# Generated by Django 5.2.11 on 2026-02-27 09:47
import django.db.models.deletion
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('location_data', '0002_soildepthdata_refactor'),
]
operations = [
migrations.CreateModel(
name='SensorDataHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid_sensor', models.UUIDField(help_text='شناسه سنسور')),
('location_id', models.IntegerField(help_text='location_id از location_data')),
('soil_moisture', models.FloatField(blank=True, null=True)),
('soil_temperature', models.FloatField(blank=True, null=True)),
('soil_ph', models.FloatField(blank=True, null=True)),
('electrical_conductivity', models.FloatField(blank=True, null=True)),
('nitrogen', models.FloatField(blank=True, null=True)),
('phosphorus', models.FloatField(blank=True, null=True)),
('potassium', models.FloatField(blank=True, null=True)),
('recorded_at', models.DateTimeField(auto_now_add=True, help_text='زمان ثبت در تاریخچه')),
],
options={
'verbose_name': 'تاریخچه داده سنسور',
'verbose_name_plural': 'تاریخچه داده\u200cهای سنسور',
'ordering': ['-recorded_at'],
},
),
migrations.CreateModel(
name='SensorParameter',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.CharField(db_index=True, help_text='کد یکتا (مثلاً soil_moisture)', max_length=64, unique=True)),
('name_fa', models.CharField(help_text='نام فارسی', max_length=128)),
('unit', models.CharField(blank=True, help_text='واحد اندازه\u200cگیری', max_length=32)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'پارامتر سنسور',
'verbose_name_plural': 'پارامترهای سنسور',
'ordering': ['code'],
},
),
migrations.CreateModel(
name='SensorData',
fields=[
('uuid_sensor', models.UUIDField(default=uuid.uuid4, editable=False, help_text='شناسه یکتای سنسور', primary_key=True, serialize=False)),
('soil_moisture', models.FloatField(blank=True, help_text='رطوبت خاک', null=True)),
('soil_temperature', models.FloatField(blank=True, help_text='دما خاک', null=True)),
('soil_ph', models.FloatField(blank=True, help_text='pH خاک', null=True)),
('electrical_conductivity', models.FloatField(blank=True, help_text='هدایت الکتریکی', null=True)),
('nitrogen', models.FloatField(blank=True, help_text='ازت (N)', null=True)),
('phosphorus', models.FloatField(blank=True, help_text='فسفر', null=True)),
('potassium', models.FloatField(blank=True, help_text='پتاسیم', null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('location', models.ForeignKey(db_column='location_id', help_text='همان location_id در location_data', on_delete=django.db.models.deletion.CASCADE, related_name='sensor_data', to='location_data.soillocation')),
],
options={
'verbose_name': 'داده سنسور',
'verbose_name_plural': 'داده\u200cهای سنسور',
'ordering': ['-updated_at'],
},
),
migrations.CreateModel(
name='ParameterUpdateLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('action', models.CharField(choices=[('added', 'اضافه شده'), ('modified', 'ویرایش شده')], max_length=16)),
('updated_at', models.DateTimeField(auto_now_add=True)),
('parameter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='update_logs', to='sensor_data.sensorparameter')),
],
options={
'verbose_name': 'لاگ آپدیت پارامتر',
'verbose_name_plural': 'لاگ آپدیت پارامترها',
'ordering': ['-updated_at'],
},
),
]
@@ -0,0 +1,13 @@
# Generated by Django 5.2.11 on 2026-02-27 09:48
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sensor_data', '0001_initial'),
]
operations = [
]
@@ -0,0 +1,19 @@
# Generated by Django 5.2.12 on 2026-03-19 15:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('plant', '0001_initial'),
('sensor_data', '0002_seed_initial_parameters'),
]
operations = [
migrations.AddField(
model_name='sensordata',
name='plants',
field=models.ManyToManyField(blank=True, help_text='گیاهان مرتبط با این سنسور', related_name='sensor_data', to='plant.plant'),
),
]
@@ -0,0 +1,20 @@
# Generated by Django 5.1.15 on 2026-03-27 08:40
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('location_data', '0005_merge_20260327_0840'),
('sensor_data', '0003_sensordata_plants'),
]
operations = [
migrations.AlterField(
model_name='sensordata',
name='location',
field=models.ForeignKey(db_column='location_id', help_text='همان location_id از location_data', on_delete=django.db.models.deletion.CASCADE, related_name='sensor_data', to='location_data.soillocation'),
),
]
@@ -0,0 +1,14 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("sensor_data", "0004_alter_sensordata_location"),
]
operations = [
migrations.DeleteModel(
name="SensorDataHistory",
),
]
@@ -0,0 +1,139 @@
from django.db import migrations, models
DEFAULT_SENSOR_KEY = "sensor-7-1"
def migrate_sensor_fields_to_payload(apps, schema_editor):
SensorData = apps.get_model("sensor_data", "SensorData")
field_names = [
"soil_moisture",
"soil_temperature",
"soil_ph",
"electrical_conductivity",
"nitrogen",
"phosphorus",
"potassium",
]
for sensor in SensorData.objects.all().iterator():
values = {}
for field_name in field_names:
value = getattr(sensor, field_name, None)
if value is not None:
values[field_name] = value
sensor.sensor_payload = {DEFAULT_SENSOR_KEY: values} if values else {}
sensor.save(update_fields=["sensor_payload"])
class Migration(migrations.Migration):
dependencies = [
("sensor_data", "0005_delete_sensordatahistory"),
]
operations = [
migrations.AddField(
model_name="sensordata",
name="sensor_payload",
field=models.JSONField(
blank=True,
default=dict,
help_text='اطلاعات سنسورها در فرمت {"sensor-7-1": {...}}',
),
),
migrations.AddField(
model_name="sensorparameter",
name="sensor_key",
field=models.CharField(
db_index=True,
default=DEFAULT_SENSOR_KEY,
help_text='کلید سنسور داخل JSON مثل "sensor-7-1" یا "leaf-sensor"',
max_length=64,
),
),
migrations.AddField(
model_name="sensorparameter",
name="data_type",
field=models.CharField(
default="float",
help_text="نوع داده پارامتر مثل float, int, string, bool",
max_length=32,
),
),
migrations.AddField(
model_name="sensorparameter",
name="metadata",
field=models.JSONField(
blank=True,
default=dict,
help_text="اطلاعات تکمیلی پارامتر مثل بازه مجاز، توضیح یا تنظیمات UI",
),
),
migrations.AddField(
model_name="parameterupdatelog",
name="payload",
field=models.JSONField(
blank=True,
default=dict,
help_text="خلاصه تغییرات پارامتر برای audit",
),
),
migrations.RunPython(
migrate_sensor_fields_to_payload,
migrations.RunPython.noop,
),
migrations.RemoveField(
model_name="sensordata",
name="soil_moisture",
),
migrations.RemoveField(
model_name="sensordata",
name="soil_temperature",
),
migrations.RemoveField(
model_name="sensordata",
name="soil_ph",
),
migrations.RemoveField(
model_name="sensordata",
name="electrical_conductivity",
),
migrations.RemoveField(
model_name="sensordata",
name="nitrogen",
),
migrations.RemoveField(
model_name="sensordata",
name="phosphorus",
),
migrations.RemoveField(
model_name="sensordata",
name="potassium",
),
migrations.AlterField(
model_name="sensorparameter",
name="code",
field=models.CharField(
db_index=True,
help_text="کد پارامتر (مثلاً soil_moisture)",
max_length=64,
),
),
migrations.AlterModelOptions(
name="sensorparameter",
options={
"ordering": ["sensor_key", "code"],
"verbose_name": "پارامتر سنسور",
"verbose_name_plural": "پارامترهای سنسور",
},
),
migrations.AddConstraint(
model_name="sensorparameter",
constraint=models.UniqueConstraint(
fields=("sensor_key", "code"),
name="sensor_parameter_unique_sensor_code",
),
),
]
@@ -0,0 +1,16 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("sensor_data", "0006_sensor_payload_and_dynamic_parameters"),
]
operations = [
migrations.RenameField(
model_name="sensordata",
old_name="uuid_sensor",
new_name="farm_uuid",
),
]
@@ -0,0 +1,29 @@
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("location_data", "0005_merge_20260327_0840"),
("sensor_data", "0007_rename_uuid_sensor_to_farm_uuid"),
]
operations = [
migrations.RenameField(
model_name="sensordata",
old_name="location",
new_name="center_location",
),
migrations.AlterField(
model_name="sensordata",
name="center_location",
field=models.ForeignKey(
db_column="center_location_id",
help_text="مرکز زمین مرتبط از جدول location_data.SoilLocation",
on_delete=django.db.models.deletion.CASCADE,
related_name="farm_data",
to="location_data.soillocation",
),
),
]
@@ -0,0 +1,45 @@
import django.db.models.deletion
from django.db import migrations, models
def link_latest_weather_forecast(apps, schema_editor):
SensorData = apps.get_model("sensor_data", "SensorData")
WeatherForecast = apps.get_model("weather", "WeatherForecast")
for farm_data in SensorData.objects.all().iterator():
forecast = (
WeatherForecast.objects.filter(location_id=farm_data.center_location_id)
.order_by("-forecast_date", "-id")
.first()
)
if forecast:
farm_data.weather_forecast_id = forecast.id
farm_data.save(update_fields=["weather_forecast"])
class Migration(migrations.Migration):
dependencies = [
("sensor_data", "0008_rename_location_to_center_location"),
("weather", "0003_seed_weather_forecasts"),
]
operations = [
migrations.AddField(
model_name="sensordata",
name="weather_forecast",
field=models.ForeignKey(
blank=True,
db_column="weather_forecast_id",
help_text="رکورد آب وهوای مرتبط با مرکز زمین",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="farm_data_entries",
to="weather.weatherforecast",
),
),
migrations.RunPython(
link_latest_weather_forecast,
migrations.RunPython.noop,
),
]
@@ -0,0 +1,44 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("sensor_data", "0009_add_weather_forecast_to_sensordata"),
]
operations = [
migrations.AlterField(
model_name="sensordata",
name="farm_uuid",
field=models.UUIDField(
editable=False,
help_text="شناسه یکتای farm که از API دریافت می‌شود",
primary_key=True,
serialize=False,
),
),
migrations.AlterField(
model_name="sensordata",
name="plants",
field=models.ManyToManyField(
blank=True,
db_table="farm_data_sensordata_plants",
help_text="گیاهان مرتبط با این farm",
related_name="farm_data",
to="plant.plant",
),
),
migrations.AlterModelTable(
name="sensordata",
table="farm_data_sensordata",
),
migrations.AlterModelTable(
name="sensorparameter",
table="farm_data_sensorparameter",
),
migrations.AlterModelTable(
name="parameterupdatelog",
table="farm_data_parameterupdatelog",
),
]
View File