Skip to content

Commit 6e1c886

Browse files
authored
Merge pull request #49 from openagri-eu/main
Sync AgStack repository with Openagri-eu fork
2 parents d4c1537 + feaf5f7 commit 6e1c886

15 files changed

Lines changed: 1157 additions & 310 deletions

File tree

.github/workflows/docker-image.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ name: Docker Image CI
33
on:
44
push:
55
branches: [ main ]
6+
workflow_dispatch:
7+
inputs:
8+
branch:
9+
description: 'Branch to run the workflow on'
10+
required: false
11+
release:
12+
types:
13+
- created
614

715
jobs:
816
build-and-push:

CONTRIBUTE.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Contributing to Reporting Service
2+
3+
We’re excited that you’re interested in contributing to Reporting Service! 🎉
4+
This project is licensed under the EUPL v1.2 and welcomes contributors of all backgrounds and experience levels.
5+
6+
## 🚀 How to Contribute
7+
8+
### Fork & Clone
9+
10+
- Fork the repository on GitHub.
11+
12+
- Clone your fork locally:
13+
14+
git clone https://github.com/your-username/reporting-service.git
15+
cd reporting-service
16+
17+
### Create a Branch
18+
19+
Always create a new branch for your work:
20+
21+
git checkout -b feature/my-new-feature
22+
23+
### Make Your Changes
24+
25+
Add or update tests when making changes.
26+
27+
### Commit & Push
28+
29+
Write clear, descriptive commit messages:
30+
31+
git commit -m "Add support for caching pdf reports"
32+
git push origin feature/my-new-feature
33+
34+
### Open a Pull Request
35+
36+
Go to the main repo and open a PR (Pull Request).
37+
38+
Describe:
39+
40+
- What your change does
41+
42+
- Why it’s needed
43+
44+
- Any related issues
45+
46+
Maintainers will review your PR and may request changes. Don’t worry — feedback is part of the process!
47+
48+
49+
### 📝 Reporting Issues
50+
51+
Check the issue tracker first.
52+
53+
If not already reported, open a new issue with:
54+
55+
- A clear description
56+
57+
- Steps to reproduce (if a bug)
58+
59+
- Expected vs actual behavior
60+
61+
### 🌱 First-Time Contributors
62+
63+
We especially welcome first-time contributors! Some good first steps:
64+
65+
Look for issues labeled good first issue.
66+
67+
Improve documentation (typos, examples, guides).
68+
69+
Add tests for untested parts of the code.
70+
71+
### 🙏 Acknowledgments
72+
73+
Every contribution — big or small — matters. Thank you for helping improve!

README.md

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
The reporting service generates .pdf reports based on information present in datasets.\
77
These datasets are required to conform to the OCSM (OpenAgri Common Semantic Model) as well as be JSON-LD compliant.
88

9+
# Roadmap
10+
11+
High-level next steps for the Reporting Service:
12+
13+
- [ ] Implement PDF reports for irrigation fertilization
14+
- [ ] Integrate with additional 3rd party Open Street Maps API for satelite images
15+
- [ ] Update PDF reports design and tables to be more adaptive for different use cases
16+
917
# Requirements
1018
<ul>
1119
<li>git</li>
@@ -52,7 +60,7 @@ docker compose up
5260

5361
The application will be served on http://127.0.0.1:8009 (I.E. typing localhost/docs in your browser will load the swagger documentation)
5462

