Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 2266 - reassessments #2334

Merged
merged 1 commit into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions backend/api/serializers/model_year_report_supplemental.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ class Meta:

class ModelYearReportSupplementalCreditActivitySerializer(ModelSerializer):
model_year = ModelYearSerializer()
category = SerializerMethodField()

def get_category(self, obj):
context = getattr(self, "context", None)
if context is not None and context.get("category_transforms") is not None:
category_transforms = context.get("category_transforms")
category = obj.category
new_category = category_transforms.get(category)
if new_category is not None:
return new_category
return obj.category

class Meta:
model = SupplementalReportCreditActivity
Expand Down
57 changes: 57 additions & 0 deletions backend/api/services/supplemental_report.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from api.models.supplemental_report import SupplementalReport
from api.models.model_year_report_statuses import ModelYearReportStatuses
from api.models.model_year_report import ModelYearReport
from api.models.supplemental_report_credit_activity import (
SupplementalReportCreditActivity,
)


def get_map_of_model_year_report_ids_to_latest_supplemental_ids(
Expand Down Expand Up @@ -55,3 +59,56 @@ def get_latest_assessed_supplemental(model_year_report):
if report_in_question is not None:
result = SupplementalReport.objects.get(id=report_in_question.id)
return result


def get_previous_reassessment_credit_activity(model_year_report_id, category):
result = []
report = (
ModelYearReport.objects.filter(id=model_year_report_id)
.select_related("organization", "model_year")
.first()
)
if report is not None:
previous_model_year = int(report.model_year.name) - 1
previous_report = (
ModelYearReport.objects.filter(organization=report.organization)
.filter(model_year__name=previous_model_year)
.filter(
validation_status__in=[
ModelYearReportStatuses.ASSESSED,
ModelYearReportStatuses.REASSESSED,
]
)
.first()
)
if previous_report is not None:
supplemental_report = (
SupplementalReport.objects.filter(model_year_report=previous_report)
.filter(
status__in=[
ModelYearReportStatuses.ASSESSED,
ModelYearReportStatuses.REASSESSED,
]
)
.order_by("-create_timestamp")
.first()
)
if supplemental_report is not None:
result = list(
SupplementalReportCreditActivity.objects.filter(
supplemental_report=supplemental_report
)
.filter(category=category)
.select_related("model_year")
)
return result


def get_reassessment_credit_activity(supplemental_id, category):
return list(
SupplementalReportCreditActivity.objects.filter(
supplemental_report=supplemental_id
)
.filter(category=category)
.select_related("model_year")
)
32 changes: 31 additions & 1 deletion backend/api/viewsets/model_year_report_compliance_obligation.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,28 @@
from api.services.summary import parse_summary_serializer, \
get_current_year_balance
from api.models.organization_deficits import OrganizationDeficits
from api.services.supplemental_report import get_latest_assessed_supplemental
from api.services.supplemental_report import (
get_latest_assessed_supplemental,
get_previous_reassessment_credit_activity,
get_reassessment_credit_activity
)
from api.services.model_year_report_ldv_sales import get_most_recent_ldv_sales
from api.permissions.same_organization import SameOrganizationPermissions
from api.models.supplemental_report import SupplementalReport
from api.serializers.model_year_report_supplemental import ModelYearReportSupplementalCreditActivitySerializer


class ModelYearReportComplianceObligationViewset(viewsets.GenericViewSet):
permission_classes = [SameOrganizationPermissions & ModelYearReportPermissions]
same_org_permissions_context = {
"default_manager": ModelYearReport.objects,
"default_path_to_org": ("organization",),
"custom_pk_actions": {
"reassessment_credit_activity": {
"manager": SupplementalReport.objects,
"path_to_org": ("model_year_report", "organization")
}
}
}
http_method_names = ['get', 'post', 'patch']

Expand Down Expand Up @@ -528,3 +540,21 @@ def details(self, request, pk=None):
'compliance_offset': compliance_offset,
'ldv_sales': get_most_recent_ldv_sales(report) if most_recent_ldv_sales else report.ldv_sales
})

