UPDATE
This commit is contained in:
@@ -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",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("irrigation", "0001_initial"),
|
||||
("sensor_data", "0010_rename_tables_to_farm_data"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="sensordata",
|
||||
name="irrigation_method",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
db_column="irrigation_method_id",
|
||||
help_text="روش آبیاری انتخابشده برای این farm",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="farm_data",
|
||||
to="irrigation.irrigationmethod",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,70 @@
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("sensor_data", "0011_sensordata_irrigation_method"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="PlantCatalogSnapshot",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
("backend_plant_id", models.PositiveIntegerField(db_index=True, help_text="شناسه گیاه در Backend/plants", unique=True)),
|
||||
("name", models.CharField(db_index=True, max_length=255)),
|
||||
("slug", models.SlugField(blank=True, default="", max_length=255)),
|
||||
("icon", models.CharField(blank=True, default="leaf", max_length=255)),
|
||||
("description", models.TextField(blank=True, default="")),
|
||||
("metadata", models.JSONField(blank=True, default=dict)),
|
||||
("light", models.CharField(blank=True, default="", max_length=255)),
|
||||
("watering", models.CharField(blank=True, default="", max_length=255)),
|
||||
("soil", models.CharField(blank=True, default="", max_length=255)),
|
||||
("temperature", models.CharField(blank=True, default="", max_length=255)),
|
||||
("growth_stage", models.CharField(blank=True, default="", max_length=255)),
|
||||
("growth_stages", models.JSONField(blank=True, default=list)),
|
||||
("planting_season", models.CharField(blank=True, default="", max_length=255)),
|
||||
("harvest_time", models.CharField(blank=True, default="", max_length=255)),
|
||||
("spacing", models.CharField(blank=True, default="", max_length=255)),
|
||||
("fertilizer", models.CharField(blank=True, default="", max_length=255)),
|
||||
("health_profile", models.JSONField(blank=True, default=dict)),
|
||||
("irrigation_profile", models.JSONField(blank=True, default=dict)),
|
||||
("growth_profile", models.JSONField(blank=True, default=dict)),
|
||||
("is_active", models.BooleanField(default=True)),
|
||||
("source_updated_at", models.DateTimeField(blank=True, help_text="updated_at رکورد canonical در Backend", null=True)),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "plant catalog snapshot",
|
||||
"verbose_name_plural": "plant catalog snapshots",
|
||||
"db_table": "farm_data_plantcatalogsnapshot",
|
||||
"ordering": ["name", "backend_plant_id"],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="FarmPlantAssignment",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
("position", models.PositiveIntegerField(default=0)),
|
||||
("stage", models.CharField(blank=True, default="", max_length=64)),
|
||||
("metadata", models.JSONField(blank=True, default=dict)),
|
||||
("assigned_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
("farm", models.ForeignKey(db_column="farm_uuid", on_delete=django.db.models.deletion.CASCADE, related_name="plant_assignments", to="sensor_data.sensordata")),
|
||||
("plant", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="farm_assignments", to="sensor_data.plantcatalogsnapshot")),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "farm plant assignment",
|
||||
"verbose_name_plural": "farm plant assignments",
|
||||
"db_table": "farm_data_farmplantassignment",
|
||||
"ordering": ["position", "id"],
|
||||
},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="farmplantassignment",
|
||||
constraint=models.UniqueConstraint(fields=("farm", "plant"), name="farm_data_unique_farm_plant_assignment"),
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user