55-
Full list of APIs available you can check [here](https://editor-next.swagger.io/?url=https://gist.githubusercontent.com/JoleVLF/b1bcdd77ac82aeb115a6c94fb3dadbdc/raw/32df1d94947b67dcc70f730a629d7c91161e532f/api.json)
63+
Full list of APIs available you can check [here](https://editor-next.swagger.io/?url=https://gist.githubusercontent.com/JoleVLF/c29adf44808a683149426912383c75eb/raw/7b57a845ab37954424c0ef2108962fd248c6966f/api_v4.json)
5664
# Documentation
5765
<h3>GET</h3>
5866

@@ -79,12 +87,26 @@ Response is generated PDF file.
7987

8088
## Request Params
8189

90+
### irrigation_id
91+
- **Type**: `uudi str`
92+
- **Description**: ID of irrigation operation for which PDF is generated (optional)
93+
8294
### data
8395
- **Type**: `UploadFile`
8496
- **Description**: API processes the data directly to generate the report if data passed. This parameter is not required and when it is, must be provided as an `UploadFile`.
8597

98+
- ### from_date
99+
- **Type**: `date`
100+
- **Description**: Optional date filter (from which data is filtered)
86101

102+
- ### to_date
103+
- **Type**: `date`
104+
- **Description**: AOptional date filter (until which data is filtered)
87105

106+
- ### parcel_id
107+
- **Type**: `str`
108+
- **Description**: Optional parcel filter.
109+
-
88110
## Response
89111

90112
Response is uuid of generated PDF file.
@@ -97,14 +119,26 @@ Response is uuid of generated PDF file.
97119

98120
## Request Params
99121

100-
### observation_type_name
122+
### calendar_activity_type
123+
- **Type**: `str`
124+
- **Description**: All Farm Calendar Observation Type values are possible as input (optional). If operation_id provided not used.
125+
126+
### operation_id
127+
- **Type**: `uudi str`
128+
- **Description**: ID of operation for which PDF is generated (optional)
129+
130+
- ### from_date
131+
- **Type**: `date`
132+
- **Description**: Optional date filter (from which data is filtered). If operation_id provided not used.
133+
134+
- ### to_date
135+
- **Type**: `date`
136+
- **Description**: Optional date filter (until which data is filtered). If operation_id provided not used.
137+
138+
- ### parcel_id
101139
- **Type**: `str`
102-
- **Description**: The name of the observation type for the report. The value of this parameter must be one of the following options:
103-
- "Pesticides"
104-
- "Irrigation"
105-
- "Fertilization"
106-
- "CropStressIndicator"
107-
- "CropGrowthObservation"
140+
- **Description**: Optional parcel filter (When operation id not used).
141+
108142

109143
### data
110144
- **Type**: `UploadFile`
@@ -129,6 +163,10 @@ When service is run without Gatekeeper data must be provided in .json file forma
129163

130164
## Request Params
131165

166+
### farm_animal_id
167+
- **Type**: `uudi str`
168+
- **Description**: ID of FarmAnimal record for which PDF is generated (optional)
169+
132170
### animal_group
133171
- **Type**: `Optional[str]`
134172
- **Description**: The group or category the animal belongs to. This is an optional string field, and it can be left as `None` if not applicable.
@@ -145,6 +183,18 @@ When service is run without Gatekeeper data must be provided in .json file forma
145183
- **Type**: `Optional[int]`
146184
- **Description**: The status code associated with the animal or the transaction. It is an optional integer field. If not specified, it defaults to `None`.
147185

186+
- ### from_date
187+
- **Type**: `date`
188+
- **Description**: Optional date filter (from which data is filtered)
189+
190+
- ### to_date
191+
- **Type**: `date`
192+
- **Description**: AOptional date filter (until which data is filtered)
193+
194+
- ### parcel_id
195+
- **Type**: `str`
196+
- **Description**: Optional parcel filter.
197+
148198
### data
149199
- **Type**: `UploadFile`
150200
- **Description**: API processes the data directly to generate the report if data passed. This parameter is not required and when it is, must be provided as an `UploadFile`.
@@ -172,8 +222,15 @@ This will run the tests and return success values for each api tested in the ter
172222

173223
<h3>These tests will NOT result in generated .pdf files.</h3>
174224

175-
# Contribution
176-
Please contact the maintainer of this repository.
225+
## Contributing
226+
227+
We welcome first-time contributions!
228+
229+
See our [Contributing Guide](CONTRIBUTE.md)
230+
231+
You can also open an issue to discuss ideas.
232+
233+
Reporting Service is part of OpenAgri project, building tools for agriculture & climate data. Your contribution helps farmers and researchers.
177234

178235
# License
179236
This project code is licensed under the EUPL 1.2 license, see the [LICENSE](https://github.com/agstack/OpenAgri-ReportingService/blob/main/LICENSE) file for more details.

app/api/api_v1/endpoints/report.py

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import os
23
import uuid
34
from typing import Optional
@@ -23,7 +24,7 @@
2324
router = APIRouter()
2425

2526

26-
@router.get("/{report_id}", response_class=FileResponse)
27+
@router.get("/{report_id}/", response_class=FileResponse)
2728
def retrieve_generated_pdf(
2829
report_id: str,
2930
token=Depends(deps.get_current_user),
@@ -56,7 +57,11 @@ def retrieve_generated_pdf(
5657
async def generate_irrigation_report(
5758
background_tasks: BackgroundTasks,
5859
token=Depends(deps.get_current_user),
60+
irrigation_id: str = None,
5961
data: UploadFile = None,
62+
from_date: datetime.date = None,
63+
to_date: datetime.date = None,
64+
parcel_id: str = None
6065
):
6166
"""
6267
Generates Irrigation Report PDF file
@@ -75,49 +80,58 @@ async def generate_irrigation_report(
7580
status_code=400,
7681
detail=f"Data file must be provided if gatekeeper is not used.",
7782
)
78-
83+
if data:
84+
data = data.file.read()
7985
background_tasks.add_task(
8086
process_irrigation_data,
8187
data=data,
8288
token=token,
8389
pdf_file_name=uuid_of_pdf,
90+
from_date=from_date,
91+
to_date=to_date,
92+
irrigation_id=irrigation_id,
93+
parcel_id=parcel_id
8494
)
8595

8696
return PDF(uuid=uuid_v4)
8797

8898

8999
@router.post("/compost-report/", response_model=PDF)
90100
async def generate_generic_observation_report(
91-
observation_type_name: str,
92101
background_tasks: BackgroundTasks,
102+
calendar_activity_type: str = None,
93103
token=Depends(deps.get_current_user),
94104
data: UploadFile = None,
105+
operation_id: str = None,
106+
from_date: datetime.date = None,
107+
to_date: datetime.date = None,
108+
parcel_id: str = None
95109
):
96110
"""
97111
Generates Observation Report PDF file
98-
possible_names = ["Pesticides", "Irrigation", "Fertilization", "CropStressIndicator", "CropGrowthObservation"]
99-
112+
All Farm Calendar Observation Type values are possible as input
100113
101114
"""
102-
if observation_type_name == "CropGrowthObservation":
103-
observation_type_name = "Crop Growth Stage Observation"
104115

105-
if observation_type_name == "CropStressIndicator":
106-
observation_type_name = "Crop Stress Indicator"
107116
uuid_v4 = str(uuid.uuid4())
108117
user_id = (
109118
decode_jwt_token(token)["user_id"]
110119
if settings.REPORTING_USING_GATEKEEPER
111120
else token.id
112121
)
113122
uuid_of_pdf = f"{user_id}/{uuid_v4}"
114-
123+
if data:
124+
data = data.file.read()
115125
background_tasks.add_task(
116126
process_farm_calendar_data,
117-
observation_type_name=observation_type_name,
127+
calendar_activity_type=calendar_activity_type,
118128
token=token,
119129
data=data,
120130
pdf_file_name=uuid_of_pdf,
131+
operation_id=operation_id,
132+
from_date=from_date,
133+
to_date=to_date,
134+
parcel_id=parcel_id
121135
)
122136

123137
return PDF(uuid=uuid_v4)
@@ -127,11 +141,15 @@ async def generate_generic_observation_report(
127141
async def generate_animal_report(
128142
background_tasks: BackgroundTasks,
129143
token=Depends(deps.get_current_user),
144+
farm_animal_id: str = None,
130145
animal_group: Optional[str] = None,
131146
name: Optional[str] = None,
132147
parcel: Optional[UUID4] = None,
133148
status: Optional[int] = None,
134149
data: UploadFile = None,
150+
from_date: datetime.date = None,
151+
to_date: datetime.date = None,
152+
parcel_id: str = None
135153
):
136154
"""
137155
Generates Animal Report PDF file
@@ -151,7 +169,7 @@ async def generate_animal_report(
151169
detail=f"Data file must be provided if gatekeeper is not used.",
152170
)
153171

154-
params = {"format": "json"}
172+
params = {}
155173
if animal_group:
156174
params["animal_group"] = animal_group
157175
if name:
@@ -160,13 +178,19 @@ async def generate_animal_report(
160178
params["parcel"] = str(parcel)
161179
if status is not None:
162180
params["status"] = status
163-
181+
if parcel_id:
182+
params['parcel'] = parcel_id
183+
if data:
184+
data = data.file.read()
164185
background_tasks.add_task(
165186
process_animal_data,
166187
data=data,
167188
token=token,
168189
params=params,
169190
pdf_file_name=uuid_of_pdf,
191+
from_date=from_date,
192+
to_date=to_date,
193+
farm_animal_id=farm_animal_id,
170194
)
171195

172196
return PDF(uuid=uuid_v4)

app/api/deps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def get_current_user(
3636
json={"token": token, "token_type": "access"},
3737
)
3838

39-
if response.status_code == 400:
39+
if str(response.status_code)[0] != "2":
4040
raise HTTPException(status_code=400, detail="Error, bad jwt token.")
4141
return token
4242
else:

app/core/config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ class Settings(BaseSettings):
2727
"irrigations": "/IrrigationOperations/",
2828
"activity_types": "/FarmCalendarActivityTypes/",
2929
"observations": "/Observations/",
30+
"operations": "/CompostOperations/",
31+
"turning_operations": "/CompostTurningOperations/",
3032
"activities": "/FarmCalendarActivities/",
3133
"parcel": "/FarmParcels/",
3234
"animals": "/FarmAnimals/",
35+
"materials": "/AddRawMaterialOperations/",
36+
"machines": "/AgriculturalMachines/",
37+
"farm": "/Farm/"
3338
}
3439

3540
PDF_DIRECTORY: str = "user_reports/"

0 commit comments

Comments
 (0)