# pk should be MYR id
@action(detail=True, methods=['get'])
def previous_reassessment_credit_activity(self, request, pk=None):
credit_activity = get_previous_reassessment_credit_activity(pk, "ProvisionalBalanceAfterCreditReduction")
serializer = ModelYearReportSupplementalCreditActivitySerializer(
credit_activity,
many=True,
context={"category_transforms": {"ProvisionalBalanceAfterCreditReduction": "PreviousReassessmentEndingBalance"}}
)
return Response(serializer.data)

# pk should be a supplemental id
@action(detail=True, methods=['get'])
def reassessment_credit_activity(self, request, pk=None):
credit_activity = get_reassessment_credit_activity(pk, "PreviousReassessmentEndingBalance")
serializer = ModelYearReportSupplementalCreditActivitySerializer(credit_activity, many=True)
return Response(serializer.data)
4 changes: 3 additions & 1 deletion frontend/src/app/routes/Compliance.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ const COMPLIANCE = {
NOA_HISTORY: `${API_BASE_PATH}/reports/:id/noa_history`,
SUPPLEMENTAL_HISTORY: `${API_BASE_PATH}/reports/:id/supplemental_history`,
STATUSES_ALLOW_REASSESSMENT: `${API_BASE_PATH}/reports/:id/statuses_allow_reassessment`,
SUPPLEMENTAL_CREDIT_ACTIVITY: `${API_BASE_PATH}/reports/:supp_id/supplemental_credit_activity`
SUPPLEMENTAL_CREDIT_ACTIVITY: `${API_BASE_PATH}/reports/:supp_id/supplemental_credit_activity`,
PREVIOUS_REASSESSMENT_CREDIT_ACTIVITY: `${API_BASE_PATH}/compliance-activity-details/:id/previous_reassessment_credit_activity`,
REASSESSMENT_CREDIT_ACTIVITY: `${API_BASE_PATH}/compliance-activity-details/:supp_id/reassessment_credit_activity`
}

export default COMPLIANCE
18 changes: 17 additions & 1 deletion frontend/src/app/utilities/reconcileSupplementaries.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
const reconcileSupplementaries = (
assessmentData,
assessedSupplementaries,
complianceData
complianceData,
previousReassessmentCreditActivities
) => {
const result = {
reconciledAssessmentData: assessmentData,
Expand Down Expand Up @@ -151,6 +152,21 @@ const reconcileSupplementaries = (
}
}

if (complianceData?.complianceObligation && previousReassessmentCreditActivities) {
const creditActivites = complianceData.complianceObligation
for (const previousReassessmentCreditActivity of previousReassessmentCreditActivities) {
const category = previousReassessmentCreditActivity.category
const modelYear = previousReassessmentCreditActivity.modelYear.name
if (category === 'PreviousReassessmentEndingBalance') {
const creditActivityInQuestion = creditActivites.find((activity) => activity.category === 'creditBalanceStart' && activity.modelYear.name === modelYear)
if (creditActivityInQuestion) {
creditActivityInQuestion.creditAValue = previousReassessmentCreditActivity.creditAValue
creditActivityInQuestion.creditBValue = previousReassessmentCreditActivity.creditBValue
}
}
}
}

return result
}

Expand Down
70 changes: 48 additions & 22 deletions frontend/src/supplementary/SupplementaryContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const SupplementaryContainer = (props) => {
])
const location = useLocation()
const [reassessmentReductions, setReassessmentReductions] = useState({})
const [previousReassessmentCreditActivities, setPreviousReassessmentCreditActivities] = useState([])

const query = qs.parse(location.search, { ignoreQueryPrefix: true })

