diff --git a/.github/readme.md b/.github/readme.md index 170b450f7..76922ff75 100644 --- a/.github/readme.md +++ b/.github/readme.md @@ -40,17 +40,8 @@ * tfrs-release.yaml (TFRS release-2.10.0): the pipeline builds the release and deploys on Test and Prod, it needs to be manually triggered * create-release.yaml (Create Release after merging to master): tag and create the release after merging release branch to master. The description of the tracking pull request becomes release notes -* dev-jan-release.yaml (TFRS Dev Jan Release): the pipeline build Jan 2024 release and deploy on dev for every commit -* dev-release.yaml (TFRS Dev release-2.9.0): the pipeline is automatically triggered when there is a commit to the release branch -* tfrs-release.yaml (TFRS release-2.9.0): the pipelin builds the release and deploy on Test and Prod, it needs to be manually triggered - ## Other Pipelines -* branch-deploy-template.yaml (Branch Deploy Template): a pipeline template to deploy a branch -* build-template.yaml (Build Template): a pipeline template to build branch or pull request * cleanup-cron-workflow-runs.yaml (Scheduled cleanup old workflow runs): a cron job to cleanup the old workflows * cleanup-workflow-runs.yaml (Cleanup old workflow runs): manually cleanup teh workflow runs -* pr-dev-cicd.yaml (TFRS Dev Jan PR CICD): the pipeline builds Jan 2024 pull requests and deploy on dev if the pull request title ends with build-on-dev -* pr-dev-database-template.yaml (PR Dev Database Template): the template to create database for pull request build -* pr-deploy-template (PR Dev Deploy Template): the template deploys pull request build to dev -* pr-teardown.yaml (TFRS Dev Jan PR Teardown): tear down the Jan 2024 pull request builds from dev + diff --git a/.github/workflows/branch-deploy-template.yaml b/.github/workflows/branch-deploy-template.yaml deleted file mode 100644 index a245407b8..000000000 --- a/.github/workflows/branch-deploy-template.yaml +++ /dev/null @@ -1,142 +0,0 @@ -name: Branch Deploy Template - -on: - workflow_call: - inputs: - branch-name: # sample value: release-2.9.0 or main-release-jan-2024 - required: true - type: string - # suffix is in format of -dev, -test, -dev-jan, test-jan, -dev-1923, dev-jan-1923 - suffix: - required: true - type: string - # env-name is in format of dev, test - env-name: - required: true - type: string - # database-service-host-name, sample tfrs-spilo, tfrs-spilo-jan, tfrs-spilo-dev-1988 - database-service-host-name: - required: true - type: string - # this virtual host name, sample tfrs-jan-vhost - rabbitmq-vhost: - required: true - type: string - secrets: - tools-namespace: - required: true - namespace: - required: true - openshift-server: - required: true - openshift-token: - required: true - -jobs: - - deploy: - - name: Deploy tfrs - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3 - with: - ref: ${{ inputs.branch-name }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Deploy tfrs-frontend - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-frontend:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-frontend:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-frontend - helm status -n ${{ secrets.namespace }} tfrs-frontend${{ inputs.suffix }} - helm upgrade --install \ - --set frontendImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-name }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-frontend${{ inputs.suffix }} . - - - name: Deploy tfrs-backend - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-backend:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-backend:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-backend - helm status -n ${{ secrets.namespace }} tfrs-backend${{ inputs.suffix }} - helm upgrade --install \ - --set backendImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-Name }} \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=${{ inputs.rabbitmq-vhost }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-backend${{ inputs.suffix }} . - - - name: Deploy tfrs-celery - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-celery:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-celery:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-celery - helm status -n ${{ secrets.namespace }} tfrs-celery${{ inputs.suffix }} - helm upgrade --install \ - --set celeryImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-Name }} \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=${{ inputs.rabbitmq-vhost }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-celery${{ inputs.suffix }} . - - - name: Deploy tfrs-scan-handler - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-scan-handler:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-scan-handler:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-scan-handler - helm status -n ${{ secrets.namespace }} tfrs-scan-handler${{ inputs.suffix }} - helm upgrade --install \ - --set scanHandlerImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-Name }} \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=${{ inputs.rabbitmq-vhost }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-scan-handler${{ inputs.suffix }} . - - - name: Deploy tfrs-scan-coordinator - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-scan-coordinator:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-scan-coordinator:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-scan-coordinator - helm status -n ${{ secrets.namespace }} tfrs-scan-coordinator${{ inputs.suffix }} - helm upgrade --install \ - --set scanCoordinatorImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-Name }} \ - --set rabbitmqVHost=${{ inputs.rabbitmq-vhost }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-scan-coordinator${{ inputs.suffix }} . - - - name: Deploy tfrs-notification-server - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-notification-server:build-${{ inputs.branch-name }} ${{ secrets.namespace }}/tfrs-notification-server:${{ inputs.env-name }}-${{ inputs.branch-name }} - cd charts/tfrs-apps/charts/tfrs-notification-server - helm status -n ${{ secrets.namespace }} tfrs-notification-server${{ inputs.suffix }} - helm upgrade --install \ - --set notificationServerImageTagName=${{ inputs.env-name }}-${{ inputs.branch-name }} \ - --set suffix=${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=${{ inputs.env-Name }} \ - --set rabbitmqVHost=${{ inputs.rabbitmq-vhost }} \ - -n ${{ secrets.namespace }} -f ./values${{ inputs.suffix }}.yaml tfrs-notification-server${{ inputs.suffix }} . \ No newline at end of file diff --git a/.github/workflows/build-template.yaml b/.github/workflows/build-template.yaml deleted file mode 100644 index ed780c316..000000000 --- a/.github/workflows/build-template.yaml +++ /dev/null @@ -1,233 +0,0 @@ - -# This template supports both pr build and branch build -name: Build Template - -on: - workflow_call: - inputs: - # when build branch, the sample value is -main-release-jan-2024 - # when build pull request, the sample value is -jan-2024 - suffix: - required: true - type: string - # when build branch, the sample value is main-release-jan-2024 - # when build pull request, the sample value is refs/pull/2024/head - checkout-ref: - required: true - type: string - secrets: - tools-namespace: - required: true - openshift-server: - required: true - openshift-token: - required: true - -env: - GIT_URL: https://github.com/bcgov/tfrs.git - -jobs: - - build-backend: - - name: Build TFRS Backend on Openshift - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build tfrs Backend - run: | - cd openshift-v4/templates/backend - oc process -f ./backend-bc.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-backend-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-backend-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} - - build-frontend: - - name: Build TFRS Frontend on Openshift - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build TFRS Frontend - run: | - cd openshift-v4/templates/frontend - oc process -f ./frontend-bc-docker.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-frontend-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-frontend-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} - - build-celery: - - name: Build TFRS Celery on Openshift - needs: [build-frontend, build-backend] - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build TFRS Celery - run: | - cd openshift-v4/templates/celery - pwd - ls -l - oc process -f ./celery-bc-docker.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-celery-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-celery-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} - - build-scan-coordinator: - - name: Build TFRS Scan Coordinator on Openshift - needs: [build-frontend, build-backend] - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build TFRS Scan Coordinator - run: | - cd openshift-v4/templates/scan-coordinator - oc process -f ./scan-coordinator-bc.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-scan-coordinator-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-scan-coordinator-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} - - build-scan-handler: - - name: Build TFRS Scan Handler on Openshift - needs: [build-scan-coordinator, build-celery] - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build TFRS Scan-Handler - run: | - cd openshift-v4/templates/scan-handler - oc process -f ./scan-handler-bc-docker.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-scan-handler-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-scan-handler-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} - - build-notification-server: - - name: Build TFRS Notification Server on Openshift - needs: [build-scan-coordinator, build-celery] - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3.5.3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Build TFRS Notification Server - run: | - cd openshift-v4/templates/notification - oc process -f ./notification-server-bc.yaml NAME=tfrs \ - SUFFIX=-build${{ inputs.suffix}} \ - VERSION=build${{ inputs.suffix }} \ - GIT_URL=${{ env.GIT_URL }} \ - GIT_REF=${{ inputs.checkout-ref }} \ - | oc apply --wait=true -f - -n ${{ secrets.tools-namespace }} - oc cancel-build bc/tfrs-notification-server-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} || true - oc start-build --wait=true tfrs-notification-server-build${{ inputs.suffix}} -n ${{ secrets.tools-namespace }} \ No newline at end of file diff --git a/.github/workflows/dev-test-jan-release.yaml b/.github/workflows/dev-test-jan-release.yaml deleted file mode 100644 index 21704738f..000000000 --- a/.github/workflows/dev-test-jan-release.yaml +++ /dev/null @@ -1,130 +0,0 @@ - -## For each release, the value of name, branches, RELEASE_NAME and PR_NUMBER need to be adjusted accordingly -## For each release, update lib/config.js: version and releaseBranch - -name: TFRS Dev/Test Jan Release - -on: - push: - branches: [ main-release-jan-2024 ] - # paths: - # - frontend/** - # - backend/** - # - security-scan/** - workflow_dispatch: - branches: - - main-release-jan-2024 - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - - unit-test: - - name: Run Backend Unit Tests - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - name: Checkout - uses: actions/checkout@v3.5.3 - - - name: Run coverage report for django tests - uses: kuanfandevops/django-test-action@itvr-django-test - continue-on-error: true - with: - settings-dir-path: "backend/api" - requirements-file: "backend/requirements.txt" - managepy-dir: backend - - lint: - - name: Linting - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - name: Checkout - uses: actions/checkout@v3.5.3 - - - name: Frontend Linting - continue-on-error: true - run: | - cd frontend - pwd - npm install - npm run lint - - - name: Backend linting - uses: github/super-linter/slim@v4 - continue-on-error: true - env: - DEFAULT_BRANCH: ${{ github.ref_name }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FILTER_REGEX_INCLUDE: .*backend/.*.py - VALIDATE_PYTHON_PYLINT: true - LOG_LEVEL: WARN - - # when build branch, the suffix sample is -main-release-jan-2024 - # the checkout-ref sample is main-release-jan-2024 - build: - name: Build - needs: [unit-test, lint] - uses: ./.github/workflows/build-template.yaml - with: - suffix: -${{ github.ref_name }} - checkout-ref: ${{ github.ref_name }} - secrets: - tools-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} - - # The suffix is -dev-jan, the deployment names are tfrs-backend-dev-jan, tfrs-frontend-dev-jan and etc.. - # The image tags are tfrs-backend:dev-main-release-jan-2024, tfrs-frontend:dev-main-release-jan-2024 and etc.. - deploy-on-dev: - name: Deploy on Dev - needs: build - uses: ./.github/workflows/branch-deploy-template.yaml - with: - branch-name: ${{ github.ref_name }} - suffix: -dev-jan - env-name: dev - database-service-host-name: tfrs-crunchy-dev-pgbouncer - rabbitmq-vhost: tfrs-jan-vhost - secrets: - tools-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-dev - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} - - approval-test-deployment: - name: Approval deployment on Test - runs-on: ubuntu-latest - needs: deploy-on-dev - timeout-minutes: 60 - steps: - - name: Ask for approval for TFRS Test deployment - uses: trstringer/manual-approval@v1.6.0 - with: - secret: ${{ github.TOKEN }} - approvers: AlexZorkin,emi-hi,tim738745,kuanfandevops,jig-patel,prv-proton,JulianForeman - minimum-approvals: 1 - issue-title: "TFRS main-release-jan-2024 Test Deployment" - - deploy-on-test: - name: Deploy on Test - needs: approval-test-deployment - uses: ./.github/workflows/branch-deploy-template.yaml - with: - branch-name: main-release-jan-2024 - suffix: -test-jan - env-name: test - database-service-host-name: tfrs-crunchy-test-pgbouncer - rabbitmq-vhost: tfrs-jan-vhost - secrets: - tools-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-test - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pr-dev-cicd.yaml b/.github/workflows/pr-dev-cicd.yaml deleted file mode 100644 index ce6128835..000000000 --- a/.github/workflows/pr-dev-cicd.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# Please refer to ./readme.md for how to build single pull request - -# Update this workflow name per pull request -name: TFRS Dev Jan PR CICD -on: - workflow_dispatch: - pull_request: - types: [opened, edited, synchronize, reopened] - branches: - - 'main-release-jan-2024' - -jobs: - - setup-database: - if: endsWith( github.event.pull_request.title, 'build-on-dev' ) - uses: ./.github/workflows/pr-dev-database-template.yaml - with: - pr-number: ${{ github.event.pull_request.number }} - dev-suffix: -jan-${{ github.event.pull_request.number }} - secrets: - dev-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-dev - tfrs-dev-username: ${{ secrets.TFRS_DEV_USERNAME }} - tfrs-dev-password: ${{ secrets.TFRS_DEV_PASSWORD }} - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} - - # when build pull reuqest, the suffix sample is -jan-1234 - # the checkout-ref is in the format of refs/pull/1234/head - build: - if: endsWith( github.event.pull_request.title, 'build-on-dev' ) - name: Build Pull Request - uses: ./.github/workflows/build-template.yaml - with: - suffix: -jan-${{ github.event.pull_request.number }} - checkout-ref: refs/pull/${{ github.event.pull_request.number }}/head - secrets: - tools-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} - - deploy: - if: endsWith( github.event.pull_request.title, 'build-on-dev' ) - needs: [setup-database, build] - uses: ./.github/workflows/pr-dev-deploy-template.yaml - with: - suffix: -jan-${{ github.event.pull_request.number }} - checkout-ref: refs/pull/${{ github.event.pull_request.number }}/head - database-service-host-name: tfrs-spilo-jan-${{ github.event.pull_request.number }} - secrets: - tools-namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - namespace: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-dev - openshift-server: ${{ secrets.OPENSHIFT_SERVER }} - openshift-token: ${{ secrets.OPENSHIFT_TOKEN }} - \ No newline at end of file diff --git a/.github/workflows/pr-dev-database-template.yaml b/.github/workflows/pr-dev-database-template.yaml deleted file mode 100644 index 458d8b62b..000000000 --- a/.github/workflows/pr-dev-database-template.yaml +++ /dev/null @@ -1,69 +0,0 @@ -name: PR Dev Database Template - -on: - workflow_call: - inputs: - # pull request number - pr-number: - required: true - type: string - # the suffix will be appended to tfrs-spilo, same values: -1234, -jan-1242 - dev-suffix: - required: true - type: string - secrets: - dev-namespace: - required: true - tfrs-dev-username: - required: true - tfrs-dev-password: - required: true - openshift-server: - required: true - openshift-token: - required: true - -jobs: - - database: - - name: Start Database - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3 - with: - ref: refs/pull/${{ inputs.pr-number }}/head - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.dev-namespace }} - - - name: Setup Database - shell: bash {0} - run: | - cd charts/tfrs-spilo - helm dependency build - helm status -n ${{ secrets.dev-namespace }} tfrs-spilo${{ inputs.dev-suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-spilo${{ inputs.dev-suffix }} exists already" - else - echo "Installing tfrs-spilo${{ inputs.dev-suffix }}" - helm install -n ${{ secrets.dev-namespace }} -f ./values-dev.yaml --wait tfrs-spilo${{ inputs.dev-suffix }} . - oc -n ${{ secrets.dev-namespace }} wait --for=condition=Ready pod/tfrs-spilo${{ inputs.dev-suffix }}-0 - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "create user \"${{ secrets.tfrs-dev-username }}\" WITH PASSWORD '${{ secrets.tfrs-dev-password }}'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "create database tfrs owner \"${{ secrets.tfrs-dev-username }}\" ENCODING 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "ALTER SYSTEM SET log_filename='postgresql-%H.log'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "ALTER SYSTEM SET log_connections='off'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "ALTER SYSTEM SET log_disconnections='off'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "ALTER SYSTEM SET log_checkpoints='off'" || true - oc -n ${{ secrets.dev-namespace }} exec tfrs-spilo${{ inputs.dev-suffix }}-0 -- psql -c "select pg_reload_conf()" || true - fi - diff --git a/.github/workflows/pr-dev-deploy-template.yaml b/.github/workflows/pr-dev-deploy-template.yaml deleted file mode 100644 index ddc583c30..000000000 --- a/.github/workflows/pr-dev-deploy-template.yaml +++ /dev/null @@ -1,191 +0,0 @@ - - -name: PR Dev Deploy Template - -on: - workflow_call: - inputs: - # suffix is in format of -jan-1923 - suffix: - required: true - type: string - # when build pull request, the sample value is refs/pull/2023/head - checkout-ref: - required: true - type: string - # database-service-host-name, sample tfrs-spilo-dev-1988 - database-service-host-name: - required: true - type: string - secrets: - tools-namespace: - required: true - namespace: - required: true - openshift-server: - required: true - openshift-token: - required: true - -jobs: - - deploy: - - name: Deploy tfrs - runs-on: ubuntu-latest - timeout-minutes: 60 - - steps: - - - name: Check out repository - uses: actions/checkout@v3 - with: - ref: ${{ inputs.checkout-ref }} - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.openshift-server }} - openshift_token: ${{ secrets.openshift-token }} - insecure_skip_tls_verify: true - namespace: ${{ secrets.tools-namespace }} - - - name: Create vhost on Rabbitmq Dev - shell: bash {0} - run: | - oc -n ${{ secrets.namespace }} exec tfrs-rabbitmq-0 -- rabbitmqctl add_vhost tfrs-dev${{ inputs.suffix }}-vhost - oc -n ${{ secrets.namespace }} exec tfrs-rabbitmq-0 -- rabbitmqctl set_permissions --vhost tfrs-dev${{ inputs.suffix }}-vhost tfrs ".*" ".*" ".*" - - - name: Deploy tfrs-frontend - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-frontend:build${{ inputs.suffix }} ${{ secrets.namespace }}/tfrs-frontend:dev${{ inputs.suffix }} - cd charts/tfrs-apps/charts/tfrs-frontend - helm status -n ${{ secrets.namespace }} tfrs-frontend-dev${{ inputs.suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-frontend-dev${{ inputs.suffix }} release exists already" - helm upgrade \ - --set frontendImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-frontend-dev${{ inputs.suffix }} . - else - echo "tfrs-frontend-dev${{ inputs.suffix }} release does not exist" - helm install \ - --set frontendImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-frontend-dev${{ inputs.suffix }} . - fi - - - name: Deploy tfrs-backend - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-backend:build${{ inputs.suffix }} ${{ secrets.namespace }}/tfrs-backend:dev${{ inputs.suffix }} - cd charts/tfrs-apps/charts/tfrs-backend - helm status -n ${{ secrets.namespace }} tfrs-backend-dev${{ inputs.suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-backend-dev${{ inputs.suffix }} release exists already" - helm upgrade \ - --set backendImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-backend-dev${{ inputs.suffix }} . - else - echo "tfrs-backend-dev${{ inputs.suffix }} release does not exist" - helm install \ - --set backendImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-backend-dev${{ inputs.suffix }} . - fi - - - name: Deploy tfrs-celery - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-celery:build${{ inputs.suffix }} ${{ secrets.namespace }}/tfrs-celery:dev${{ inputs.suffix }} - cd charts/tfrs-apps/charts/tfrs-celery - helm status -n ${{ secrets.namespace }} tfrs-celery-dev${{ inputs.suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-celery-dev${{ inputs.suffix }} release exists already" - helm upgrade \ - --set celeryImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-celery-dev${{ inputs.suffix }} . - else - echo "tfrs-celery-dev${{ inputs.suffix }} release does not exist" - helm install \ - --set celeryImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-celery-dev${{ inputs.suffix }} . - fi - - - name: Deploy tfrs-scan-handler - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-scan-handler:build${{ inputs.suffix }} ${{ secrets.namespace }}/tfrs-scan-handler:dev${{ inputs.suffix }} - cd charts/tfrs-apps/charts/tfrs-scan-handler - helm status -n ${{ secrets.namespace }} tfrs-scan-handler-dev${{ inputs.suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-scan-handler-dev${{ inputs.suffix }} release exists already" - helm upgrade \ - --set scanHandlerImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-scan-handler-dev${{ inputs.suffix }} . - else - echo "tfrs-scan-handler-dev${{ inputs.suffix }} release does not exist" - helm install \ - --set scanHandlerImageTagName=dev${{ inputs.suffix }} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set databaseServiceHostName=${{ inputs.database-service-host-name }} \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-scan-handler-dev${{ inputs.suffix }} . - fi - - - name: Deploy tfrs-scan-coordinator - shell: bash {0} - run: | - oc tag ${{ secrets.tools-namespace }}/tfrs-scan-coordinator:build${{ inputs.suffix}} ${{ secrets.namespace }}/tfrs-scan-coordinator:dev${{ inputs.suffix}} - cd charts/tfrs-apps/charts/tfrs-scan-coordinator - helm status -n ${{ secrets.namespace }} tfrs-scan-coordinator-dev${{ inputs.suffix }} - if [ $? -eq 0 ]; then - echo "tfrs-scan-coordinator-dev${{ inputs.suffix }} release exists already" - helm upgrade \ - --set scanCoordinatorImageTagName=dev${{ inputs.suffix}} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-scan-coordinator-dev${{ inputs.suffix }} . - else - echo "tfrs-scan-coordinator${{ inputs.suffix }} release does not exist" - helm install \ - --set scanCoordinatorImageTagName=dev${{ inputs.suffix}} \ - --set suffix=-dev${{ inputs.suffix }} \ - --set namespace=${{ secrets.namespace }} \ - --set envName=dev \ - --set rabbitmqVHost=tfrs-dev${{ inputs.suffix }}-vhost \ - -n ${{ secrets.namespace }} -f ./values-dev-jan.yaml tfrs-scan-coordinator-dev${{ inputs.suffix }} . - fi \ No newline at end of file diff --git a/.github/workflows/pr-teardown.yaml b/.github/workflows/pr-teardown.yaml deleted file mode 100644 index f6e426cbd..000000000 --- a/.github/workflows/pr-teardown.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: TFRS Dev Jan PR Teardown - -on: - pull_request: - types: closed - branches: - - 'main-release-jan-2024' - -env: - TOOLS_NAMESPACE: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-tools - DEV_NAMESPACE: ${{ secrets.OPENSHIFT_NAMESPACE_PLATE }}-dev - -jobs: - - teardown-on-dev: - if: endsWith( github.event.pull_request.title, 'build-on-dev' ) - name: Tear TFRS down on Dev - runs-on: ubuntu-latest - timeout-minutes: 20 - - steps: - - - name: Log in to Openshift - uses: redhat-actions/oc-login@v1.2 - with: - openshift_server_url: ${{ secrets.OPENSHIFT_SERVER }} - openshift_token: ${{ secrets.OPENSHIFT_TOKEN }} - insecure_skip_tls_verify: true - namespace: ${{ env.TOOLS_NAMESPACE }} - - - name: Undeploy on Dev - shell: bash {0} - run: | - oc -n ${{ env.DEV_NAMESPACE }} exec tfrs-rabbitmq-0 -- rabbitmqctl delete_vhost tfrs-dev-jan-${{ github.event.pull_request.number }}-vhost - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-spilo-jan-${{ github.event.pull_request.number }} || true - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-backend-dev-jan-${{ github.event.pull_request.number }} || true - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-frontend-dev-jan-${{ github.event.pull_request.number }} || true - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-celery-dev-jan-${{ github.event.pull_request.number }} || true - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-scan-handler-dev-jan-${{ github.event.pull_request.number }} || true - helm -n ${{ env.DEV_NAMESPACE }} uninstall tfrs-scan-coordinator-dev-jan-${{ github.event.pull_request.number }} || true - diff --git a/README.md b/README.md index c6a689b58..e05c7acc3 100644 --- a/README.md +++ b/README.md @@ -120,4 +120,3 @@ This is a list that was created on 2023-02-01 with all Zelda Devs to provide alt - New learning and applying it to our work - Innovation work - diff --git a/backend/api/fixtures/test/test_carbon_intensity_limits.json b/backend/api/fixtures/test/test_carbon_intensity_limits.json index beec13ceb..44bdd22f5 100644 --- a/backend/api/fixtures/test/test_carbon_intensity_limits.json +++ b/backend/api/fixtures/test/test_carbon_intensity_limits.json @@ -70,41 +70,4 @@ }, "model": "api.carbonintensitylimit", "pk": null -}, { - "fields": { - "compliance_period": ["2023"], - "fuel_class": ["Diesel"], - "density": "79.64", - "effective_date": "2023-01-01" - }, - "model": "api.carbonintensitylimit", - "pk": null -}, { - "fields": { - "compliance_period": ["2023"], - "fuel_class": ["Gasoline"], - "density": "74.08", - "effective_date": "2023-01-01" - }, - "model": "api.carbonintensitylimit", - "pk": null -}, { - "fields": { - "compliance_period": ["2022"], - "fuel_class": ["Diesel"], - "density": "79.64", - "effective_date": "2022-01-01" - }, - "model": "api.carbonintensitylimit", - "pk": null -}, { - "fields": { - "compliance_period": ["2022"], - "fuel_class": ["Gasoline"], - "density": "74.08", - "effective_date": "2022-01-01" - }, - "model": "api.carbonintensitylimit", - "pk": null -} -] \ No newline at end of file +}] \ No newline at end of file diff --git a/backend/api/fixtures/test/test_fuel_codes.json b/backend/api/fixtures/test/test_fuel_codes.json index 54263dabd..9f54f969f 100644 --- a/backend/api/fixtures/test/test_fuel_codes.json +++ b/backend/api/fixtures/test/test_fuel_codes.json @@ -20,30 +20,6 @@ }, "model": "api.fuelcode", "pk": 1 -}, -{ - "model": "api.fuelcode", - "pk": 21, - "fields": { - "fuel_code": "BCLCF", - "fuel_code_version": "114", - "fuel_code_version_minor": "0", - "company": "ETH Alco", - "carbon_intensity": "38.12", - "application_date": "2021-09-01", - "effective_date": "2021-09-02", - "expiry_date": "2024-09-01", - "fuel": ["LNG"], - "feedstock": "MSW", - "feedstock_location": "Test", - "feedstock_misc": "", - "facility_location": "Test", - "facility_nameplate": "654", - "former_company": "", - "approval_date": "2021-09-02", - "status": ["Approved"], - "renewable_percentage": "50.00" - } }, { "fields": { diff --git a/backend/api/fixtures/test/test_post_compliance_unit_reporting.json b/backend/api/fixtures/test/test_post_compliance_unit_reporting.json deleted file mode 100644 index eacbd745b..000000000 --- a/backend/api/fixtures/test/test_post_compliance_unit_reporting.json +++ /dev/null @@ -1,378 +0,0 @@ -[ - { - "fields": { - "fuel_supplier_status": "Draft", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 1 - }, - { - "fields": { - "fuel_supplier_status": "Submitted", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 2 - }, - { - "fields": { - "fuel_supplier_status": "Draft", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 3 - }, - { - "fields": { - "status": 1, - "type": [ - "Compliance Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2018" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 1, - "latest_report": 1, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 1 - }, - { - "fields": { - "status": 2, - "type": [ - "Exclusion Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2018" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 2, - "latest_report": 2, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 2 - }, - { - "fields": { - "status": 3, - "type": [ - "Compliance Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2019" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 3, - "latest_report": 3, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 3 - }, - { - "fields": { - "role": [ - "ComplianceReporting" - ], - "user": [ - "fs_user_1" - ] - }, - "model": "api.userrole", - "pk": null - }, - { - "fields": { - "description": "Other", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.expecteduse", - "pk": 3 - }, - { - "fields": { - "the_type": "Received", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.notionaltransfertype", - "pk": 1 - }, - { - "fields": { - "the_type": "Carbon Intensity", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 1 - }, - { - "fields": { - "the_type": "Fuel Code", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 2 - }, - { - "fields": { - "the_type": "Default Carbon Intensity", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 3 - }, - { - "fields": { - "the_type": "GHGenius", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 4 - }, - { - "fields": { - "the_type": "Alternative", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 5 - }, - { - "model": "api.provisionoftheact", - "pk": 5, - "fields": { - "display_order": 5, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (a)", - "description": "Prescribed carbon intensity" - } - }, - { - "model": "api.provisionoftheact", - "pk": 6, - "fields": { - "display_order": 6, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (b)", - "description": "Prescribed carbon intensity" - } - }, - { - "model": "api.provisionoftheact", - "pk": 2, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (c)", - "description": "Approved fuel code" - } - }, - { - "model": "api.provisionoftheact", - "pk": 4, - "fields": { - "display_order": 4, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (i)", - "description": "Default Carbon Intensity Value" - } - }, - { - "model": "api.provisionoftheact", - "pk": 3, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (ii) (A)", - "description": "GHGenius modelled" - } - }, - { - "model": "api.provisionoftheact", - "pk": 1, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (ii) (B)", - "description": "Alternative Method" - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 11, - "fields": { - "fuel": ["LNG"], - "provision_act": 2, - "determination_type": ["Carbon Intensity"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 12, - "fields": { - "fuel": ["CNG"], - "provision_act": 2, - "determination_type": ["Fuel Code"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 13, - "fields": { - "fuel": ["LNG"], - "provision_act": 6, - "determination_type": ["Fuel Code"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 14, - "fields": { - "fuel": ["CNG"], - "provision_act": 6, - "determination_type": ["Carbon Intensity"] - } - }, - { - "model": "api.energyeffectivenessratiocategory", - "pk": 6, - "fields": { - "display_order": 6, - "name": "Petroleum-based gasoline, natural gas-based gasoline or renewable fuel in relation to gasoline class fuel" - } - }, - { - "model": "api.energyeffectivenessratiocategory", - "pk": 5, - "fields": { - "display_order": 5, - "name": "'Petroleum-based diesel fuel or renewable fuel in relation to diesel class fuel'" - } - }, - { - "model": "api.energyeffectivenessratio", - "pk": 1, - "fields": { - "effective_date": "2016-01-01", - "expiration_date": "2023-12-31", - "category": 6, - "fuel_class": ["Gasoline"], - "ratio": "1.00" - } - }, - { - "model": "api.energyeffectivenessratio", - "pk": 2, - "fields": { - "effective_date": "2016-01-01", - "expiration_date": "2023-12-31", - "category": 5, - "fuel_class": ["Diesel"], - "ratio": "1.00" - } - }, - { - "model": "api.energydensity", - "pk": 4, - "fields": { - "effective_date": "2017-01-01", - "category": 4, - "density": "23.58" - } - }, - { - "model": "api.energydensity", - "pk": 9, - "fields": { - "effective_date": "2017-01-01", - "category": 9, - "density": "38.65" - } - }, - { - "model": "api.approvedfuel", - "pk": 4, - "fields": { - "effective_date": "2017-01-01", - "name": "Ethanol", - "description": "Ethanol produced from biomass", - "credit_calculation_only": false, - "default_carbon_intensity_category": 10, - "energy_density_category": 4, - "energy_effectiveness_ratio_category": 6, - "unit_of_measure": ["L"], - "is_partially_renewable": true - } - }, - { - "model": "api.approvedfuel", - "pk": 19, - "fields": { - "effective_date": "2017-01-01", - "name": "'Petroleum-based diesel'", - "description": "'Diesel fuel, diesel, petroleum-based diesel'", - "credit_calculation_only": true, - "default_carbon_intensity_category": 6, - "energy_density_category": 9, - "energy_effectiveness_ratio_category": 5, - "unit_of_measure": ["L"], - "is_partially_renewable": false - } - }, - { - "fields": { - "determination_type": ["Carbon Intensity"], - "provision_act": 1, - "fuel": ["CNG"] - }, - "model": "api.approvedfuelprovision", - "pk": 500 - }, - { - "fields": { - "determination_type": ["GHGenius"], - "provision_act": 3, - "fuel": ["LNG"] - }, - "model": "api.approvedfuelprovision" - }, - { - "fields": { - "determination_type": ["Carbon Intensity"], - "provision_act": 1, - "fuel": ["LNG"] - }, - "model": "api.approvedfuelprovision", - "pk": 500 - } -] diff --git a/backend/api/fixtures/test/test_pre_compliance_unit_reporting.json b/backend/api/fixtures/test/test_pre_compliance_unit_reporting.json deleted file mode 100644 index 4a98f0045..000000000 --- a/backend/api/fixtures/test/test_pre_compliance_unit_reporting.json +++ /dev/null @@ -1,378 +0,0 @@ -[ - { - "fields": { - "fuel_supplier_status": "Draft", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 1 - }, - { - "fields": { - "fuel_supplier_status": "Submitted", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 2 - }, - { - "fields": { - "fuel_supplier_status": "Draft", - "analyst_status": "Unreviewed", - "director_status": "Unreviewed", - "manager_status": "Unreviewed" - }, - "model": "api.compliancereportworkflowstate", - "pk": 3 - }, - { - "fields": { - "status": 1, - "type": [ - "Compliance Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2018" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 1, - "latest_report": 1, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 1 - }, - { - "fields": { - "status": 2, - "type": [ - "Exclusion Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2018" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 2, - "latest_report": 2, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 2 - }, - { - "fields": { - "status": 3, - "type": [ - "Compliance Report" - ], - "organization": [ - "Test Org 1" - ], - "compliance_period": [ - "2019" - ], - "create_timestamp": "2019-01-01", - "update_timestamp": "2019-01-01", - "root_report": 3, - "latest_report": 3, - "traversal": 0 - }, - "model": "api.compliancereport", - "pk": 3 - }, - { - "fields": { - "role": [ - "ComplianceReporting" - ], - "user": [ - "fs_user_1" - ] - }, - "model": "api.userrole", - "pk": null - }, - { - "fields": { - "description": "Other", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.expecteduse", - "pk": 3 - }, - { - "fields": { - "the_type": "Received", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.notionaltransfertype", - "pk": 1 - }, - { - "fields": { - "the_type": "Carbon Intensity", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 1 - }, - { - "fields": { - "the_type": "Fuel Code", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 2 - }, - { - "fields": { - "the_type": "Default Carbon Intensity", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 3 - }, - { - "fields": { - "the_type": "GHGenius", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 4 - }, - { - "fields": { - "the_type": "Alternative", - "display_order": 99, - "effective_date": "2017-01-01" - }, - "model": "api.carbonintensitydeterminationtype", - "pk": 5 - }, - { - "model": "api.provisionoftheact", - "pk": 5, - "fields": { - "display_order": 5, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (a)", - "description": "Prescribed carbon intensity" - } - }, - { - "model": "api.provisionoftheact", - "pk": 6, - "fields": { - "display_order": 6, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (b)", - "description": "Prescribed carbon intensity" - } - }, - { - "model": "api.provisionoftheact", - "pk": 2, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (c)", - "description": "Approved fuel code" - } - }, - { - "model": "api.provisionoftheact", - "pk": 4, - "fields": { - "display_order": 4, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (i)", - "description": "Default Carbon Intensity Value" - } - }, - { - "model": "api.provisionoftheact", - "pk": 3, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (ii) (A)", - "description": "GHGenius modelled" - } - }, - { - "model": "api.provisionoftheact", - "pk": 1, - "fields": { - "display_order": 99, - "effective_date": "2017-01-01", - "provision": "Section 6 (5) (d) (ii) (B)", - "description": "Alternative Method" - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 11, - "fields": { - "fuel": ["LNG"], - "provision_act": 2, - "determination_type": ["Carbon Intensity"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 12, - "fields": { - "fuel": ["CNG"], - "provision_act": 2, - "determination_type": ["Fuel Code"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 13, - "fields": { - "fuel": ["LNG"], - "provision_act": 6, - "determination_type": ["Fuel Code"] - } - }, - { - "model": "api.approvedfuelprovision", - "pk": 14, - "fields": { - "fuel": ["CNG"], - "provision_act": 6, - "determination_type": ["Carbon Intensity"] - } - }, - { - "model": "api.energyeffectivenessratiocategory", - "pk": 6, - "fields": { - "display_order": 6, - "name": "Petroleum-based gasoline, natural gas-based gasoline or renewable fuel in relation to gasoline class fuel" - } - }, - { - "model": "api.energyeffectivenessratiocategory", - "pk": 5, - "fields": { - "display_order": 5, - "name": "'Petroleum-based diesel fuel or renewable fuel in relation to diesel class fuel'" - } - }, - { - "model": "api.energyeffectivenessratio", - "pk": 1, - "fields": { - "effective_date": "2016-01-01", - "expiration_date": "2023-12-31", - "category": 6, - "fuel_class": ["Gasoline"], - "ratio": "1.00" - } - }, - { - "model": "api.energyeffectivenessratio", - "pk": 2, - "fields": { - "effective_date": "2016-01-01", - "expiration_date": "2023-12-31", - "category": 5, - "fuel_class": ["Diesel"], - "ratio": "1.00" - } - }, - { - "model": "api.energydensity", - "pk": 4, - "fields": { - "effective_date": "2017-01-01", - "category": 4, - "density": "23.58" - } - }, - { - "model": "api.energydensity", - "pk": 9, - "fields": { - "effective_date": "2017-01-01", - "category": 9, - "density": "38.65" - } - }, - { - "model": "api.approvedfuel", - "pk": 4, - "fields": { - "effective_date": "2017-01-01", - "name": "Ethanol", - "description": "Ethanol produced from biomass", - "credit_calculation_only": false, - "default_carbon_intensity_category": 10, - "energy_density_category": 4, - "energy_effectiveness_ratio_category": 6, - "unit_of_measure": ["L"], - "is_partially_renewable": true - } - }, - { - "model": "api.approvedfuel", - "pk": 19, - "fields": { - "effective_date": "2017-01-01", - "name": "'Petroleum-based diesel'", - "description": "'Diesel fuel, diesel, petroleum-based diesel'", - "credit_calculation_only": true, - "default_carbon_intensity_category": 6, - "energy_density_category": 9, - "energy_effectiveness_ratio_category": 5, - "unit_of_measure": ["L"], - "is_partially_renewable": false - } - }, - { - "fields": { - "determination_type": ["Carbon Intensity"], - "provision_act": 1, - "fuel": ["CNG"] - }, - "model": "api.approvedfuelprovision", - "pk": 500 - }, - { - "fields": { - "determination_type": ["GHGenius"], - "provision_act": 3, - "fuel": ["LNG"] - }, - "model": "api.approvedfuelprovision" - }, - { - "fields": { - "determination_type": ["Carbon Intensity"], - "provision_act": 1, - "fuel": ["LNG"] - }, - "model": "api.approvedfuelprovision", - "pk": 500 - } -] diff --git a/backend/api/migrations/0014_new_label_changes.py b/backend/api/migrations/0014_new_label_changes.py deleted file mode 100644 index 5f536ccd7..000000000 --- a/backend/api/migrations/0014_new_label_changes.py +++ /dev/null @@ -1,216 +0,0 @@ -from django.db import migrations -from django.db.migrations import RunPython - - -def update_permissions(apps, schema_editor): - """ - Updates the permissions and removes the create/edit fuel suppliers - from Government Analyst and Director roles - """ - db_alias = schema_editor.connection.alias - - permission = apps.get_model("api", "Permission") - notification_subscription = apps.get_model("api", "NotificationSubscription") - permission.objects.using(db_alias).filter( - code="VIEW_CREDIT_TRANSFERS" - ).update( - name="View compliance unit transactions", - description="View compliance unit transactions" - ) - - permission.objects.using(db_alias).filter( - code="VIEW_APPROVED_CREDIT_TRANSFERS" - ).update( - name="View recorded compliance unit transactions", - description="view compliance unit transactions within the Historical " - "Data Entry tool prior to them being committed" - ) - - permission.objects.using(db_alias).filter( - code="CREDIT_CALCULATION_MANAGE" - ).update( - name="Edit compliance unit calculation values", - description="edit values used in compliance unit calculation formula" - ) - - permission.objects.using(db_alias).filter( - code="DOCUMENTS_LINK_TO_CREDIT_TRADE" - ).update( - name="Link file submissions to compliance unit transactions", - description="establish link between file submissions and compliance unit transactions" - ) - - permission.objects.using(db_alias).filter( - code="RECOMMEND_CREDIT_TRANSFER" - ).update( - name="Recommend Credit transfers and Initiative Agreement submissions", - description="Make recommendations to the director for Credit transfers and Initiative Agreement submissions" - ) - - permission.objects.using(db_alias).filter( - code="APPROVE_CREDIT_TRANSFER" - ).update( - name="Record credit transfers and issue credits under Initiative Agreements", - description="Record credit transfers and issue credits under Initiative Agreements" - ) - - permission.objects.using(db_alias).filter( - code="DECLINE_CREDIT_TRANSFER" - ).update( - name="Decline credit transfers Initiative Agreement submissions", - description="Decline to record credit transfers and decline to issue credits under Initiative Agreements" - ) - - permission.objects.using(db_alias).filter( - code="PROPOSE_CREDIT_TRANSFER" - ).update( - name="Create new credit transfer", - description="Create new credit transfer" - ) - - permission.objects.using(db_alias).filter( - code="RESCIND_CREDIT_TRANSFER" - ).update( - name="Rescind a credit transfer", - description="Rescind a credit transfer sent to another organization" - ) - - permission.objects.using(db_alias).filter( - code="CREDIT_CALCULATION_VIEW" - ).update( - name="View compliance unit calculation values", - description="View values used in compliance unit calculation formula" - ) - - permission.objects.using(db_alias).filter( - code="REFUSE_CREDIT_TRANSFER" - ).update( - name="Refuse a credit transfer", - description="Refuse a credit transfer proposed by another organization" - ) - - permission.objects.using(db_alias).filter( - code="SIGN_CREDIT_TRANSFER" - ).update( - name="Propose and accept credit transfers", - description="Propose and accept credit transfers" - ) - - permission.objects.using(db_alias).filter( - code="USE_HISTORICAL_DATA_ENTRY" - ).update( - name="Use Historical Data Entry", - description="Record compliance unit transactions approved outside of TFRS" - ) - -def revert_permissions(apps, schema_editor): - """ - Reverts the permission back to its previous state by assigning - back the permission back to Government Analyst and Director - """ - db_alias = schema_editor.connection.alias - - permission = apps.get_model("api", "Permission") - permission.objects.using(db_alias).filter( - code="VIEW_CREDIT_TRANSFERS" - ).update( - name="View credit transactions", - description="View credit transactions" - ) - - permission.objects.using(db_alias).filter( - code="VIEW_APPROVED_CREDIT_TRANSFERS" - ).update( - name="View recorded credit transactions", - description="view credit transactions within the Historical " - "Data Entry tool prior to them being committed" - ) - - permission.objects.using(db_alias).filter( - code="CREDIT_CALCULATION_MANAGE" - ).update( - name="Edit credit calculation values", - description="edit values used in credit calculation formula" - ) - - permission.objects.using(db_alias).filter( - code="DOCUMENTS_LINK_TO_CREDIT_TRADE" - ).update( - name="Link file submissions to Part 3 Awards", - description="establish link between file submissions and Part 3 Awards" - ) - - permission.objects.using(db_alias).filter( - code="RECOMMEND_CREDIT_TRANSFER" - ).update( - name="Recommend Credit Transfer Proposals and Part 3 Awards", - description="recommend or not recommend approval of Credit Transfer Proposals and Part 3 Awards" - ) - - permission.objects.using(db_alias).filter( - code="APPROVE_CREDIT_TRANSFER" - ).update( - name="Approve credit transfer proposals and Part 3 Awards", - description="approve credit transfer proposals and Part 3 Awards" - ) - - permission.objects.using(db_alias).filter( - code="DECLINE_CREDIT_TRANSFER" - ).update( - name="Decline to approve credit transfer proposals and Part 3 Awards", - description="decline credit transfer proposals and Part 3 Awards" - ) - - permission.objects.using(db_alias).filter( - code="PROPOSE_CREDIT_TRANSFER" - ).update( - name="Create New Credit Transfer Proposal", - description="create new credit transfer proposal" - ) - - permission.objects.using(db_alias).filter( - code="RESCIND_CREDIT_TRANSFER" - ).update( - name="Rescind a credit transfer proposal", - description="rescind a credit transfer proposal sent to another organization" - ) - - permission.objects.using(db_alias).filter( - code="CREDIT_CALCULATION_VIEW" - ).update( - name="View credit calculation values", - description="view values used in credit calculation formula" - ) - - permission.objects.using(db_alias).filter( - code="REFUSE_CREDIT_TRANSFER" - ).update( - name="Refuse a credit transfer proposal", - description="refuse a credit transfer proposal received from another organization" - ) - - permission.objects.using(db_alias).filter( - code="SIGN_CREDIT_TRANSFER" - ).update( - name="Propose and accept credit transfer proposals", - description="propose and accept credit transfer proposals" - ) - - permission.objects.using(db_alias).filter( - code="USE_HISTORICAL_DATA_ENTRY" - ).update( - name="Use Historical Data Entry", - description="Record credit transactions approved outside of TFRS" - ) - -class Migration(migrations.Migration): - """ - Attaches the functions for the migrations - """ - dependencies = [ - ('api', '0013_create_missing_rescinded_history_records'), - ] - - operations = [ - RunPython(update_permissions, revert_permissions) - ] \ No newline at end of file diff --git a/backend/api/migrations/0015_add_admin_adjustment_20230808_1803.py b/backend/api/migrations/0015_add_admin_adjustment_20230808_1803.py deleted file mode 100644 index a63c19022..000000000 --- a/backend/api/migrations/0015_add_admin_adjustment_20230808_1803.py +++ /dev/null @@ -1,34 +0,0 @@ -from django.db import migrations - -# Forward operation: Adds the 'Administrative Adjustment' entry -def add_administrative_adjustment(apps, schema_editor): - CreditTradeType = apps.get_model('api', 'CreditTradeType') - credit_trade_type = CreditTradeType( - id=6, - the_type="Administrative Adjustment", - description="An administrative adjustment of the number of Fuel Credits owned by a Fuel Supplier initiated by the BC Government.", - is_gov_only_type=True, - display_order=6, - effective_date='2017-01-01', - expiration_date='2117-01-01' - ) - credit_trade_type.save() - -# Reverse operation: Removes the 'Administrative Adjustment' entry -def remove_administrative_adjustment(apps, schema_editor): - CreditTradeType = apps.get_model('api', 'CreditTradeType') - try: - credit_trade_type = CreditTradeType.objects.get(the_type="Administrative Adjustment") - credit_trade_type.delete() - except CreditTradeType.DoesNotExist: - pass - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0014_new_label_changes'), - ] - - operations = [ - migrations.RunPython(add_administrative_adjustment, remove_administrative_adjustment) - ] diff --git a/backend/api/migrations/0016_alter_credittrade_number_of_credits.py b/backend/api/migrations/0016_alter_credittrade_number_of_credits.py deleted file mode 100644 index d5bfb4b02..000000000 --- a/backend/api/migrations/0016_alter_credittrade_number_of_credits.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.19 on 2023-08-09 00:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0015_add_admin_adjustment_20230808_1803'), - ] - - operations = [ - migrations.AlterField( - model_name='credittrade', - name='number_of_credits', - field=models.IntegerField(), - ), - ] diff --git a/backend/api/migrations/0017_alter_compliace_report_history_status.py b/backend/api/migrations/0017_alter_compliace_report_history_status.py deleted file mode 100644 index 04f6c1ec5..000000000 --- a/backend/api/migrations/0017_alter_compliace_report_history_status.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.db import migrations, models, connection - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0016_alter_credittrade_number_of_credits'), - ] - # apply migration only to test database - if connection.settings_dict['NAME'] == 'test_tfrs': - operations = [ - migrations.RemoveField( - model_name='compliancereporthistory', - name='status' - ), - migrations.AddField( - model_name='compliancereporthistory', - name='status', - field=models.ForeignKey(on_delete=models.deletion.PROTECT, related_name='history_records', to='api.compliancereportworkflowstate'), - ), - ] diff --git a/backend/api/migrations/0018_report_history_grouping.py b/backend/api/migrations/0018_report_history_grouping.py deleted file mode 100644 index 4373c524f..000000000 --- a/backend/api/migrations/0018_report_history_grouping.py +++ /dev/null @@ -1,58 +0,0 @@ -from django.db import migrations, transaction, models -import collections - -def update_report_fields(apps, schema_editor): - ComplianceReport = apps.get_model('api', 'compliancereport') - for report in ComplianceReport.objects.filter(supplements__isnull=False): - with transaction.atomic(): - ancestor = report - root = None - latest = None - while ancestor.supplements is not None: - ancestor = ancestor.supplements - - visited = [] - id_traversal = {} - to_visit = collections.deque([ancestor.id]) - i = 0 - - while len(to_visit) > 0: - current_id = to_visit.popleft() - - # break loops - if current_id in visited: - continue - visited.append(current_id) - - current = ComplianceReport.objects.get(id=current_id) - - if current.supplements is None: - root = current - latest = current - # don't count non-supplement reports (really should just be the root) - if current.supplements is not None and \ - not current.status.fuel_supplier_status_id == "Deleted": - latest = current - i += 1 - id_traversal[current_id] = i - for descendant in current.supplemental_reports.order_by('create_timestamp').all(): - to_visit.append(descendant.id) - - for compliance_id, traversal in id_traversal.items(): - ComplianceReport.objects.filter(id=int(compliance_id)) \ - .update(latest_report=latest, root_report=root, traversal=traversal) - - -class Migration(migrations.Migration): - dependencies = [ - ('api', '0017_alter_compliace_report_history_status'), - ] - - operations = [ - migrations.AlterField( - model_name='compliancereport', - name='traversal', - field=models.IntegerField(default=0), - ), - migrations.RunPython(update_report_fields, reverse_code=migrations.RunPython.noop), - ] diff --git a/backend/api/migrations/0019_update_signing_authority_declaration_statement.py b/backend/api/migrations/0019_update_signing_authority_declaration_statement.py deleted file mode 100644 index 31781ff0f..000000000 --- a/backend/api/migrations/0019_update_signing_authority_declaration_statement.py +++ /dev/null @@ -1,38 +0,0 @@ -import logging -from django.db import migrations - -def update_sign_auth_assertion(apps, schema_editor): - """ - Updates the signing authority declaration statement - - Previous label: - "I confirm that records evidencing each matter reported under section 11.11 (2) of the - Regulation are available on request." - - New label: - "I confirm that records evidencing each matter reported under section 17 of the Low Carbon - Fuel (General) Regulation are available on request." - """ - signing_authority_assertion = apps.get_model('api', 'SigningAuthorityAssertion') - try: - assertion = signing_authority_assertion.objects.get(id=1) - assertion.description = ( - 'I confirm that records evidencing each matter reported under section 17 ' - 'of the Low Carbon Fuel (General) Regulation are available on request.' - ) - assertion.save() - except signing_authority_assertion.DoesNotExist: - logging.warning('Failed to update SigningAuthorityAssertion: No entry found with id "1".') - raise - -class Migration(migrations.Migration): - """ - Attaches the update function to the migration operations - """ - dependencies = [ - ('api', '0018_report_history_grouping'), - ] - - operations = [ - migrations.RunPython(update_sign_auth_assertion), - ] diff --git a/backend/api/migrations/0020_correct_effective_date_of_transfer_2095.py b/backend/api/migrations/0020_correct_effective_date_of_transfer_2095.py deleted file mode 100644 index fbb0d2b99..000000000 --- a/backend/api/migrations/0020_correct_effective_date_of_transfer_2095.py +++ /dev/null @@ -1,39 +0,0 @@ -import logging -from django.db import migrations, transaction -from django.utils import timezone - -def update_transfer_effective_date(apps, schema_editor): - """ - Update transfer ID #2095 to correct effective date from March 30, 2022 to March 30, 2023. - If any record is not updated, all changes are reverted. - """ - credit_trade_history = apps.get_model('api', 'CreditTradeHistory') - new_trade_effective_date = timezone.datetime.strptime('2023-03-30', "%Y-%m-%d").date() - - # IDs of the CreditTradeHistory records to update - history_ids = [4666, 4709] - - with transaction.atomic(): - for history_id in history_ids: - try: - history = credit_trade_history.objects.get(id=history_id) - history.trade_effective_date = new_trade_effective_date - history.save() - except credit_trade_history.DoesNotExist: - logging.warning( - 'Failed to update CreditTradeHistory: No entry found with id "%s"; ' - 'all changes within this transaction will be reverted.', - history_id - ) - -class Migration(migrations.Migration): - """ - Attaches the update function to the migration operations - """ - dependencies = [ - ('api', '0019_update_signing_authority_declaration_statement'), - ] - - operations = [ - migrations.RunPython(update_transfer_effective_date, reverse_code=migrations.RunPython.noop), - ] diff --git a/backend/api/migrations/0021_correct_compliance_period_of_transfer_2095.py b/backend/api/migrations/0021_correct_compliance_period_of_transfer_2095.py deleted file mode 100644 index fce3d3880..000000000 --- a/backend/api/migrations/0021_correct_compliance_period_of_transfer_2095.py +++ /dev/null @@ -1,40 +0,0 @@ -import logging -from django.db import migrations, transaction - -def update_credit_trade_history(apps, schema_editor): - """ - Update transfer ID #2095 to correct compliance period to the year 2023 (compliance_period_id=13) - from the previous year 2022 (compliance_period_id=12) - - If any record is not updated, all changes are reverted. - """ - credit_trade_history = apps.get_model('api', 'CreditTradeHistory') - new_compliance_period_id = 13 - - # IDs of the CreditTradeHistory records to update - history_ids = [978, 979] - - with transaction.atomic(): - for history_id in history_ids: - try: - history = credit_trade_history.objects.get(id=history_id) - history.compliance_period_id = new_compliance_period_id - history.save() - except credit_trade_history.DoesNotExist: - logging.warning( - 'Failed to update CreditTradeHistory: No entry found with id "%s"; ' - 'all changes within this transaction will be reverted.', - history_id - ) - -class Migration(migrations.Migration): - """ - Attaches the update function to the migration operations - """ - dependencies = [ - ('api', '0020_correct_effective_date_of_transfer_2095'), - ] - - operations = [ - migrations.RunPython(update_credit_trade_history, reverse_code=migrations.RunPython.noop), - ] diff --git a/backend/api/models/ComplianceReport.py b/backend/api/models/ComplianceReport.py index 67de36066..cd9c99199 100644 --- a/backend/api/models/ComplianceReport.py +++ b/backend/api/models/ComplianceReport.py @@ -233,7 +233,7 @@ class ComplianceReport(Auditable): related_name='latest_reports') traversal = models.IntegerField( - default=0, + default=1, db_comment="Traversal position of this compliance report. " ) @@ -247,6 +247,7 @@ class ComplianceReport(Auditable): db_comment='An explanatory note required when submitting a supplemental report' ) + @property def generated_nickname(self): """ Used for display in the UI when no nickname is set""" diff --git a/backend/api/models/CreditTrade.py b/backend/api/models/CreditTrade.py index 3fc1546bf..b5bac5b9f 100644 --- a/backend/api/models/CreditTrade.py +++ b/backend/api/models/CreditTrade.py @@ -70,6 +70,7 @@ class CreditTrade(Auditable): related_name='credit_trades', on_delete=models.PROTECT) number_of_credits = models.IntegerField( + validators=[validators.CreditTradeNumberOfCreditsValidator], db_comment="Number of credits to be transferred on approval" ) fair_market_value_per_credit = models.DecimalField( @@ -131,8 +132,8 @@ def credits_from(self): And for type: Buy and Retirement Credits From is the Respondent """ - # 3, 5 and 6 is government - if self.type.id in [1, 3, 5, 6]: + # 3 and 5 is government + if self.type.id in [1, 3, 5]: return self.initiator # elif self.type.id in [2, 4] return self.respondent @@ -246,10 +247,6 @@ def comment(self): def comment(self, comment): self._comment = comment - def clean(self): - super().clean() - validators.CreditTradeNumberOfCreditsValidator(self.number_of_credits, self) - class Meta: db_table = 'credit_trade' diff --git a/backend/api/models/CreditTradeType.py b/backend/api/models/CreditTradeType.py index 85e3cabef..ce34072c8 100644 --- a/backend/api/models/CreditTradeType.py +++ b/backend/api/models/CreditTradeType.py @@ -81,27 +81,5 @@ def friendly_name(self): if self.the_type == "Credit Validation": return "Validation" - - if self.the_type == "Administrative Adjustment": - return "Admin Adjustment" - - return self.the_type - - @property - def notification_name(self): - """ - Front-end Notification language for the Credit Trade Type - """ - if self.the_type in ["Buy", "Sell"]: - return "Transfer" - - if self.the_type == "Credit Reduction" or self.the_type == "Credit Validation": - return "Assessment" - - if self.the_type == "Part 3 Award": - return "Initiative Agreement" - - if self.the_type == "Administrative Adjustment": - return "Admin Adjustment" return self.the_type diff --git a/backend/api/serializers/ComplianceReport.py b/backend/api/serializers/ComplianceReport.py index 93c459fea..e53964bdb 100644 --- a/backend/api/serializers/ComplianceReport.py +++ b/backend/api/serializers/ComplianceReport.py @@ -53,7 +53,6 @@ from api.serializers.constants import ComplianceReportValidation from api.services.ComplianceReportService import ComplianceReportService from api.services.OrganizationService import OrganizationService -from api.services.ComplianceReportSummaryService import ComplianceReportSummaryService class ComplianceReportBaseSerializer: def get_last_accepted_offset(self, obj): @@ -474,7 +473,7 @@ def get_deltas(self, obj): ) if qs.exists(): - ancestor_snapshot = ComplianceReportDetailSerializer.build_compliance_units(qs.first().snapshot, obj) if int(obj.compliance_period.description) > 2022 else qs.first().snapshot + ancestor_snapshot = qs.first().snapshot ancestor_computed = False else: # no snapshot. make one. @@ -490,7 +489,7 @@ def get_deltas(self, obj): ) if qs.exists(): - current_snapshot = ComplianceReportDetailSerializer.build_compliance_units(qs.first().snapshot, obj) if int(obj.compliance_period.description) > 2022 else qs.first().snapshot + current_snapshot = qs.first().snapshot else: # no snapshot ser = ComplianceReportDetailSerializer( @@ -518,68 +517,6 @@ def get_deltas(self, obj): current = current.supplements return deltas - - @staticmethod - def build_compliance_units(snapshot, obj): - lines = snapshot['summary']['lines'] - if lines.get('29A') is None: - previous_transactions = [] - previous_snapshots = [] - current = obj - is_supplemental = False - - if current.supplements: - is_supplemental = True - - available_compliance_unit_balance = OrganizationService.get_max_credit_offset_for_interval( - obj.organization, - obj.update_timestamp - ) - net_compliance_unit_balance = int(lines['25']) - desired_net_credit_balance_change = Decimal(0.0) - if is_supplemental: - while current.supplements is not None: - current = current.supplements - if current.credit_transaction is not None: - previous_transactions.append(current.credit_transaction) - if current.compliance_report_snapshot is not None: - previous_snapshots.append(current.compliance_report_snapshot.snapshot) - - total_previous_reduction = Decimal(0.0) - total_previous_validation = Decimal(0.0) - - for transaction in previous_transactions: - if transaction.type.the_type in ['Credit Validation']: - total_previous_validation += transaction.number_of_credits - if transaction.type.the_type in ['Credit Reduction']: - total_previous_reduction += transaction.number_of_credits - desired_net_credit_balance_change = Decimal(lines['25']) - net_compliance_unit_balance = desired_net_credit_balance_change - \ - (total_previous_validation - total_previous_reduction) - - adjusted_balance = available_compliance_unit_balance + net_compliance_unit_balance - if available_compliance_unit_balance <= 0 and net_compliance_unit_balance < 0: - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if (adjusted_balance < 0) else 0 - lines['29A'] = 0 - total_previous_compliance_units = Decimal(0.0) - for snapshots in previous_snapshots: - if snapshots.get("summary").get("lines") is not None: - total_previous_compliance_units += Decimal(snapshots.get("summary").get("lines").get("25")) - lines['29B'] = Decimal(lines['25']) - total_previous_compliance_units - lines['29C'] = 0 - else: - lines['29A'] = available_compliance_unit_balance - lines['28'] = 0 - if (net_compliance_unit_balance < 0 <= adjusted_balance) or (net_compliance_unit_balance >= 0): - lines['29B'] = net_compliance_unit_balance - elif net_compliance_unit_balance < 0 and adjusted_balance < 0: - lines['29B'] = net_compliance_unit_balance if (adjusted_balance > 0) else -available_compliance_unit_balance - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if (adjusted_balance < 0) else 0 - lines['29C'] = lines['29A'] + lines['29B'] - snapshot['summary']['total_payable'] = Decimal(lines['11']) + Decimal(lines['22']) + lines['28'] - snapshot['summary']['lines'] = lines - - return snapshot def get_max_credit_offset(self, obj): max_credit_offset = OrganizationService.get_max_credit_offset( @@ -605,17 +542,150 @@ def get_max_credit_offset_exclude_reserved(self, obj): return max_credit_offset_exclude_reserved def get_summary(self, obj): - """ - Retrieve a summary that merges synthetic totals with existing summary data. - - :param obj: The compliance report object containing summary and synthetic details. - :return: A dictionary combining synthetic totals with existing summary data. - """ - # Compute the synthetic totals for the provided compliance report object. - synthetic_totals = ComplianceReportSummaryService.calculate_synthetic_totals(obj) + total_petroleum_diesel = Decimal(0) + total_petroleum_gasoline = Decimal(0) + total_renewable_diesel = Decimal(0) + total_renewable_gasoline = Decimal(0) + total_credits = Decimal(0) + total_debits = Decimal(0) + net_gasoline_class_transferred = Decimal(0) + net_diesel_class_transferred = Decimal(0) + + lines = {} + + if obj.summary is not None: + lines['6'] = obj.summary.gasoline_class_retained \ + if obj.summary.gasoline_class_retained is not None \ + else Decimal(0) + lines['7'] = obj.summary.gasoline_class_previously_retained \ + if obj.summary.gasoline_class_previously_retained is not None \ + else Decimal(0) + lines['8'] = obj.summary.gasoline_class_deferred \ + if obj.summary.gasoline_class_deferred is not None \ + else Decimal(0) + lines['9'] = obj.summary.gasoline_class_obligation \ + if obj.summary.gasoline_class_obligation is not None \ + else Decimal(0) + lines['17'] = obj.summary.diesel_class_retained \ + if obj.summary.diesel_class_retained is not None \ + else Decimal(0) + lines['18'] = obj.summary.diesel_class_previously_retained \ + if obj.summary.diesel_class_previously_retained is not None \ + else Decimal(0) + lines['19'] = obj.summary.diesel_class_deferred \ + if obj.summary.diesel_class_deferred is not None \ + else Decimal(0) + lines['20'] = obj.summary.diesel_class_obligation \ + if obj.summary.diesel_class_obligation is not None \ + else Decimal(0) + lines['26'] = Decimal(obj.summary.credits_offset) \ + if obj.summary.credits_offset is not None else Decimal(0) + lines['26A'] = Decimal(obj.summary.credits_offset_a) \ + if obj.summary.credits_offset_a is not None else Decimal(0) + lines['26B'] = Decimal(obj.summary.credits_offset_b) \ + if obj.summary.credits_offset_b is not None else Decimal(0) + lines['26C'] = Decimal(obj.summary.credits_offset_c) \ + if obj.summary.credits_offset_c is not None else Decimal(0) + else: + lines['6'] = Decimal(0) + lines['7'] = Decimal(0) + lines['8'] = Decimal(0) + lines['9'] = Decimal(0) + lines['17'] = Decimal(0) + lines['18'] = Decimal(0) + lines['19'] = Decimal(0) + lines['20'] = Decimal(0) + lines['26'] = Decimal(0) + lines['26A'] = Decimal(0) + lines['26B'] = Decimal(0) + lines['26C'] = Decimal(0) + + if obj.schedule_a: + net_gasoline_class_transferred += \ + obj.schedule_a.net_gasoline_class_transferred + net_diesel_class_transferred += \ + obj.schedule_a.net_diesel_class_transferred + + lines['5'] = net_gasoline_class_transferred + lines['16'] = net_diesel_class_transferred + + if obj.schedule_b: + total_petroleum_diesel += obj.schedule_b.total_petroleum_diesel + total_petroleum_gasoline += obj.schedule_b.total_petroleum_gasoline + total_renewable_diesel += obj.schedule_b.total_renewable_diesel + total_renewable_gasoline += obj.schedule_b.total_renewable_gasoline + total_credits += obj.schedule_b.total_credits + total_debits += obj.schedule_b.total_debits + + if obj.schedule_c: + total_petroleum_diesel += obj.schedule_c.total_petroleum_diesel + total_petroleum_gasoline += obj.schedule_c.total_petroleum_gasoline + total_renewable_diesel += obj.schedule_c.total_renewable_diesel + total_renewable_gasoline += obj.schedule_c.total_renewable_gasoline + + lines['1'] = total_petroleum_gasoline + lines['2'] = total_renewable_gasoline + lines['3'] = lines['1'] + lines['2'] + lines['4'] = (lines['3'] * Decimal('0.05')).quantize( + Decimal('1.'), rounding=ROUND_HALF_UP + ) # hardcoded 5% renewable requirement + lines['10'] = lines['2'] + lines['5'] - lines['6'] + lines['7'] + \ + lines['8'] - lines['9'] + lines['11'] = ((lines['4'] - lines['10']) * Decimal('0.30')).max( + Decimal(0)).quantize(Decimal('.01'), rounding=ROUND_HALF_UP) + + lines['12'] = total_petroleum_diesel + lines['13'] = total_renewable_diesel + lines['14'] = lines['12'] + lines['13'] + lines['15'] = (lines['14'] * Decimal('0.04')).quantize( + Decimal('1.'), rounding=ROUND_HALF_UP + ) # hardcoded 4% renewable requirement + lines['21'] = lines['13'] + lines['16'] - lines['17'] + lines['18'] + \ + lines['19'] - lines['20'] + lines['22'] = ((lines['15'] - lines['21']) * Decimal('0.45')).max( + Decimal(0)).quantize(Decimal('.01'), rounding=ROUND_HALF_UP) + + lines['23'] = total_credits + lines['24'] = total_debits + lines['25'] = lines['23'] - lines['24'] + + # if current_balance is positive it means the supplier + # has a positive amount of credits for this compliance period + # and there is no penalty, otherwise use current_balance + # to calculate penalty + current_balance = lines['25'] + lines['26'] + if current_balance > 0: + lines['27'] = 0 + else: + lines['27'] = current_balance + + # 26C represents credits that need to be returned to the fuel supplier. + # Line 27 should end up being zero in this situation because + # 26C is the difference between lines 26A and 25 when 26A > 25 + if lines['26C'] is not None and lines['26C'] > 0: + lines['27'] = 0 # eqv. to lines['25'] + lines['26A'] - lines['26C'] + + # Penalty adjustment made by business area for + # 2023 and above compliance periods + if int(obj.compliance_period.description) <= 2022: + lines['28'] = (lines['27'] * Decimal('-200.00')).max(Decimal(0)) + else: + lines['28'] = (lines['27'] * Decimal('-600.00')).max(Decimal(0)) + + total_payable = lines['11'] + lines['22'] + lines['28'] + + synthetic_totals = { + "total_petroleum_diesel": total_petroleum_diesel, + "total_petroleum_gasoline": total_petroleum_gasoline, + "total_renewable_diesel": total_renewable_diesel, + "total_renewable_gasoline": total_renewable_gasoline, + "net_diesel_class_transferred": net_diesel_class_transferred, + "net_gasoline_class_transferred": net_gasoline_class_transferred, + "lines": lines, + "total_payable": total_payable + } - # If a summary already exists for the object, merge it with the computed synthetic totals. - if obj.summary: + if obj.summary is not None: ser = ScheduleSummaryDetailSerializer(obj.summary) data = ser.data synthetic_totals = {**data, **synthetic_totals} @@ -1180,8 +1250,6 @@ def create(self, validated_data): ComplianceReport.objects.filter(root_report=root_report).update(latest_report=new_compliance_report) else: new_compliance_report.traversal = previous_report.traversal - ComplianceReport.objects.filter(root_report_id=root_report.id)\ - .update(latest_report=new_compliance_report) else: new_compliance_report.root_report = new_compliance_report new_compliance_report.latest_report = new_compliance_report @@ -1224,7 +1292,6 @@ class ComplianceReportUpdateSerializer( ) actions = serializers.SerializerMethodField() actor = serializers.SerializerMethodField() - deltas = serializers.SerializerMethodField() display_name = SerializerMethodField() max_credit_offset = SerializerMethodField() max_credit_offset_exclude_reserved = SerializerMethodField() @@ -1236,7 +1303,6 @@ class ComplianceReportUpdateSerializer( strip_summary = False disregard_status = False - skip_deltas = False def get_display_name(self, obj): if obj.nickname is not None and obj.nickname != '': @@ -1306,69 +1372,6 @@ def get_history(self, obj): return serializer.data else: return None - - def get_deltas(self, obj): - - deltas = [] - - if self.skip_deltas: - return deltas - - current = obj - - while current: - if current.supplements: - ancestor = current.supplements - - qs = ComplianceReportSnapshot.objects.filter( - compliance_report=ancestor - ) - - if qs.exists(): - ancestor_snapshot = ComplianceReportDetailSerializer.build_compliance_units(qs.first().snapshot, obj) if int(obj.compliance_period.description) > 2022 else qs.first().snapshot - ancestor_computed = False - else: - # no snapshot. make one. - ser = ComplianceReportDetailSerializer( - ancestor, context=self.context - ) - ser.skip_deltas = True - ancestor_snapshot = ser.data - ancestor_computed = True - - qs = ComplianceReportSnapshot.objects.filter( - compliance_report=current - ) - - if qs.exists(): - current_snapshot = ComplianceReportDetailSerializer.build_compliance_units(qs.first().snapshot, obj) if int(obj.compliance_period.description) > 2022 else qs.first().snapshot - else: - # no snapshot - ser = ComplianceReportDetailSerializer( - current, context=self.context - ) - ser.skip_deltas = True - current_snapshot = ser.data - - deltas += [{ - 'levels_up': 1, - 'ancestor_id': ancestor.id, - 'ancestor_display_name': ancestor.nickname - if (ancestor.nickname is not None and - ancestor.nickname != '') - else ancestor.generated_nickname, - 'delta': ComplianceReportService.compute_delta( - current_snapshot, ancestor_snapshot - ), - 'snapshot': { - 'data': ancestor_snapshot, - 'computed': ancestor_computed - } - }] - - current = current.supplements - - return deltas def update(self, instance, validated_data): request = self.context.get('request') @@ -1387,20 +1390,19 @@ def update(self, instance, validated_data): instance.compliance_period.description ) - if int(instance.compliance_period.description) <= 2022: - if summary_data and instance.supplements_id is None and \ - summary_data.get('credits_offset', 0) and \ - summary_data.get('credits_offset', 0) > max_credit_offset: - raise (serializers.ValidationError( - 'Insufficient available credit balance. Please adjust Line 26.' - )) - - if summary_data and instance.supplements_id and \ - summary_data.get('credits_offset_b', 0) and \ - summary_data.get('credits_offset_b', 0) > max_credit_offset and not self.strip_summary: - raise (serializers.ValidationError( - 'Insufficient available credit balance. Please adjust Line 26b.' - )) + if summary_data and instance.supplements_id is None and \ + summary_data.get('credits_offset', 0) and \ + summary_data.get('credits_offset', 0) > max_credit_offset: + raise (serializers.ValidationError( + 'Insufficient available credit balance. Please adjust Line 26.' + )) + + if summary_data and instance.supplements_id and \ + summary_data.get('credits_offset_b', 0) and \ + summary_data.get('credits_offset_b', 0) > max_credit_offset and not self.strip_summary: + raise (serializers.ValidationError( + 'Insufficient available credit balance. Please adjust Line 26b.' + )) if 'status' in validated_data: status_data = validated_data.pop('status') @@ -1677,7 +1679,7 @@ class Meta: fields = ( 'status', 'type', 'compliance_period', 'organization', 'schedule_a', 'schedule_b', 'schedule_c', 'schedule_d', - 'summary', 'read_only', 'has_snapshot', 'actions', 'actor', 'deltas', + 'summary', 'read_only', 'has_snapshot', 'actions', 'actor', 'display_name', 'supplemental_note', 'is_supplemental', 'max_credit_offset', 'max_credit_offset_exclude_reserved', 'total_previous_credit_reductions', 'supplemental_number', 'last_accepted_offset', 'history', @@ -1715,8 +1717,6 @@ def destroy(self): compliance_report.status.fuel_supplier_status = \ ComplianceReportStatus.objects.get(status="Deleted") - ComplianceReport.objects.filter(root_report_id=compliance_report.root_report.id)\ - .update(latest_report=compliance_report.supplements) compliance_report.status.save() class Meta: diff --git a/backend/api/serializers/CreditTrade.py b/backend/api/serializers/CreditTrade.py index 0af953064..79a8bb581 100644 --- a/backend/api/serializers/CreditTrade.py +++ b/backend/api/serializers/CreditTrade.py @@ -48,8 +48,10 @@ from .Organization import OrganizationMinSerializer, OrganizationSerializer from .User import UserMinSerializer -INSUFFICIENT_CREDITS_MESSAGE = "Unable to initiate transfer. " \ - "Your organization does not have enough compliance units for this transfer." +INSUFFICIENT_CREDITS_MESSAGE = "Unable to initiate this Credit Transfer " \ + "Proposal. Your organization either does not have enough " \ + "validated credits or has pending Credit Transfer Proposal(s) that " \ + "could result in an insufficient credit balance for this transfer." class CreditTradeCreateSerializer(serializers.ModelSerializer): @@ -133,8 +135,7 @@ def validate(self, data): the_type__in=[ "Credit Validation", "Credit Reduction", - "Part 3 Award", - "Administrative Adjustment" + "Part 3 Award" ] ).only('id') ) @@ -259,7 +260,7 @@ class Meta: extra_kwargs = { 'compliance_period': { 'error_messages': { - 'does_not_exist': "Please specify the compliance period " + 'does_not_exist': "Please specify the Compliance Period " "in which the transaction relates." } }, @@ -631,7 +632,7 @@ class Meta: extra_kwargs = { 'compliance_period': { 'error_messages': { - 'does_not_exist': "Please specify the compliance period " + 'does_not_exist': "Please specify the Compliance Period " "in which the transaction relates." } }, diff --git a/backend/api/serializers/CreditTradeType.py b/backend/api/serializers/CreditTradeType.py index 851c90def..27beb6e4c 100644 --- a/backend/api/serializers/CreditTradeType.py +++ b/backend/api/serializers/CreditTradeType.py @@ -31,7 +31,7 @@ class Meta: fields = ( 'id', 'the_type', 'description', 'effective_date', 'expiration_date', - 'display_order', 'is_gov_only_type', 'notification_name') + 'display_order', 'is_gov_only_type') class CreditTradeTypeMinSerializer(serializers.ModelSerializer): diff --git a/backend/api/serializers/Document.py b/backend/api/serializers/Document.py index 962fbb04c..7a5a4d9e2 100644 --- a/backend/api/serializers/Document.py +++ b/backend/api/serializers/Document.py @@ -127,7 +127,7 @@ def validate_title(self, value): the_type="Evidence").id: if not value: raise serializers.ValidationError( - "Please provide the name of the Initiative Agreement to which " + "Please provide the name of the Part 3 Agreement to which " "the submission relates." ) @@ -150,8 +150,8 @@ def validate_milestone(self, value): the_type="Evidence").id: if not value: raise serializers.ValidationError( - "Please indicate the Designated Action(s) to which the " - "submission relates." + "Please indicate the Milestone(s) to which the submission " + "relates." ) return value @@ -223,8 +223,8 @@ class Meta: extra_kwargs = { 'compliance_period': { 'error_messages': { - 'does_not_exist': "Please specify the compliance period " - "to which the submission relates." + 'does_not_exist': "Please specify the Compliance Period " + "to which the request relates." } } } @@ -432,7 +432,7 @@ def validate_title(self, value): if document.type == DocumentType.objects.get(the_type="Evidence").id: if not value: raise serializers.ValidationError( - "Please provide the name of the Initiative Agreement to which " + "Please provide the name of the Part 3 Agreement to which " "the submission relates." ) @@ -455,8 +455,8 @@ def validate_milestone(self, value): the_type="Evidence"): if not value: raise serializers.ValidationError( - "Please indicate the Designated Action(s) to which the " - "submission relates." + "Please indicate the Milestone(s) to which the submission " + "relates." ) return value @@ -516,8 +516,8 @@ def validate(self, data): if 'milestone' in request.data and \ not request.data.get('milestone'): raise serializers.ValidationError({ - 'milestone': "Please indicate the Designated " - "Action(s) to which the submission relates." + 'milestone': "Please indicate the Milestone(s) to " + "which the submission relates." }) current_attachments = document.attachments @@ -656,8 +656,8 @@ class Meta: extra_kwargs = { 'compliance_period': { 'error_messages': { - 'does_not_exist': "Please specify the compliance period " - "to which the submission relates." + 'does_not_exist': "Please specify the Compliance Period " + "to which the request relates." } }, 'milestone': { diff --git a/backend/api/services/ComplianceReportService.py b/backend/api/services/ComplianceReportService.py index 38f3c05b0..b18015228 100644 --- a/backend/api/services/ComplianceReportService.py +++ b/backend/api/services/ComplianceReportService.py @@ -255,7 +255,6 @@ def create_director_transactions(compliance_report, creating_user): raise InvalidStateException() snapshot = compliance_report.snapshot - COMPLIANCE_PERIOD_2023_AND_ABOVE = int(snapshot['compliance_period']['description']) >= 2023 if 'summary' not in snapshot: raise InvalidStateException() @@ -263,45 +262,33 @@ def create_director_transactions(compliance_report, creating_user): raise InvalidStateException() lines = snapshot['summary']['lines'] - if COMPLIANCE_PERIOD_2023_AND_ABOVE: - # If a compliance report is in a deficit position(i.e., a negative net compliance unit balance for the - # compliance period or negative value in Line 25 in the summary section) that is greater than - # the organization’s available credit balance, then the available compliance unit balance needs to be - # zeroed out when the director assesses (accepts) the compliance report. - if Decimal(lines['25']) < Decimal(0) \ - and (Decimal(lines['29A']) + Decimal(lines['25'])) < 0: - required_credit_transaction = Decimal(lines['29A']) * Decimal(-1.0) - else: - desired_net_credit_balance_change = Decimal(lines['25']) - required_credit_transaction = desired_net_credit_balance_change - \ - (total_previous_validation - total_previous_reduction) - else: - desired_net_credit_balance_change = Decimal(0.0) - - if Decimal(lines['25']) > Decimal(0): - desired_net_credit_balance_change = Decimal(lines['25']) - elif Decimal(lines['25']) < 0 and Decimal(lines['26']) > Decimal(0): - desired_net_credit_balance_change = Decimal(lines['26']) * Decimal(-1.0) - - required_credit_transaction = desired_net_credit_balance_change - \ - (total_previous_validation - total_previous_reduction) - - if settings.DEVELOPMENT: - print('line 25 of current report: {}'.format(lines['25'])) - print('desired credit balance change: {}'.format(desired_net_credit_balance_change)) - print('required transaction to effect change: {}'.format(required_credit_transaction)) - - if is_supplemental and Decimal(lines['25']) < 0 and \ - (Decimal(lines['26']) + Decimal(lines['25'])) > 0: - required_credit_transaction = Decimal(lines['26']) + Decimal(lines['25']) - - # Code 26C is used to identify credits that must be refunded to the supplier. - # This occurs when our debit position decreases and we have already spent credits. - # In such cases, any excess credits must be returned to the supplier. - if is_supplemental and Decimal(lines['26C']) > 0: - print("*** DIRECTOR 26C Increase to Credits ***") - required_credit_transaction = Decimal(lines['26C']) - + + desired_net_credit_balance_change = Decimal(0.0) + + if Decimal(lines['25']) > Decimal(0): + desired_net_credit_balance_change = Decimal(lines['25']) + elif Decimal(lines['25']) < 0 and Decimal(lines['26']) > Decimal(0): + desired_net_credit_balance_change = Decimal(lines['26']) * Decimal(-1.0) + + required_credit_transaction = desired_net_credit_balance_change - \ + (total_previous_validation - total_previous_reduction) + + if settings.DEVELOPMENT: + print('line 25 of current report: {}'.format(lines['25'])) + print('desired credit balance change: {}'.format(desired_net_credit_balance_change)) + print('required transaction to effect change: {}'.format(required_credit_transaction)) + + if is_supplemental and Decimal(lines['25']) < 0 and \ + (Decimal(lines['26']) + Decimal(lines['25'])) > 0: + required_credit_transaction = Decimal(lines['26']) + Decimal(lines['25']) + + # Code 26C is used to identify credits that must be refunded to the supplier. + # This occurs when our debit position decreases and we have already spent credits. + # In such cases, any excess credits must be returned to the supplier. + if is_supplemental and Decimal(lines.get('26C', 0)) > 0: + print("*** DIRECTOR 26C Increase to Credits ***") + required_credit_transaction = Decimal(lines['26C']) + if required_credit_transaction > Decimal(0): # do validation for Decimal(lines['25']) credit_transaction = CreditTrade( @@ -322,19 +309,7 @@ def create_director_transactions(compliance_report, creating_user): CreditTradeService.pvr_notification(None, credit_transaction) else: if required_credit_transaction < Decimal(0): - if COMPLIANCE_PERIOD_2023_AND_ABOVE: - # Fetch the organization's balance from organization_balance property - org_balance = Decimal(compliance_report.organization.organization_balance['validated_credits']) - - # Deduct the pending deductions, if any, from the organization balance. - if 'deductions' in compliance_report.organization.organization_balance: - org_balance -= Decimal(compliance_report.organization.organization_balance['deductions']) - - # If required_credit_transaction is more negative than the organization balance, - # set it to be equal to the organization balance. - if org_balance + required_credit_transaction < Decimal(0): - required_credit_transaction = -org_balance - + # do_reduction for Decimal(lines['26']) credit_transaction = CreditTrade( initiator=Organization.objects.get(id=1), respondent=compliance_report.organization, diff --git a/backend/api/services/ComplianceReportSpreadSheet.py b/backend/api/services/ComplianceReportSpreadSheet.py index ede04739f..b7ca48e2d 100644 --- a/backend/api/services/ComplianceReportSpreadSheet.py +++ b/backend/api/services/ComplianceReportSpreadSheet.py @@ -84,7 +84,7 @@ def add_schedule_a(self, schedule_a): worksheet.write(row_index, 3, record['transfer_type']) worksheet.write(row_index, 4, Decimal(record['quantity']), quantity_format) - def add_schedule_b(self, schedule_b, compliance_period): + def add_schedule_b(self, schedule_b): worksheet = self.workbook.add_sheet("Schedule B") row_index = 0 @@ -93,12 +93,6 @@ def add_schedule_b(self, schedule_b, compliance_period): "Quantity", "Units", "Carbon Intensity Limit", "Carbon Intensity of Fuel", "Energy Density", "EER", "Energy Content", "Credit", "Debit" ] - if compliance_period >= 2023: - columns = [ - "Fuel Type", "Fuel Class", "Provision", "Fuel Code or Schedule D Provision", - "Quantity", "Units", "Carbon Intensity Limit", "Carbon Intensity of Fuel", - "Energy Density", "EER", "Energy Content", "Compliance Units" - ] header_style = xlwt.easyxf('font: bold on') @@ -141,18 +135,10 @@ def add_schedule_b(self, schedule_b, compliance_period): worksheet.write(row_index, 8, Decimal(record['energy_density'])) worksheet.write(row_index, 9, Decimal(record['eer'])) worksheet.write(row_index, 10, Decimal(record['energy_content'])) - if compliance_period < 2023: - if record['credits'] is not None: - worksheet.write(row_index, 11, Decimal(record['credits'])) - if record['debits'] is not None: - worksheet.write(row_index, 12, Decimal(record['debits'])) - else: - compliance_units = None - if record['credits'] is not None: - compliance_units = Decimal(record['credits']) - if compliance_units is None and record['debits'] is not None: - compliance_units = Decimal(record['debits']) * -1 - worksheet.write(row_index, 11, compliance_units) + if record['credits'] is not None: + worksheet.write(row_index, 11, Decimal(record['credits'])) + if record['debits'] is not None: + worksheet.write(row_index, 12, Decimal(record['debits'])) def add_schedule_c(self, schedule_c): worksheet = self.workbook.add_sheet("Schedule C") @@ -257,7 +243,7 @@ def add_schedule_d(self, schedule_d): worksheet.write(row_index, 0, output['description']) worksheet.write(row_index, 1, Decimal(output['intensity']), value_format) - def add_schedule_summary(self, summary, compliance_period): + def add_schedule_summary(self, summary): worksheet = self.workbook.add_sheet("Summary") row_index = 0 @@ -266,8 +252,6 @@ def add_schedule_summary(self, summary, compliance_period): value_format = xlwt.easyxf(num_format_str='#,##0.00') currency_format = xlwt.easyxf(num_format_str='$#,##0.00') description_format = xlwt.easyxf('align: wrap on') - if summary is None: - return line_details = { '1': 'Volume of gasoline class non-renewable fuel supplied', @@ -306,18 +290,15 @@ def add_schedule_summary(self, summary, compliance_period): '27': 'Outstanding debit balance', '28': 'Part 3 non-compliance penalty payable' } - if compliance_period >= 2023: - line_details['25'] = 'Net compliance unit balance for compliance period' - line_details['29A'] = 'Available compliance unit balance on March 31, ' + str(int(compliance_period) + 1) - line_details['29B'] = 'Compliance unit balance change from assessment' - line_details['29C'] = 'Available compliance unit balance after assessment on March 31, ' + str(int(compliance_period) + 1) - line_details['28'] = 'Non-compliance penalty payable (' + str(int(Decimal(summary['lines']['28'])/600)) + ' units * $600 CAD per unit)' line_format = defaultdict(lambda: quantity_format) line_format['11'] = currency_format line_format['22'] = currency_format line_format['28'] = currency_format + if summary is None: + return + columns = [ "Part 2 Gasoline Class - 5% Renewable Requirement", "Line", @@ -350,7 +331,7 @@ def add_schedule_summary(self, summary, compliance_period): row_index += 1 columns = [ - "Part 3 - Low Carbon Fuel Requirement Summary" if compliance_period < 2023 else "Low Carbon Fuel Requirement", + "Part 3 - Low Carbon Fuel Requirement Summary", "Line", "Value" ] @@ -358,21 +339,11 @@ def add_schedule_summary(self, summary, compliance_period): for col_index, value in enumerate(columns): worksheet.write(row_index, col_index, value, header_style) - if compliance_period >= 2023: - compliance_lines = ['25','29A','29B','28','29C'] - for line in compliance_lines: - if line != '28' or (line == '28' and summary['lines'][line] > 0): - row_index += 1 - worksheet.write(row_index, 0, line_details[line], description_format) - if line.isdigit(): - worksheet.write(row_index, 1, f'Line {line}') - worksheet.write(row_index, 2, Decimal(summary['lines'][line]), line_format[str(line)]) - else: - for line in range(23, 28+1): - row_index += 1 - worksheet.write(row_index, 0, line_details[str(line)], description_format) - worksheet.write(row_index, 1, 'Line {}'.format(line)) - worksheet.write(row_index, 2, Decimal(summary['lines'][str(line)]), line_format[str(line)]) + for line in range(23, 28+1): + row_index += 1 + worksheet.write(row_index, 0, line_details[str(line)], description_format) + worksheet.write(row_index, 1, 'Line {}'.format(line)) + worksheet.write(row_index, 2, Decimal(summary['lines'][str(line)]), line_format[str(line)]) row_index += 1 columns = [ diff --git a/backend/api/services/ComplianceReportSummaryService.py b/backend/api/services/ComplianceReportSummaryService.py deleted file mode 100644 index 3b5b22684..000000000 --- a/backend/api/services/ComplianceReportSummaryService.py +++ /dev/null @@ -1,262 +0,0 @@ -from decimal import Decimal, ROUND_HALF_UP -from django.db.models import Q -from django.db.transaction import on_commit -from api.services.OrganizationService import OrganizationService - - -class ComplianceReportSummaryService(object): - """ - Helper functions for Compliance Report Summary Calculations - """ - - @staticmethod - def initialize_lines(): - """Initialize all lines to 0""" - return {key: Decimal(0) for key in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', - '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', - '22', '23', '24', '25', '26', '26A', '26B', '26C', '27', - '28', '29A', '29B', '29C']} - - @staticmethod - def extract_summary_values(summary): - """Extract and assign values from summary to corresponding lines.""" - attributes = [ - ('gasoline_class_retained', '6'), - ('gasoline_class_previously_retained', '7'), - ('gasoline_class_deferred', '8'), - ('gasoline_class_obligation', '9'), - ('diesel_class_retained', '17'), - ('diesel_class_previously_retained', '18'), - ('diesel_class_deferred', '19'), - ('diesel_class_obligation', '20'), - ('credits_offset', '26'), - ('credits_offset_a', '26A'), - ('credits_offset_b', '26B'), - ('credits_offset_c', '26C') - ] - return {line: Decimal(0) if getattr(summary, attr) is None else getattr(summary, attr) for attr, line in attributes} - - @staticmethod - def calculate_synthetic_totals(obj): - """ - Calculate synthetic totals for a given object based on its schedules. - This method takes in a main object and, based on its schedules, calculates the various totals and their - interactions, returning a dictionary that represents the synthetic totals for different fields. - - :param obj: The main object which contains schedules and other relevant attributes. - :return: A dictionary containing the synthetic totals for different fields. - """ - # Initialize the lines with default values - lines = ComplianceReportSummaryService.initialize_lines() - - # If the object has a summary, update the initialized lines with its values - if obj.summary: - lines.update(ComplianceReportSummaryService.extract_summary_values(obj.summary)) - - # Extract values from individual schedules and update the lines accordingly - lines.update(ComplianceReportSummaryService.process_schedule_a(obj.schedule_a, lines)) - lines.update(ComplianceReportSummaryService.process_schedule_b(obj.schedule_b, lines)) - lines.update(ComplianceReportSummaryService.process_schedule_c(obj.schedule_c, lines)) - - # Compute derived gasoline totals - lines['3'] = lines['1'] + lines['2'] # Sum of petroleum and renewable gasoline - # Apply hardcoded 5% renewable requirement to the sum - lines['4'] = (lines['3'] * Decimal('0.05')).quantize(Decimal('1.'), rounding=ROUND_HALF_UP) - - # Sum up adjustments for gasoline values - lines['10'] = lines['2'] + lines['5'] - lines['6'] + lines['7'] + lines['8'] - lines['9'] - lines['11'] = ((lines['4'] - lines['10']) * Decimal('0.30')).max(Decimal(0)).quantize(Decimal('.01'), rounding=ROUND_HALF_UP) - - # Compute derived diesel totals - lines['14'] = lines['12'] + lines['13'] # Sum of petroleum and renewable diesel - # Apply hardcoded 4% renewable requirement to the sum - lines['15'] = (lines['14'] * Decimal('0.04')).quantize(Decimal('1.'), rounding=ROUND_HALF_UP) - # Sum up adjustments for diesel values - lines['21'] = lines['13'] + lines['16'] - lines['17'] + lines['18'] + lines['19'] - lines['20'] - lines['22'] = ((lines['15'] - lines['21']) * Decimal('0.45')).max(Decimal(0)).quantize(Decimal('.01'), rounding=ROUND_HALF_UP) - - # Calculate credits, debits, and resulting balance - lines['25'] = lines['23'] - lines['24'] # Resulting balance from credits minus debits - credit_difference = Decimal(lines['25']) - - # Determine if there's a penalty based on current balance - current_balance = lines['25'] + lines['26'] - lines['27'] = 0 if current_balance > 0 else current_balance - - # Adjust for credits that need to be returned - if lines.get('26C') and lines['26C'] > 0: - lines['27'] = 0 - - # Handle the logic for different compliance periods - if int(obj.compliance_period.description) <= 2022: - lines['28'] = int((lines['27'] * Decimal('-200.00')).max(Decimal(0))) - else: - # For later compliance periods, gather maximum available credit offsets - max_credit_offset = max(0, OrganizationService.get_max_credit_offset( - obj.organization, - obj.compliance_period.description - )) - max_credit_offset_exclude_reserved = max(0, OrganizationService.get_max_credit_offset( - obj.organization, - obj.compliance_period.description, - exclude_reserved=True - )) - if obj.summary is not None and obj.summary.credits_offset is not None and obj.summary.credits_offset > 0: - max_credit_offset += obj.summary.credits_offset - available_compliance_unit_balance = min(max_credit_offset, max_credit_offset_exclude_reserved) - net_compliance_unit_balance = lines['25'] - - # Initialize snapshots and txs to their default values. - previous_snapshots = [] - previous_transactions = [] - - # If there are supplements, fetch and process previous transactions and snapshots - if obj.supplements: - previous_transactions, previous_snapshots = ComplianceReportSummaryService.get_previous_values(obj) - total_previous_validation, total_previous_reduction = ComplianceReportSummaryService.calculate_balance_from_transactions(previous_transactions) - - desired_net_credit_balance_change = Decimal(lines['25']) - net_compliance_unit_balance = desired_net_credit_balance_change - (total_previous_validation - total_previous_reduction) - - adjusted_balance = available_compliance_unit_balance + net_compliance_unit_balance - - # Update the 'lines' dictionary with the newly computed values from 'compute_lines_balance' without overwriting existing entries. - updated_lines = ComplianceReportSummaryService.compute_lines_balance(net_compliance_unit_balance, adjusted_balance, - available_compliance_unit_balance, previous_snapshots, credit_difference) - - lines.update(updated_lines) - - # Compile and return the final synthetic totals - synthetic_totals = { - "total_petroleum_diesel": lines['12'], - "total_petroleum_gasoline": lines['1'], - "total_renewable_diesel": lines['13'], - "total_renewable_gasoline": lines['2'], - "net_diesel_class_transferred": lines['16'], - "net_gasoline_class_transferred": lines['5'], - "lines": lines, - "total_payable": lines['11'] + lines['22'] + lines.get('28', Decimal(0)) # Assuming '28' might be an optional field - } - return synthetic_totals - - @staticmethod - def process_schedule_a(schedule, lines): - """Process schedule A values and return related values.""" - if schedule: - net_gasoline_class_transferred = Decimal(schedule.net_gasoline_class_transferred if schedule else 0) - net_diesel_class_transferred = Decimal(schedule.net_diesel_class_transferred if schedule else 0) - - lines['5'] = net_gasoline_class_transferred - lines['16'] = net_diesel_class_transferred - - return lines - - @staticmethod - def process_schedule_b(schedule, lines): - """Process schedule B values and return related values.""" - if schedule: - total_petroleum_diesel = Decimal(schedule.total_petroleum_diesel) - total_petroleum_gasoline = Decimal(schedule.total_petroleum_gasoline) - total_renewable_diesel = Decimal(schedule.total_renewable_diesel) - total_renewable_gasoline = Decimal(schedule.total_renewable_gasoline) - total_credits = Decimal(schedule.total_credits) - total_debits = Decimal(schedule.total_debits) - - lines['1'] += total_petroleum_gasoline - lines['2'] += total_renewable_gasoline - lines['12'] += total_petroleum_diesel - lines['13'] += total_renewable_diesel - lines['23'] += total_credits - lines['24'] += total_debits - - return lines - - @staticmethod - def process_schedule_c(schedule, lines): - """Process schedule C values and return related values.""" - if schedule: - total_petroleum_diesel = Decimal(schedule.total_petroleum_diesel) - total_petroleum_gasoline = Decimal(schedule.total_petroleum_gasoline) - total_renewable_diesel = Decimal(schedule.total_renewable_diesel) - total_renewable_gasoline = Decimal(schedule.total_renewable_gasoline) - - lines['1'] += total_petroleum_gasoline - lines['2'] += total_renewable_gasoline - lines['12'] += total_petroleum_diesel - lines['13'] += total_renewable_diesel - - return lines - - @staticmethod - def get_previous_values(current): - """ - Traverse through supplements to gather previous transactions and snapshots. - - :param current: The starting object which has potential supplements. - :return: A tuple containing lists of previous transactions and snapshots. - """ - previous_transactions = [] - previous_snapshots = [] - - # Loop through the supplements to fetch transactions and snapshots - while current.supplements: - current = current.supplements - if current.credit_transaction: - previous_transactions.append(current.credit_transaction) - if current.compliance_report_snapshot: - previous_snapshots.append(current.compliance_report_snapshot.snapshot) - - return previous_transactions, previous_snapshots - - @staticmethod - def calculate_balance_from_transactions(transactions): - """ - Calculate the total of previous validations and reductions from the transactions. - - :param transactions: A list of credit transactions. - :return: A tuple containing the total of previous validations and reductions. - """ - # Calculate the total number of credits for validations - total_previous_validation = sum(t.number_of_credits for t in transactions if t.type.the_type == 'Credit Validation') - # Calculate the total number of credits for reductions - total_previous_reduction = sum(t.number_of_credits for t in transactions if t.type.the_type == 'Credit Reduction') - - return total_previous_validation, total_previous_reduction - - @staticmethod - def compute_lines_balance(net_compliance_unit_balance, adjusted_balance, available_compliance_unit_balance, - previous_snapshots, credit_difference): - """ - Compute the balance for various line items based on the given parameters. - - :param net_compliance_unit_balance: Net balance of compliance units. - :param adjusted_balance: Adjusted balance value. - :param available_compliance_unit_balance: Available balance of compliance units excluding reserves. - :param previous_snapshots: List of previous compliance report snapshots. - :return: A dictionary representing the computed balance for different line items. - """ - lines = {} - total_previous_compliance_units = Decimal(0.0) - - # Determine balance for line items based on available and net compliance unit balances - if available_compliance_unit_balance <= 0 and net_compliance_unit_balance < 0: - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if (adjusted_balance < 0) else 0 - lines['29A'] = 0 - if previous_snapshots: - total_previous_compliance_units = sum(Decimal(snap.get("summary", {}).get("lines", {}).get("25", 0)) for snap in previous_snapshots) - lines['29B'] = 0 if (available_compliance_unit_balance <= 0) else credit_difference - total_previous_compliance_units - lines['29C'] = 0 - else: - lines['29A'] = available_compliance_unit_balance - lines['28'] = 0 - - # Adjust the line item values based on the net and adjusted balances - if net_compliance_unit_balance < 0 and adjusted_balance < 0: - lines['29B'] = net_compliance_unit_balance if adjusted_balance > 0 else -available_compliance_unit_balance - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if adjusted_balance < 0 else 0 - else: - lines['29B'] = net_compliance_unit_balance - - lines['29C'] = lines['29A'] + lines['29B'] - - return lines diff --git a/backend/api/services/CreditTradeService.py b/backend/api/services/CreditTradeService.py index d6c7713de..fd48cad19 100644 --- a/backend/api/services/CreditTradeService.py +++ b/backend/api/services/CreditTradeService.py @@ -4,7 +4,6 @@ from collections import defaultdict, namedtuple from dateutil.relativedelta import relativedelta from django.utils import timezone -from decimal import Decimal from django.core.exceptions import ValidationError from django.db.models import Q @@ -191,23 +190,6 @@ def approve(credit_trade, update_user=None, batch_process=False): effective_date = credit_trade.trade_effective_date \ if credit_trade.trade_effective_date and credit_trade.trade_effective_date > today else today - # Check if the transaction is an administrative adjustment and - # if it would result in a negative balance for the organization - if credit_trade.type.the_type == "Administrative Adjustment": - org_balance = Decimal(credit_trade.respondent.organization_balance['validated_credits']) - - # Adjust org_balance to accont for pending deductions - if 'deductions' in credit_trade.respondent.organization_balance: - org_balance -= Decimal(credit_trade.respondent.organization_balance['deductions']) - - if org_balance <= 0 and credit_trade.number_of_credits < Decimal(0): - raise ValidationError(f"Organization {credit_trade.respondent.name} already has a balance of {org_balance}") - - # number_of_credits can be negative so we add to org balance here - if org_balance + credit_trade.number_of_credits < Decimal(0): - credit_trade.number_of_credits = -org_balance # Adjust the number of credits to prevent a negative balance - credit_trade.save() # Save the updated number_of_credits to the database - # Only transfer credits if the effective_date is today or in the past if effective_date <= today: CreditTradeService.transfer_credits( diff --git a/backend/api/services/OrganizationService.py b/backend/api/services/OrganizationService.py index c31be6e6e..38fb823e3 100644 --- a/backend/api/services/OrganizationService.py +++ b/backend/api/services/OrganizationService.py @@ -1,5 +1,5 @@ import datetime -from django.db.models import Q, Sum, Count, Case, When, F +from django.db.models import Q, Sum, Count from api.models.ComplianceReport import ComplianceReport from api.models.CreditTrade import CreditTrade @@ -22,6 +22,7 @@ def get_pending_transfers_value(organization): Q(is_rescinded=False) & (Q(trade_effective_date__gte=datetime.datetime.now()) | Q(trade_effective_date__isnull=True))) ).aggregate(total_credits=Sum('number_of_credits')) + if pending_trades['total_credits'] is not None: pending_transfers_value = pending_trades['total_credits'] @@ -57,6 +58,7 @@ def get_pending_deductions( "Deleted" ]) ).filter(id=group_id).first() + if compliance_report and compliance_report.summary: if compliance_report.supplements_id and \ compliance_report.supplements_id > 0: @@ -105,11 +107,12 @@ def get_pending_deductions( elif compliance_report.status.director_status_id not in \ ["Rejected"]: if compliance_report.summary.credits_offset is not None: - deductions += compliance_report.summary.credits_offset + deductions += compliance_report.summary.credits_offset # if report.status.director_status_id == 'Accepted' and \ # ignore_pending_supplemental: # deductions -= report.summary.credits_offset + if deductions < 0: deductions = 0 @@ -123,6 +126,7 @@ def get_max_credit_offset(organization, compliance_year, exclude_reserved=False) compliance_period_effective_date = datetime.date( int(compliance_year), 1, 1 ) + credits = CreditTrade.objects.filter( (Q(status__status="Approved") & Q(type__the_type="Sell") & @@ -145,14 +149,9 @@ def get_max_credit_offset(organization, compliance_year, exclude_reserved=False) Q(status__status="Approved") & Q(respondent_id=organization.id) & Q(is_rescinded=False) & - Q(compliance_period__effective_date__lte=compliance_period_effective_date)) | - (Q(type__the_type="Administrative Adjustment") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(number_of_credits__gte=0) & - Q(trade_effective_date__lte=effective_date_deadline)) + Q(compliance_period__effective_date__lte=compliance_period_effective_date)) ).aggregate(total=Sum('number_of_credits')) + debits = CreditTrade.objects.filter( (Q(status__status="Approved") & Q(type__the_type="Sell") & @@ -168,25 +167,8 @@ def get_max_credit_offset(organization, compliance_year, exclude_reserved=False) Q(status__status="Approved") & Q(respondent_id=organization.id) & Q(is_rescinded=False) & - Q(compliance_period__effective_date__lte=compliance_period_effective_date)) | - (Q(type__the_type="Administrative Adjustment") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(number_of_credits__lt=0) & - Q(trade_effective_date__lte=effective_date_deadline)) - ).aggregate( - total=Sum( - Case( - When( - Q(type__the_type="Administrative Adjustment") & - Q(number_of_credits__lt=0), - then=F('number_of_credits') * -1 - ), - default=F('number_of_credits') - ) - ) - ) + Q(compliance_period__effective_date__lte=compliance_period_effective_date)) + ).aggregate(total=Sum('number_of_credits')) total_in_compliance_period = 0 if credits and credits.get('total') is not None: @@ -199,99 +181,6 @@ def get_max_credit_offset(organization, compliance_year, exclude_reserved=False) else: pending_deductions = OrganizationService.get_pending_deductions(organization, ignore_pending_supplemental=False) - validated_credits = organization.organization_balance.get( - 'validated_credits', 0 - ) - total_balance = validated_credits - pending_deductions - total_available_credits = min(total_in_compliance_period, total_balance) - if total_available_credits < 0: - total_available_credits = 0 - - return total_available_credits - - - @staticmethod - def get_max_credit_offset_for_interval(organization, compliance_date): - effective_date_deadline = compliance_date.date() - effective_year = effective_date_deadline.year - if effective_date_deadline < datetime.date(effective_year, 4, 1): - effective_year -= 1 - compliance_period_effective_date = datetime.date( - int(effective_year), 1, 1 - ) - - credits = CreditTrade.objects.filter( - (Q(status__status="Approved") & - Q(type__the_type="Sell") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(trade_effective_date__lte=effective_date_deadline)) | - (Q(status__status="Approved") & - Q(type__the_type="Buy") & - Q(initiator_id=organization.id) & - Q(is_rescinded=False) & - Q(trade_effective_date__lte=effective_date_deadline)) | - (Q(type__the_type="Part 3 Award") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(trade_effective_date__lte=effective_date_deadline)) | - (Q(type__the_type="Credit Validation") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(compliance_period__effective_date__lte=compliance_period_effective_date)) | - (Q(type__the_type="Administrative Adjustment") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(number_of_credits__gte=0) & - Q(trade_effective_date__lte=effective_date_deadline)) - ).aggregate(total=Sum('number_of_credits')) - - debits = CreditTrade.objects.filter( - (Q(status__status="Approved") & - Q(type__the_type="Sell") & - Q(initiator_id=organization.id) & - Q(is_rescinded=False) & - Q(trade_effective_date__lte=effective_date_deadline)) | - (Q(status__status="Approved") & - Q(type__the_type="Buy") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(trade_effective_date__lte=effective_date_deadline)) | - (Q(type__the_type="Credit Reduction") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(compliance_period__effective_date__lte=compliance_period_effective_date)) | - (Q(type__the_type="Administrative Adjustment") & - Q(status__status="Approved") & - Q(respondent_id=organization.id) & - Q(is_rescinded=False) & - Q(number_of_credits__lt=0) & - Q(trade_effective_date__lte=effective_date_deadline)) - ).aggregate( - total=Sum( - Case( - When( - Q(type__the_type="Administrative Adjustment") & - Q(number_of_credits__lt=0), - then=F('number_of_credits') * -1 - ), - default=F('number_of_credits') - ) - ) - ) - - total_in_compliance_period = 0 - if credits and credits.get('total') is not None: - total_in_compliance_period = credits.get('total') - - if debits and debits.get('total') is not None: - total_in_compliance_period -= debits.get('total') - pending_deductions = OrganizationService.get_pending_deductions(organization, ignore_pending_supplemental=False) - validated_credits = organization.organization_balance.get( 'validated_credits', 0 ) diff --git a/backend/api/services/SpreadSheetBuilder.py b/backend/api/services/SpreadSheetBuilder.py index de09d806f..885771b2f 100644 --- a/backend/api/services/SpreadSheetBuilder.py +++ b/backend/api/services/SpreadSheetBuilder.py @@ -92,12 +92,12 @@ def add_credit_transfers(self, credit_trades, user): """ Adds a spreadsheet for credit transfers """ - worksheet = self.workbook.add_sheet("Transactions") + worksheet = self.workbook.add_sheet("Credit Transactions") row_index = 0 columns = [ - "Transaction ID", "Compliance Period", "Type", "Compliance Units From", - "Compliance Units To", "Number of Units", "Value per unit", "Category", + "Transaction ID", "Compliance Period", "Type", "Credits From", + "Credits To", "Quantity of Credits", "Value per Credit", "Category", "Status", "Effective Date", "Comments" ] @@ -151,9 +151,7 @@ def add_credit_transfers(self, credit_trades, user): worksheet.write(row_index, 8, credit_trade.status.friendly_name) # If the trade doesn't have an effective date but meets certain other criteria, write the update timestamp. - if credit_trade.trade_effective_date: - worksheet.write(row_index, 9, credit_trade.trade_effective_date, date_format) - elif credit_trade.update_timestamp: + if credit_trade.update_timestamp: # Conditions for using the update timestamp. approved_status = credit_trade.status.status == "Approved" valid_trade_type = credit_trade.type.the_type in ["Credit Reduction", "Credit Validation"] @@ -183,18 +181,17 @@ def add_credit_transfers(self, credit_trades, user): worksheet.col(9).width = 3500 worksheet.col(10).width = 10000 - def add_fuel_suppliers(self, fuel_suppliers, include_actions=False): + def add_fuel_suppliers(self, fuel_suppliers): """ Adds a spreadsheet for fuel suppliers """ - worksheet = self.workbook.add_sheet("Organizations") + worksheet = self.workbook.add_sheet("Fuel Suppliers") row_index = 0 columns = [ - "ID", "Organization Name", "Compliance Units", "Registered" + "ID", "Organization Name", "Credit Balance", "Status", "Actions" ] - if include_actions: - columns.append("Actions") + header_style = xlwt.easyxf('font: bold on') # Build Column Headers @@ -210,18 +207,13 @@ def add_fuel_suppliers(self, fuel_suppliers, include_actions=False): worksheet.write( row_index, 2, fuel_supplier.organization_balance['validated_credits']) - - # Adjust the value for the 'Registered' column based on the status - registered_status = 'Yes' if fuel_supplier.status.status.lower() == 'active' else 'No' - worksheet.write(row_index, 3, registered_status) - if include_actions: - worksheet.write(row_index, 4, fuel_supplier.actions_type.the_type) + worksheet.write(row_index, 3, fuel_supplier.status.status) + worksheet.write(row_index, 4, fuel_supplier.actions_type.the_type) # set the widths for the columns that we expect to be longer worksheet.col(1).width = 7500 worksheet.col(2).width = 3500 - if include_actions: - worksheet.col(4).width = 3500 + worksheet.col(4).width = 3500 def add_users(self, fuel_supplier_users): """ diff --git a/backend/api/tests/base_test_case.py b/backend/api/tests/base_test_case.py index e25ddc1f3..2654ab6c3 100644 --- a/backend/api/tests/base_test_case.py +++ b/backend/api/tests/base_test_case.py @@ -128,10 +128,7 @@ def setUp(self): self.credit_trade_types = { 'buy': CreditTradeType.objects.get(the_type='Buy'), 'sell': CreditTradeType.objects.get(the_type='Sell'), - 'part3award': CreditTradeType.objects.get(the_type='Part 3 Award'), - 'adminAdjustment': CreditTradeType.objects.get(the_type='Administrative Adjustment'), - 'creditReduction': CreditTradeType.objects.get(the_type='Credit Reduction'), - 'creditValidation': CreditTradeType.objects.get(the_type='Credit Validation'), + 'part3award': CreditTradeType.objects.get(the_type='Part 3 Award') } self.organizations = { diff --git a/backend/api/tests/payloads/compliance_unit_payloads.py b/backend/api/tests/payloads/compliance_unit_payloads.py deleted file mode 100644 index 27de03f1f..000000000 --- a/backend/api/tests/payloads/compliance_unit_payloads.py +++ /dev/null @@ -1,156 +0,0 @@ -compliance_unit_initial_payload = { - 'status': { - 'fuelSupplierStatus': 'Draft' - }, - "scheduleB": { - "records": [ - { - "fuelCode": "21", - "fuelType": "Ethanol", - "fuelClass": "Gasoline", - "provisionOfTheAct": "Section 6 (5) (c)", - "quantity": 117933500 - }, - { - "fuelCode": None, - "fuelType": "Petroleum-based diesel", - "fuelClass": "Diesel", - "provisionOfTheAct": "Section 6 (5) (b)", - "quantity": 136896000 - } - ] - }, - 'summary': { - 'creditsOffset': 0, - } -} - -compliance_unit_supplemental_payload = { - 'status': { - 'fuelSupplierStatus': 'Submitted' - }, - "scheduleB": { - "records": [ - { - "fuelCode": "21", - "fuelType": "Ethanol", - "fuelClass": "Gasoline", - "provisionOfTheAct": "Section 6 (5) (c)", - "quantity": 117933500 - }, - { - "fuelCode": None, - "fuelType": "Petroleum-based diesel", - "fuelClass": "Diesel", - "provisionOfTheAct": "Section 6 (5) (b)", - "quantity": 136896000 - } - ] - }, - 'summary': { - 'creditsOffset': 0, - 'creditOffsetA': 0, - 'creditOffsetB': 0, - 'creditOffsetC': 0, - }, - 'supplemental_note': 'test compliance units' -} - -compliance_unit_positive_offset_payload = { - 'status': { - 'fuelSupplierStatus': 'Draft' - }, - "scheduleB": { - "records": [ - { - "fuelCode": "21", - "fuelType": "Ethanol", - "fuelClass": "Gasoline", - "provisionOfTheAct": "Section 6 (5) (c)", - "quantity": 117933500 - } - ] - }, - 'summary': { - 'creditsOffset': 0, - } -} - -compliance_unit_negative_offset_payload = { - 'status': { - 'fuelSupplierStatus': 'Draft' - }, - "scheduleB": { - "records": [ - { - "fuelCode": None, - "fuelType": "Petroleum-based diesel", - "fuelClass": "Diesel", - "provisionOfTheAct": "Section 6 (5) (b)", - "quantity": 136896000 - } - ] - }, - "summary": { - "dieselClassDeferred": 0, - "dieselClassObligation": 0, - "dieselClassPreviouslyRetained": 0, - "dieselClassRetained": 0, - "gasolineClassDeferred": 0, - "gasolineClassObligation": 0, - "gasolineClassPreviouslyRetained": 0, - "gasolineClassRetained": 0, - "creditsOffset": 0, - "creditsOffsetA": 0, - "creditsOffsetB": 0, - "creditsOffsetC": 0 - } -} - -compliance_unit_positive_supplemental_payload = { - 'status': { - 'fuelSupplierStatus': 'Submitted' - }, - "scheduleB": { - "records": [ - { - "fuelCode": "21", - "fuelType": "Ethanol", - "fuelClass": "Gasoline", - "provisionOfTheAct": "Section 6 (5) (c)", - "quantity": 117933500 - } - ] - }, - 'summary': { - 'creditsOffset': 0, - 'creditOffsetA': 0, - 'creditOffsetB': 0, - 'creditOffsetC': 0, - }, - 'supplemental_note': 'test compliance units' -} - -compliance_unit_negative_supplemental_payload = { - 'status': { - 'fuelSupplierStatus': 'Submitted' - }, - "scheduleB": { - "records": [ - { - "fuelCode": None, - "fuelType": "Petroleum-based diesel", - "fuelClass": "Diesel", - "provisionOfTheAct": "Section 6 (5) (b)", - "quantity": 136896000 - } - ] - }, - 'summary': { - 'creditsOffset': 0, - 'creditOffsetA': 0, - 'creditOffsetB': 0, - 'creditOffsetC': 0, - }, - 'supplemental_note': 'test compliance units' -} \ No newline at end of file diff --git a/backend/api/tests/test_compliance_supplemental_reporting.py b/backend/api/tests/test_compliance_supplemental_reporting.py index 8a7c2811b..1658657be 100644 --- a/backend/api/tests/test_compliance_supplemental_reporting.py +++ b/backend/api/tests/test_compliance_supplemental_reporting.py @@ -156,4 +156,4 @@ def test_supplemental_accepted_by_director_success(self): content_type='application/json', data=json.dumps(obj['payload']) ) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, 200) \ No newline at end of file diff --git a/backend/api/tests/test_compliance_unit_reporting_after_2023.py b/backend/api/tests/test_compliance_unit_reporting_after_2023.py deleted file mode 100644 index a179804bf..000000000 --- a/backend/api/tests/test_compliance_unit_reporting_after_2023.py +++ /dev/null @@ -1,1016 +0,0 @@ -# -*- coding: utf-8 -*- -# pylint: disable=no-member,invalid-name -""" - REST API Documentation for the NRsS TFRS Credit Trading Application - The Transportation Fuels Reporting System is being designed to streamline - compliance reporting for transportation fuel suppliers in accordance with - the Renewable & Low Carbon Fuel Requirements Regulation. - OpenAPI spec version: v1 - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" -import json -import logging -from decimal import Decimal - -from django.utils import timezone -from rest_framework import status - -from api.models.CompliancePeriod import CompliancePeriod -from api.models.ComplianceReport import ComplianceReport, ComplianceReportStatus, ComplianceReportType, \ - ComplianceReportWorkflowState -from api.models.Organization import Organization -from .base_test_case import BaseTestCase -from .payloads.compliance_unit_payloads import * -from ..services.OrganizationService import OrganizationService - -logger = logging.getLogger('supplemental_reporting') -logger.setLevel(logging.INFO) -handler = logging.StreamHandler() -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') -handler.setFormatter(formatter) -logger.addHandler(handler) -COMPLIANCE_YEAR = '2023' - -class TestComplianceUnitReporting(BaseTestCase): - """Tests for the compliance unit reporting and supplemental reporting endpoints""" - extra_fixtures = [ - 'test/test_post_compliance_unit_reporting.json', - 'test/test_fuel_codes.json', - 'test/test_unit_of_measures.json', - 'test/test_carbon_intensity_limits.json', - 'test/test_default_carbon_intensities.json', - 'test/test_petroleum_carbon_intensities.json', - 'test/test_transaction_types.json' - ] - - def _create_draft_compliance_report(self, report_type="Compliance Report"): - report = ComplianceReport() - report.status = ComplianceReportWorkflowState.objects.create( - fuel_supplier_status=ComplianceReportStatus.objects.get_by_natural_key('Draft') - ) - report.organization = Organization.objects.get_by_natural_key( - "Test Org 1") - report.compliance_period = CompliancePeriod.objects.get_by_natural_key(COMPLIANCE_YEAR) - report.type = ComplianceReportType.objects.get_by_natural_key(report_type) - report.create_timestamp = timezone.now() - report.update_timestamp = timezone.now() - - report.save() - report.refresh_from_db() - return report.id - - def _add_or_remove_credits(self, num_of_credits, validation=True): - # Create a recommended credit trade request i.e., either reduction or validation using historical data entry. - payload = { - "compliancePeriod": CompliancePeriod.objects.get_by_natural_key(COMPLIANCE_YEAR).id, - "initiator": self.users['gov_director'].organization.id, - "numberOfCredits": num_of_credits, - "respondent": self.users['fs_user_1'].organization.id, - "status": self.statuses['recommended'].id, - "tradeEffectiveDate": "2021-01-01", - "type": self.credit_trade_types['creditValidation'].id if validation else self.credit_trade_types['creditReduction'].id, - "is_rescinded": False, - "zeroReason": None, - "comment": "testing" - } - response = self.clients['gov_multi_role'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload)) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - ct_id = response.data['id'] - # Approve the credit trade - payload['status'] = self.statuses['approved'].id - response = self.clients['gov_multi_role'].put( - '/api/credit_trades/{}'.format(ct_id), - content_type='application/json', - data=json.dumps(payload)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - def _create_supplemental_report(self, rid): - payload = { - 'supplements': rid, - 'status': {'fuelSupplierStatus': 'Draft'}, - 'type': 'Compliance Report', - 'compliancePeriod': COMPLIANCE_YEAR - } - response = self.clients['fs_user_1'].post( - '/api/compliance_reports', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - sid = response.data['id'] - return sid - - def _patch_fs_user_for_compliance_report(self, payload, cr_id): - response = self.clients['fs_user_1'].patch( - '/api/compliance_reports/{id}'.format(id=cr_id), - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - return response - - def _acceptance_from_director(self, cr_id): - # we are only allowed to change one status at a time so this - # loops the statuses in order to get to accepted by director - status_payloads = [ - {'user': 'gov_analyst', 'payload': {'status': {'analystStatus': 'Recommended'}}}, - {'user': 'gov_manager', 'payload': {'status': {'managerStatus': 'Recommended'}}}, - {'user': 'gov_director', 'payload': {'status': {'directorStatus': 'Accepted'}}} - ] - for obj in status_payloads: - response = self.clients[obj['user']].patch( - '/api/compliance_reports/{id}'.format(id=cr_id), - content_type='application/json', - data=json.dumps(obj['payload']) - ) - self.assertEqual(response.status_code, 200) - - """ - | Scenario 1: Initial Report - positive net balance | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Values | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 100 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | - | Compliance unit balance change from assessment | | X | 100 | - | If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 900 | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - """ - def test_initial_report_positive_net_balance(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = {'status': {'fuelSupplierStatus': 'Submitted'}} - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data.get('summary').get('lines').get('25'), 100) - self.assertEqual(response.data.get('summary').get('lines').get('29A'), 800) - self.assertEqual(response.data.get('summary').get('lines').get('29B'), 100) - self.assertEqual(response.data.get('summary').get('lines').get('28'), 0) - self.assertEqual(response.data.get('summary').get('lines').get('29C'), 900) - - """ - | Scenario 2: Initial Report - negative net balance, no penalty | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Values | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -200 | - | Available compliance unit balance on March 31, YYYY | | A | 700 | - | Compliance unit balance change from assessment | | X | -200 | - | If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 500 | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - """ - def test_initial_report_negative_net_balance_no_penalty(self): - self._add_or_remove_credits(700) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -200 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -200) - self.assertEqual(response.data.get('summary').get('lines').get('29A'), 700) - self.assertEqual(response.data.get('summary').get('lines').get('29B'), -200) - self.assertEqual(response.data.get('summary').get('lines').get('28'), 0) - self.assertEqual(response.data.get('summary').get('lines').get('29C'), 500) - - """ - | Scenario 3: Initial Report - negative net balance with penalty | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Values | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -400 | - | Available compliance unit balance on March 31, YYYY | | A | 300 | - | Compliance unit balance change from assessment | | X | -300 | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | - | Non-compliance penalty payable (100 units * $600 CAD per unit) | Line 28 | | 60,000 | - | ^---- (abs(Z) - A) * $600 | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 0 | - |-----------------------------------------------------------------------|---------------|-------------|-----------------| - """ - def test_initial_report_negative_net_balance_with_penalty(self): - self._add_or_remove_credits(300) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -300 - self._patch_fs_user_for_compliance_report(payload, rid) - - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -400) - self.assertEqual(response.data.get('summary').get('lines').get('29A'), 300) - self.assertEqual(response.data.get('summary').get('lines').get('29B'), -300) - self.assertEqual(response.data.get('summary').get('lines').get('28'), 60000) - self.assertEqual(response.data.get('summary').get('lines').get('29C'), 0) - - def test_initial_report_zero_starting_value(self): - self._add_or_remove_credits(0) # Starting with zero credits - rid = self._create_draft_compliance_report() - - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 0 - self._patch_fs_user_for_compliance_report(payload, rid) - - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - self.assertEqual(response.data.get('summary').get('lines').get('25'), -400) - self.assertEqual(response.data.get('summary').get('lines').get('29A'), 0) - self.assertEqual(response.data.get('summary').get('lines').get('29B'), 0) - self.assertEqual(response.data.get('summary').get('lines').get('28'), 240000) - self.assertEqual(response.data.get('summary').get('lines').get('29C'), 0) - - """ - | Scenario 4: Supplemental Report Submission #1, increasing, positive net balance, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 100 | 250 | 150 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | 900 | 100 | - | Compliance unit balance change from assessment | | X | 100 | 150 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 900 | 1,050 | 150 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_positive_net_balance_previous_report_assessed(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(800)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(900)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 294833 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the supplemental compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(250)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(900)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(150)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(1050)) - - """ - | Scenario 5: Supplemental Report Submission #4, decreasing, positive net balance, no penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 100 | 50 | -50 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | 900 | 100 | - | Compliance unit balance change from assessment | | X | 100 | -50 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 900 | 850 | -50 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_4_decreasing_positive_net_balance_previous_report_assessed(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(800)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(900)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 58967 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(50)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(900)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-50)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(850)) - - """ - | Scenario 6: Supplemental Report Submission #1, decreasing, positive net balance, with penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 100 | 50 | -50 | - | Available compliance unit balance on March 31, YYYY | | A | 0 | 25 | 25 | - | Compliance unit balance change from assessment | | X | 100 | -25 | -125 | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (25 units * $600 CAD per unit) | Line 28 | | | $15,000 | $15,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 100 | 0 | -100 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | * Scenario 6 could occur if the organization sold 75 compliance units after the initial report was assessed and then had to submit a supplemental when they only had 25 compliance units remaining - """ - def test_supplemental_report_1_decreasing_positive_net_balance_penalty_previous_report_assessed(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(100)) - # remove 75 units from Org balance to create the scenario of it selling them - self._add_or_remove_credits(75, False) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 58967 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(50)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(25)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-25)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(15000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """ - | Scenario 7: Supplemental Report Submission #1, increasing, negative net balance, no penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -200 | -100 | 100 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | 600 | -200 | - | Compliance unit balance change from assessment | | X | -200 | 100 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 600 | 700 | 100 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_negative_net_balance_no_penalty_previous_report_assessed(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -200 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(800)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(600)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 171119 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -100 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(600)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(700)) - - """ - | Scenario 8: Supplemental Report Submission #1, increasing, negative net balance, with penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -400 | -350 | 50 | - | Available compliance unit balance on March 31, YYYY | | A | 100 | 0 | -100 | - | Compliance unit balance change from assessment | | X | -100 | 50 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (250 units * $600 CAD per unit) | Line 28 | | $180,000 | $150,000 | -$30,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 0 | 0 | 0 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_negative_net_balance_penalty_previous_report_assessed(self): - self._add_or_remove_credits(100) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -400 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(180000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 598917 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -350 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-350)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(50)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(150000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """ - | Scenario 9: Supplemental Report Submission #1, decreasing, negative net balance, no penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -200 | -300 | -100 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | 600 | -200 | - | Compliance unit balance change from assessment | | X | -200 | -100 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 600 | 500 | -100 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_decreasing_negative_net_balance_no_penalty_previous_report_assessed(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -200 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(800)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(600)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 513358 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -300 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(600)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(500)) - - """ - | Scenario 10: Supplemental Report Submission #1, decreasing, negative net balance, with penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -200 | -300 | -100 | - | Available compliance unit balance on March 31, YYYY | | A | 800 | 0 | -800 | - | Compliance unit balance change from assessment | | X | -200 | -100 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (250 units * $600 CAD per unit) | Line 28 | | | $60,000 | $60,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 600 | 0 | -600 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_decreasing_negative_net_balance_penalty_previous_report_assessed(self): - self._add_or_remove_credits(800) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -200 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(800)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(600)) - # * Scenario 10 could occur if the organization sold all 600 compliance units after the initial report was - # assessed and then had to submit a supplemental when they had 0 compliance units in their available balance - self._add_or_remove_credits(600, False) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 513358 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -300 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(60000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """ - | Scenario 11: Supplemental Report Submission #1, increasing, negative net balance to positive net balance, no penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -300 | 200 | 500 | - | Available compliance unit balance on March 31, YYYY | | A | 500 | 200 | -300 | - | Compliance unit balance change from assessment | | X | -300 | 500 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 200 | 700 | 500 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_negative_net_balance_to_positive_no_penalty_previous_report_assessed(self): - self._add_or_remove_credits(500) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 513358 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -300 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(500)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(200)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 235867 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(500)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(700)) - - """ - | Scenario 12: Supplemental Report Submission #1, decreasing, positive net balance to negative net balance, with penalty, previous report was assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 200 | -100 | -300 | - | Available compliance unit balance on March 31, YYYY | | A | 0 | 200 | 200 | - | Compliance unit balance change from assessment | | X | 200 | -200 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (250 units * $600 CAD per unit) | Line 28 | | | $60,000 | $60,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 200 | 0 | -200 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_decreasing_positive_net_balance_to_negative_penalty_previous_report_assessed(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 235867 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(200)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 171119 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -100 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(60000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """ - | Scenario 13: Supplemental Report Submission #1, increasing, positive net balance, previous report was not assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 300 | 400 | 100 | - | Available compliance unit balance on March 31, YYYY | | A | 1000 | 1000 | 0 | - | Compliance unit balance change from assessment | | X | 300 | 400 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 1300 | 1400 | 100 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_positive_net_balance_previous_report_not_assessed(self): - self._add_or_remove_credits(1000) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 353800 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report which is not accessed and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(1300)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 471733 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(1400)) - - """ - | Scenario 14: Supplemental Report Submission #1, increasing, negative net balance, no penalty, previous report was not assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -200 | -300 | -100 | - | Available compliance unit balance on March 31, YYYY | | A | 1000 | 1000 | 0 | - | Compliance unit balance change from assessment | | X | -200 | -300 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 800 | 700 | -100 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_increasing_negative_net_balance_no_penalty_previous_report_not_assessed(self): - self._add_or_remove_credits(1000) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -200 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report which is not accessed and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(800)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 513358 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -300 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-300)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(700)) - - """ - | Scenario 15: Supplemental Report Submission #1, decreasing, negative net balance, with penalty, previous report was not assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -400 | -600 | -200 | - | Available compliance unit balance on March 31, YYYY | | A | 200 | 200 | 0 | - | Compliance unit balance change from assessment | | X | -200 | -200 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (400 units * $600 CAD per unit) | Line 28 | | $120,000 | $240,000 | $120,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 0 | 0 | 0 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_decreasing_negative_net_balance_penalty_previous_report_not_assessed(self): - self._add_or_remove_credits(200) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -400 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report which is not accessed and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(120000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 1026715 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -600 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-600)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(240000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """ - | Scenario 16: Supplemental Report Submission #1, no change to net balance, positive net balance, previous report was not assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | 400 | 400 | 0 | - | Available compliance unit balance on March 31, YYYY | | A | 1000 | 1000 | 0 | - | Compliance unit balance change from assessment | | X | 400 | 400 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 1400 | 0 | 0 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_no_change_positive_net_balance_previous_report_not_assessed(self): - self._add_or_remove_credits(1000) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_positive_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 471733 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report which is not accessed and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(1400)) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_positive_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 471733 # credits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(1000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(0)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(1400)) - - """ - | Scenario 17: Supplemental Report Submission #1, no change to net balance, negative net balance, penalty, previous report was not assessed | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Low Carbon Fuel Requirement Summary | |Calculations | Example Old Values | Example New Values | Example Change Values | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - | Net compliance unit balance for compliance period | Line 25 | Z | -400 | -400 | 0 | - | Available compliance unit balance on March 31, YYYY | | A | 200 | 100 | -100 | - | Compliance unit balance change from assessment | | X | -200 | -100 | | - | ^---- If Z>0, then Z; If Z<0 & A+Z>0, then Z; If Z<0 & A+Z<0, then -A| | | | - | Non-compliance penalty payable (400 units * $600 CAD per unit) | Line 28 | | $120,000 | $180,000 | $60,000 | - | ^---- (abs(Z) - A) * $600 | | | | - | Available compliance unit balance after assessment on March 31, YYYY | | A+X | 0 | 0 | 0 | - |-----------------------------------------------------------------------|---------------|-------------|---------------------|--------------------|-----------------------| - """ - def test_supplemental_report_1_no_change_negative_net_balance_penalty_previous_report_not_assessed(self): - self._add_or_remove_credits(200) - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -400 - self._patch_fs_user_for_compliance_report(payload, rid) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report which is not accessed and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-200)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(120000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - # * Scenario 17 could occur if the organization submitted a supplemental report for a previous compliance period - # after they submitted the initial report for this period; processing the supplemental report from the previous - # period could lead to a decrease in the available credit balance for this compliance period - self._add_or_remove_credits(100, False) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_negative_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 684477 # debits from fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = -400 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-400)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-100)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(180000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - """Testing that even in penalty situation, organization balances never go below zero""" - def test_organization_balance_never_below_zero(self): - self._add_or_remove_credits(100000) - - organization = Organization.objects.get_by_natural_key("Test Org 1") - initial_balance = organization.organization_balance - - self.assertEqual(initial_balance['validated_credits'], Decimal(100000)) - - # Create inital draft report - rid = self._create_draft_compliance_report() - - # Patch compliance report info - payload = compliance_unit_negative_offset_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 342238999 # debits from fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - } - self._patch_fs_user_for_compliance_report(payload, rid) - - # Successful director acceptance - self._acceptance_from_director(rid) - - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}/snapshot'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('25')), Decimal(-200000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29A')), Decimal(100000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29B')), Decimal(-100000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('28')), Decimal(60000000)) - self.assertEqual(Decimal(response.data.get('summary').get('lines').get('29C')), Decimal(0)) - - # Ensure that the organization balance is zero and not negative - updated_balance = organization.organization_balance - self.assertEqual(updated_balance['validated_credits'], 0) - - lastest_transaction = CreditTrade.objects.last() - # Optionally: Ensure that the credit transaction was made for the amount of available balance - # Replace with the actual way you get the transaction amount. - self.assertEqual(lastest_transaction.number_of_credits, initial_balance['validated_credits']) - diff --git a/backend/api/tests/test_compliance_unit_reporting_before_2023.py b/backend/api/tests/test_compliance_unit_reporting_before_2023.py deleted file mode 100644 index 7056a9dad..000000000 --- a/backend/api/tests/test_compliance_unit_reporting_before_2023.py +++ /dev/null @@ -1,849 +0,0 @@ -# -*- coding: utf-8 -*- -# pylint: disable=no-member,invalid-name -""" - REST API Documentation for the NRsS TFRS Credit Trading Application - The Transportation Fuels Reporting System is being designed to streamline - compliance reporting for transportation fuel suppliers in accordance with - the Renewable & Low Carbon Fuel Requirements Regulation. - OpenAPI spec version: v1 - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" -import json -import logging - -from django.utils import timezone -from rest_framework import status - -from api.models.CompliancePeriod import CompliancePeriod -from api.models.ComplianceReport import ComplianceReport, ComplianceReportStatus, ComplianceReportType, \ - ComplianceReportWorkflowState -from api.models.Organization import Organization -from .base_test_case import BaseTestCase -from .payloads.compliance_unit_payloads import * -from ..services.OrganizationService import OrganizationService - -logger = logging.getLogger('supplemental_reporting') -logger.setLevel(logging.INFO) -handler = logging.StreamHandler() -formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') -handler.setFormatter(formatter) -logger.addHandler(handler) - - -class TestComplianceUnitReporting(BaseTestCase): - """Tests for the compliance unit reporting and supplemental reporting endpoints""" - extra_fixtures = [ - 'test/test_pre_compliance_unit_reporting.json', - 'test/test_fuel_codes.json', - 'test/test_unit_of_measures.json', - 'test/test_carbon_intensity_limits.json', - 'test/test_default_carbon_intensities.json', - 'test/test_petroleum_carbon_intensities.json', - 'test/test_transaction_types.json' - ] - - def _create_draft_compliance_report(self, report_type="Compliance Report"): - report = ComplianceReport() - report.status = ComplianceReportWorkflowState.objects.create( - fuel_supplier_status=ComplianceReportStatus.objects.get_by_natural_key('Draft') - ) - report.organization = Organization.objects.get_by_natural_key( - "Test Org 1") - report.compliance_period = CompliancePeriod.objects.get_by_natural_key('2022') - report.type = ComplianceReportType.objects.get_by_natural_key(report_type) - report.create_timestamp = timezone.now() - report.update_timestamp = timezone.now() - - report.save() - report.refresh_from_db() - return report.id - - def _add_part3_awards_to_org(self, add_credits): - # Create a recommended credit trade request - payload = { - "compliancePeriod": CompliancePeriod.objects.get_by_natural_key('2022').id, - "initiator": self.users['gov_director'].organization.id, - "numberOfCredits": add_credits, - "respondent": self.users['fs_user_1'].organization.id, - "status": self.statuses['recommended'].id, - "tradeEffectiveDate": "2021-01-01", - "type": self.credit_trade_types['part3award'].id, - "is_rescinded": False, - "zeroReason": None, - "comment": "testing" - } - response = self.clients['gov_multi_role'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload)) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - ct_id = response.data['id'] - # Approve the credit trade - payload['status'] = self.statuses['approved'].id - response = self.clients['gov_multi_role'].put( - '/api/credit_trades/{}'.format(ct_id), - content_type='application/json', - data=json.dumps(payload)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - def _create_supplemental_report(self, rid): - payload = { - 'supplements': rid, - 'status': {'fuelSupplierStatus': 'Draft'}, - 'type': 'Compliance Report', - 'compliancePeriod': '2022' - } - response = self.clients['fs_user_1'].post( - '/api/compliance_reports', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - sid = response.data['id'] - return sid - - def _patch_fs_user_for_compliance_report(self, payload, cr_id): - response = self.clients['fs_user_1'].patch( - '/api/compliance_reports/{id}'.format(id=cr_id), - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - return response - - def _acceptance_from_director(self, cr_id): - # we are only allowed to change one status at a time so this - # loops the statuses in order to get to accepted by director - status_payloads = [ - {'user': 'gov_analyst', 'payload': {'status': {'analystStatus': 'Recommended'}}}, - {'user': 'gov_manager', 'payload': {'status': {'managerStatus': 'Recommended'}}}, - {'user': 'gov_director', 'payload': {'status': {'directorStatus': 'Accepted'}}} - ] - for obj in status_payloads: - response = self.clients[obj['user']].patch( - '/api/compliance_reports/{id}'.format(id=cr_id), - content_type='application/json', - data=json.dumps(obj['payload']) - ) - self.assertEqual(response.status_code, 200) - - """ - | Scenario 0: Initial Report in a net credit position | - |--------------------------------------------------------------------------------------------------| - | Line | Description | Units | Example Value | - |------|-------------------------------------------------------------|-------------|---------------| - | 23 | Total credits from fuel supplied (from Schedule B) | Credits | 100,000 | - | 24 | Total debits from fuel supplied (from Schedule B) | (Debits) | 80,000 | - | 25 | Net credit or debit balance for the compliance period | Credits | 20,000 | - | 26 | Total banked credits used to offset outstanding debits | Credits | | - | 27 | Outstanding debit balance | (Debits) | | - | 28 | Part 3 non-compliance penalty payable | $CAD | | - |------|-------------------------------------------------------------|-------------|---------------| - | | Corresponding Compliance Unit conversion / transaction | | +20,000 | - """ - def test_initial_report_in_net_credit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload.copy() - payload['status']['fuelSupplierStatus'] = 'Submitted' - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 20000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), 20000.0) - - """ - | Scenario 1: Initial Report in a net debit position | - |--------------------------------------------------------------------------------------------------| - | Line | Description | Units | Example Value | - |------|-------------------------------------------------------------|-------------|---------------| - | 23 | Total credits from fuel supplied (from Schedule B) | Credits | 105,000 | - | 24 | Total debits from fuel supplied (from Schedule B) | (Debits) | 150,000 | - | 25 | Net credit or debit balance for the compliance period | (Debits) | -45,000 | - | 26 | Total banked credits used to offset outstanding debits | Credits | 45,000 | - | 27 | Outstanding debit balance | (Debits) | 0 | - | 28 | Part 3 non-compliance penalty payable | $CAD | | - |------|-------------------------------------------------------------|-------------|---------------| - | | Corresponding Compliance Unit conversion / transaction | | -45,000 | - """ - def test_initial_report_in_net_debit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 123830000 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256679000 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(50000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 45000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check (50,000 - 45,000) [50,000 from org balance) - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 5000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -45000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 45000.0) - - """ - | Scenario 2: Supplemental Report Submission #1 that increases debit obligation | - |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Example Values - Initial Submission | Example Values - Supplemental #1 | - |---------------------------------------------------------------------------|---------|--------------|-------------------------------------|-------------------------------------|----------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | 100,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 145,000 | 150,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -45,000 | -50,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B | Credits | 45,000 | 50,000 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a| A | Credits | n/a | 45,000 | - | Banked credits used to offset outstanding debits - Supplemental Report #1 | Line 26b| B (editable) | Credits | n/a | 5,000 | - | Outstanding debit balance | Line 27 | Z - (A+B) | (Debits) | 0 | 0 | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | | - |---------------------------------------------------------------------------|---------|--------------|-------------------------------------|-------------------------------------|----------------------------------| - | Report Status (for compliance units conversion) | | | | Accepted | Accepted | - | Corresponding Compliance Unit conversion / transaction | | | | -45,000 | -5,000 | - """ - def test_supplemental_report_submission_increasing_debit_obligation(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 248122823 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(50000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 45000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check (50,000 - 45,000) [50,000 from org balance) - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 5000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -45000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 45000.0) - # Create supplemental report #1 - sid = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 45000 - payload['summary']['creditsOffsetB'] = 5000 - self._patch_fs_user_for_compliance_report(payload, sid) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check (5000 - 5000) [5000 from org balance) - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 0) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 45000.0) - self.assertEqual(response.data['summary']['lines']['26B'], 5000.0) - - """ - | Scenario 3: Supplemental Report Submission #2 that increases debit obligation - Example 1 | - |--------------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Initial Submission - Accepted | Example 1 - Supplemental #1 - Accepted | Example 1 - Supplemental #2 - Accepted | - |---------------------------------------------------------------------------|----------|---------------|-------------------------------|----------------------------------------|----------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | 100,000 | 100,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 145,000 | 148,000 | 150,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -45,000 | -48,000 | -50,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C+D | Credits | 45,000 | 48,000 | 50,000 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | Credits | n/a | 45,000 | 48,000 | - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | D (editable) | Credits | n/a | 3,000 | 2,000 | - | Outstanding debit balance | Line 27 | Z - (A+B+C+D) | (Debits) | 0 | 0 | 0 | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | $- | $- | $- | - | Report Status (for compliance units conversion) | | | | Accepted | Accepted | Accepted | - | Corresponding Compliance Unit conversion / transaction | | | | -45,000 | -3,000 | -2,000 | - """ - def test_supplemental_report_submission_2_ex1_increasing_debit_obligation(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 248122823 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(50000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 45000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check (50,000 - 45,000) [50,000 from org balance] - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 5000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -45000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 45000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 253256398 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 48000 - payload['summary']['creditsOffsetA'] = 45000 - payload['summary']['creditsOffsetB'] = 3000 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -48000.0) - self.assertEqual(response.data['summary']['lines']['26'], 48000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 45000.0) - self.assertEqual(response.data['summary']['lines']['26B'], 3000.0) - # compliance unit balance check (5000 - 3000) [5000 from org balance] - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 2000) - # Create supplemental report #2 - sid2 = self._create_supplemental_report(sid1) - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 48000 - payload['summary']['creditsOffsetB'] = 2000 - self._patch_fs_user_for_compliance_report(payload, sid2) - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid2)) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid2) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid2)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 48000.0) - self.assertEqual(response.data['summary']['lines']['26B'], 2000.0) - # compliance unit balance check (2000 - 2000) [2000 from org balance] - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 0) - - """ - | Scenario 3: Supplemental Report Submission #2 that increases debit obligation - Example 2 | - |--------------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Initial Submission - Accepted | Example 2 - Supplemental #1 - Submitted | Example 2 - Supplemental #2 - Accepted | - |---------------------------------------------------------------------------|----------|---------------|-------------------------------|--------------------------------|-----------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | 100,000 | 100,000 - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 144,000 | 148,000 | 150,000 - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -44,000 | -48,000 | -50,000 - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C+D | Credits | 44,000 | 46,000 | 46,000 - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | Credits | n/a | 44,000 | 44,000 - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | D (editable) | Credits | n/a | 2,000 | 2,000 - | Outstanding debit balance | Line 27 | Z - (A+B+C+D) | (Debits) | 0 | 2,000 | 4,000 - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | $- | $400,000 | $800,000 - |---------------------------------------------------------------------------|----------|---------------|-------------------------------|--------------------------------|-----------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | | Accepted | Submitted (not Accepted) | Accepted - |---------------------------------------------------------------------------|----------|---------------|-------------------------------|--------------------------------|-----------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | -44,000 | | -2,000 - """ - def test_supplemental_report_submission_2_ex2_increasing_debit_obligation(self): - rid = self._create_draft_compliance_report() - # patch compliance report information - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 246411631 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(50000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 44000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -44000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 44000.0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 6000) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 253256398 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 46000 - payload['summary']['creditsOffsetA'] = 44000 - payload['summary']['creditsOffsetB'] = 2000 - self._patch_fs_user_for_compliance_report(payload, sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -48000.0) - self.assertEqual(response.data['summary']['lines']['26'], 46000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 44000.0) - self.assertEqual(response.data['summary']['lines']['26B'], 2000.0) - self.assertEqual(response.data['summary']['lines']['27'], -2000.0) - self.assertEqual(response.data['summary']['lines']['28'], 400000.0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 6000) - # Create supplemental report #2 - sid2 = self._create_supplemental_report(sid1) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 46000 - payload['summary']['creditsOffsetA'] = 44000 - payload['summary']['creditsOffsetB'] = 2000 - self._patch_fs_user_for_compliance_report(payload, sid2) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid2) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid2)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 46000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 44000.0) - self.assertEqual(response.data['summary']['lines']['26B'], 2000.0) - self.assertEqual(response.data['summary']['lines']['27'], -4000.0) - self.assertEqual(response.data['summary']['lines']['28'], 800000.0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 4000) - - """ - | Scenario 4: Supplemental Report Submission #1 that decreases debit obligation and still in a net debit position overall (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Initial Submission - Accepted | Example 1 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | 100,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 160,000 | 150,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits)| -60,000 | -50,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A-R | Credits | 60,000 | 50,000 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A | Credits | n/a | 60,000 | - | Banked credits used to offset outstanding debits - Supplemental Report #1 | Line 26b | Not editable | Credits | n/a | n/a | - | Outstanding debit balance | Line 27 | | (Debits) | 0 | 0 | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | | | 10,000 | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | | Accepted | Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | -60,000 | +10,000 | - """ - def test_supplemental_report_submission_1_ex1_decreasing_debit_obligation_under_net_debit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 273790701 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 60000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 40000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -60000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 60000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 60000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 60000.0) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 50000) - - """ - | Scenario 4: Supplemental Report Submission #1 that decreases debit obligation and still in a net debit position overall (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Example 2 - Initial Submission - Accepted | Example 2 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | 100,000 - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 160,000 | 150,000 - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits)| -60,000 | -50,000 - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A-R | Credits | 60,000 | 50,000 - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A | Credits | n/a | 60,000 - | Banked credits used to offset outstanding debits - Supplemental Report #1 | Line 26b | Not editable | Credits | n/a | - | Outstanding debit balance | Line 27 | | (Debits) | 0 | 0 - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | | | - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | | Submitted (not Accepted) | Accepted - |-------------------------------------------------------------------------------------|----------|--------------|-----------------|-------------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | | -50,000 - """ - def test_supplemental_report_submission_1_ex2_decreasing_debit_obligation_under_net_debit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 273790701 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 60000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 40000) - # exclude the reserved amount as in this case report is not submitted. - self.assertEqual(response.data.get('max_credit_offset_exclude_reserved'), 100000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -60000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 60000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 60000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 60000.0) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 50000) - - """ - | Scenario 5: Supplemental Report Submission #2 that decreases debit obligation and still in a net debit position overall (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | Units | Example 1 - Initial Submission - Accepted | Example 1 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 100,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 170,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -70,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C-R | Credits | 70,000 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | Credits | n/a | - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | Not editable | Credits | n/a | - | Outstanding debit balance | Line 27 | | (Debits) | 0 | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | | | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | Accepted | Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | -70,000 | - """ - def test_supplemental_report_submission_2_ex1_decreasing_debit_obligation_under_net_debit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 290902619 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 70000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 30000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -70000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 70000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 70000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 70000.0) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 50000) - - """ - | Scenario 5: Supplemental Report Submission #2 that decreases debit obligation and still in a net debit position overall (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | Units | Example 2 - Initial Submission - Accepted | Example 2 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | 100,000 | 100,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | 150,000 | 170,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | -50,000 | -70,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C-R | 50,000 | 70,000 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | 70,000 | n/a | - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | Not editable | 0 | n/a | - | Outstanding debit balance | Line 27 | | 0 | 0 | - | Part 3 non-compliance penalty payable | Line 28 | | | | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | 20,000 | | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | Submitted (not Accepted) | Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | +20,000 | | - """ - def test_supplemental_report_submission_2_ex2_decreasing_debit_obligation_under_net_debit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 290902619 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 70000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 30000) - # exclude the reserved amount as in this case report is not submitted. - self.assertEqual(response.data.get('max_credit_offset_exclude_reserved'), 100000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -70000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 70000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 117933318 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 256678782 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 50000 - payload['summary']['creditsOffsetA'] = 70000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], -50000.0) - self.assertEqual(response.data['summary']['lines']['26'], 50000.0) - self.assertEqual(response.data['summary']['lines']['26A'], 70000.0) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 50000) - - """ - | Scenario 6: Supplemental Report Submission #2 that decreases debit obligation and is now in a net credit position (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Example 1 - Initial Submission - Accepted | Example 1 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 80,000 | 105,000 | - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 100,000 | 100,000 | - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -20,000 | 5,000 | - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C-R | Credits | 20,000 | 0 | - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | Credits | n/a | 20,000 | - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | Not editable | Credits | n/a | 0 | - | Outstanding debit balance | Line 27 | | (Debits) | | | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | | | 25,000 | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | | Accepted | Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | -20,000 | +25,000 | - """ - def test_supplemental_report_submission_2_ex1_decreasing_debit_obligation_now_in_net_credit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 94346654 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 171119188 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 20000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # Successful director acceptance - self._acceptance_from_director(rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 80000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -20000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 20000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 123829984 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 171119188 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 0 - payload['summary']['creditsOffsetA'] = 20000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], 5000.0) - self.assertEqual(response.data['summary']['lines']['26'], 0) - self.assertEqual(response.data['summary']['lines']['26A'], 20000.0) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual(min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 105000) - - """ - | Scenario 6: Supplemental Report Submission #2 that decreases debit obligation and is now in a net credit position (Line 25) | - |-----------------------------------------------------------------------------------------------------------------------------| - | Part 3 - Low Carbon Fuel Requirement Summary | Line | | Units | Example 2 - Initial Submission - Accepted | Example 2 - Supplemental #1 - Accepted | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Total credits from fuel supplied (from Schedule B) | Line 23 | X | Credits | 80,000 | 105,000 - | Total debits from fuel supplied (from Schedule B) | Line 24 | Y | (Debits) | 100,000 | 100,000 - | Net credit or debit balance for compliance period | Line 25 | Z | Credits (Debits) | -20,000 | 5,000 - | Total banked credits used to offset outstanding debits (if applicable) | Line 26 | A+B+C-R | Credits | 20,000 | 0 - | Banked credits used to offset outstanding debits - Previous Reports | Line 26a | A+B+C | Credits | n/a | 20,000 - | Banked credits used to offset outstanding debits - Supplemental Report #2 | Line 26b | Not editable | Credits | n/a | 0 - | Outstanding debit balance | Line 27 | | (Debits) | | - | Part 3 non-compliance penalty payable | Line 28 | | $CAD | | - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Banked credits to be returned as a result of supplemental reporting (if applicable) | | R | | | 5,000 - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Report Status (for compliance units conversion) | | | | Submitted (not Accepted) | Accepted - |-------------------------------------------------------------------------------------|----------|--------------|------------------|-------------------------------------------|----------------------------------------| - | Corresponding Compliance Unit conversion / transaction | | | | | +5,000 - """ - def test_supplemental_report_submission_2_ex2_decreasing_debit_obligation_now_in_net_credit_position(self): - rid = self._create_draft_compliance_report() - # patch compliance report info - payload = compliance_unit_initial_payload - payload['status']['fuelSupplierStatus'] = 'Draft' - payload['scheduleB']['records'][0]['quantity'] = 94346654 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 171119188 # debits of fuel supplied (from Schedule B) - self._patch_fs_user_for_compliance_report(payload, rid) - self._add_part3_awards_to_org(100000) - # Submit the compliance report - payload = { - 'status': {'fuelSupplierStatus': 'Submitted'}, - 'summary': { - 'creditsOffset': 20000, - } - } - self._patch_fs_user_for_compliance_report(payload, rid) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=rid)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 80000) - # exclude the reserved amount as in this case report is not submitted. - self.assertEqual(response.data.get('max_credit_offset_exclude_reserved'), 100000) - self.assertEqual(response.data.get('summary').get('lines').get('25'), -20000.0) - self.assertEqual(response.data.get('summary').get('lines').get('26'), 20000.0) - # Create supplemental report #1 - sid1 = self._create_supplemental_report(rid) - payload = compliance_unit_supplemental_payload - payload['scheduleB']['records'][0]['quantity'] = 123829984 # credits of fuel supplied (from Schedule B) - payload['scheduleB']['records'][1]['quantity'] = 171119188 # debits of fuel supplied (from Schedule B) - payload['summary']['creditsOffset'] = 0 - payload['summary']['creditsOffsetA'] = 20000 - payload['summary']['creditsOffsetB'] = 0 - self._patch_fs_user_for_compliance_report(payload, sid1) - # Successful director acceptance for supplemental report #1 - self._acceptance_from_director(sid1) - # retrieve the compliance report and validate the Summary report fields - response = self.clients['fs_user_1'].get('/api/compliance_reports/{id}'.format(id=sid1)) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['summary']['lines']['25'], 5000.0) - self.assertEqual(response.data['summary']['lines']['26'], 0) - self.assertEqual(response.data['summary']['lines']['26A'], 20000) - self.assertEqual(response.data['summary']['lines']['27'], 0) - # compliance unit balance check - self.assertEqual( - min(response.data.get('max_credit_offset'), response.data.get('max_credit_offset_exclude_reserved')), 105000) diff --git a/backend/api/tests/test_credit_trade_admin_adjustment.py b/backend/api/tests/test_credit_trade_admin_adjustment.py deleted file mode 100644 index 5998305d6..000000000 --- a/backend/api/tests/test_credit_trade_admin_adjustment.py +++ /dev/null @@ -1,142 +0,0 @@ -import datetime -import json - -from rest_framework import status - -from django.db.models import Sum -from api.models.CreditTrade import CreditTrade -from api.tests.base_test_case import BaseTestCase -from api.models.OrganizationBalance import OrganizationBalance - - -class TestAdministrativeAdjustmentOperations(BaseTestCase): - - extra_fixtures = ['test/test_credit_trades.json'] - - def test_administrative_adjustment_positive(self): - """ - Testing positive administrative adjustment - """ - - initial_balance = OrganizationBalance.objects.get( - organization_id=self.users['fs_user_1'].organization.id, - expiration_date=None).validated_credits - - payload = { - 'initiator': self.users['gov_director'].organization.id, - 'respondent': self.users['fs_user_1'].organization.id, - 'numberOfCredits': 10, - 'status': self.statuses['recorded'].id, - 'tradeEffectiveDate': datetime.datetime.today().strftime('%Y-%m-%d'), - 'type': self.credit_trade_types['adminAdjustment'].id - } - response = self.clients['gov_director'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - payload = { - 'initiator': self.users['gov_director'].organization.id, - 'respondent': self.users['fs_user_1'].organization.id, - 'numberOfCredits': 10, - 'status': self.statuses['recorded'].id, - 'tradeEffectiveDate': datetime.datetime.today().strftime('%Y-%m-%d'), - 'type': self.credit_trade_types['adminAdjustment'].id - } - response = self.clients['gov_director'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - response = self.clients['gov_director'].put('/api/credit_trades/batch_process') - self.assertEqual(response.status_code, status.HTTP_200_OK) - - orgBalances = OrganizationBalance.objects.filter( - organization_id=self.users['fs_user_1'].organization.id, - expiration_date=None) - for org in orgBalances: - print("ORG BALANCE") - print(vars(org)) - - new_balance = OrganizationBalance.objects.get( - organization_id=self.users['fs_user_1'].organization.id, - expiration_date=None).validated_credits - - self.assertEqual(new_balance, initial_balance + 20) - - - def test_administrative_adjustment_negative(self): - """ - Testing negative administrative adjustment - """ - - initial_balance = OrganizationBalance.objects.get( - organization_id=self.users['fs_user_1'].organization.id, - expiration_date=None).validated_credits - print('INITIAL BALANCE') - print(initial_balance) - - payload = { - 'initiator': self.users['gov_director'].organization.id, - 'respondent': self.users['fs_user_1'].organization.id, - 'numberOfCredits': -10, - 'status': self.statuses['recorded'].id, - 'tradeEffectiveDate': datetime.datetime.today().strftime('%Y-%m-%d'), - 'type': self.credit_trade_types['adminAdjustment'].id - } - response = self.clients['gov_director'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - payload = { - 'initiator': self.users['gov_director'].organization.id, - 'respondent': self.users['fs_user_1'].organization.id, - 'numberOfCredits': -10, - 'status': self.statuses['recorded'].id, - 'tradeEffectiveDate': datetime.datetime.today().strftime('%Y-%m-%d'), - 'type': self.credit_trade_types['adminAdjustment'].id - } - response = self.clients['gov_director'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload) - ) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - response = self.clients['gov_director'].put('/api/credit_trades/batch_process') - self.assertEqual(response.status_code, status.HTTP_200_OK) - - new_balance = OrganizationBalance.objects.get( - organization_id=self.users['fs_user_1'].organization.id, - expiration_date=None).validated_credits - - self.assertEqual(new_balance, initial_balance - 20) - - - def test_administrative_adjustment_insufficient_funds(self): - """ - Testing administrative adjustment with insufficient funds - """ - - # Set a very high negative administrative adjustment value - payload = { - 'initiator': self.users['gov_director'].organization.id, - 'respondent': self.users['fs_user_1'].organization.id, - 'numberOfCredits': -100000000000, - 'status': self.statuses['recorded'].id, - 'tradeEffectiveDate': datetime.datetime.today().strftime('%Y-%m-%d'), - 'type': self.credit_trade_types['adminAdjustment'].id - } - - response = self.clients['gov_director'].post( - '/api/credit_trades', - content_type='application/json', - data=json.dumps(payload) - ) - - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/backend/api/tests/test_get_summary.py b/backend/api/tests/test_get_summary.py index 61b83f0f4..f195df338 100644 --- a/backend/api/tests/test_get_summary.py +++ b/backend/api/tests/test_get_summary.py @@ -3,7 +3,6 @@ from datetime import datetime from api.serializers.ComplianceReport import ComplianceReportDetailSerializer, CompliancePeriodSerializer from unittest.mock import MagicMock, Mock -from api.models.Organization import Organization class TestComplianceReportDetailSerializer(TestCase): @@ -11,8 +10,6 @@ def setUp(self): self.serializer = ComplianceReportDetailSerializer() self.serializer.compliance_period = CompliancePeriodSerializer() self.serializer.summary = None - self.serializer.supplements = None - self.serializer.organization = Organization.objects.first() self.serializer.schedule_a = MagicMock( net_gasoline_class_transferred=Decimal('10'), diff --git a/backend/api/validators.py b/backend/api/validators.py index 8ece9e093..826406c4b 100644 --- a/backend/api/validators.py +++ b/backend/api/validators.py @@ -3,15 +3,13 @@ from .exceptions import PositiveIntegerException -def CreditTradeNumberOfCreditsValidator(value, instance): +def CreditTradeNumberOfCreditsValidator(value): """ Validates and makes sure that the user doesn't enter 0 or a negative value for the number of - credits, unless the credit_trade_type is 'Administrative Adjustment'. + credits """ - if instance.credit_trade_type == 'Administrative Adjustment': - return # Allow any value for Administrative Adjustment - elif value <= 0: + if value <= 0: raise PositiveIntegerException( "Please enter at least 1 credit." ) diff --git a/backend/api/viewsets/ComplianceReport.py b/backend/api/viewsets/ComplianceReport.py index 30ebd49e9..8a52314e8 100644 --- a/backend/api/viewsets/ComplianceReport.py +++ b/backend/api/viewsets/ComplianceReport.py @@ -1,5 +1,4 @@ import datetime -from decimal import * from django.core.cache import caches, cache from django.db import transaction @@ -24,7 +23,6 @@ ExclusionReportDetailSerializer, ExclusionReportUpdateSerializer, ExclusionReportValidationSerializer from api.services.ComplianceReportService import ComplianceReportService from api.services.ComplianceReportSpreadSheet import ComplianceReportSpreadsheet -from api.services.OrganizationService import OrganizationService from auditable.views import AuditableMixin from api.paginations import BasicPagination from django.db.models import Q, F, Value @@ -116,7 +114,7 @@ def get_queryset(self): qs = qs.annotate(reports_updatedtime=Max('update_timestamp')).order_by('-reports_updatedtime') else: qs = qs.annotate(reports_updatedtime=Max('update_timestamp')).order_by('reports_updatedtime') - + filters = request.data.get('filters') if filters: for filter in filters: @@ -212,12 +210,12 @@ def filter_compliance_status_old(self, qs, value): Q(status__director_status__status='Unreviewed') & Q(status__manager_status__status='Unreviewed') ) - + if 'recommended rejection - analyst'.find(value) != -1 or 'rejection'.find(value) != -1: return qs.filter( Q(status__analyst_status__status='Not Recommended') ) - + if 'recommended acceptance - manager'.find(value) != -1 or 'manager'.find(value) != -1: return qs.filter( Q(status__manager_status__status='Recommended') & @@ -230,13 +228,13 @@ def filter_compliance_status_old(self, qs, value): return qs.filter( Q(status__manager_status__status='Not Recommended') ) - + return qs - + def filter_compliance_status(self, qs, value): query_result = [] for val in value: - if val == 'Accepted' : + if val == 'Accepted' : qs_accepted = qs.filter( Q(status__director_status__status='Accepted') ) @@ -260,7 +258,7 @@ def filter_compliance_status(self, qs, value): query_result.extend(qs_draft) if val == 'For Analyst Review': - qs_analyst = qs.filter( + qs_analyst = qs.filter( Q(status__analyst_status__status='Unreviewed') & Q(status__director_status__status='Unreviewed') & Q(status__fuel_supplier_status__status='Submitted') & @@ -270,12 +268,12 @@ def filter_compliance_status(self, qs, value): if val == 'For Manager Review': qs_manager = qs.filter( - + Q(status__analyst_status__status='Recommended') & Q(status__director_status__status='Unreviewed') & Q(status__manager_status__status='Unreviewed') & Q(status__fuel_supplier_status__status='Submitted') - + ) query_result.extend(qs_manager) qs_man_rej = qs.filter( @@ -285,22 +283,22 @@ def filter_compliance_status(self, qs, value): Q(status__fuel_supplier_status__status='Submitted') ) query_result.extend(qs_man_rej) - + if val == 'For Director Review': qs_director = qs.filter( Q(status__manager_status__status='Recommended') & - Q(status__director_status__status='Unreviewed') + Q(status__director_status__status='Unreviewed') ) query_result.extend(qs_director) qs_dir_rej = qs.filter( Q(status__manager_status__status='Not Recommended') & - Q(status__director_status__status='Unreviewed') + Q(status__director_status__status='Unreviewed') ) query_result.extend(qs_dir_rej) if val == 'awaiting government review': - qs_agr = qs.filter( + qs_agr = qs.filter( Q(status__analyst_status__status='Unreviewed') & Q(status__director_status__status='Unreviewed') & Q(status__fuel_supplier_status__status='Submitted') & @@ -308,9 +306,9 @@ def filter_compliance_status(self, qs, value): ) query_result.extend(qs_agr) - + ids = [i.id for i in query_result] - qs = qs.filter(id__in = ids) + qs = qs.filter(id__in = ids) return qs def filter_supplemental_report_status(self, qs, value): @@ -337,7 +335,7 @@ def filter_supplemental_report_status(self, qs, value): return qs.filter( Q(status__director_status__status='Rejected') ) - + if 'recommended'.find(value) != -1: return qs.filter( (Q(supplements__status__manager_status__status='Recommended') & @@ -388,7 +386,7 @@ def filter_current_status(self, qs, value): def filter_manager_status(self, qs, value): try: - supplemental_reports = ComplianceReport.objects.filter(id__in=value) + supplemental_reports = ComplianceReport.objects.filter(id__in=value) except Exception as e: print(e) return supplemental_reports @@ -401,7 +399,7 @@ def filter_draft(self, latest_supplemental): latest_supplemental = latest_supplemental.filter(~Q(status__fuel_supplier_status__status='Draft')) else: latest_supplemental = latest_supplemental.filter(Q(organization=organization)) - + return latest_supplemental def get_latest_supplemental_reports(self): @@ -548,74 +546,8 @@ def list(self, request, *args, **kwargs): sorted_qs, many=True, context={'request': request}) data = serializer.data cached_page.set(sanitized_cache_key, data, 60 * 15) - return Response(data) - def compliance_to_new_act(self, obj, snapshot): - if int(obj.compliance_period.description) > 2022 and snapshot is not None: - lines = snapshot.get('summary').get('lines') - if lines.get('29A') is None: - previous_transactions = [] - previous_snapshots = [] - current = obj - is_supplemental = False - - if current.supplements: - is_supplemental = True - - available_compliance_unit_balance = OrganizationService.get_max_credit_offset_for_interval( - obj.organization, - obj.update_timestamp - ) - net_compliance_unit_balance = int(lines['25']) - desired_net_credit_balance_change = Decimal(0.0) - if is_supplemental: - while current.supplements is not None: - current = current.supplements - if current.credit_transaction is not None: - previous_transactions.append(current.credit_transaction) - if current.compliance_report_snapshot is not None: - previous_snapshots.append(current.compliance_report_snapshot.snapshot) - - total_previous_reduction = Decimal(0.0) - total_previous_validation = Decimal(0.0) - - for transaction in previous_transactions: - if transaction.type.the_type in ['Credit Validation']: - total_previous_validation += transaction.number_of_credits - if transaction.type.the_type in ['Credit Reduction']: - total_previous_reduction += transaction.number_of_credits - desired_net_credit_balance_change = Decimal(lines['25']) - net_compliance_unit_balance = desired_net_credit_balance_change - \ - (total_previous_validation - total_previous_reduction) - - adjusted_balance = available_compliance_unit_balance + net_compliance_unit_balance - if available_compliance_unit_balance <= 0 and net_compliance_unit_balance < 0: - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if ( - adjusted_balance < 0) else 0 - lines['29A'] = 0 - total_previous_compliance_units = Decimal(0.0) - for snapshots in previous_snapshots: - if snapshots.get("summary").get("lines") is not None: - total_previous_compliance_units += Decimal(snapshots.get("summary").get("lines").get("25")) - lines['29B'] = Decimal(lines['25']) - total_previous_compliance_units - lines['29C'] = 0 - else: - lines['29A'] = available_compliance_unit_balance - lines['28'] = 0 - if (net_compliance_unit_balance < 0 <= adjusted_balance) or (net_compliance_unit_balance >= 0): - lines['29B'] = net_compliance_unit_balance - elif net_compliance_unit_balance < 0 and adjusted_balance < 0: - lines['29B'] = net_compliance_unit_balance if ( - adjusted_balance > 0) else -available_compliance_unit_balance - lines['28'] = int((adjusted_balance * Decimal('-600.00')).max(Decimal(0))) if ( - adjusted_balance < 0) else 0 - lines['29C'] = lines['29A'] + lines['29B'] - snapshot['summary']['total_payable'] = Decimal(lines['11']) + Decimal(lines['22']) + lines[ - '28'] - snapshot['summary']['lines'] = lines - return snapshot - @action(detail=False, methods=['post']) def paginated(self, request): queryset = self.get_queryset() @@ -633,7 +565,7 @@ def paginated(self, request): serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) - + @action(detail=False, methods=['get'], permission_classes=[AllowAny]) def types(self, request): @@ -668,8 +600,8 @@ def snapshot(self, request, pk=None): # failure to find an object will trigger an exception that is # translated into a 404 snapshot = ComplianceReportSnapshot.objects.get(compliance_report=obj) - snapshot = self.compliance_to_new_act(obj, snapshot.snapshot) - return Response(snapshot) + + return Response(snapshot.snapshot) @action(detail=True, methods=['patch']) def compute_totals(self, request, pk=None): @@ -739,14 +671,11 @@ def xls(self, request, pk=None): if obj.type.the_type == 'Exclusion Report': workbook.add_exclusion_agreement(snapshot['exclusion_agreement']) if obj.type.the_type == 'Compliance Report': - snapshot = self.compliance_to_new_act(obj, snapshot) workbook.add_schedule_a(snapshot['schedule_a']) - workbook.add_schedule_b(snapshot['schedule_b'], - int(snapshot['compliance_period']['description'])) + workbook.add_schedule_b(snapshot['schedule_b']) workbook.add_schedule_c(snapshot['schedule_c']) workbook.add_schedule_d(snapshot['schedule_d']) - workbook.add_schedule_summary(snapshot['summary'], - int(snapshot['compliance_period']['description'])) + workbook.add_schedule_summary(snapshot['summary']) workbook.save(response) @@ -768,7 +697,7 @@ def dashboard(self, request): data = serializer.data cached_page.set(sanitized_cache_key, data, 60 * 15) return Response(data) - + @action(detail=False, methods=['get']) def supplemental(self, request): query_params = request.GET.urlencode() diff --git a/backend/api/viewsets/CreditTrade.py b/backend/api/viewsets/CreditTrade.py index 7cc55f8f4..5742826de 100644 --- a/backend/api/viewsets/CreditTrade.py +++ b/backend/api/viewsets/CreditTrade.py @@ -219,23 +219,19 @@ def batch_process(self, request): """ Call the approve function on multiple Credit Trades """ - try: - status_approved = CreditTradeStatus.objects \ - .get(status="Recorded") - - credit_trades = CreditTrade.objects.filter( - status_id=status_approved.id).order_by('id') + status_approved = CreditTradeStatus.objects \ + .get(status="Recorded") - CreditTradeService.validate_credits(credit_trades) + credit_trades = CreditTrade.objects.filter( + status_id=status_approved.id).order_by('id') - for credit_trade in credit_trades: - credit_trade.update_user_id = request.user.id - CreditTradeService.approve(credit_trade, batch_process=True) - CreditTradeService.dispatch_notifications( - None, credit_trade) + CreditTradeService.validate_credits(credit_trades) - except Exception as e: - return Response(e, status=status.HTTP_400_BAD_REQUEST) + for credit_trade in credit_trades: + credit_trade.update_user_id = request.user.id + CreditTradeService.approve(credit_trade,batch_process=True) + CreditTradeService.dispatch_notifications( + None, credit_trade) return Response({"message": "Approved credit transactions have been processed."}, @@ -252,7 +248,7 @@ def xls(self, request): response['Content-Disposition'] = ( 'attachment; filename="{}.xls"'.format( datetime.datetime.now().strftime( - "BC-LCFS_transactions_%Y-%m-%d") + "BC-LCFS_credit_transactions_%Y-%m-%d") )) credit_trades = self.get_queryset().filter( @@ -279,7 +275,7 @@ def xls(self, request): type="Part3FuelSupplier")) \ .order_by('lower_name') - workbook.add_fuel_suppliers(fuel_suppliers, include_actions=True) + workbook.add_fuel_suppliers(fuel_suppliers) workbook.save(response) diff --git a/backend/api/viewsets/Organization.py b/backend/api/viewsets/Organization.py index b7bd5819d..274cdedba 100644 --- a/backend/api/viewsets/Organization.py +++ b/backend/api/viewsets/Organization.py @@ -29,7 +29,6 @@ from api.services.CreditTradeService import CreditTradeService from auditable.views import AuditableMixin -from api.services.OrganizationService import OrganizationService cached_page = caches['cached_pages'] @@ -69,7 +68,7 @@ def get_serializer_class(self): @method_decorator(permission_required('VIEW_FUEL_SUPPLIERS')) def list(self, request, *args, **kwargs): """ - Returns a list of Organizations + Returns a list of Fuel Suppliers There are two types of organizations: Government and Fuel Suppliers The function needs to separate the organizations based on type """ @@ -103,24 +102,19 @@ def balance(self, request, pk=None): """ organization = self.get_object() - # get the latest balance for the organization + # Process future effective dates + # This future effective_date feature has been disabled so this + # service method call has been commented out but left here if + # this feature is needed in the future + # CreditTradeService.process_future_effective_dates(organization) balance = OrganizationBalance.objects.get( organization=organization, expiration_date=None) serializer = self.get_serializer(balance) - # access the credit trade data like effective date and compliance period - effective_date_year = datetime.datetime.now().year - max_credit_offset = OrganizationService.get_max_credit_offset(organization, effective_date_year) - max_credit_offset_exclude_reserved = OrganizationService.get_max_credit_offset( - organization, - effective_date_year, - exclude_reserved=True) - data = serializer.data - if data is not None: - data['availableBalance'] = min(max_credit_offset, max_credit_offset_exclude_reserved) - return Response(data) + + return Response(serializer.data) @action(detail=False, methods=['get']) def fuel_suppliers(self, request): @@ -241,7 +235,7 @@ def users(self, request, pk=None): @method_decorator(permission_required('VIEW_FUEL_SUPPLIERS')) def xls(self, request): """ - Exports the Organizations as a spreadsheet + Exports the Fuel Suppliers as a spreadsheet """ response = HttpResponse(content_type='application/ms-excel') response['Content-Disposition'] = ( @@ -257,7 +251,7 @@ def xls(self, request): .order_by('lower_name') workbook = SpreadSheetBuilder() - workbook.add_fuel_suppliers(fuel_suppliers, include_actions=False) + workbook.add_fuel_suppliers(fuel_suppliers) workbook.save(response) return response diff --git a/backend/tfrs/urls.py b/backend/tfrs/urls.py index e0b67cadf..8dec8a929 100644 --- a/backend/tfrs/urls.py +++ b/backend/tfrs/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import url from django.urls import path, include from django.contrib import admin -# import debug_toolbar +import debug_toolbar from . import views from django.urls import path diff --git a/charts/tfrs-apps/Chart.yaml b/charts/tfrs-apps/Chart.yaml index 0b9a41aee..9a8fc539e 100644 --- a/charts/tfrs-apps/Chart.yaml +++ b/charts/tfrs-apps/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.0.0 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "3.0.0" +appVersion: "1.16.0" diff --git a/charts/tfrs-apps/charts/tfrs-backend/Chart.yaml b/charts/tfrs-apps/charts/tfrs-backend/Chart.yaml index e02f42332..4efbf3ad4 100644 --- a/charts/tfrs-apps/charts/tfrs-backend/Chart.yaml +++ b/charts/tfrs-apps/charts/tfrs-backend/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.0 +version: 1.0.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/tfrs-apps/charts/tfrs-backend/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-backend/templates/_helpers.tpl index 1b1c0be19..a64557262 100644 --- a/charts/tfrs-apps/charts/tfrs-backend/templates/_helpers.tpl +++ b/charts/tfrs-apps/charts/tfrs-backend/templates/_helpers.tpl @@ -16,13 +16,10 @@ The selector lables: .Release.Name comes from command helm install example: helm install tfrs-backend-dev ... or helm install tfrs-backend-dev-jan ... -.Chart.Name come from the name attribute in Chart.yaml - */}} {{/* -Expand the name of the chart. If nameOverride is empty, use .Chart.Name. -Typically no need to assign value to nameOverride, +Expand the name of the chart. */}} {{- define "tfrs-backend.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} @@ -31,7 +28,8 @@ Typically no need to assign value to nameOverride, {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -The .Release.Name is the first parameter of command helm install tfrs-backend-dev or tfrs-backend-dev-jan +If release name contains chart name it will be used as a full name. +The .Release.Name is the first parameter of command helm install tfrs-backend */}} {{- define "tfrs-backend.fullname" -}} {{- .Release.Name }} @@ -62,6 +60,76 @@ Selector labels */}} {{- define "tfrs-backend.selectorLabels" -}} app.kubernetes.io/name: {{ include "tfrs-backend.name" . }} -app.kubernetes.io/instance: {{ include "tfrs-backend.fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "tfrs-backend.deploymentconfigName" -}} +{{- include "tfrs-backend.fullname" . }} +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "tfrs-backend.imagestreamName" -}} +{{- include "tfrs-backend.fullname" . }} +{{- end }} + +{{/* +Define the service name +*/}} +{{- define "tfrs-backend.serviceName" -}} +{{- include "tfrs-backend.fullname" . }} +{{- end }} + + +{{/* +Define the backend route name +*/}} +{{- define "tfrs-backend.routeName" -}} +{{- include "tfrs-backend.fullname" . }} +{{- end }} + +{{/* +Define the backend admin route name, used by task queue +*/}} +{{- define "tfrs-backend.adminRouteName" -}} +tfrs-backend-admin{{ .Values.suffix }} +{{- end }} + +{{/* +Define the backend static route name, used by task queue +*/}} +{{- define "tfrs-backend.staticRouteName" -}} +tfrs-backend-static{{ .Values.suffix }} +{{- end }} + +{{/* +Define the djangoSecretKey +*/}} +{{- define "tfrs-backend.djangoSecretKey" -}} +{{- randAlphaNum 50 | nospace | b64enc }} {{- end }} +{{/* +Define the djangoSaltKey +*/}} +{{- define "tfrs-backend.djangoSaltKey" -}} +{{- randAlphaNum 50 | nospace | b64enc }} +{{- end }} + +{{/* +Define the django-secret name +*/}} +{{- define "tfrs-backend.django-secret" -}} +tfrs-django-secret +{{- end }} + +{{/* +Define the django-salt name +*/}} +{{- define "tfrs-backend.django-salt" -}} +tfrs-django-salt +{{- end }} \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-backend/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-backend/templates/deployment-config.yaml index 94f238e07..2f19fe2e9 100644 --- a/charts/tfrs-apps/charts/tfrs-backend/templates/deployment-config.yaml +++ b/charts/tfrs-apps/charts/tfrs-backend/templates/deployment-config.yaml @@ -3,7 +3,7 @@ apiVersion: apps.openshift.io/v1 metadata: annotations: description: Defines how to deploy the backend application - name: tfrs-backend{{ .Values.suffix }} + name: {{ include "tfrs-backend.deploymentconfigName" . }} labels: {{- include "tfrs-backend.labels" . | nindent 4 }} spec: @@ -30,7 +30,7 @@ spec: from: kind: ImageStreamTag namespace: {{ .Values.namespace }} - name: tfrs-backend:{{ .Values.backendImageTagName }} + name: {{ include "tfrs-backend.name" . }}:{{ .Values.backendImageTagName }} - type: ConfigChange replicas: {{ .Values.replicaCount }} revisionHistoryLimit: 10 @@ -79,7 +79,7 @@ spec: - name: SMTP_SERVER_PORT value: '2500' - name: DATABASE_SERVICE_NAME - value: {{ .Values.databaseServiceHostName }} + value: {{ .Values.env.databaseServiceName }} - name: DATABASE_ENGINE value: postgresql - name: DATABASE_NAME @@ -98,7 +98,7 @@ spec: name: tfrs-patroni-app key: app-db-password - name: POSTGRESQL_SERVICE_HOST - value: {{ .Values.databaseServiceHostName }}.{{ .Values.namespace }}.svc.cluster.local + value: {{ .Values.env.postgresqlServiceHost }} - name: POSTGRESQL_SERVICE_PORT value: '5432' - name: RABBITMQ_USER @@ -107,9 +107,9 @@ spec: name: tfrs-rabbitmq-app key: username - name: RABBITMQ_VHOST - value: {{ .Values.rabbitmqVHost }} + value: tfrs-vhost - name: RABBITMQ_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local + value: {{ .Values.env.rabbitmqHost }} - name: RABBITMQ_PASSWORD valueFrom: secretKeyRef: @@ -118,7 +118,7 @@ spec: - name: RABBITMQ_PORT value: '5672' - name: MINIO_ENDPOINT - value: tfrs-minio-{{ .Values.envName }}.apps.silver.devops.gov.bc.ca:443 + value: {{ .Values.env.minioEndpoint }} - name: MINIO_USE_SSL value: 'true' - name: DOCUMENTS_API_ENABLED @@ -126,13 +126,13 @@ spec: - name: MINIO_ACCESS_KEY valueFrom: secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_ACCESS_KEY + name: {{ .Values.env.minioSecretName }} + key: {{ .Values.env.minioAccessKey}} - name: MINIO_SECRET_KEY valueFrom: secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_SECRET_KEY + name: {{ .Values.env.minioSecretName }} + key: {{ .Values.env.minioSecretKey}} - name: FUEL_CODES_API_ENABLED value: '{{ .Values.env.fuelCodesApiEnabled}}' - name: CREDIT_CALCULATION_API_ENABLED @@ -151,7 +151,8 @@ spec: - name: KEYCLOAK_AUDIENCE value: tfrs-on-gold-4308 - name: WELL_KNOWN_ENDPOINT - value: https://{{ .Values.envName }}.loginproxy.gov.bc.ca/auth/realms/standard/.well-known/openid-configuration + value: >- + {{ .Values.env.wellKnownEndpoint}} ports: - containerPort: 8080 protocol: TCP diff --git a/charts/tfrs-apps/charts/tfrs-backend/templates/hpa.yaml b/charts/tfrs-apps/charts/tfrs-backend/templates/hpa.yaml deleted file mode 100644 index abfdbc826..000000000 --- a/charts/tfrs-apps/charts/tfrs-backend/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: tfrs-backend{{ .Values.suffix }} - labels: - {{- include "tfrs-backend.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: DeploymentConfig - name: tfrs-backend{{ .Values.suffix }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-backend/templates/route.yaml b/charts/tfrs-apps/charts/tfrs-backend/templates/route.yaml deleted file mode 100644 index 52105f810..000000000 --- a/charts/tfrs-apps/charts/tfrs-backend/templates/route.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - name: tfrs-backend{{ .Values.suffix }} - annotations: - haproxy.router.openshift.io/timeout: 1200s - labels: - {{- include "tfrs-backend.labels" . | nindent 4 }} -spec: - host: tfrs-backend{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca - port: - targetPort: web - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: tfrs-backend{{ .Values.suffix }} - weight: 100 - wildcardPolicy: None diff --git a/charts/tfrs-apps/charts/tfrs-backend/templates/service.yaml b/charts/tfrs-apps/charts/tfrs-backend/templates/service.yaml deleted file mode 100644 index d5c5bc4df..000000000 --- a/charts/tfrs-apps/charts/tfrs-backend/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: tfrs-backend{{ .Values.suffix }} - labels: - {{- include "tfrs-backend.labels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: 8080 - targetPort: 8080 - protocol: TCP - name: web - selector: - {{- include "tfrs-backend.selectorLabels" . | nindent 4 }} diff --git a/charts/tfrs-apps/charts/tfrs-backend/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-backend/values-dev-jan.yaml index d1508cea6..ab839e9a6 100644 --- a/charts/tfrs-apps/charts/tfrs-backend/values-dev-jan.yaml +++ b/charts/tfrs-apps/charts/tfrs-backend/values-dev-jan.yaml @@ -2,33 +2,40 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# backendImageTagName is not in this file, it comes as a argument from the helm command line -# helm template command -# helm template --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml tfrs-backend-dev-jan . -# helm -n --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml upgrade tfrs-backend-dev-jan . - replicaCount: 1 resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. limits: - cpu: 400m - memory: 1200Mi + cpu: 60m + memory: 60Mi requests: - cpu: 200m - memory: 600Mi + cpu: 30m + memory: 30Mi autoscaling: - enabled: true + enabled: false minReplicas: 1 - maxReplicas: 2 + maxReplicas: 1 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 90 env: emailSendingEnabled: true djangoDebug: true + databaseServiceName: tfrs-spilo + postgresqlServiceHost: tfrs-spilo.0ab226-dev.svc.cluster.local + rabbitmqHost: tfrs-rabbitmq.0ab226-dev.svc.cluster.local + minioEndpoint: tfrs-minio-test.apps.silver.devops.gov.bc.ca:443 documentsApiEnabled: true + minioSecretName: tfrs-minio-test + minioAccessKey: MINIO_ACCESS_KEY + minioSecretKey: MINIO_SECRET_KEY fuelCodesApiEnabled: true creditCalculationApiEnabled: true complianceReportingApiEnabled: true exclusionReportsApiEnabled: true + wellKnownEndpoint: https://test.loginproxy.gov.bc.ca/auth/realms/standard/.well-known/openid-configuration diff --git a/charts/tfrs-apps/charts/tfrs-backend/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-backend/values-test-jan.yaml deleted file mode 100644 index d1508cea6..000000000 --- a/charts/tfrs-apps/charts/tfrs-backend/values-test-jan.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# Default values for itvr-backend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# backendImageTagName is not in this file, it comes as a argument from the helm command line -# helm template command -# helm template --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml tfrs-backend-dev-jan . -# helm -n --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml upgrade tfrs-backend-dev-jan . - -replicaCount: 1 - -resources: - limits: - cpu: 400m - memory: 1200Mi - requests: - cpu: 200m - memory: 600Mi - -autoscaling: - enabled: true - minReplicas: 1 - maxReplicas: 2 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 90 - -env: - emailSendingEnabled: true - djangoDebug: true - documentsApiEnabled: true - fuelCodesApiEnabled: true - creditCalculationApiEnabled: true - complianceReportingApiEnabled: true - exclusionReportsApiEnabled: true diff --git a/charts/tfrs-apps/charts/tfrs-backend/values.yaml b/charts/tfrs-apps/charts/tfrs-backend/values.yaml new file mode 100644 index 000000000..3826baed2 --- /dev/null +++ b/charts/tfrs-apps/charts/tfrs-backend/values.yaml @@ -0,0 +1,82 @@ +# Default values for tfrs-backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/charts/tfrs-apps/charts/tfrs-celery/.helmignore b/charts/tfrs-apps/charts/tfrs-celery/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/tfrs-apps/charts/tfrs-celery/Chart.yaml b/charts/tfrs-apps/charts/tfrs-celery/Chart.yaml deleted file mode 100644 index 754644731..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/Chart.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v2 -name: tfrs-celery -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "3.0.0" - - diff --git a/charts/tfrs-apps/charts/tfrs-celery/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-celery/templates/_helpers.tpl deleted file mode 100644 index 95d14c7a9..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -{{/* - -The labels for all components: - labels: - helm.sh/chart: tfrs-celery-1.0.0 - app.kubernetes.io/name: tfrs-celery - app.kubernetes.io/instance: tfrs-celery-dev or tfrs-celery-dev-jan - app.kubernetes.io/version: "3.0.0" - app.kubernetes.io/managed-by: Helm - -The selector lables: - selector: - app.kubernetes.io/name: tfrs-celery - app.kubernetes.io/instance: tfrs-celery-dev-1977 - -.Release.Name comes from command helm install - example: helm install tfrs-celery-dev ... or helm install tfrs-celery-dev-jan ... - -.Chart.Name come from the name attribute in Chart.yaml - -*/}} - -{{/* -Expand the name of the chart. If nameOverride is empty, use .Chart.Name. -Typically no need to assign value to nameOverride, -*/}} -{{- define "tfrs-celery.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -The .Release.Name is the first parameter of command helm install tfrs-celery-dev or tfrs-celery-dev-jan -*/}} -{{- define "tfrs-celery.fullname" -}} -{{- .Release.Name }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tfrs-celery.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels: -app.kubernetes.io/managed-by would be Helm -*/}} -{{- define "tfrs-celery.labels" -}} -helm.sh/chart: {{ include "tfrs-celery.chart" . }} -{{ include "tfrs-celery.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "tfrs-celery.selectorLabels" -}} -app.kubernetes.io/name: {{ include "tfrs-celery.name" . }} -app.kubernetes.io/instance: {{ include "tfrs-celery.fullname" . }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-celery/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-celery/templates/deployment-config.yaml deleted file mode 100644 index 0136244f7..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/templates/deployment-config.yaml +++ /dev/null @@ -1,104 +0,0 @@ -kind: DeploymentConfig -apiVersion: apps.openshift.io/v1 -metadata: - name: tfrs-celery{{ .Values.suffix }} - labels: - {{- include "tfrs-celery.labels" . | nindent 4 }} -spec: - strategy: - type: Recreate - recreateParams: - timeoutSeconds: 300 - resources: {} - activeDeadlineSeconds: 600 - triggers: - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - celery - from: - kind: ImageStreamTag - name: tfrs-celery:{{ .Values.celeryImageTagName }} - - type: ConfigChange - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: 10 - test: false - selector: - {{- include "tfrs-celery.selectorLabels" . | nindent 4 }} - template: - metadata: - creationTimestamp: null - labels: - {{- include "tfrs-celery.labels" . | nindent 8 }} - spec: - containers: - - name: celery - env: - - name: RABBITMQ_VHOST - value: {{ .Values.rabbitmqVHost }} - - name: RABBITMQ_USER - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: username - - name: RABBITMQ_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: password - - name: RABBITMQ_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local - - name: RABBITMQ_PORT - value: '5672' - - name: DATABASE_SERVICE_NAME - value: {{ .Values.databaseServiceHostName }} - - name: DATABASE_ENGINE - value: postgresql - - name: DATABASE_NAME - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-name - - name: DATABASE_USER - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-username - - name: DATABASE_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-password - - name: MINIO_ENDPOINT - value: tfrs-minio-{{ .Values.envName }}.apps.silver.devops.gov.bc.ca:443 - - name: MINIO_USE_SSL - value: 'true' - - name: MINIO_ACCESS_KEY - valueFrom: - secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_ACCESS_KEY - - name: MINIO_SECRET_KEY - valueFrom: - secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_SECRET_KEY - - name: MINIO_BUCKET_NAME - value: tfrs - - name: EMAIL_FROM_ADDRESS - value: tfrs@gov.bc.ca - - name: EMAIL_SENDING_ENABLED - value: 'true' - - name: SMTP_SERVER_HOST - value: apps.smtp.gov.bc.ca - resources: -{{ toYaml .Values.resources | indent 12 }} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - imagePullPolicy: Always - restartPolicy: Always - terminationGracePeriodSeconds: 30 - dnsPolicy: ClusterFirst - securityContext: {} - schedulerName: default-scheduler diff --git a/charts/tfrs-apps/charts/tfrs-celery/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-celery/values-dev-jan.yaml deleted file mode 100644 index f69d068ae..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/values-dev-jan.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Default values for itvr-backend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# backendImageTagName is not in this file, it comes as a argument from the helm command line -# helm template command -# helm template --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml tfrs-backend-dev-jan . -# helm -n --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml upgrade tfrs-backend-dev-jan . - -replicaCount: 1 - -resources: - limits: - cpu: 200m - memory: 3Gi - requests: - cpu: 100m - memory: 1500Mi - diff --git a/charts/tfrs-apps/charts/tfrs-celery/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-celery/values-test-jan.yaml deleted file mode 100644 index f69d068ae..000000000 --- a/charts/tfrs-apps/charts/tfrs-celery/values-test-jan.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Default values for itvr-backend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -# backendImageTagName is not in this file, it comes as a argument from the helm command line -# helm template command -# helm template --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml tfrs-backend-dev-jan . -# helm -n --set backendImageTagName=dev-main-release-jan-2024 -f ./values-dev-jan.yaml upgrade tfrs-backend-dev-jan . - -replicaCount: 1 - -resources: - limits: - cpu: 200m - memory: 3Gi - requests: - cpu: 100m - memory: 1500Mi - diff --git a/charts/tfrs-apps/charts/tfrs-frontend/.helmignore b/charts/tfrs-apps/charts/tfrs-frontend/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/tfrs-apps/charts/tfrs-frontend/Chart.yaml b/charts/tfrs-apps/charts/tfrs-frontend/Chart.yaml deleted file mode 100644 index 2321fa7c9..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: tfrs-frontend -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "3.0.0" diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-frontend/templates/_helpers.tpl deleted file mode 100644 index a34119769..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -{{/* - -The labels for all components: - labels: - helm.sh/chart: tfrs-frontend-1.0.0 - app.kubernetes.io/name: tfrs-frontend - app.kubernetes.io/instance: tfrs-frontend-dev or tfrs-frontend-dev-jan - app.kubernetes.io/version: "3.0.0" - app.kubernetes.io/managed-by: Helm - -The selector lables: - selector: - app.kubernetes.io/name: tfrs-frontend - app.kubernetes.io/instance: tfrs-frontend-dev-1977 - -.Release.Name comes from command helm install - example: helm install tfrs-frontend-dev ... or helm install tfrs-frontend-dev-jan ... - -.Chart.Name come from the name attribute in Chart.yaml - -*/}} - -{{/* -Expand the name of the chart. If nameOverride is empty, use .Chart.Name. -Typically no need to assign value to nameOverride, -*/}} -{{- define "tfrs-frontend.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -The .Release.Name is the first parameter of command helm install tfrs-frontend-dev or tfrs-frontend-dev-jan -*/}} -{{- define "tfrs-frontend.fullname" -}} -{{- .Release.Name }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tfrs-frontend.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels: -app.kubernetes.io/managed-by would be Helm -*/}} -{{- define "tfrs-frontend.labels" -}} -helm.sh/chart: {{ include "tfrs-frontend.chart" . }} -{{ include "tfrs-frontend.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "tfrs-frontend.selectorLabels" -}} -app.kubernetes.io/name: {{ include "tfrs-frontend.name" . }} -app.kubernetes.io/instance: {{ include "tfrs-frontend.fullname" . }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/configmap.yaml b/charts/tfrs-apps/charts/tfrs-frontend/templates/configmap.yaml deleted file mode 100644 index 8f3e92ee1..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/configmap.yaml +++ /dev/null @@ -1,28 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: tfrs-frontend{{ .Values.suffix }} - creationTimestamp: -data: - features.js: | - window.tfrs_config = { - "keycloak.realm": "standard", - "keycloak.client_id": "{{ .Values.configmap.keycloak.clientId }}", - "keycloak.auth_url": "https://{{ .Values.envName }}.loginproxy.gov.bc.ca/auth", - "keycloak.callback_url": "https://tfrs{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca", - "keycloak.post_logout_url": "https://tfrs{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca", - "keycloak.siteminder_logout_url": "{{ .Values.configmap.keycloak.siteminderLogoutUrl }}", - "debug.enabled": {{ .Values.configmap.debugEnabled }}, - "secure_document_upload.enabled": true, - "secure_document_upload.max_file_size": 50000000, - "fuel_codes.enabled": true, - "keycloak.custom_login": true, - "credit_transfer.enabled": true, - "compliance_reporting.enabled": true, - "compliance_reporting.starting_year": 2017, - "compliance_reporting.create_effective_date": "2019-01-01", - "credit_calculation_api.enabled": true, - "exclusion_reports.enabled": true, - "exclusion_reports.create_effective_date": "2019-01-01", - "api_base": "https://tfrs-backend{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca/api" - }; \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-frontend/templates/deployment-config.yaml deleted file mode 100644 index d099bf859..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/deployment-config.yaml +++ /dev/null @@ -1,95 +0,0 @@ - -apiVersion: apps.openshift.io/v1 -kind: DeploymentConfig -metadata: - name: tfrs-frontend{{ .Values.suffix }} - annotations: - description: Defines how to deploy the frontend application - creationTimestamp: null - labels: - {{- include "tfrs-frontend.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: 10 - selector: - {{- include "tfrs-frontend.selectorLabels" . | nindent 4 }} - strategy: - activeDeadlineSeconds: 600 - recreateParams: - timeoutSeconds: 300 - resources: {} - type: Recreate - template: - metadata: - creationTimestamp: null - labels: - {{- include "tfrs-frontend.labels" . | nindent 8 }} - spec: - volumes: - - name: tfrs-frontend{{ .Values.suffix }} - configMap: - name: tfrs-frontend{{ .Values.suffix }} - containers: - - name: frontend - env: null - image: - imagePullPolicy: IfNotPresent - volumeMounts: - - name: tfrs-frontend{{ .Values.suffix }} - mountPath: /app/static/js/config - ports: - - containerPort: 8080 - protocol: TCP - env: - - name: RABBITMQ_VHOST - value: tfrs{{ .Values.suffix }}-vhost - - name: RABBITMQ_USER - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: username - - name: RABBITMQ_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: password - - name: RABBITMQ_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local - - name: RABBITMQ_PORT - value: '5672' - livenessProbe: - failureThreshold: 10 - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - tcpSocket: - port: 8080 - timeoutSeconds: 3 - readinessProbe: - failureThreshold: 10 - initialDelaySeconds: 20 - periodSeconds: 10 - successThreshold: 1 - tcpSocket: - port: 8080 - timeoutSeconds: 3 - resources: -{{ toYaml .Values.resources | indent 12 }} - terminationMessagePolicy: File - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: {} - terminationGracePeriodSeconds: 30 - test: false - triggers: - - imageChangeParams: - automatic: true - containerNames: - - frontend - from: - kind: ImageStreamTag - name: tfrs-frontend:{{ .Values.frontendImageTagName }} - lastTriggeredImage: - type: ImageChange - - type: ConfigChange diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/hpa.yaml b/charts/tfrs-apps/charts/tfrs-frontend/templates/hpa.yaml deleted file mode 100644 index 85d57587e..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: tfrs-frontend{{ .Values.suffix }} - labels: - {{- include "tfrs-frontend.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: DeploymentConfig - name: tfrs-frontend{{ .Values.suffix }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/route.yaml b/charts/tfrs-apps/charts/tfrs-frontend/templates/route.yaml deleted file mode 100644 index b2b24b776..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/route.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.route.createFrontendRoute }} -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - name: tfrs{{ .Values.suffix }} - annotations: - haproxy.router.openshift.io/timeout: 1200s - labels: - {{- include "tfrs-frontend.labels" . | nindent 4 }} -spec: - host: tfrs{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca - port: - targetPort: web - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge - to: - kind: Service - name: tfrs-frontend{{ .Values.suffix }} - weight: 100 - wildcardPolicy: None - {{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-frontend/templates/service.yaml b/charts/tfrs-apps/charts/tfrs-frontend/templates/service.yaml deleted file mode 100644 index 3cd86a0a9..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/templates/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: tfrs-frontend{{ .Values.suffix }} - labels: - {{- include "tfrs-frontend.labels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: 8080 - targetPort: 8080 - protocol: TCP - name: web - sessionAffinity: None - selector: - {{- include "tfrs-frontend.selectorLabels" . | nindent 4 }} diff --git a/charts/tfrs-apps/charts/tfrs-frontend/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-frontend/values-dev-jan.yaml deleted file mode 100644 index 882ab1112..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/values-dev-jan.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Default values for tfrs-frontend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -configmap: - keycloak: - clientId: tfrs-on-gold-4308 - siteminderLogoutUrl: https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi?retnow=1&returl= - debugEnabled: true - -resources: - limits: - cpu: 80m - memory: 120Mi - requests: - cpu: 40m - memory: 60Mi - -route: - createFrontendRoute: true - -autoscaling: - enabled: true - minReplicas: 1 - maxReplicas: 2 - targetCPUUtilizationPercentage: 80 diff --git a/charts/tfrs-apps/charts/tfrs-frontend/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-frontend/values-test-jan.yaml deleted file mode 100644 index 882ab1112..000000000 --- a/charts/tfrs-apps/charts/tfrs-frontend/values-test-jan.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Default values for tfrs-frontend. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -configmap: - keycloak: - clientId: tfrs-on-gold-4308 - siteminderLogoutUrl: https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi?retnow=1&returl= - debugEnabled: true - -resources: - limits: - cpu: 80m - memory: 120Mi - requests: - cpu: 40m - memory: 60Mi - -route: - createFrontendRoute: true - -autoscaling: - enabled: true - minReplicas: 1 - maxReplicas: 2 - targetCPUUtilizationPercentage: 80 diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/.helmignore b/charts/tfrs-apps/charts/tfrs-notification-server/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/Chart.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/Chart.yaml deleted file mode 100644 index a36160a8b..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: tfrs-notification-server -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "3.0.0" diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-notification-server/templates/_helpers.tpl deleted file mode 100644 index 49f5f2f47..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/templates/_helpers.tpl +++ /dev/null @@ -1,67 +0,0 @@ - -{{/* - -The labels for all components: - labels: - helm.sh/chart: tfrs-backend-1.0.0 - app.kubernetes.io/name: tfrs-backend - app.kubernetes.io/instance: tfrs-backend-dev or tfrs-backend-dev-jan - app.kubernetes.io/version: "3.0.0" - app.kubernetes.io/managed-by: Helm - -The selector lables: - selector: - app.kubernetes.io/name: tfrs-backend - app.kubernetes.io/instance: tfrs-backend-dev-1977 - -.Release.Name comes from command helm install - example: helm install tfrs-backend-dev ... or helm install tfrs-backend-dev-jan ... - -.Chart.Name come from the name attribute in Chart.yaml - -*/}} - -{{/* -Expand the name of the chart. If nameOverride is empty, use .Chart.Name. -Typically no need to assign value to nameOverride, -*/}} -{{- define "tfrs-notification-server.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -The .Release.Name is the first parameter of command helm install tfrs-notification-server-dev or tfrs-notification-server-dev-jan -*/}} -{{- define "tfrs-notification-server.fullname" -}} -{{- .Release.Name }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tfrs-notification-server.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels: -app.kubernetes.io/managed-by would be Helm -*/}} -{{- define "tfrs-notification-server.labels" -}} -helm.sh/chart: {{ include "tfrs-notification-server.chart" . }} -{{ include "tfrs-notification-server.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "tfrs-notification-server.selectorLabels" -}} -app.kubernetes.io/name: {{ include "tfrs-notification-server.name" . }} -app.kubernetes.io/instance: {{ include "tfrs-notification-server.fullname" . }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/templates/deployment-config.yaml deleted file mode 100644 index 036bd253f..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/templates/deployment-config.yaml +++ /dev/null @@ -1,93 +0,0 @@ -kind: DeploymentConfig -apiVersion: apps.openshift.io/v1 -metadata: - name: tfrs-notification-server{{ .Values.suffix }} - creationTimestamp: - labels: - {{- include "tfrs-notification-server.labels" . | nindent 4 }} -spec: - strategy: - type: Recreate - recreateParams: - timeoutSeconds: 600 - resources: {} - activeDeadlineSeconds: 21600 - triggers: - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - notification-server - from: - kind: ImageStreamTag - name: tfrs-notification-server:{{ .Values.notificationServerImageTagName }} - lastTriggeredImage: '' - - type: ConfigChange - replicas: 1 - test: false - selector: - {{- include "tfrs-notification-server.selectorLabels" . | nindent 4 }} - template: - metadata: - creationTimestamp: - labels: - {{- include "tfrs-notification-server.labels" . | nindent 8 }} - spec: - containers: - - name: notification-server - image: '' - ports: - - containerPort: 3000 - protocol: TCP - env: - - name: RABBITMQ_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local - - name: RABBITMQ_VHOST - value: {{ .Values.rabbitmqVHost }} - - name: RABBITMQ_USER - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: username - - name: RABBITMQ_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: password - - name: NPM_RUN - value: start:notifications - - name: KEYCLOAK_CERTS_URL - value: {{ .Values.keycloak.certsUrl }} - resources: -{{ toYaml .Values.resources | indent 12 }} - livenessProbe: - tcpSocket: - port: 3000 - initialDelaySeconds: 35 - timeoutSeconds: 3 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - tcpSocket: - port: 3000 - initialDelaySeconds: 30 - timeoutSeconds: 3 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - terminationMessagePath: "/dev/termination-log" - terminationMessagePolicy: File - imagePullPolicy: IfNotPresent - restartPolicy: Always - terminationGracePeriodSeconds: 30 - dnsPolicy: ClusterFirst - securityContext: {} - schedulerName: default-scheduler -status: - latestVersion: 0 - observedGeneration: 0 - replicas: 0 - updatedReplicas: 0 - availableReplicas: 0 - unavailableReplicas: 0 diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/templates/hpa.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/templates/hpa.yaml deleted file mode 100644 index 8f6195528..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "tfrs-notification-server.fullname" . }} - labels: - {{- include "tfrs-notification-server.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "tfrs-notification-server.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/templates/route.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/templates/route.yaml deleted file mode 100644 index 2e8d7395c..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/templates/route.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.route.createNotificationServerRoute }} -kind: Route -apiVersion: route.openshift.io/v1 -metadata: - name: tfrs-notification-server{{ .Values.suffix }} - creationTimestamp: - labels: - {{- include "tfrs-notification-server.labels" . | nindent 4 }} -spec: - host: tfrs{{ .Values.suffix }}.apps.silver.devops.gov.bc.ca - path: /socket.io - to: - kind: Service - name: tfrs-notification-server${SUFFIX} - weight: 100 - port: - targetPort: notification - tls: - termination: edge - wildcardPolicy: None -status: {} -{{- end }} \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/templates/service.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/templates/service.yaml deleted file mode 100644 index 58022384b..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/templates/service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: tfrs-notification-server{{ .Values.suffix }} - creationTimestamp: -spec: - ports: - - name: notification - protocol: TCP - port: 8080 - targetPort: 3000 - selector: - {{- include "tfrs-notification-server.selectorLabels" . | nindent 4 }} - type: ClusterIP - sessionAffinity: None -status: - loadBalancer: {} \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/values-dev-jan.yaml deleted file mode 100644 index d02f1aa48..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/values-dev-jan.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Default values for tfrs-notification-server. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -resources: - limits: - cpu: 200m - memory: 240Mi - requests: - cpu: 100m - memory: 120Mi - -route: - createNotificationServerRoute: true - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 2 - targetCPUUtilizationPercentage: 80 - -keycloak: - certsUrl: https://dev.loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/certs \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-notification-server/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-notification-server/values-test-jan.yaml deleted file mode 100644 index 8264d87e6..000000000 --- a/charts/tfrs-apps/charts/tfrs-notification-server/values-test-jan.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Default values for tfrs-notification-server. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -resources: - limits: - cpu: 200m - memory: 240Mi - requests: - cpu: 100m - memory: 120Mi - -route: - createNotificationServerRoute: true - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 2 - targetCPUUtilizationPercentage: 80 - -keycloak: - certsUrl: https://test.loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/certs \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/.helmignore b/charts/tfrs-apps/charts/tfrs-scan-coordinator/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/Chart.yaml b/charts/tfrs-apps/charts/tfrs-scan-coordinator/Chart.yaml deleted file mode 100644 index 6d3f252a7..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: tfrs-scan-coordinator -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/_helpers.tpl deleted file mode 100644 index 3a11fdba7..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -{{/* - -The labels for all components: - labels: - helm.sh/chart: tfrs-scan-coordinator-1.0.0 - app.kubernetes.io/name: tfrs-scan-coordinator - app.kubernetes.io/instance: tfrs-scan-coordinator-dev or tfrs-scan-coordinator-dev-jan - app.kubernetes.io/version: "3.0.0" - app.kubernetes.io/managed-by: Helm - -The selector lables: - selector: - app.kubernetes.io/name: tfrs-scan-coordinator - app.kubernetes.io/instance: tfrs-scan-coordinator-dev-1977 - -.Release.Name comes from command helm install - example: helm install tfrs-scan-coordinator-dev ... or helm install tfrs-scan-coordinator-dev-jan ... - -.Chart.Name come from the name attribute in Chart.yaml - -*/}} - -{{/* -Expand the name of the chart. If nameOverride is empty, use .Chart.Name. -Typically no need to assign value to nameOverride, -*/}} -{{- define "tfrs-scan-coordinator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -The .Release.Name is the first parameter of command helm install tfrs-scan-coordinator-dev or tfrs-scan-coordinator-dev-jan -*/}} -{{- define "tfrs-scan-coordinator.fullname" -}} -{{- .Release.Name }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tfrs-scan-coordinator.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels: -app.kubernetes.io/managed-by would be Helm -*/}} -{{- define "tfrs-scan-coordinator.labels" -}} -helm.sh/chart: {{ include "tfrs-scan-coordinator.chart" . }} -{{ include "tfrs-scan-coordinator.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "tfrs-scan-coordinator.selectorLabels" -}} -app.kubernetes.io/name: {{ include "tfrs-scan-coordinator.name" . }} -app.kubernetes.io/instance: {{ include "tfrs-scan-coordinator.fullname" . }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/deployment-config.yaml deleted file mode 100644 index 1b4181c2d..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/templates/deployment-config.yaml +++ /dev/null @@ -1,83 +0,0 @@ -kind: DeploymentConfig -apiVersion: apps.openshift.io/v1 -metadata: - name: tfrs-scan-coordinator{{ .Values.suffix }} - labels: - {{- include "tfrs-scan-coordinator.labels" . | nindent 4 }} -spec: - strategy: - type: Recreate - recreateParams: - timeoutSeconds: 300 - resources: {} - activeDeadlineSeconds: 600 - triggers: - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - scan-coordinator - from: - kind: ImageStreamTag - name: tfrs-scan-coordinator:{{ .Values.scanCoordinatorImageTagName }} - - type: ConfigChange - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: 10 - test: false - selector: - {{- include "tfrs-scan-coordinator.selectorLabels" . | nindent 4 }} - template: - metadata: - creationTimestamp: null - labels: - {{- include "tfrs-scan-coordinator.labels" . | nindent 8 }} - spec: - containers: - - name: scan-coordinator - env: - - name: BYPASS_CLAMAV - value: 'false' - - name: CLAMAV_HOST - value: tfrs-clamav.{{ .Values.namespace }}.svc.cluster.local - - name: CLAMAV_PORT - value: '3310' - - name: AMQP_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local - - name: AMQP_VHOST - value: {{ .Values.rabbitmqVHost }} - - name: AMQP_PORT - value: '5672' - - name: AMQP_USER - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: username - - name: MINIO_ENDPOINT - value: tfrs-minio-{{ .Values.envName }}.apps.silver.devops.gov.bc.ca - - name: MINIO_USE_SSL - value: 'true' - - name: AMQP_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: password - - name: MINIO_ACCESS_KEY - valueFrom: - secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_ACCESS_KEY - - name: MINIO_SECRET_KEY - valueFrom: - secretKeyRef: - name: tfrs-minio-{{ .Values.envName }} - key: MINIO_SECRET_KEY - resources: -{{ toYaml .Values.resources | indent 12 }} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - imagePullPolicy: Always - restartPolicy: Always - terminationGracePeriodSeconds: 30 - dnsPolicy: ClusterFirst - securityContext: {} - schedulerName: default-scheduler diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-dev-jan.yaml deleted file mode 100644 index df615bbe3..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-dev-jan.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Default values for tfrs-scan-coordinator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 -resources: - limits: - cpu: 100m - memory: 60Mi - requests: - cpu: 50m - memory: 30Mi \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-test-jan.yaml deleted file mode 100644 index df615bbe3..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-coordinator/values-test-jan.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Default values for tfrs-scan-coordinator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 -resources: - limits: - cpu: 100m - memory: 60Mi - requests: - cpu: 50m - memory: 30Mi \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/.helmignore b/charts/tfrs-apps/charts/tfrs-scan-handler/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/Chart.yaml b/charts/tfrs-apps/charts/tfrs-scan-handler/Chart.yaml deleted file mode 100644 index a7145fffe..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: tfrs-scan-handler -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "3.0.0" diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/templates/_helpers.tpl b/charts/tfrs-apps/charts/tfrs-scan-handler/templates/_helpers.tpl deleted file mode 100644 index 3106bcc86..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "tfrs-scan-handler.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "tfrs-scan-handler.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tfrs-scan-handler.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "tfrs-scan-handler.labels" -}} -helm.sh/chart: {{ include "tfrs-scan-handler.chart" . }} -{{ include "tfrs-scan-handler.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "tfrs-scan-handler.selectorLabels" -}} -app.kubernetes.io/name: {{ include "tfrs-scan-handler.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "tfrs-scan-handler.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "tfrs-scan-handler.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/templates/deployment-config.yaml b/charts/tfrs-apps/charts/tfrs-scan-handler/templates/deployment-config.yaml deleted file mode 100644 index 0d7481446..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/templates/deployment-config.yaml +++ /dev/null @@ -1,82 +0,0 @@ -kind: DeploymentConfig -apiVersion: apps.openshift.io/v1 -metadata: - name: tfrs-scan-handler{{ .Values.suffix }} - labels: - {{- include "tfrs-scan-handler.labels" . | nindent 4 }} -spec: - strategy: - type: Recreate - recreateParams: - timeoutSeconds: 600 - resources: {} - activeDeadlineSeconds: 21600 - triggers: - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - scan-handler - from: - kind: ImageStreamTag - name: tfrs-scan-handler:{{ .Values.scanHandlerImageTagName }} - - type: ConfigChange - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: 10 - test: false - selector: - {{- include "tfrs-scan-handler.selectorLabels" . | nindent 4 }} - template: - metadata: - creationTimestamp: null - labels: - {{- include "tfrs-scan-handler.selectorLabels" . | nindent 8 }} - spec: - containers: - - name: scan-handler - env: - - name: RABBITMQ_VHOST - value: {{ .Values.rabbitmqVHost }} - - name: RABBITMQ_USER - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: username - - name: RABBITMQ_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-rabbitmq-app - key: password - - name: RABBITMQ_HOST - value: tfrs-rabbitmq.{{ .Values.namespace }}.svc.cluster.local - - name: RABBITMQ_PORT - value: '5672' - - name: DATABASE_SERVICE_NAME - value: {{ .Values.databaseServiceHostName }} - - name: DATABASE_ENGINE - value: postgresql - - name: DATABASE_NAME - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-name - - name: DATABASE_USER - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-username - - name: DATABASE_PASSWORD - valueFrom: - secretKeyRef: - name: tfrs-patroni-app - key: app-db-password - resources: -{{ toYaml .Values.resources | indent 12 }} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - imagePullPolicy: Always - restartPolicy: Always - terminationGracePeriodSeconds: 30 - dnsPolicy: ClusterFirst - securityContext: {} - schedulerName: default-scheduler diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/values-dev-jan.yaml b/charts/tfrs-apps/charts/tfrs-scan-handler/values-dev-jan.yaml deleted file mode 100644 index e4228c386..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/values-dev-jan.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Default values for tfrs-scan-handler. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 -resources: - limits: - cpu: 50m - memory: 100Mi - requests: - cpu: 25m - memory: 50Mi \ No newline at end of file diff --git a/charts/tfrs-apps/charts/tfrs-scan-handler/values-test-jan.yaml b/charts/tfrs-apps/charts/tfrs-scan-handler/values-test-jan.yaml deleted file mode 100644 index e4228c386..000000000 --- a/charts/tfrs-apps/charts/tfrs-scan-handler/values-test-jan.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Default values for tfrs-scan-handler. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 -resources: - limits: - cpu: 50m - memory: 100Mi - requests: - cpu: 25m - memory: 50Mi \ No newline at end of file diff --git a/charts/tfrs-spilo/values-dev.yaml b/charts/tfrs-spilo/values-dev.yaml index be1c1bfbd..a51647b97 100644 --- a/charts/tfrs-spilo/values-dev.yaml +++ b/charts/tfrs-spilo/values-dev.yaml @@ -1,6 +1,6 @@ spilo: - replicaCount: 1 + replicaCount: 2 credentials: useExistingSecret: true diff --git a/frontend/__tests__/actions/CreditTransfersActions/getCreditTransferType.js b/frontend/__tests__/actions/CreditTransfersActions/getCreditTransferType.js index ad4f82b9c..2704b217d 100644 --- a/frontend/__tests__/actions/CreditTransfersActions/getCreditTransferType.js +++ b/frontend/__tests__/actions/CreditTransfersActions/getCreditTransferType.js @@ -1,38 +1,32 @@ -import { getCreditTransferType } from '../../../src/actions/creditTransfersActions' -import { CREDIT_TRANSFER_TYPES } from '../../../src/constants/values' +import { getCreditTransferType } from '../../../src/actions/creditTransfersActions'; +import { CREDIT_TRANSFER_TYPES } from '../../../src/constants/values'; test('getCreditTransferType should return a display value for Validation', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.validation.id) + const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.validation.id); - expect('Assessment').toEqual(data) -}) + expect('Validation').toEqual(data); +}); test('getCreditTransferType should return a display value for Reduction', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.retirement.id) + const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.retirement.id); - expect('Assessment').toEqual(data) -}) + expect('Reduction').toEqual(data); +}); test('getCreditTransferType should return a display value for Part 3 Award', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.part3Award.id) + const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.part3Award.id); - expect('Part 3 Award').toEqual(data) -}) - -test('getCreditTransferType should return a display value for Administrative Adjustment', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.adminAdjustment.id) - - expect('Administrative Adjustment').toEqual(data) -}) + expect('Part 3 Award').toEqual(data); +}); test('getCreditTransferType should return a display value for Sell', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.sell.id) + const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.sell.id); - expect('Transfer').toEqual(data) -}) + expect('Credit Transfer').toEqual(data); +}); test('getCreditTransferType should return a display value for Buy', () => { - const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.buy.id) + const data = getCreditTransferType(CREDIT_TRANSFER_TYPES.buy.id); - expect('Transfer').toEqual(data) -}) + expect('Credit Transfer').toEqual(data); +}); diff --git a/frontend/__tests__/actions/CreditTransfersActions/prepareCreditTransfer.js b/frontend/__tests__/actions/CreditTransfersActions/prepareCreditTransfer.js index a69107dc4..bc9772a08 100644 --- a/frontend/__tests__/actions/CreditTransfersActions/prepareCreditTransfer.js +++ b/frontend/__tests__/actions/CreditTransfersActions/prepareCreditTransfer.js @@ -1,5 +1,5 @@ -import { prepareCreditTransfer } from '../../../src/actions/creditTransfersActions' -import { CREDIT_TRANSFER_STATUS, CREDIT_TRANSFER_TYPES, DEFAULT_ORGANIZATION } from '../../../src/constants/values' +import { prepareCreditTransfer } from '../../../src/actions/creditTransfersActions'; +import { CREDIT_TRANSFER_STATUS, CREDIT_TRANSFER_TYPES, DEFAULT_ORGANIZATION } from '../../../src/constants/values'; test('prepareCreditTransfer should return the right data for Credit Transfers (Sell)', () => { const data = prepareCreditTransfer({ @@ -13,7 +13,7 @@ test('prepareCreditTransfer should return the right data for Credit Transfers (S tradeEffectiveDate: '2018-01-01', transferType: CREDIT_TRANSFER_TYPES.sell.id, zeroDollarReason: '' - }) + }); expect({ compliancePeriod: null, @@ -24,8 +24,8 @@ test('prepareCreditTransfer should return the right data for Credit Transfers (S tradeEffectiveDate: '2018-01-01', type: CREDIT_TRANSFER_TYPES.sell.id, zeroReason: '' - }).toEqual(data) -}) + }).toEqual(data); +}); test('prepareCreditTransfer should return the right data for Part 3 Award', () => { const data = prepareCreditTransfer({ @@ -39,7 +39,7 @@ test('prepareCreditTransfer should return the right data for Part 3 Award', () = tradeEffectiveDate: '2018-01-01', transferType: CREDIT_TRANSFER_TYPES.part3Award.id, zeroDollarReason: '' - }) + }); expect({ compliancePeriod: null, @@ -50,60 +50,8 @@ test('prepareCreditTransfer should return the right data for Part 3 Award', () = tradeEffectiveDate: '2018-01-01', type: CREDIT_TRANSFER_TYPES.part3Award.id, zeroReason: '' - }).toEqual(data) -}) - -test('prepareCreditTransfer should return the right data for a positive Administrative Adjustment', () => { - const data = prepareCreditTransfer({ - creditsFrom: { - id: 0 - }, - creditsTo: { - id: 5 - }, - numberOfCredits: 100, - tradeEffectiveDate: '2018-01-01', - transferType: CREDIT_TRANSFER_TYPES.adminAdjustment.id, - zeroDollarReason: '' - }) - - expect({ - compliancePeriod: null, - initiator: DEFAULT_ORGANIZATION.id, - numberOfCredits: 100, - respondent: 5, - status: CREDIT_TRANSFER_STATUS.recorded.id, - tradeEffectiveDate: '2018-01-01', - type: CREDIT_TRANSFER_TYPES.adminAdjustment.id, - zeroReason: '' - }).toEqual(data) -}) - -test('prepareCreditTransfer should return the right data for a negative Administrative Adjustment', () => { - const data = prepareCreditTransfer({ - creditsFrom: { - id: 0 - }, - creditsTo: { - id: 5 - }, - numberOfCredits: -100, - tradeEffectiveDate: '2018-01-01', - transferType: CREDIT_TRANSFER_TYPES.adminAdjustment.id, - zeroDollarReason: '' - }) - - expect({ - compliancePeriod: null, - initiator: DEFAULT_ORGANIZATION.id, - numberOfCredits: -100, - respondent: 5, - status: CREDIT_TRANSFER_STATUS.recorded.id, - tradeEffectiveDate: '2018-01-01', - type: CREDIT_TRANSFER_TYPES.adminAdjustment.id, - zeroReason: '' - }).toEqual(data) -}) + }).toEqual(data); +}); test('prepareCreditTransfer should return the right data for Validation', () => { const data = prepareCreditTransfer({ @@ -117,7 +65,7 @@ test('prepareCreditTransfer should return the right data for Validation', () => tradeEffectiveDate: '2018-01-01', transferType: CREDIT_TRANSFER_TYPES.validation.id, zeroDollarReason: '' - }) + }); expect({ compliancePeriod: null, @@ -128,8 +76,8 @@ test('prepareCreditTransfer should return the right data for Validation', () => tradeEffectiveDate: '2018-01-01', type: CREDIT_TRANSFER_TYPES.validation.id, zeroReason: '' - }).toEqual(data) -}) + }).toEqual(data); +}); test('prepareCreditTransfer should return the right data for Reduction', () => { const data = prepareCreditTransfer({ @@ -143,7 +91,7 @@ test('prepareCreditTransfer should return the right data for Reduction', () => { tradeEffectiveDate: '2018-01-01', transferType: CREDIT_TRANSFER_TYPES.retirement.id, zeroDollarReason: '' - }) + }); expect({ compliancePeriod: null, @@ -154,5 +102,5 @@ test('prepareCreditTransfer should return the right data for Reduction', () => { tradeEffectiveDate: '2018-01-01', type: CREDIT_TRANSFER_TYPES.retirement.id, zeroReason: '' - }).toEqual(data) -}) + }).toEqual(data); +}); diff --git a/frontend/package.json b/frontend/package.json index 767ff001e..f0c4b0fe2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "tfrs", - "version": "3.0.0", + "version": "2.13.0", "dependencies": { "@babel/eslint-parser": "^7.19.1", "@babel/plugin-proposal-object-rest-spread": "^7.20.7", diff --git a/frontend/src/actions/creditTransfersActions.js b/frontend/src/actions/creditTransfersActions.js index c218aeda1..f6d4d4266 100644 --- a/frontend/src/actions/creditTransfersActions.js +++ b/frontend/src/actions/creditTransfersActions.js @@ -4,7 +4,7 @@ import ActionTypes from '../constants/actionTypes/CreditTransfers' import ReducerTypes from '../constants/reducerTypes/CreditTransfers' import * as Routes from '../constants/routes' import { CREDIT_TRANSFER_STATUS, CREDIT_TRANSFER_TYPES, DEFAULT_ORGANIZATION } from '../constants/values' -import moment from 'moment-timezone' + /* * Credit Transfers */ @@ -18,19 +18,16 @@ export const getCreditTransfers = () => (dispatch) => { }) } -export const getCreditTransferType = (typeId, updateTimestamp=null) => { - const jan2024Timestamp = moment('2024-01-01'); +export const getCreditTransferType = (typeId) => { switch (typeId) { case CREDIT_TRANSFER_TYPES.validation.id: - return updateTimestamp && moment(updateTimestamp).isAfter(jan2024Timestamp) ? 'Assessment' : 'Validation'; + return 'Validation' case CREDIT_TRANSFER_TYPES.retirement.id: - return updateTimestamp && moment(updateTimestamp).isAfter(jan2024Timestamp) ? 'Assessment' : 'Reduction'; + return 'Reduction' case CREDIT_TRANSFER_TYPES.part3Award.id: - return 'Initiative Agreement' - case CREDIT_TRANSFER_TYPES.adminAdjustment.id: - return 'Administrative Adjustment' + return 'Part 3 Award' default: - return 'Transfer' + return 'Credit Transfer' } } @@ -64,11 +61,6 @@ export const prepareCreditTransfer = (fields) => { data.initiator = DEFAULT_ORGANIZATION.id data.respondent = fields.creditsFrom.id - break - case CREDIT_TRANSFER_TYPES.adminAdjustment.id.toString(): - data.initiator = DEFAULT_ORGANIZATION.id - data.respondent = fields.creditsTo.id - break default: data.initiator = (fields.creditsFrom.id > 0) diff --git a/frontend/src/actions/organizationActions.js b/frontend/src/actions/organizationActions.js index c6535172c..77c774c3a 100644 --- a/frontend/src/actions/organizationActions.js +++ b/frontend/src/actions/organizationActions.js @@ -54,35 +54,6 @@ const getMyOrganizationMembers = () => (dispatch) => { }) } -const getOrganizationBalance = id => (dispatch) => { - dispatch(getOrganizationBalanceRequest()) - - axios.get(`${Routes.BASE_URL}${Routes.ORGANIZATIONS_API}/${id}/balance`) - .then((response) => { - dispatch(getOrganizationBalanceSuccess(response.data)) - }).catch((error) => { - dispatch(getOrganizationBalanceError(error.response)) - }) -} - -const getOrganizationBalanceError = error => ({ - errorMessage: error, - name: ReducerTypes.ERROR_ORGANIZATION_BALANCE_REQUEST, - type: ActionTypes.ERROR -}) - -const getOrganizationBalanceSuccess = balance => ({ - details: balance, - name: ReducerTypes.RECEIVE_ORGANIZATION_BALANCE_REQUEST, - receivedAt: Date.now(), - type: ActionTypes.RECEIVE_ORGANIZATION_BALANCE -}) - -const getOrganizationBalanceRequest = () => ({ - name: ReducerTypes.GET_ORGANIZATION_BALANCE_REQUEST, - type: ActionTypes.GET_ORGANIZATION_BALANCE -}) - const getOrganization = id => (dispatch) => { dispatch(getOrganizationRequest()) @@ -229,5 +200,5 @@ const updateOrganizationSuccess = response => ({ export { getFuelSuppliers, getMyOrganization, getMyOrganizationMembers, getOrganization, getOrganizationMembers, getOrganizations, - addOrganization, updateOrganization, getOrganizationBalance + addOrganization, updateOrganization } diff --git a/frontend/src/admin/historical_data_entry/components/HistoricalConfirmationTable.js b/frontend/src/admin/historical_data_entry/components/HistoricalConfirmationTable.js deleted file mode 100644 index f9574017c..000000000 --- a/frontend/src/admin/historical_data_entry/components/HistoricalConfirmationTable.js +++ /dev/null @@ -1,131 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { connect } from 'react-redux' -import PropTypes from 'prop-types' -import { bindActionCreators } from 'redux' -import ReactDataSheet from 'react-datasheet' -import Loading from '../../../app/components/Loading' - -import { getOrganizationBalance } from '../../../actions/organizationActions' - -const HistoricalConfirmationTable = props => { - const { item, organizationBalance, getOrganizationBalance } = props - const [availableBalance, setAvailableBalance] = useState(0) - - useEffect(() => { - // Check if organization balance is fetching - if (!organizationBalance.isFetching) { - getOrganizationBalance(item.creditsTo.id) - } - }, [item.creditsTo.id]) - - // Check if organization balance is still fetching, if so, display a loading indicator - if (organizationBalance.isFetching) { - return - } - if (organizationBalance.details && - organizationBalance.details.availableBalance !== availableBalance && - item.creditsTo.id === organizationBalance.details.organization) { - setAvailableBalance(organizationBalance.details.availableBalance) - } - - function decimalViewer (digits = 2) { - return cell => Number(cell.value).toFixed(digits) - .toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,') - } - - function buildGrid (item) { - const credits = item.numberOfCredits - const offset = availableBalance + credits - - const nonCompliancePenalty = (credits < 0 && offset < 0) ? offset * -600 : 0 - const balanceChange = (offset < 0) ? (availableBalance * -1) : credits - const balanceAfterTransaction = availableBalance + balanceChange - - const grid = [ - [{ - className: 'text', - readOnly: true, - value: 'Transaction' - }, { - className: 'number', - readOnly: true, - valueViewer: decimalViewer(0), - value: credits // credits - }], [{ - className: 'text', - readOnly: true, - value: 'Current compliance unit balance' - }, { - className: 'number', - readOnly: true, - valueViewer: decimalViewer(0), - value: availableBalance // balance - }], [{ - className: 'text', - readOnly: true, - value: 'Compliance unit balance change from this transaction' - }, { - className: 'number', - readOnly: true, - valueViewer: decimalViewer(0), - value: balanceChange // balance change from this transaction - }], [{ - className: 'text', - readOnly: true, - value: 'Compliance unit balance after this transaction is committed' - }, { - className: 'number', - readOnly: true, - valueViewer: decimalViewer(0), - value: balanceAfterTransaction // balance after transaction - }], [{ - className: 'text', - readOnly: true, - value: `Non-compliance penalty payable, if applicable (${offset * -1} * $600 CAD per unit)` - }, { - className: 'number', - readOnly: true, - valueViewer: decimalViewer(0), - value: nonCompliancePenalty // balance after transaction - }] - ] - if (nonCompliancePenalty <= 0) { - grid[4][0].className = 'hidden' - grid[4][1].className = 'hidden' - } - return grid - } - - return ( - <> -

