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

replaced Minio with Document Record Service #760

Open
wants to merge 4 commits into
base: feature-drs-integration
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
24 changes: 19 additions & 5 deletions src/components/ContinuationIn/AuthorizationInformation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,28 @@ export default class AuthorizationInformation extends Mixins(DateMixin, Document
if (!documentKey || !documentName) return // safety check

this.isDownloading = true
await this.downloadDocument(documentKey, documentName).catch(error => {
const documentClass = 'CORP'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create an enum for document classes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about an enum for the document type as well? (I'd be OK with both enums in the same file, fwiw.)

try {
const docUrl: string = await this.getDownloadLink(documentKey, documentName, documentClass)
const link = document.createElement('a')
link.href = docUrl
link.download = documentName
link.target = '_blank' // This opens the link in a new browser tab

// Append to the document and trigger the download
document.body.appendChild(link)
link.click()

// Remove the link after the download is triggered
document.body.removeChild(link)
this.isDownloading = false
} catch (error) {
flutistar marked this conversation as resolved.
Show resolved Hide resolved
// eslint-disable-next-line no-console
console.log('fetchDocument() error =', error)
console.log('downloadDocument() error =', error)
this.errorDialogTitle = 'Unable to download document'
this.errorDialogText = 'We were unable to download your document. If this error persists, please contact us.'
this.errorDialogText = 'An error occurred while downloading the document. Please try again.'
this.errorDialog = true
})
this.isDownloading = false
}
}

@Watch('isValid', { immediate: true })
Expand Down
55 changes: 33 additions & 22 deletions src/components/ContinuationIn/AuthorizationProof.vue
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ import { Action, Getter } from 'pinia-class'
import { StatusCodes } from 'http-status-codes'
import { useStore } from '@/store/store'
import { DocumentMixin } from '@/mixins'
import { AuthorizationProofIF, ExistingBusinessInfoIF, PresignedUrlIF } from '@/interfaces'
import { AuthorizationProofIF, ExistingBusinessInfoIF } from '@/interfaces'
import { FilingStatus } from '@/enums'
import FileUploadPreview from '@/components/common/FileUploadPreview.vue'
import AutoResize from 'vue-auto-resize'
Expand All @@ -183,14 +183,17 @@ export default class AuthorizationProof extends Mixins(DocumentMixin) {
$refs!: {
fileUploadPreview: FileUploadPreview
}

@Getter(useStore) getBusinessId!: string
@Getter(useStore) getTempId!: string
@Getter(useStore) getContinuationInAuthorizationProof!: AuthorizationProofIF
@Getter(useStore) getExistingBusinessInfo!: ExistingBusinessInfoIF
@Getter(useStore) getFilingStatus!: FilingStatus
@Getter(useStore) getKeycloakGuid!: string
@Getter(useStore) getShowErrors!: boolean
@Getter(useStore) getContinuationInConsumerDocumentId!: string

@Action(useStore) setContinuationAuthorization!: (x: AuthorizationProofIF) => void
@Action(useStore) setContinuationConsumerDocumentId!: (x: string) => void

// Local properties
authorization = null as AuthorizationProofIF
Expand Down Expand Up @@ -277,33 +280,40 @@ export default class AuthorizationProof extends Mixins(DocumentMixin) {
return // don't add to array
}

// try to upload to Minio
let psu: PresignedUrlIF
// try to upload to Document Record Service
try {
this.isDocumentLoading = true
psu = await this.getPresignedUrl(file.name)
const res = await this.uploadToUrl(psu.preSignedUrl, file, psu.key, this.getKeycloakGuid)
if (!res || res.status !== StatusCodes.OK) throw new Error()
const res = await this.uploadDocumentToDRS(
file,
this.DOCUMENT_TYPES.contInAuthorization.class,
this.DOCUMENT_TYPES.contInAuthorization.type,
this.getTempId,
this.getContinuationInConsumerDocumentId
severinbeauvais marked this conversation as resolved.
Show resolved Hide resolved
)

if (!res || ![StatusCodes.OK, StatusCodes.CREATED].includes(res.status)) throw new Error()

// add file to array
this.authorization.files.push({
file: {
name: file.name,
lastModified: file.lastModified,
size: file.size
} as File,
fileKey: res.data.documentServiceId,
fileName: file.name
})

this.setContinuationConsumerDocumentId(res.data.consumerDocumentId)

this.isFileAdded = true
} catch {
// set error message
this.customErrorMessage = this.UPLOAD_FAILED_MESSAGE
return // don't add to array
} finally {
this.isDocumentLoading = false
}

// add file to array
this.authorization.files.push({
file: {
name: file.name,
lastModified: file.lastModified,
size: file.size
} as File,
fileKey: psu.key,
fileName: file.name
})

this.isFileAdded = true
}
}

