agroplan-ai-cli 1.0.32 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli_version": "1.0.32",
3
- "backend_template_version": "1.0.32",
2
+ "cli_version": "1.0.33",
3
+ "backend_template_version": "1.0.33",
4
4
  "zarc_index_version": "2025-2026-fast-index-v2",
5
5
  "price_index_version": "2025-05-reference-v1",
6
6
  "features": [
@@ -21,7 +21,8 @@
21
21
  "smart_crop_calendar_engine",
22
22
  "manual_field_registration",
23
23
  "crop_calendar_from_manual_field",
24
- "expanded_crop_calendar_10_cultures"
24
+ "expanded_crop_calendar_10_cultures",
25
+ "calendar_date_safety"
25
26
  ],
26
- "generated_at": "2026-05-10T18:30:00Z"
27
+ "generated_at": "2026-05-10T20:00:00Z"
27
28
  }
@@ -875,6 +875,48 @@ def gerar_calendario_cultura(
875
875
  # Ordenar tarefas por data
876
876
  tasks.sort(key=lambda t: t.date)
877
877
 
878
+ # Detectar e ajustar tarefas no passado
879
+ today = date.today()
880
+ adjusted_tasks_count = 0
881
+ calendar_warnings = []
882
+
883
+ for task in tasks:
884
+ if task.date < today:
885
+ # Marcar tarefa como ajustada
886
+ task.original_date = task.date
887
+ task.date = today
888
+ task.adjusted = True
889
+
890
+ # Aumentar prioridade se não for crítica
891
+ if task.priority != TaskPriority.CRITICAL:
892
+ task.priority = TaskPriority.HIGH
893
+
894
+ # Adicionar observação à descrição
895
+ task.description += f" [AJUSTADA: Data original era {task.original_date.isoformat()}, mas já passou. Tarefa reagendada para hoje.]"
896
+
897
+ adjusted_tasks_count += 1
898
+
899
+ # Adicionar avisos se houver tarefas ajustadas
900
+ if adjusted_tasks_count > 0:
901
+ calendar_warnings.append(
902
+ f"{adjusted_tasks_count} tarefa(s) foram ajustadas porque a data original já havia passado. "
903
+ "Considere escolher uma data de plantio mais distante no futuro."
904
+ )
905
+
906
+ # Verificar se data de plantio está muito próxima
907
+ days_until_planting = (planting_date - today).days
908
+ if days_until_planting <= 7 and days_until_planting >= 0:
909
+ calendar_warnings.append(
910
+ f"Sua data de plantio está em {days_until_planting} dia(s). "
911
+ "Tarefas preparatórias podem ter sido ajustadas. "
912
+ "Recomendamos planejar com pelo menos 2 semanas de antecedência."
913
+ )
914
+ elif days_until_planting < 0:
915
+ calendar_warnings.append(
916
+ "A data de plantio escolhida já passou. "
917
+ "O calendário foi ajustado, mas recomendamos escolher uma data futura."
918
+ )
919
+
878
920
  # Montar resposta
879
921
  return {
880
922
  "cultura": cultura,
@@ -906,6 +948,9 @@ def gerar_calendario_cultura(
906
948
  "total_tasks": len(tasks),
907
949
  "weather_sensitive_tasks": sum(1 for task in tasks if task.weather_sensitive),
908
950
  "critical_tasks": sum(1 for task in tasks if task.priority == TaskPriority.CRITICAL),
951
+ "has_adjusted_tasks": adjusted_tasks_count > 0,
952
+ "adjusted_tasks_count": adjusted_tasks_count,
953
+ "calendar_warnings": calendar_warnings,
909
954
  "cautela": "Este calendário é uma base inicial de planejamento. As datas e tarefas devem ser ajustadas conforme clima, solo, cultivar, manejo e orientação técnica."
910
955
  }
911
956
 
@@ -259,9 +259,11 @@ class CalendarTask:
259
259
  status: TaskStatus = TaskStatus.PENDING
260
260
  weather_sensitive: bool = False
261
261
  completed_at: Optional[datetime] = None
262
+ adjusted: bool = False # Se a tarefa foi ajustada por estar no passado
263
+ original_date: Optional[date] = None # Data original antes do ajuste
262
264
 
263
265
  def to_dict(self) -> Dict:
264
- return {
266
+ result = {
265
267
  "id": self.id,
266
268
  "crop_plan_id": self.crop_plan_id,
267
269
  "date": self.date.isoformat(),
@@ -272,8 +274,14 @@ class CalendarTask:
272
274
  "source": self.source,
273
275
  "status": self.status.value,
274
276
  "weather_sensitive": self.weather_sensitive,
275
- "completed_at": self.completed_at.isoformat() if self.completed_at else None
277
+ "completed_at": self.completed_at.isoformat() if self.completed_at else None,
278
+ "adjusted": self.adjusted
276
279
  }
280
+
281
+ if self.original_date:
282
+ result["original_date"] = self.original_date.isoformat()
283
+
284
+ return result
277
285
 
278
286
 
279
287
  @dataclass
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agroplan-ai-cli",
3
- "version": "1.0.32",
3
+ "version": "1.0.33",
4
4
  "description": "CLI global para AgroPlan AI - modo local acelerado",
5
5
  "type": "module",
6
6
  "bin": {