{item.creditsTo.name} compliance unit balance will change as follows:

- cell.value} - /> - - ) -} - -HistoricalConfirmationTable.propTypes = { - item: PropTypes.object.isRequired, - getOrganizationBalance: PropTypes.func.isRequired, - organizationBalance: PropTypes.shape({ - details: PropTypes.object, - isFetching: PropTypes.bool - }).isRequired -} - -const mapStateToProps = state => ({ - organizationBalance: { - details: state.rootReducer.organizationBalanceRequest.details, - isFetching: state.rootReducer.organizationBalanceRequest.isFetching - } -}) - -const mapDispatchToProps = dispatch => ({ - getOrganizationBalance: bindActionCreators(getOrganizationBalance, dispatch) -}) - -export default connect(mapStateToProps, mapDispatchToProps)(HistoricalConfirmationTable) diff --git a/frontend/src/admin/historical_data_entry/components/HistoricalDataEntryFormDetails.js b/frontend/src/admin/historical_data_entry/components/HistoricalDataEntryFormDetails.js index 657096cd8..1394ac778 100644 --- a/frontend/src/admin/historical_data_entry/components/HistoricalDataEntryFormDetails.js +++ b/frontend/src/admin/historical_data_entry/components/HistoricalDataEntryFormDetails.js @@ -39,19 +39,17 @@ const HistoricalDataEntryFormDetails = props => (
-
@@ -147,7 +144,6 @@ const HistoricalDataEntryFormDetails = props => (