Expand All @@ -314,8 +324,9 @@ export default class AuthorizationProof extends Mixins(DocumentMixin) {
onRemoveClicked (index = NaN): void {
// safety check
if (index >= 0) {
// delete file from Minio, not waiting for response and ignoring errors
this.deleteDocument(this.authorization.files[index].fileKey).catch(() => null)
// delete file from DRS, not waiting for response and ignoring errors
this.deleteDocumentFromDRS(this.authorization.files[index].fileKey).catch((res) => console.error(res.data))

// remove file from array
this.authorization.files.splice(index, 1)
// clear any existing error message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ import { Action, Getter } from 'pinia-class'
import { StatusCodes } from 'http-status-codes'
import { useStore } from '@/store/store'
import { DateMixin, DocumentMixin } from '@/mixins'
import { ExistingBusinessInfoIF, PresignedUrlIF } from '@/interfaces'
import { ExistingBusinessInfoIF } from '@/interfaces'
import FileUploadPreview from '../common/FileUploadPreview.vue'

@Component({
Expand All @@ -115,9 +115,12 @@ export default class UnlimitedLiabilityCorporationInformation extends Mixins(Dat
@Getter(useStore) getExistingBusinessInfo!: ExistingBusinessInfoIF
@Getter(useStore) getKeycloakGuid!: string
@Getter(useStore) getShowErrors!: boolean
@Getter(useStore) getContinuationInConsumerDocumentId!: string
@Getter(useStore) getTempId!: string

@Action(useStore) setExistingBusinessInfo!: (x: ExistingBusinessInfoIF) => void
@Action(useStore) setHaveChanges!: (x: boolean) => void
@Action(useStore) setContinuationConsumerDocumentId!: (x: string) => void

// Local properties
customErrorMessage = ''
Expand Down Expand Up @@ -164,13 +167,28 @@ export default class UnlimitedLiabilityCorporationInformation extends Mixins(Dat
return // don't add to array
}

// try to upload to Minio
let psu: PresignedUrlIF
// try to upload to Document Record Service
try {
this.isDocumentLoading = true
psu = await this.getPresignedUrl(file.name)
const res = await this.uploadToUrl(psu.preSignedUrl, file, psu.key, this.getKeycloakGuid)
if (!res || res.status !== StatusCodes.OK) throw new Error()
const res = await this.uploadDocumentToDRS(
file,
this.DOCUMENT_TYPES.affidavitDocument.class,
this.DOCUMENT_TYPES.affidavitDocument.type,
this.getTempId,
this.getContinuationInConsumerDocumentId
)
if (!res || ![StatusCodes.OK, StatusCodes.CREATED].includes(res.status)) throw new Error()

// add properties reactively to business object
this.$set(this.getExistingBusinessInfo, 'affidavitFile', {
name: file.name,
lastModified: file.lastModified,
size: file.size
} as File)
this.$set(this.getExistingBusinessInfo, 'affidavitFileKey', res.data.documentServiceId)
this.$set(this.getExistingBusinessInfo, 'affidavitFileName', file.name)

this.setContinuationConsumerDocumentId(res.data.consumerDocumentId)
} catch {
// set error message
this.customErrorMessage = this.UPLOAD_FAILED_MESSAGE
Expand All @@ -179,15 +197,6 @@ export default class UnlimitedLiabilityCorporationInformation extends Mixins(Dat
this.isDocumentLoading = false
}

// add properties reactively to business object
this.$set(this.getExistingBusinessInfo, 'affidavitFile', {
name: file.name,
lastModified: file.lastModified,
size: file.size
} as File)
this.$set(this.getExistingBusinessInfo, 'affidavitFileKey', psu.key)
this.$set(this.getExistingBusinessInfo, 'affidavitFileName', file.name)

// user has changed something
this.setHaveChanges(true)
}
Expand All @@ -198,8 +207,8 @@ export default class UnlimitedLiabilityCorporationInformation extends Mixins(Dat
* May also be called by parent component to remove the file info.
*/
onRemoveClicked (): void {
// delete file from Minio, not waiting for response and ignoring errors
this.deleteDocument(this.getExistingBusinessInfo.affidavitFileKey).catch(() => null)
// delete file from DRS, not waiting for response and ignoring errors
this.deleteDocumentFromDRS(this.getExistingBusinessInfo.affidavitFileKey).catch((res) => console.error(res.data))

// delete properties reactively
this.$delete(this.getExistingBusinessInfo, 'affidavitFile')
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/filing-interfaces/filing-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export interface ContinuationInFilingIF {
incorporationDate: string // YYYY-MM-DD
taxId?: string // aka Business Number
affidavitFile?: File
affidavitFileKey?: string
affidavitFileKey?: string // documentServiceId
affidavitFileName?: string
}
authorization?: AuthorizationProofIF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface AuthorizationProofIF {
fileKey: string
fileName: string
}>
consumerDocumentId?: string
Copy link
Collaborator

@severinbeauvais severinbeauvais Jan 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this name consistent with documentServiceId (in filing-interfaces.ts and elsewhere)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have both documentServiceId and consumerDocumentId as well.
Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this documentServiceId + documentConsumerId.

Is the first one "service id" and second one "document id"? If yes then what you have makes sense.

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface ContinuationInStateIF {
continuationAuthorizationPageValid: boolean
authorizationProof: AuthorizationProofIF
existingBusinessInfo: ExistingBusinessInfoIF
consumerDocumentId: string
severinbeauvais marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { EntityStates } from '@bcrs-shared-components/enums'

export interface ExistingBusinessInfoIF {
affidavitFile?: File // only used by UI
affidavitFileKey?: string
affidavitFileKey?: string // documentServiceId
affidavitFileName?: string
bcRegistrationDate?: string // expro only (ISO date-time: '2007-04-25T22:42:42-00:00')
bcRegistrationNumber?: string // expro only (aka Identifier)
Expand Down
83 changes: 83 additions & 0 deletions src/mixins/document-mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ export default class DocumentMixin extends Vue {
validationErrorMsg: 'Document must be set to fit onto 8.5” x 11” letter-size paper.'
}
}
readonly DOCUMENT_TYPES = {
contInAuthorization: {
class: 'CORP',
type: 'CNTA'
severinbeauvais marked this conversation as resolved.
Show resolved Hide resolved
},
affidavitDocument: {
class: 'CORP',
type: 'DIRECTOR_AFFIDAVIT'
}
}

pdfjsLib: any

Expand Down Expand Up @@ -192,4 +202,77 @@ export default class DocumentMixin extends Vue {
if (sizeKB > 1) return `${sizeKB.toFixed(0)} KB`
return `${size} bytes`
}

/**
* Uploads the specified file to Document Record Service.
* @param file the file to upload
* @param documentClass the document class defined for the document service. e.g. 'CORP'
* @param documentType the type of document. e.g. 'CNTA'
* @param temPid the temp business identifier
* @param consumerDocumentId the identifier of one or more documents associated with the filing.
severinbeauvais marked this conversation as resolved.
Show resolved Hide resolved
* @returns a promise to return the axios response or the error response
*/
async uploadDocumentToDRS (
document: File,
documentClass: string,
documentType: string,
tempId: string,
consumerDocumentId: string = undefined
): Promise<AxiosResponse> {
const consumerFilingDate = new Date().toISOString()

// Set request params.
let url = `${sessionStorage.getItem('DRS_API_URL')}/documents/${documentClass}/${documentType}`
url += `?consumerFilingDate=${consumerFilingDate}&consumerFilename=${document.name}`
url += `&consumerIdentifier=${tempId}`
if (consumerDocumentId) {
url += `&consumerDocumentId=${consumerDocumentId}`
}

const headers = {
'x-apikey': sessionStorage.getItem('DRS_API_KEY'),
'Account-Id': sessionStorage.getItem('DRS_ACCOUNT_ID'),
'Content-Type': 'application/pdf'
}
return axios.post(url, document, { headers: headers })
.then(response => {
return response
}).catch(error => {
return error.response
})
}

/**
* Deletes a document from Document Record Service.
* @param documentServiceId the unique identifier of document on Document Record Service
* @returns a promise to return the axios response or the error response
*/
async deleteDocumentFromDRS (documentServiceId: string): Promise<AxiosResponse> {
// safety checks
if (!documentServiceId) {
throw new Error('Invalid parameters')
}

const url = `documents/drs/${documentServiceId}`

return axios.delete(url)
}

async getDownloadLink (
documentKey: string,
documentName: string,
documentClass: string
): Promise<string> {
// safety checks
if (!documentKey || !documentName) {
throw new Error('Invalid parameters')
}

const url = `documents/drs/${documentClass}/${documentKey}`

return axios.get(url).then(response => {
if (!response) throw new Error('Null response')
return response.data.documentURL
})
}
}
4 changes: 3 additions & 1 deletion src/mixins/filing-template-mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default class FilingTemplateMixin extends Mixins(AmalgamationMixin, DateM
@Getter(useStore) getCertifyState!: CertifyIF
@Getter(useStore) getCompletingParty!: CompletingPartyIF
@Getter(useStore) getContinuationInAuthorizationProof!: AuthorizationProofIF
@Getter(useStore) getContinuationInConsumerDocumentId!: string
@Getter(useStore) getCorrectNameOption!: CorrectNameOptions
@Getter(useStore) getCourtOrderStep!: CourtOrderStepIF
@Getter(useStore) getCreateMemorandumStep!: CreateMemorandumIF
Expand Down Expand Up @@ -413,7 +414,8 @@ export default class FilingTemplateMixin extends Mixins(AmalgamationMixin, DateM
// Add continuation in authorization proof.
if (this.getContinuationInAuthorizationProof) {
filing.continuationIn.authorization = {
files: this.getContinuationInAuthorizationProof.files
files: this.getContinuationInAuthorizationProof.files,
consumerDocumentId: this.getContinuationInConsumerDocumentId
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/store/state/state-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ export const stateModel: StateModelIF = {
continuationIn: {
continuationAuthorizationPageValid: false,
authorizationProof: null,
existingBusinessInfo: {} as ExistingBusinessInfoIF
existingBusinessInfo: {} as ExistingBusinessInfoIF,
consumerDocumentId: null
},
restoration: {
applicationDate: null,
Expand Down
9 changes: 9 additions & 0 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ export const useStore = defineStore('store', {
return this.getContinuationIn.existingBusinessInfo
},

/** The document ID used for Document Record Service. */
getContinuationInConsumerDocumentId (): string {
return this.getContinuationIn.consumerDocumentId
},

/** The account folio number. */
getFolioNumber (): string {
return this.stateModel.tombstone.folioNumber
Expand Down Expand Up @@ -1205,6 +1210,10 @@ export const useStore = defineStore('store', {
this.stateModel.continuationIn.existingBusinessInfo = val
if (!this.stateModel.ignoreChanges) this.stateModel.haveChanges = true
},
setContinuationConsumerDocumentId (val: string) {
this.stateModel.continuationIn.consumerDocumentId = val
if (!this.stateModel.ignoreChanges) this.stateModel.haveChanges = true
},
setIsFutureEffective (isFutureEffective: boolean) {
this.stateModel.effectiveDateTime.isFutureEffective = isFutureEffective
if (!this.stateModel.ignoreChanges) this.stateModel.haveChanges = true
Expand Down
Loading
Loading