@defra-fish/dynamics-lib 1.67.0 → 1.68.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra-fish/dynamics-lib",
3
- "version": "1.67.0",
3
+ "version": "1.68.0-rc.1",
4
4
  "description": "Framework to support integration with dynamics",
5
5
  "type": "module",
6
6
  "engines": {
@@ -43,5 +43,5 @@
43
43
  "simple-oauth2": "4.3.0",
44
44
  "uuid": "8.3.2"
45
45
  },
46
- "gitHead": "cf7cd653d7484f6b11de2f0ae80421b42dbc7b59"
46
+ "gitHead": "4f207098227f786b2e82105109bbd6125707a8fc"
47
47
  }
@@ -1,6 +1,6 @@
1
- import { contactForLicensee, contactForLicenseeNoReference } from '../contact.queries.js'
2
- import { dynamicsClient } from '../../client/dynamics-client.js'
1
+ import { contactAndPermissionForLicensee, contactForLicenseeNoReference } from '../contact.queries.js'
3
2
  import { Contact } from '../../entities/contact.entity.js'
3
+ import { Permission } from '../../entities/permission.entity.js'
4
4
  import { PredefinedQuery } from '../predefined-query.js'
5
5
 
6
6
  jest.mock('dynamics-web-api', () => {
@@ -12,94 +12,6 @@ jest.mock('dynamics-web-api', () => {
12
12
  })
13
13
 
14
14
  describe('Contact Queries', () => {
15
- describe('contactForLicensee', () => {
16
- const mockResponse = {
17
- ContactId: 'f1bb733e-3b1e-ea11-a810-000d3a25c5d6',
18
- FirstName: 'Fester',
19
- LastName: 'Tester',
20
- DateOfBirth: '9/13/1946 12:00:00 AM',
21
- Premises: '47',
22
- Street: null,
23
- Town: 'Testerton',
24
- Locality: null,
25
- Postcode: 'AB12 3CD',
26
- ReturnStatus: 'success',
27
- SuccessMessage: 'contact found successfully',
28
- ErrorMessage: null,
29
- ReturnPermissionNumber: '11100420-2WT1SFT-KPMW2C',
30
- oDataContext: 'https://api.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.defra_GetContactByLicenceAndPostcodeResponse'
31
- }
32
-
33
- const noContactResponse = {
34
- ContactId: null,
35
- FirstName: null,
36
- LastName: null,
37
- DateOfBirth: null,
38
- Premises: null,
39
- Street: null,
40
- Town: null,
41
- Locality: null,
42
- Postcode: null,
43
- ReturnStatus: 'error',
44
- SuccessMessage: '',
45
- ErrorMessage: 'contact does not exists',
46
- ReturnPermissionNumber: null,
47
- oDataContext:
48
- 'https://api.crm4.dynamics.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.defra_GetContactByLicenceAndPostcodeResponse'
49
- }
50
-
51
- it('should call dynamicsClient with correct parameters', async () => {
52
- dynamicsClient.executeUnboundAction.mockResolvedValue(mockResponse)
53
-
54
- const permissionNumber = 'KPMW2C'
55
- const postcode = 'AB12 3CD'
56
-
57
- await contactForLicensee(permissionNumber, postcode)
58
-
59
- expect(dynamicsClient.executeUnboundAction).toHaveBeenCalledWith('defra_GetContactByLicenceAndPostcode', {
60
- PermissionNumber: permissionNumber,
61
- InputPostCode: postcode
62
- })
63
- })
64
-
65
- it('should return the CRM response correctly', async () => {
66
- dynamicsClient.executeUnboundAction.mockResolvedValue(mockResponse)
67
-
68
- const result = await contactForLicensee('KPMW2C', 'AB12 3CD')
69
-
70
- expect(result).toEqual(mockResponse)
71
- })
72
-
73
- it('should handle error in dynamicsClient response', async () => {
74
- const error = new Error('Failed to fetch data')
75
- dynamicsClient.executeUnboundAction.mockRejectedValue(error)
76
-
77
- await expect(contactForLicensee('KPMW2C', 'AB12 3CD')).rejects.toThrow('Failed to fetch data')
78
- })
79
-
80
- it('should handle the case where contact does not exist', async () => {
81
- dynamicsClient.executeUnboundAction.mockResolvedValue(noContactResponse)
82
-
83
- const result = await contactForLicensee('654321', 'ZZ1 1ZZ')
84
-
85
- expect(result).toMatchObject({
86
- ContactId: null,
87
- FirstName: null,
88
- LastName: null,
89
- DateOfBirth: null,
90
- Premises: null,
91
- Street: null,
92
- Town: null,
93
- Locality: null,
94
- Postcode: null,
95
- ReturnStatus: 'error',
96
- SuccessMessage: '',
97
- ErrorMessage: 'contact does not exists',
98
- ReturnPermissionNumber: null
99
- })
100
- })
101
- })
102
-
103
15
  describe('contactForLicenseeNoReference', () => {
104
16
  beforeEach(() => {
105
17
  jest.resetAllMocks()
@@ -145,4 +57,96 @@ describe('Contact Queries', () => {
145
57
  })
146
58
  })
147
59
  })
60
+
61
+ describe('contactAndPermissionForLicensee', () => {
62
+ beforeEach(() => {
63
+ jest.resetAllMocks()
64
+
65
+ jest.spyOn(Contact.definition, 'mappings', 'get').mockReturnValue({
66
+ id: { field: 'mock_contactid' },
67
+ postcode: { field: 'mock_postcode' }
68
+ })
69
+
70
+ jest.spyOn(Permission.definition, 'mappings', 'get').mockReturnValue({
71
+ referenceNumber: { field: 'mock_reference' },
72
+ issueDate: { field: 'mock_issueDate' }
73
+ })
74
+
75
+ jest.spyOn(Permission.definition, 'defaultFilter', 'get').mockReturnValue('statecode eq 0')
76
+
77
+ jest.spyOn(Permission.definition, 'relationships', 'get').mockReturnValue({
78
+ licensee: { property: 'mock_licensee' }
79
+ })
80
+ })
81
+
82
+ it('should return a predefined query', () => {
83
+ const result = contactAndPermissionForLicensee('ABC123', 'AB12 3CD')
84
+ expect(result).toBeInstanceOf(PredefinedQuery)
85
+ })
86
+
87
+ it('root should return Permission', () => {
88
+ const result = contactAndPermissionForLicensee('ABC123', 'AB12 3CD')
89
+ expect(result._root).toEqual(Permission)
90
+ })
91
+
92
+ it('should build correct filter', () => {
93
+ const result = contactAndPermissionForLicensee('ABC123', 'AB12 3CD')
94
+
95
+ expect(result._retrieveRequest.filter).toEqual(
96
+ "endswith(mock_reference, 'ABC123') and statecode eq 0 and mock_licensee/mock_postcode eq 'AB12 3CD'"
97
+ )
98
+ })
99
+
100
+ it('should build correct orderBy', () => {
101
+ const result = contactAndPermissionForLicensee('ABC123', 'AB12 3CD')
102
+
103
+ expect(result._retrieveRequest.orderBy).toEqual(['mock_issueDate desc', 'mock_licensee/mock_contactid asc'])
104
+ })
105
+
106
+ it('should set expand correctly', () => {
107
+ const result = contactAndPermissionForLicensee('ABC123', 'AB12 3CD')
108
+
109
+ expect(result._retrieveRequest.expand).toEqual([
110
+ {
111
+ property: 'mock_licensee',
112
+ select: ['mock_contactid', 'mock_postcode']
113
+ }
114
+ ])
115
+ })
116
+
117
+ it.each([
118
+ ['XYZ999', 'EF45 6GH'],
119
+ ['123ABC', 'IJ78 9KL'],
120
+ ['AAAAAA', 'ZZ99 9ZZ']
121
+ ])(
122
+ 'should return correct retrieve request when the last 6 characters of the permission is %s and postcode is %s',
123
+ (permissionLast6, postcode) => {
124
+ const result = contactAndPermissionForLicensee(permissionLast6, postcode)
125
+
126
+ expect(result._retrieveRequest).toEqual({
127
+ collection: 'defra_permissions',
128
+ filter: `endswith(mock_reference, '${permissionLast6}') and statecode eq 0 and mock_licensee/mock_postcode eq '${postcode}'`,
129
+ orderBy: ['mock_issueDate desc', 'mock_licensee/mock_contactid asc'],
130
+ expand: [
131
+ {
132
+ property: 'mock_licensee',
133
+ select: ['mock_contactid', 'mock_postcode']
134
+ }
135
+ ],
136
+ select: [
137
+ 'defra_permissionid',
138
+ 'defra_name',
139
+ 'defra_issuedate',
140
+ 'defra_startdate',
141
+ 'defra_enddate',
142
+ 'defra_stagingid',
143
+ 'defra_datasource',
144
+ 'defra_renewal',
145
+ 'defra_rcpagreement',
146
+ 'defra_licenceforyou'
147
+ ]
148
+ })
149
+ }
150
+ )
151
+ })
148
152
  })
@@ -1,42 +1,8 @@
1
- import { dynamicsClient } from '../client/dynamics-client.js'
2
1
  import { Contact } from '../entities/contact.entity.js'
2
+ import { Permission } from '../entities/permission.entity.js'
3
3
  import { escapeODataStringValue } from '../client/util.js'
4
4
  import { PredefinedQuery } from './predefined-query.js'
5
5
 
6
- /**
7
- * @typedef {Object} ContactByLicenceAndPostcode
8
- * @property {string|null} ContactId - The contact's unique identifier
9
- * @property {string|null} FirstName - The contact's first name
10
- * @property {string|null} LastName - The contact's last name
11
- * @property {string|null} DateOfBirth - The contact's date of birth
12
- * @property {string|null} Street - The contact's street
13
- * @property {string|null} Town - The contact's town
14
- * @property {string|null} Locality - The contact's locality
15
- * @property {string|null} Postcode - The contact's postcode
16
- * @property {string} ReturnStatus - The status of the request (e.g., "success" or "error")
17
- * @property {string|null} SuccessMessage - A success message if the contact is found
18
- * @property {string|null} ErrorMessage - An error message if the contact is not found
19
- * @property {string|null} ReturnPermissionNumber - The full permission number of the contact
20
- * @property {string} oDataContext - The OData context URL
21
- */
22
-
23
- /**
24
- * Calls the defra_GetContactByLicenceAndPostcode CRM plugin to retrieve a contact by the last 6 characters if their license number and postcode
25
- *
26
- * @param permissionReferenceNumberLast6Characters the last 6 characters of the permission reference number
27
- * @param licenseePostcode the postcode of the contact associated with the permission
28
- * @returns {Promise<ContactByLicenceAndPostcode>}
29
- */
30
-
31
- export const contactForLicensee = (permissionReferenceNumberLast6Characters, licenseePostcode) => {
32
- const request = {
33
- PermissionNumber: permissionReferenceNumberLast6Characters,
34
- InputPostCode: licenseePostcode
35
- }
36
-
37
- return dynamicsClient.executeUnboundAction('defra_GetContactByLicenceAndPostcode', request)
38
- }
39
-
40
6
  export const contactForLicenseeNoReference = (licenseeBirthDate, licenseePostcode) => {
41
7
  const { postcode, birthDate } = Contact.definition.mappings
42
8
  const filter = `${postcode.field} eq '${escapeODataStringValue(licenseePostcode)}' and ${birthDate.field} eq ${licenseeBirthDate} and ${
@@ -48,3 +14,38 @@ export const contactForLicenseeNoReference = (licenseeBirthDate, licenseePostcod
48
14
  expand: []
49
15
  })
50
16
  }
17
+
18
+ /**
19
+ * Gets the query to get a contact by the last 6 characters if their license number and postcode
20
+ *
21
+ * @param permissionLast6Characters the last 6 characters of the permission reference number
22
+ * @param licenseePostcode the postcode of the contact associated with the permission
23
+ * @returns {Object} returns a query as an object to fetch the contact
24
+ */
25
+
26
+ export const contactAndPermissionForLicensee = (permissionLast6Characters, licenseePostcode) => {
27
+ const filter = `endswith(${Permission.definition.mappings.referenceNumber.field}, '${escapeODataStringValue(
28
+ permissionLast6Characters
29
+ )}') and ${Permission.definition.defaultFilter} and ${Permission.definition.relationships.licensee.property}/${
30
+ Contact.definition.mappings.postcode.field
31
+ } eq '${escapeODataStringValue(licenseePostcode)}'`
32
+ const orderBy = [
33
+ `${Permission.definition.mappings.issueDate.field} desc`,
34
+ `${Permission.definition.relationships.licensee.property}/${Contact.definition.mappings.id.field} asc`
35
+ ]
36
+
37
+ const query = new PredefinedQuery({
38
+ root: Permission,
39
+ filter,
40
+ orderBy
41
+ })
42
+
43
+ query._retrieveRequest.expand = [
44
+ {
45
+ property: Permission.definition.relationships.licensee.property,
46
+ select: [Contact.definition.mappings.id.field, Contact.definition.mappings.postcode.field]
47
+ }
48
+ ]
49
+
50
+ return query
51
+ }