usdigitalresponse / cpf-reporter

CPF Reporter application maintained by the USDR Grants program.
Apache License 2.0
0 stars 3 forks source link

Treasury Report - Add helper function to get valid uploads #298

Open as1729 opened 1 month ago

as1729 commented 1 month ago

Blocks

Blocked By

Current State

N/A

Expected State

A function that returns the valid set of upload files needed for treasury report generation. This function must get all the valid uploads for the user's organization's current-reporting-period and ensure that these are grouped by expenditure-category and agency. This means that there cannot be two uploads that have the same EC-Code and agencyId, we must only pick the most recently created one.

Definition of Done

  1. The function is added and accessible via import { getUploadsByExpenditureCategory } from 'src/services/uploads/uploads'
  2. The function has unit tests and type definitions that have appropriate scenarios that ensure the value returned by the function is accurate.

Implementation Details

  1. Add helper function to get S3 object keys for uploads in aws.ts

    export async function getS3UploadFileKey(organizationId, upload) {
    return `uploads/${organizationId}/${upload.agencyId}/${upload.reportingPeriodId}/${upload.id}/${upload.filename}`
    }
  2. The below implementation should be correct. However, it does not include typescript and unit tests. Please add those prior to submitting a pull request.

    
    src/services/uploads/uploads.ts

/ This function should return the most recent upload for each expenditure category and agency for the currentUser's organization. The uploads must be grouped by expenditure category and agency. If there are multiple uploads for the grouping, the most recent upload must be chosen. The S3 Object key must be set on each upload object. The return value structure should look like the following: { EC-Code: { AgencyId: { UploadObject } } } Example: { '1A': { '1': { id: 1, filename: 'file1.csv', objectKey: 'uploads/1/1/1/1/file1.csv', ... }, '2': { id: 2, filename: 'file2.csv', objectKey: 'uploads/1/2/1/2/file2.csv', ... }, ... }, '1B': { '1': { id: 3, filename: 'file3.csv', objectKey: 'uploads/1/1/1/3/file3.csv', ... }, ... }, ... } / export const getUploadsByExpenditureCategory = async () => { const organization = await db.organization.findFirst({ where: { id: context.currentUser.agency.organizationId }, })

const reportingPeriod = await db.reportingPeriod.findFirst({ where: { id: organization.preferences.current_reporting_period_id }, })

// valid upload validations const validUploadIds = await db.uploadValidation.findMany({ where: { passed: true, upload: { agency: { organizationId: organization.id } }, }, select: { uploadId: true, }, distinct: ['uploadId'], })

const uploadsForPeriod = await db.upload.findMany({ where: { reportingPeriodId: reportingPeriod.id, agency: { organizationId: organization.id }, id: { in: validUploadIds.map((v) => v.uploadId) }, }, include: { expenditureCategory: true }, })

const uploadsByExpenditureCategory = {}

// Get the most recent upload for each expenditure category and agency and set the S3 Object key for (const upload of uploadsForPeriod) { // Set the S3 Object key const objectKey = await getS3UploadFileKey(organization.id, upload) upload.objectKey = objectKey

// Filter the uploads by expenditure category of the current upload.
const uploadsByAgency =
  uploadsByExpenditureCategory[upload.expenditureCategory.code]

if (!uploadsByAgency) {
  // The EC code was never added. This is the time to initialize it.
  uploadsByExpenditureCategory[upload.expenditureCategory.code] = {}

  // Set the upload for this agency
  uploadsByExpenditureCategory[upload.expenditureCategory.code][
    upload.agencyId
  ] = upload
} else {
  if (!uploadsByAgency[upload.agencyId]) {
    // The agency was never added. This is the time to initialize it.
    uploadsByExpenditureCategory[upload.expenditureCategory.code][
      upload.agencyId
    ] = upload
  } else {
    // If the current upload is newer than the one stored, replace it
    if (upload.createdAt > uploadsByAgency[upload.agencyId].createdAt) {
      uploadsByExpenditureCategory[upload.expenditureCategory.code][
        upload.agencyId
      ] = upload
    }
  }
}

}

return uploadsByExpenditureCategory }

ClaireValdivia commented 5 days ago

Based on this PR being closed, I believe this issue is addressed. https://github.com/usdigitalresponse/cpf-reporter/pull/340 @tzinckgraf is that correct?

cc @as1729