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

feature/cb2-12317: Refactor into services #187

Merged
merged 4 commits into from
Oct 7, 2024
Merged

Conversation

me-matt
Copy link
Contributor

@me-matt me-matt commented Sep 18, 2024

Refactor services

Refactor service methods into their own service classes to improve readability, extendability and code reuse.

Refactor services

Note: This is dependent on the repositories refactor PR #186.

Checklist

  • Branch is rebased against the latest develop/common
  • Necessary id required prepended with "test-" have been checked with automation testers and added
  • Code and UI has been tested manually after the additional changes
  • PR title includes the JIRA ticket number
  • Squashed commits contain the JIRA ticket number
  • Link to the PR added to the repo
  • Delete branch after merge

naathanbrown
naathanbrown previously approved these changes Sep 25, 2024
@me-matt me-matt changed the title feature/cb2-12317: Refactor services feature/cb2-12317: Refactor into services Sep 26, 2024
Comment on lines +31 to +53
private processGetCurrentProvisionalRecords = async <T extends TechRecordGet['techRecord_vehicleType']>(
searchResult: ISearchResult[]
): Promise<TechRecordType<T> | undefined> => {
if (searchResult) {
const processRecordsRes = this.groupRecordsByStatusCode(searchResult);
return processRecordsRes.currentCount !== 0
? this.techRecordRepository.callGetTechRecords(
processRecordsRes.currentRecords[0].systemNumber,
processRecordsRes.currentRecords[0].createdTimestamp
)
: processRecordsRes.provisionalCount === 1
? this.techRecordRepository.callGetTechRecords(
processRecordsRes.provisionalRecords[0].systemNumber,
processRecordsRes.provisionalRecords[0].createdTimestamp
)
: this.techRecordRepository.callGetTechRecords(
processRecordsRes.provisionalRecords[1].systemNumber,
processRecordsRes.provisionalRecords[1].createdTimestamp
);
} else {
await Promise.reject('Tech record Search returned nothing.');
}
};

Choose a reason for hiding this comment

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

Just checking, what happens here if searchResult is an empty array? Do we need to guard against that? If so, maybe the method would look like

 private async processGetCurrentProvisionalRecords<T extends TechRecordGet['techRecord_vehicleType']>(
    searchResult: ISearchResult[]
  ): Promise<TechRecordType<T> | undefined> {
    if (!searchResult || searchResult.length === 0) {
      throw new Error('Tech record Search returned nothing.');
    }

    const { currentRecords, provisionalRecords } = this.groupRecordsByStatusCode(searchResult);

    const recordToProcess = 
      currentRecords[0] || 
      provisionalRecords[0] || 
      provisionalRecords[1];

    if (!recordToProcess) {
      throw new Error('No suitable record found for processing.');
    }

    return this.techRecordRepository.callGetTechRecords(
      recordToProcess.systemNumber,
      recordToProcess.createdTimestamp
    );
  }
}

Either way, I'm happy. What are your thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If searchResult is empty, is should throw the 'Tech record Search returned nothing.' error. Though I'm not a fan of this, it's basically a lift and shift of the existing logic.

I haven't really tried to improve the code on a functional level because of the subsequent changes to testing that would make it harder to know if regressions have been introduced.

In my opinion, errors should be reserved for legitimate unexpected behaviours, whether this meets that criteria (amongst many other places) needs evaluating. Similarly the practice of returning empty collections when an outbound request is successful but returns a 404 should be introduced to make code paths easier to follow.

This is all for a later PR though ;)

* helper function is used to process records and count provisional and current records
* @param records
*/
private groupRecordsByStatusCode = (

Choose a reason for hiding this comment

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

Might be one for the future, but there is now a groupBy method from ES2023 onwards (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy).

We could have then had removed this method completely and utilised something like

const { current, provisional } = Object.groupBy(records, (record) => record.techRecord_statusCode)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Absolutely agree 👍

Also agree that I think functional changes should be in follow up PRs.

Comment on lines +124 to +127
public getAdrDetails = async (testResult: any) => {
const searchRes = await this.techRecordRepository.callSearchTechRecords(testResult.systemNumber);
return (await this.processGetCurrentProvisionalRecords(searchRes)) as TechRecordType<'hgv' | 'trl'>;
};

Choose a reason for hiding this comment

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

I'm not sure we need the type coercion here, processGetCurrentProvisionalRecords takes in a generic argument, therefore this can just be

	public getAdrDetails = async (testResult: any) => {
		const searchRes = await this.techRecordRepository.callSearchTechRecords(testResult.systemNumber);
		return await this.processGetCurrentProvisionalRecords<'hgv' | 'trl'>(searchRes);
	};

Where we pass in the vehicle type as T.

We can also remove the generic any argument where this is called and let it be inferred i.e.

const adrDetails = await this.techRecordService.getAdrDetails(testResult);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah good spot, happy for me to include this in a later PR? (for same reasons as above)

Choose a reason for hiding this comment

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

Functionally this PR looks good, so happy to defer potential clean ups / improvements for another time. Same goes for all of the comments I've made on this PR. 👍

* Calculates the retest date for an IVA or MSVA test
* @param testTypeStartTimestamp - the test start timestamp of the test
*/
public calculateVehicleApprovalRetestDate = (testTypeStartTimestamp: string): string => {
Copy link
Contributor

Choose a reason for hiding this comment

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

This method is no longer being used as FE now provide the date in the payload, so can be removed. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good spot, will remove 🙏

@me-matt me-matt requested a review from cb-cs October 7, 2024 08:03
@cb-cs
Copy link
Contributor

cb-cs commented Oct 7, 2024

I think this PR needs a quick rebase, but apart from that agree with the comments made regarding making any functional changes/improvements in subsequent PR's.

cb-cs
cb-cs previously approved these changes Oct 7, 2024
* @param vehicleType - the vehicle type from the test result
* @param flattenedDefects - the list of flattened defects
*/
public formatDefectWelsh(defect: any, vehicleType: any, flattenedDefects: IFlatDefect[]) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be inclined to say to merge the defect formatting into one function given that they're both functionally very similar to each other

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep agree with this, same as the previous comments. I'm trying to constraint these PRs to structural changes, functional changes will be easier to review in isolation in a follow up PR.

const flatDefects: IFlatDefect[] = [];
try {
// go through each defect in un-flattened array
defects.forEach((defect: IDefectParent) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think using a flat map might be more useful here instead of the nested for loops, so would have a flatmap to get the im number, im descirptin, and desc welsh, then another flatmap to go thorgugh the items and destructure the item number etc... then finally return the deficiciencies map and directly return an array, instead of having to make an array and push to it each time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above comment.

@me-matt me-matt merged commit 0788939 into develop Oct 7, 2024
7 checks passed
@me-matt me-matt deleted the feature/cb2-12317 branch October 7, 2024 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants