diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index b0f2b126d..d6abc1145 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -24,6 +24,7 @@ jobs: with: name: ${{ steps.newereleasename.outputs.value }} tag_name: ${{ steps.newereleasename.outputs.value }} + target_commitish: master body: | ${{ github.event.pull_request.body }} token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/dev-release.yaml b/.github/workflows/dev-release.yaml index 2f8581401..274bfbcc1 100644 --- a/.github/workflows/dev-release.yaml +++ b/.github/workflows/dev-release.yaml @@ -1,11 +1,11 @@ ## 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 release-2.12.0 +name: TFRS Dev release-2.13.0 on: push: - branches: [ release-2.12.0 ] + branches: [ release-2.13.0 ] paths: - frontend/** - backend/** @@ -15,8 +15,8 @@ on: env: ## The pull request number of the Tracking pull request to merge the release branch to main ## Also remember to update the version in .pipeline/lib/config.js - PR_NUMBER: 2701 - RELEASE_NAME: release-2.12.0 + PR_NUMBER: 2723 + RELEASE_NAME: release-2.13.0 concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/tfrs-release.yaml b/.github/workflows/tfrs-release.yaml index d5d910994..604214a31 100644 --- a/.github/workflows/tfrs-release.yaml +++ b/.github/workflows/tfrs-release.yaml @@ -1,7 +1,7 @@ ## 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 release-2.12.0 +name: TFRS release-2.13.0 on: workflow_dispatch: @@ -10,8 +10,8 @@ on: env: ## The pull request number of the Tracking pull request to merge the release branch to main ## Also remember to update the version in .pipeline/lib/config.js - PR_NUMBER: 2701 - RELEASE_NAME: release-2.12.0 + PR_NUMBER: 2723 + RELEASE_NAME: release-2.13.0 concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.pipeline/lib/config.js b/.pipeline/lib/config.js index 21c4b42aa..821505397 100644 --- a/.pipeline/lib/config.js +++ b/.pipeline/lib/config.js @@ -1,7 +1,7 @@ 'use strict'; const options= require('@bcgov/pipeline-cli').Util.parseArguments() const changeId = options.pr //aka pull-request -const version = '2.12.0' +const version = '2.13.0' const name = 'tfrs' const ocpName = 'apps.silver.devops' @@ -13,7 +13,7 @@ options.git.repository='tfrs' const phases = { build: { namespace:'0ab226-tools' , name: `${name}`, phase: 'build' , changeId:changeId, suffix: `-build-${changeId}` , instance: `${name}-build-${changeId}` , version:`${version}-${changeId}`, tag:`build-${version}-${changeId}`, - releaseBranch: 'release-2.12.0' + releaseBranch: 'release-2.13.0' }, dev: {namespace:'0ab226-dev' , name: `${name}`, phase: 'dev' , changeId:changeId, suffix: `-dev` , instance: `${name}-dev` , version:`${version}`, tag:`dev-${version}`, dbServiceName: 'tfrs-spilo', diff --git a/backend/api/migrations/0011_credit_trade_category.py b/backend/api/migrations/0011_credit_trade_category.py new file mode 100644 index 000000000..49ee08af6 --- /dev/null +++ b/backend/api/migrations/0011_credit_trade_category.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.23 on 2023-11-06 23:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0010_migrate_compliance_report'), + ] + + operations = [ + migrations.RunSQL("UPDATE credit_trade SET trade_category_id = null FROM credit_trade_type WHERE credit_trade.trade_category_id IS NOT NULL AND credit_trade_type.id = credit_trade.trade_category_id AND credit_trade_type.the_type NOT IN ('Buy', 'Sell');") + ] \ No newline at end of file diff --git a/backend/api/migrations/0012_update_signing_authority_assertion_expirations.py b/backend/api/migrations/0012_update_signing_authority_assertion_expirations.py new file mode 100644 index 000000000..e63a1dc93 --- /dev/null +++ b/backend/api/migrations/0012_update_signing_authority_assertion_expirations.py @@ -0,0 +1,39 @@ +import logging +from django.db import migrations, transaction +from django.utils import timezone + +def update_expiration_dates(apps, schema_editor): + """ + Sets new expiration dates for specific SigningAuthorityAssertion records + If any record is not updated, all changes are reverted. + """ + signing_authority_assertion = apps.get_model('api', 'SigningAuthorityAssertion') + new_expiration_date = timezone.datetime.strptime('2023-11-06', "%Y-%m-%d").date() + + # IDs of the SigningAuthorityAssertion records to update + assertion_ids = [2, 3] + + with transaction.atomic(): + for assertion_id in assertion_ids: + try: + assertion = signing_authority_assertion.objects.get(id=assertion_id) + assertion.expiration_date = new_expiration_date + assertion.save() + except signing_authority_assertion.DoesNotExist: + logging.warning( + 'Failed to update SigningAuthorityAssertion: No entry found with id "%s"; ' + 'all changes within this transaction will be reverted.', + assertion_id + ) + +class Migration(migrations.Migration): + """ + Attaches the update function to the migration operations + """ + dependencies = [ + ('api', '0011_credit_trade_category'), + ] + + operations = [ + migrations.RunPython(update_expiration_dates), + ] diff --git a/backend/api/migrations/0013_create_missing_rescinded_history_records.py b/backend/api/migrations/0013_create_missing_rescinded_history_records.py new file mode 100644 index 000000000..37578efd0 --- /dev/null +++ b/backend/api/migrations/0013_create_missing_rescinded_history_records.py @@ -0,0 +1,59 @@ +from django.db import migrations +from django.core.exceptions import ValidationError + +def create_missing_credit_trade_history(apps, schema_editor): + CreditTrade = apps.get_model('api', 'CreditTrade') + CreditTradeHistory = apps.get_model('api', 'CreditTradeHistory') + User = apps.get_model('auth', 'User') + Role = apps.get_model('api', 'Role') + + for credit_trade in CreditTrade.objects.filter(is_rescinded=True): + if not CreditTradeHistory.objects.filter(credit_trade_id=credit_trade.id, is_rescinded=True).exists(): + user = credit_trade.create_user if credit_trade.create_user else User.objects.first() + + user_roles = Role.objects.filter(user_roles__user_id=user.id) + + role_id = None + if user_roles.filter(name="GovDirector").exists(): + role_id = user_roles.get(name="GovDirector").id + elif user_roles.filter(name="GovDeputyDirector").exists(): + role_id = user_roles.get(name="GovDeputyDirector").id + elif user_roles.exists(): + role_id = user_roles.first().id + + history = CreditTradeHistory( + credit_trade_id=credit_trade.id, + respondent_id=credit_trade.respondent.id, + status_id=credit_trade.status.id, + type_id=credit_trade.type.id, + number_of_credits=credit_trade.number_of_credits, + fair_market_value_per_credit=credit_trade.fair_market_value_per_credit, + zero_reason_id=credit_trade.zero_reason.id if credit_trade.zero_reason else None, + trade_effective_date=credit_trade.trade_effective_date, + compliance_period_id=credit_trade.compliance_period.id if credit_trade.compliance_period else None, + is_rescinded=True, + create_user=user, + user_role_id=role_id, + date_of_written_agreement=credit_trade.date_of_written_agreement, + category_d_selected=credit_trade.category_d_selected + ) + + try: + history.full_clean() + history.save() + except ValidationError as error: + # Handle validation error if necessary + raise ValidationError(error) + + # Update the create_timestamp field + history.create_timestamp = credit_trade.update_timestamp + history.save(update_fields=['create_timestamp']) + +class Migration(migrations.Migration): + dependencies = [ + ('api', '0012_update_signing_authority_assertion_expirations'), + ] + + operations = [ + migrations.RunPython(create_missing_credit_trade_history), + ] diff --git a/backend/api/services/CreditTradeService.py b/backend/api/services/CreditTradeService.py index 67b15d062..fd48cad19 100644 --- a/backend/api/services/CreditTradeService.py +++ b/backend/api/services/CreditTradeService.py @@ -172,16 +172,17 @@ def calculate_transfer_category(agreement_date, proposal_date, category_d_select @staticmethod - def approve(credit_trade, update_user=None): + def approve(credit_trade, update_user=None, batch_process=False): """ Transfers the credits between the organizations Sets the Credit Transfer to Approved """ status_approved = CreditTradeStatus.objects.get(status="Approved") - # Calculate and assign trade category - credit_trade.trade_category = CreditTradeService.calculate_transfer_category( - credit_trade.date_of_written_agreement, credit_trade.create_timestamp, credit_trade.category_d_selected) + # Calculate and assign trade category. Dont assign category if transfer are added through historical data entry or if credit trade type is NOT 1 (buy) or 2 (sell) + if not batch_process and credit_trade.type_id in (1, 2): + credit_trade.trade_category = CreditTradeService.calculate_transfer_category( + credit_trade.date_of_written_agreement, credit_trade.create_timestamp, credit_trade.category_d_selected) # Set the effective_date to today if credit_trade's trade_effective_date is null or in the past, # otherwise use trade_effective_date diff --git a/backend/api/viewsets/CreditTrade.py b/backend/api/viewsets/CreditTrade.py index 0e9e31585..5742826de 100644 --- a/backend/api/viewsets/CreditTrade.py +++ b/backend/api/viewsets/CreditTrade.py @@ -229,7 +229,7 @@ def batch_process(self, request): for credit_trade in credit_trades: credit_trade.update_user_id = request.user.id - CreditTradeService.approve(credit_trade) + CreditTradeService.approve(credit_trade,batch_process=True) CreditTradeService.dispatch_notifications( None, credit_trade) diff --git a/frontend/package.json b/frontend/package.json index 025d172f0..f0c4b0fe2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "tfrs", - "version": "2.12.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/credit_transfers/components/CreditTransferSigningHistory.js b/frontend/src/credit_transfers/components/CreditTransferSigningHistory.js index a3e35f111..31fe47282 100644 --- a/frontend/src/credit_transfers/components/CreditTransferSigningHistory.js +++ b/frontend/src/credit_transfers/components/CreditTransferSigningHistory.js @@ -163,7 +163,7 @@ class CreditTransferSigningHistory extends Component { const lastHistoryItem = history[history.length - 1] const createdByGov = history[0].creditTrade?.initiator?.id === 1 - if (history.length > 0 && loggedInUser.isGovernmentUser && !createdByGov) { + if (history.length > 0 && !createdByGov) { const agreementDate = dateOfWrittenAgreement || history[0].createTimestamp const { category, nextChangeInMonths } = CreditTransferSigningHistory .calculateTransferCategoryAndNextChange(agreementDate, history[0].createTimestamp, categoryDSelected) diff --git a/frontend/src/organizations/OrganizationRolesContainer.js b/frontend/src/organizations/OrganizationRolesContainer.js index 34021c5a6..308459cad 100644 --- a/frontend/src/organizations/OrganizationRolesContainer.js +++ b/frontend/src/organizations/OrganizationRolesContainer.js @@ -19,6 +19,10 @@ const OrganizationRolesContainer = props => { ,