Expand Down Expand Up @@ -460,6 +461,17 @@ const SupplementaryContainer = (props) => {
}
creditActivity.push(creditActivityAddition)
}
if (!supplementaryId) {
for (const each of previousReassessmentCreditActivities) {
const category = each.category
if (category === 'PreviousReassessmentEndingBalance') {
const creditActivityAddition = { ... each }
creditActivityAddition.modelYear = each.modelYear.name
delete creditActivityAddition.id
creditActivity.push(creditActivityAddition)
}
}
}

setNewData({ ...newData, creditActivity })
if (status) {
Expand Down Expand Up @@ -575,36 +587,47 @@ const SupplementaryContainer = (props) => {

const refreshDetails = () => {
setLoading(true)
const promises = [
axios.get(
`${ROUTES_SUPPLEMENTARY.DETAILS.replace(':id', id)}?supplemental_id=${
supplementaryId || ''
}`
),
axios.get(
`${ROUTES_SUPPLEMENTARY.ASSESSED_SUPPLEMENTALS.replace(':id', id)}`
),
axios.get(
`${ROUTES_COMPLIANCE.REPORT_COMPLIANCE_DETAILS_BY_ID.replace(':id', id)}?most_recent_ldv_sales=true&use_from_gov_snapshot=True`
),
axios.get(ROUTES_COMPLIANCE.RATIOS),
axios.get(
`${ROUTES_SUPPLEMENTARY.ASSESSMENT.replace(
':id',
id
)}?supplemental_id=${supplementaryId || ''}`
)
]
if (supplementaryId) {
promises.push(
axios.get(ROUTES_COMPLIANCE.REASSESSMENT_CREDIT_ACTIVITY.replace(':supp_id', supplementaryId))
)
} else {
promises.push(
axios.get(ROUTES_COMPLIANCE.PREVIOUS_REASSESSMENT_CREDIT_ACTIVITY.replace(':id', id))
)
}

axios
.all([
axios.get(
`${ROUTES_SUPPLEMENTARY.DETAILS.replace(':id', id)}?supplemental_id=${
supplementaryId || ''
}`
),
axios.get(
`${ROUTES_SUPPLEMENTARY.ASSESSED_SUPPLEMENTALS.replace(':id', id)}`
),
axios.get(
`${ROUTES_COMPLIANCE.REPORT_COMPLIANCE_DETAILS_BY_ID.replace(':id', id)}?most_recent_ldv_sales=true&use_from_gov_snapshot=True`
),
axios.get(ROUTES_COMPLIANCE.RATIOS),
axios.get(
`${ROUTES_SUPPLEMENTARY.ASSESSMENT.replace(
':id',
id
)}?supplemental_id=${supplementaryId || ''}`
)
])
.all(promises)
.then(
axios.spread(
(
response,
assessedSupplementals,
complianceResponse,
ratioResponse,
assessmentResponse
assessmentResponse,
previousReassessmentCreditActivityResponse
) => {
if (response.data) {
let assessedSupplementalsData = assessedSupplementals.data
Expand Down Expand Up @@ -635,14 +658,16 @@ const SupplementaryContainer = (props) => {
}
}
}
const previousReassessmentCreditActivityResponseData = previousReassessmentCreditActivityResponse.data
const {
reconciledAssessmentData,
reconciledLdvSales,
reconciledComplianceObligation
} = reconcileSupplementaries(
response.data.assessmentData,
assessedSupplementalsData,
complianceResponse.data
complianceResponse.data,
previousReassessmentCreditActivityResponseData
)
if (reconciledAssessmentData) {
response.data.assessmentData = reconciledAssessmentData
Expand Down Expand Up @@ -803,6 +828,7 @@ const SupplementaryContainer = (props) => {

if (reconciledComplianceObligation) {
setObligationDetails(reconciledComplianceObligation)
setPreviousReassessmentCreditActivities(previousReassessmentCreditActivityResponseData)
}

if (reconciledLdvSales) {
Expand Down