diff --git a/CHANGELOG.md b/CHANGELOG.md index 1815df9..bb40652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.23.0] - 2025-06-26 + +### Added +- Add year query parameter to Title-I program and top-level endpoints. [#300](https://github.com/policy-design-lab/pdl-api/issues/300) +- Add year query parameter to SNAP endpoints. [#303](https://github.com/policy-design-lab/pdl-api/issues/303) +- Add year query parameter to Crop Insurance endpoints. [#302](https://github.com/policy-design-lab/pdl-api/issues/302) +- Add year query parameter to Title-II program and top-level endpoints. [#301](https://github.com/policy-design-lab/pdl-api/issues/301) + +### Changed +- Update Title II endpoints to include data from 2014 to 2023. [#313](https://github.com/policy-design-lab/pdl-api/issues/313) +- Update Title XI endpoints to include data from 2014 to 2023. [#319](https://github.com/policy-design-lab/pdl-api/issues/319) +- Update API endpoints to make start and end years configurable. [#321](https://github.com/policy-design-lab/pdl-api/issues/321) +- Update ARC PLC data. [#324](https://github.com/policy-design-lab/pdl-api/issues/324) +- Update ARC PLC base acres rules. [#327](https://github.com/policy-design-lab/pdl-api/issues/327) + ## [0.22.0] - 2025-02-26 ### Added - Add back summary endpoint to SNAP. [#271](https://github.com/policy-design-lab/pdl-api/issues/271) - Add top-level endpoints to Title-II. [#270](https://github.com/policy-design-lab/pdl-api/issues/270) +- Add endpoints (proposals and current) to support new model H. [#305](https://github.com/policy-design-lab/pdl-api/issues/305) ### Changed - Change house api path. [#295](https://github.com/policy-design-lab/pdl-api/issues/295) @@ -50,7 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CRP endpoints to use data from the database. [#237](https://github.com/policy-design-lab/pdl-api/issues/237) - ACEP endpoints to use data from the database. [#239](https://github.com/policy-design-lab/pdl-api/issues/239) - RCPP endpoints to use data from the database. [#241](https://github.com/policy-design-lab/pdl-api/issues/241) -- ProgramName attribute has been removed from crop insurance's state-distibution output [#255](https://github.com/polciy-design-lab/pdl-api/issues/255) +- ProgramName attribute has been removed from crop insurance's state-distribution output [#255](https://github.com/polciy-design-lab/pdl-api/issues/255) ## [0.17.0] - 2024-08-28 @@ -85,7 +101,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update Title-4 endpoints to use database calls. [#190](https://github.com/policy-design-lab/pdl-api/issues/190) - Update EQIP IRA data with changed name of US Virgin Islands. [#201](https://github.com/policy-design-lab/pdl-api/issues/201) - Update EQIP IRA state distribution data [#205](https://githoub.com/policy-design-lab/pdl-api/issues/205) -- Update EQIP IRA summary data with future predctions. [#207](https://github.com/policy-design-lab/pdl-api/issues/207) +- Update EQIP IRA summary data with future predictions. [#207](https://github.com/policy-design-lab/pdl-api/issues/207) - Update EQIP IRA state distribution data [#208](https://github.com/policy-design-lab/pdl-api/issues/208) - EQIP IRA state distribution's nationwide data matches with summary [#210](https://github.com/policy-design-lab/pdl-api/issues/210) - EQIP IRA to use only 50 U.S. state data [#212](https://github.com/policy-design-lab/pdl-api/issues/212) @@ -225,6 +241,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Open API specification file. [#50](https://github.com/policy-design-lab/pdl-api/issues/50) +[0.23.0]: https://github.com/policy-design-lab/pdl-api/compare/0.22.0...0.23.0 [0.22.0]: https://github.com/policy-design-lab/pdl-api/compare/0.21.0...0.22.0 [0.21.0]: https://github.com/policy-design-lab/pdl-api/compare/0.20.0...0.21.0 [0.20.0]: https://github.com/policy-design-lab/pdl-api/compare/0.19.0...0.20.0 diff --git a/Dockerfile b/Dockerfile index 6d8bf51..ba0d58c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,23 +2,40 @@ FROM python:3.9-slim ENV POETRY_VIRTUALENVS_CREATE false -RUN apt update && apt upgrade -y +RUN apt update \ + && apt upgrade -y \ + && apt install -y gcc libpq-dev \ + && rm -rf /var/lib/apt/lists/* WORKDIR /usr/src/pdl-api -COPY . . +# Copy app folder and poetry files to the working directory +COPY app /usr/src/pdl-api/app +COPY pyproject.toml poetry.lock README.md /usr/src/pdl-api/ -RUN pip install -U pip -RUN pip install poetry -RUN poetry install +RUN pip install -U pip \ + && pip install poetry \ + && poetry install \ + && pip install --upgrade psycopg2-binary # Upgrade psycopg2-binary to avoid error related to SCRAM-SHA-256 authentication when running locally +# The values of these default environment variables can be overridden at runtime ENV DB_HOST=localhost \ DB_PORT=5432 \ DB_NAME=pdl \ DB_USERNAME=user \ DB_PASSWORD=password \ API_PORT=5000 \ - WORKER=4 + WORKER=4 \ + ALL_PROGRAMS_START_YEAR=2018 \ + ALL_PROGRAMS_END_YEAR=2022 \ + TITLE_I_START_YEAR=2014 \ + TITLE_I_END_YEAR=2021 \ + TITLE_II_START_YEAR=2014 \ + TITLE_II_END_YEAR=2023 \ + CROP_INSURANCE_START_YEAR=2014 \ + CROP_INSURANCE_END_YEAR=2023 \ + SNAP_START_YEAR=2018 \ + SNAP_END_YEAR=2022 WORKDIR /usr/src/pdl-api/app diff --git a/app/controllers/configs.py b/app/controllers/configs.py index f2e4374..607ea46 100644 --- a/app/controllers/configs.py +++ b/app/controllers/configs.py @@ -27,3 +27,20 @@ class to list all configuration settings required for preprocessing and formatti # API port, default to 5000 API_PORT = int(os.getenv('API_PORT', '5000')) + + # PDL data duration parameters + # NOTE: these are the minimum and maximum years for which data will be retrieved from the database for different endpoints + ALL_PROGRAMS_START_YEAR = int(os.getenv('ALL_PROGRAMS_START_YEAR', '2018')) # Landing Page endpoint + ALL_PROGRAMS_END_YEAR = int(os.getenv('ALL_PROGRAMS_END_YEAR', '2022')) # Landing Page endpoint + + TITLE_I_START_YEAR = int(os.getenv('TITLE_I_START_YEAR', '2014')) + TITLE_I_END_YEAR = int(os.getenv('TITLE_I_END_YEAR', '2021')) + + TITLE_II_START_YEAR = int(os.getenv('TITLE_II_START_YEAR', '2014')) + TITLE_II_END_YEAR = int(os.getenv('TITLE_II_END_YEAR', '2023')) + + CROP_INSURANCE_START_YEAR = int(os.getenv('CROP_INSURANCE_START_YEAR', '2014')) + CROP_INSURANCE_END_YEAR = int(os.getenv('CROP_INSURANCE_END_YEAR', '2023')) + + SNAP_START_YEAR = int(os.getenv('SNAP_START_YEAR', '2018')) + SNAP_END_YEAR = int(os.getenv('SNAP_END_YEAR', '2022')) diff --git a/app/controllers/data/title-i/proposals/subtitle-a/arc_plc_payments_proposed.json.gz b/app/controllers/data/title-i/proposals/subtitle-a/arc_plc_payments_proposed.json.gz new file mode 100644 index 0000000..8bd8c4c Binary files /dev/null and b/app/controllers/data/title-i/proposals/subtitle-a/arc_plc_payments_proposed.json.gz differ diff --git a/app/controllers/data/title-i/subtitle-a/arc_plc_payments_current.json.gz b/app/controllers/data/title-i/subtitle-a/arc_plc_payments_current.json.gz new file mode 100644 index 0000000..b27c4de Binary files /dev/null and b/app/controllers/data/title-i/subtitle-a/arc_plc_payments_current.json.gz differ diff --git a/app/controllers/pdl.py b/app/controllers/pdl.py index e0c4f1c..d12471f 100644 --- a/app/controllers/pdl.py +++ b/app/controllers/pdl.py @@ -1,8 +1,10 @@ +import gzip import json import logging import os from collections import OrderedDict -from flask import request +from app.controllers.configs import Config as cfg +from flask import request, Response from sqlalchemy import func, desc, Numeric, BigInteger, Integer, text, or_, and_ import app.utils.jsonutils as jsonutils @@ -29,6 +31,9 @@ COMMOD_MAP_DATA_JSON = "commodities_map_data.json" COMMOD_STATE_DISTRIBUTION_DATA_JSON = "commodities_state_distribution_data.json" COMMOD_SUBPROGRAMS_DATA_JSON = "commodities_subprograms_data.json" +ARC_PLC_DATA_JSON = "arc_plc_payments_current.json.gz" +I_PROPOSALS_SUBTITLE_A_DATA_PATH = os.path.join(TITLE_I_DATA_PATH, "proposals", "subtitle-a") +ARC_PLC_PROPOSAL_DATA_JSON = "arc_plc_payments_proposed.json.gz" I_SUBTITLE_D_DATA_PATH = os.path.join(TITLE_I_DATA_PATH, "subtitle-d") DMC_STATE_DISTRIBUTION_DATA_JSON = "dmc_state_distribution_data.json" DMC_SUBPROGRAMS_DATA_JSON = "dmc_subprograms_data.json" @@ -78,7 +83,7 @@ TITLE_I_NAME = "Title I: Commodities" TITLE_II_NAME = "Title II: Conservation" TITLE_IV_NAME = "Title IV: Nutrition" -TITLE_XI_NAME = "Title IX: Crop Insurance" +TITLE_XI_NAME = "Title XI: Crop Insurance" TITLE_I_SUBTITLE_A_NAME = "Total Commodities Programs, Subtitle A" TITLE_I_SUBTITLE_D_NAME = "Dairy Margin Coverage, Subtitle D" @@ -91,7 +96,6 @@ TITLE_IV_SNAP_PROGRAM_NAME = "Supplemental Nutrition Assistance Program (SNAP)" TITLE_XI_CROP_INSURANCE_PROGRAM_NAME = "Crop Insurance" - def search(): out_json = jsonutils.create_test_message() @@ -100,10 +104,7 @@ def search(): # GET all the entries from summary table def summary_search(): - start_year = 2018 - end_year = 2022 - - endpoint_response = generate_summary_response(start_year, end_year) + endpoint_response = generate_summary_response(cfg.ALL_PROGRAMS_START_YEAR, cfg.ALL_PROGRAMS_END_YEAR) return endpoint_response @@ -204,27 +205,46 @@ def statecodes_search(code=None, name=None): # GET all the entries from states table def allprograms_search(): - start_year = 2018 - end_year = 2022 - - endpoint_response = generate_allprograms_response(start_year, end_year) + endpoint_response = generate_allprograms_response(cfg.ALL_PROGRAMS_START_YEAR, cfg.ALL_PROGRAMS_END_YEAR) return endpoint_response # /pdl/titles/title-i/summary: def titles_title_i_summary_search(): - start_year = 2014 - end_year = 2021 + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) title_id = 100 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_total_summary_response(title_id, start_year, end_year) return endpoint_response # /pdl/titles/title-i/state-distribution: def titles_title_i_state_distribution_search(): - start_year = 2014 - end_year = 2021 + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) title_id = 100 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_total_state_distribution_response(title_id, start_year, end_year) return endpoint_response @@ -254,8 +274,20 @@ def titles_title_i_subtitles_subtitle_a_state_distribution_search(): } logging.error("Subtitle A: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_state_distribution_response(subtitle_id, start_year, end_year) return endpoint_response @@ -270,8 +302,20 @@ def titles_title_i_subtitles_subtitle_a_summary_search(): } logging.error("Subtitle A: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_summary_response(subtitle_id, start_year, end_year) return endpoint_response @@ -286,8 +330,20 @@ def titles_title_i_subtitles_subtitle_d_state_distribution_search(): } logging.error("Subtitle D: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_state_distribution_response(subtitle_id, start_year, end_year) return endpoint_response @@ -302,8 +358,20 @@ def titles_title_i_subtitles_subtitle_d_summary_search(): } logging.error("Subtitle D: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_summary_response(subtitle_id, start_year, end_year) return endpoint_response @@ -318,8 +386,20 @@ def titles_title_i_subtitles_subtitle_e_state_distribution_search(): } logging.error("Subtitle E: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_state_distribution_response(subtitle_id, start_year, end_year) return endpoint_response @@ -334,26 +414,105 @@ def titles_title_i_subtitles_subtitle_e_summary_search(): } logging.error("Subtitle E: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2014 - end_year = 2021 + + min_year, max_year = cfg.TITLE_I_START_YEAR, cfg.TITLE_I_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_i_summary_response(subtitle_id, start_year, end_year) return endpoint_response + +# /pdl/titles/title-i/subtitles/subtitle-a/arc-plc-payments/current +def titles_title_i_subtitles_subtitle_a_arc_plc_payments_current_search(): + # set the file path + arc_plc_current_data = os.path.join(I_SUBTITLE_A_DATA_PATH, ARC_PLC_DATA_JSON) + + with open(arc_plc_current_data, 'rb') as current_data: + file_data = current_data.read() + + response = Response(file_data, mimetype='application/json') + response.headers['Content-Encoding'] = 'gzip' + return response + + +# /pdl/titles/title-i/subtitles/subtitle-a/arc-plc-payments/proposed +def titles_title_i_subtitles_subtitle_a_arc_plc_payments_proposed_search(): + # set the file path + arc_plc_proposed_data = os.path.join(I_PROPOSALS_SUBTITLE_A_DATA_PATH, ARC_PLC_PROPOSAL_DATA_JSON) + + with open(arc_plc_proposed_data, 'rb') as proposed_data: + file_data = proposed_data.read() + + response = Response(file_data, mimetype='application/json') + response.headers['Content-Encoding'] = 'gzip' + return response + + # /pdl/titles/title-ii/summary: def titles_title_ii_summary_search(): - start_year = 2018 - end_year = 2022 - title_id = 101 + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + title_id = get_title_id(TITLE_II_NAME) + if title_id is None: + msg = { + "reason": "No record for the given title name " + TITLE_II_NAME, + "error": "Not found: " + request.url, + } + logging.error("Title II: " + json.dumps(msg)) + return rs_handlers.not_found(msg) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_total_summary_response(title_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/state-distribution: def titles_title_ii_state_distribution_search(): - start_year = 2018 - end_year = 2022 - title_id = 101 + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + title_id = get_title_id(TITLE_II_NAME) + if title_id is None: + msg = { + "reason": "No record for the given title name " + TITLE_II_NAME, + "error": "Not found: " + request.url, + } + logging.error("Title II: " + json.dumps(msg)) + return rs_handlers.not_found(msg) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_total_state_distribution_response(title_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/programs/eqip/map @@ -373,6 +532,10 @@ def titles_title_ii_programs_eqip_map_search(): # /pdl/titles/title-ii/programs/eqip/state-distribution def titles_title_ii_programs_eqip_state_distribution_search(practice_code=None): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_EQIP_PROGRAM_NAME) if program_id is None: msg = { @@ -382,14 +545,26 @@ def titles_title_ii_programs_eqip_state_distribution_search(practice_code=None): logging.error("EQIP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_state_distribution_response(program_id, start_year, end_year, practice_code=practice_code) + return endpoint_response # /pdl/titles/title-ii/programs/eqip/summary def titles_title_ii_programs_eqip_summary_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_EQIP_PROGRAM_NAME) if program_id is None: msg = { @@ -398,14 +573,27 @@ def titles_title_ii_programs_eqip_summary_search(): } logging.error("EQIP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_summary_response(program_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/programs/eqip/practice-names def titles_title_ii_programs_eqip_practice_names_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_EQIP_PROGRAM_NAME) if program_id is None: msg = { @@ -414,9 +602,19 @@ def titles_title_ii_programs_eqip_practice_names_search(): } logging.error("EQIP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + + endpoint_response = generate_title_ii_practice_names_response(program_id, start_year, end_year) + return endpoint_response @@ -497,6 +695,10 @@ def titles_title_ii_programs_csp_map_search(): # /pdl/titles/title-ii/programs/csp/state-distribution def titles_title_ii_programs_csp_state_distribution_search(practice_code=None): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_CSP_PROGRAM_NAME) if program_id is None: msg = { @@ -505,14 +707,27 @@ def titles_title_ii_programs_csp_state_distribution_search(practice_code=None): } logging.error("CSP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_state_distribution_response(program_id, start_year, end_year, practice_code=practice_code) + return endpoint_response # /pdl/titles/title-ii/programs/csp/summary def titles_title_ii_programs_csp_summary_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_CSP_PROGRAM_NAME) if program_id is None: msg = { @@ -521,14 +736,27 @@ def titles_title_ii_programs_csp_summary_search(): } logging.error("CSP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_summary_response(program_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/programs/eqip/practice-names def titles_title_ii_programs_csp_practice_names_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_CSP_PROGRAM_NAME) if program_id is None: msg = { @@ -537,9 +765,18 @@ def titles_title_ii_programs_csp_practice_names_search(): } logging.error("EQIP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_practice_names_response(program_id, start_year, end_year) + return endpoint_response @@ -602,8 +839,13 @@ def titles_title_ii_programs_csp_ira_predicted_search(): return data_json + # /pdl/titles/title-ii/programs/crp/state-distribution def titles_title_ii_programs_crp_state_distribution_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_CRP_PROGRAM_NAME) if program_id is None: msg = { @@ -612,14 +854,27 @@ def titles_title_ii_programs_crp_state_distribution_search(): } logging.error("CRP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_state_distribution_response(program_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/programs/crp/summary def titles_title_ii_programs_crp_summary_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_CRP_PROGRAM_NAME) if program_id is None: msg = { @@ -628,14 +883,27 @@ def titles_title_ii_programs_crp_summary_search(): } logging.error("CRP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_summary_response(program_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/programs/acep/state-distribution def titles_title_ii_programs_acep_state_distribution_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_ACEP_PROGRAM_NAME) if program_id is None: msg = { @@ -644,14 +912,26 @@ def titles_title_ii_programs_acep_state_distribution_search(): } logging.error("ACEP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_state_distribution_response(program_id, start_year, end_year) return endpoint_response # /pdl/titles/title-ii/programs/acep/summary def titles_title_ii_programs_acep_summary_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_ACEP_PROGRAM_NAME) if program_id is None: msg = { @@ -660,14 +940,26 @@ def titles_title_ii_programs_acep_summary_search(): } logging.error("ACEP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_summary_response(program_id, start_year, end_year) return endpoint_response # /pdl/titles/title-ii/programs/rcpp/state-distribution def titles_title_ii_programs_rcpp_state_distribution_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_RCPP_PROGRAM_NAME) if program_id is None: msg = { @@ -676,14 +968,26 @@ def titles_title_ii_programs_rcpp_state_distribution_search(): } logging.error("RCPP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_state_distribution_response(program_id, start_year, end_year) return endpoint_response # /pdl/titles/title-ii/programs/rcpp/summary def titles_title_ii_programs_rcpp_summary_search(): + min_year, max_year = cfg.TITLE_II_START_YEAR, cfg.TITLE_II_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + program_id = get_program_id(TITLE_II_RCPP_PROGRAM_NAME) if program_id is None: msg = { @@ -692,9 +996,18 @@ def titles_title_ii_programs_rcpp_summary_search(): } logging.error("RCPP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Return all data if invalid range + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_ii_summary_response(program_id, start_year, end_year) + return endpoint_response # /pdl/titles/title-ii/proposals/2024/house/eqip/predicted @@ -711,6 +1024,7 @@ def titles_title_ii_proposals_2024_house_eqip_predicted_search(): return data_json + # /pdl/titles/title-ii/proposals/2024/house/eqip/practice-names def titles_title_ii_proposals_2024_house_eqip_practice_names_search(): # set the file path @@ -725,6 +1039,7 @@ def titles_title_ii_proposals_2024_house_eqip_practice_names_search(): return data_json + # /pdl/titles/title-xi/programs/crop-insurance/state-distribution def titles_title_xi_programs_crop_insurance_state_distribution_search(): program_id = get_program_id(TITLE_XI_CROP_INSURANCE_PROGRAM_NAME) @@ -735,8 +1050,20 @@ def titles_title_xi_programs_crop_insurance_state_distribution_search(): } logging.error("Crop Insurance: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + min_year, max_year = cfg.CROP_INSURANCE_START_YEAR, cfg.CROP_INSURANCE_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to the earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_xi_state_distribution_response(program_id, start_year, end_year) return endpoint_response @@ -751,8 +1078,20 @@ def titles_title_xi_programs_crop_insurance_summary_search(): } logging.error("Crop Insurance: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + min_year, max_year = cfg.CROP_INSURANCE_START_YEAR, cfg.CROP_INSURANCE_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to the earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_xi_summary_response(program_id, start_year, end_year) return endpoint_response @@ -766,8 +1105,20 @@ def titles_title_iv_programs_snap_state_distribution_search(): } logging.error("SNAP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + + min_year, max_year = cfg.SNAP_START_YEAR, cfg.SNAP_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_iv_state_distribution_response(program_id, start_year, end_year) return endpoint_response @@ -782,8 +1133,19 @@ def titles_title_iv_programs_snap_summary_search(): logging.error("SNAP: " + json.dumps(msg)) return rs_handlers.not_found(msg) - start_year = 2018 - end_year = 2022 + min_year, max_year = cfg.SNAP_START_YEAR, cfg.SNAP_END_YEAR + start_year = request.args.get('start_year', type=int, default=min_year) + end_year = request.args.get('end_year', type=int, default=max_year) + + if start_year and end_year and start_year > end_year: + start_year, end_year = min_year, max_year # Reset to full range if invalid + + if start_year is None: + start_year = min_year # Default to earliest available year + + if end_year is None: + end_year = max_year # Default to latest available year + endpoint_response = generate_title_iv_summary_response(program_id, start_year, end_year) return endpoint_response @@ -1408,6 +1770,7 @@ def generate_title_i_total_summary_response(title_id, start_year, end_year): return final_summary + def generate_title_ii_total_summary_response(title_id, start_year, end_year): session = Session() @@ -1459,6 +1822,8 @@ def generate_title_ii_total_summary_response(title_id, start_year, end_year): title_entry = { 'titleName': title_name, 'totalPaymentInDollars': title_total_payment, + 'startYear': start_year, + 'endYear': end_year, 'programs': program_list } @@ -2454,6 +2819,10 @@ def generate_title_ii_state_distribution_response(program_id, start_year, end_ye state_dict.update(state_practice_category_grouping_dict[state]) if "statutes" in state_dict: for statute in state_dict['statutes']: + # skip statutes that have no totals entry yet + if statute['statuteName'] not in total_payment_by_practice_category_grouping_dict: + continue + for practice_category in state_total_payment_by_practice_categories_dict[state][statute['statuteName']]['practiceCategories']: practice_category_name = practice_category['practiceCategoryName'] @@ -2950,6 +3319,10 @@ def generate_title_ii_summary_response(program_id, start_year, end_year): # Add missing practice categories with zero payment for statute_name in practice_categories_dict: + # skip statutes that have no totals entry yet + if statute_name not in total_payment_by_practice_categories_dict: + continue + for practice in practice_categories_dict[statute_name]['practiceCategories']: found = False for practice_category in total_payment_by_practice_categories_dict[statute_name]['practiceCategories']: @@ -2986,7 +3359,7 @@ def generate_title_ii_summary_response(program_id, start_year, end_year): # Sort the sub programs by total payment in descending order sub_programs_list = sorted(sub_programs_list, key=lambda x: x['totalPaymentInDollars'], reverse=True) - response = {**total_values_dict, "statutes": statutes_list, "subPrograms": sub_programs_list} + response = {"startYear": start_year, "endYear": end_year, **total_values_dict, "statutes": statutes_list, "subPrograms": sub_programs_list} return response @@ -3078,6 +3451,9 @@ def generate_title_xi_summary_response(program_id, start_year, end_year): # aggregate dictionary for summing aggregate_dict = { + 'titleName': TITLE_XI_NAME, + 'startYear': start_year, + 'endYear': end_year, 'totalIndemnitiesInDollars': 0, 'totalPremiumInDollars': 0, 'totalPremiumSubsidyInDollars': 0, diff --git a/app/pdl.yaml b/app/pdl.yaml index c57da86..5774623 100644 --- a/app/pdl.yaml +++ b/app/pdl.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: Policy Design Lab API description: Policy Design Lab API Documentation - version: 0.22.0 + version: 0.23.0 servers: - url: https://localhost description: Production server @@ -199,7 +199,26 @@ paths: - "Title I: Commodities" summary: Gets the Title I summary data for all states. description: | - Returns the Title I summary data for all states in JSON format. + Returns the Title I summary data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -219,7 +238,26 @@ paths: - "Title I: Commodities" summary: Gets the Title I's state distribution data for all states. description: | - Returns the Title I state distribution data for all states in JSON format. + Returns the Title I state distribution data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -240,6 +278,25 @@ paths: summary: Gets the Title I Subtitle A commodities data for all states. description: | Returns the Title I Subtitle A commodities data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -260,6 +317,25 @@ paths: summary: Gets the Title I Subtitle A commodities distribution data for all subprograms. description: | Returns the Title I Subtitle A commodities distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -293,6 +369,46 @@ paths: description: Unauthorized 500: description: Internal error + /pdl/titles/title-i/subtitles/subtitle-a/arc-plc-payments/current: + get: + tags: + - "Title I: Commodities - Subtitle A" + summary: Gets the current Title I Subtitle A commodities payment distribution for ARC and PLC. + description: | + Returns the current Title I Subtitle A commodities payment distribution data for ARC and PLC in JSON format. + responses: + 200: + description: Ok + content: + application/json: + schema: + type: string + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error + /pdl/titles/title-i/subtitles/subtitle-a/arc-plc-payments/proposed: + get: + tags: + - "Title I: Commodities - Subtitle A" + summary: Gets the projected Title I Subtitle A commodities payment distribution data ARC and PLC. + description: | + Returns the projected Title I Subtitle A commodities payment distribution for ARC and PLC in JSON format. + responses: + 200: + description: Ok + content: + application/json: + schema: + type: string + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal error /pdl/titles/title-i/subtitles/subtitle-d/state-distribution: get: tags: @@ -300,6 +416,25 @@ paths: summary: Gets the Title I Subtitle D Dairy Margin Coverage data for all states. description: | Returns the Title I Subtitle D Dairy Margin Coverage data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -320,6 +455,25 @@ paths: summary: Gets the Title I Subtitle D Dairy Margin Coverage distribution data for all subprograms. description: | Returns the Title I Subtitle D Dairy Margin Coverage distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -340,6 +494,25 @@ paths: summary: Gets the Title I Subtitle E Supplemental Agricultural Disaster Assistance data for all states. description: | Returns the Title I Subtitle E Supplemental Agricultural Disaster Assistance data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -360,6 +533,25 @@ paths: summary: Gets the Title I Subtitle E Supplemental Agricultural Disaster Assistance distribution data for all subprograms. description: | Returns the Title I Subtitle E Supplemental Agricultural Disaster Assistance distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2021 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -380,6 +572,25 @@ paths: summary: Gets the Title II summary data for all states. description: | Returns the Title II summary data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -400,6 +611,25 @@ paths: summary: Gets the Title II's state distribution data for all states. description: | Returns the Title II state distribution data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -454,7 +684,24 @@ paths: value: "314" multiple: value: "314,315" - + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -475,6 +722,25 @@ paths: summary: Gets the Title II EQIP conservation data for all practice categories. description: | Returns the Title II EQIP conservation data for all practice categories in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -495,6 +761,25 @@ paths: summary: Gets the Title II EQIP list of all practice names for the given start to end year duration. description: | Returns the Title II EQIP list of all practice names for the given start to end year duration. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -615,6 +900,7 @@ paths: summary: Gets the Title II CSP conservation data for all states. description: | Returns the Title II CSP conservation data for all states in JSON format. + parameters: - name: practice_code in: query @@ -629,6 +915,24 @@ paths: value: "314" multiple: value: "314,315" + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -649,6 +953,25 @@ paths: summary: Gets the Title II CSP conservation data for all program categories. description: | Returns the Title II CSP conservation data for all program categories in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -669,6 +992,25 @@ paths: summary: Gets the Title II CSP list of all practice names for the given start to end year duration. description: | Returns the Title II CSP list of all practice names for the given start to end year duration. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -770,6 +1112,25 @@ paths: summary: Gets the Title II CRP conservation data for all states. description: | Returns the Title II CRP conservation data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -790,6 +1151,25 @@ paths: summary: Gets the Title II CRP conservation distribution data for all subprograms. description: | Returns the Title II CRP conservation distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -810,6 +1190,25 @@ paths: summary: Gets the Title II ACEP conservation data for all states. description: | Returns the Title II ACEP conservation data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -830,6 +1229,25 @@ paths: summary: Gets the Title II ACEP conservation distribution data for all subprograms. description: | Returns the Title II ACEP conservation distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -850,6 +1268,25 @@ paths: summary: Gets the Title II RCPP conservation data for all states. description: | Returns the Title II RCPP conservation data for all states in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -870,6 +1307,25 @@ paths: summary: Gets the Title II RCPP conservation distribution data for all subprograms. description: | Returns the Title II RCPP conservation distribution data for all subprograms in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2014 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2023 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -930,6 +1386,25 @@ paths: summary: Gets the Title XI Crop Insurance state distribution data. description: | Returns the Title XI Crop Insurance State Distribution Data in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2018 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2022 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -950,6 +1425,25 @@ paths: summary: Gets the Title XI crop insurance summary data. description: | Returns the Title XI Crop Insurance Summary Data in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2018 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2022 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -970,6 +1464,25 @@ paths: summary: Gets the Title IV SNAP state distribution data. description: | Returns the Title IV SNAP State Distribution Data in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2018 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2022 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok @@ -990,6 +1503,25 @@ paths: summary: Gets the Title IV SNAP summary data. description: | Returns the Title IV SNAP Summary Data in JSON format. + parameters: + - name: start_year + in: query + description: The start year for filtering the data. + required: false + schema: + type: integer + example: 2018 + minimum: 1950 + maximum: 2050 + - name: end_year + in: query + description: The end year for filtering the data. + required: false + schema: + type: integer + example: 2022 + minimum: 1950 + maximum: 2050 responses: 200: description: Ok diff --git a/pyproject.toml b/pyproject.toml index 2fc5c69..15d7b6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pdl-api" -version = "0.22.0" +version = "0.23.0" description = "" authors = ["Yong Wook Kim "] readme = "README.md"