Skip to content

Commit

Permalink
feat: Add cleanRelatedContacts service
Browse files Browse the repository at this point in the history
When you delete a contact, this service deletes any
relationships it may have had with other contacts.
  • Loading branch information
Merkur39 committed Nov 13, 2024
1 parent 362c60b commit e32419e
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
5 changes: 5 additions & 0 deletions manifest.webapp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
"file": "services/autoDefineLabels/contacts.js",
"trigger": "@event io.cozy.contacts:CREATED,UPDATED",
"debounce": "5s"
},
"cleanRelatedContacts": {
"type": "node",
"file": "services/cleanRelatedContacts/contacts.js",
"trigger": "@event io.cozy.contacts:DELETED"
}
}
}
25 changes: 25 additions & 0 deletions src/helpers/cleanRelatedContactsService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Q } from 'cozy-client'
import {
getHasManyItem,
removeHasManyItem
} from 'cozy-client/dist/associations/HasMany'

import { DOCTYPE_CONTACTS } from '../helpers/doctypes'

export const cleanRelatedContactsService = async (client, contactDeletedId) => {
const allContacts = await client.queryAll(Q(DOCTYPE_CONTACTS))

if (allContacts?.length > 0) {
const contactsWithRelatedRelDeleted = allContacts.filter(
contact =>
getHasManyItem(contact, 'related', contactDeletedId) !== undefined
)

if (contactsWithRelatedRelDeleted.length > 0) {
const allContactsUpdated = contactsWithRelatedRelDeleted.map(contact =>
removeHasManyItem(contact, 'related', contactDeletedId)
)
await client.saveAll(allContactsUpdated)
}
}
}
110 changes: 110 additions & 0 deletions src/helpers/cleanRelatedService.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { waitFor } from '@testing-library/react'

import {
getHasManyItem,
removeHasManyItem
} from 'cozy-client/dist/associations/HasMany'

import { cleanRelatedContactsService } from './cleanRelatedContactsService'

jest.mock('cozy-client', () => ({
Q: jest.fn()
}))

jest.mock('cozy-client/dist/associations/HasMany', () => ({
getHasManyItem: jest.fn(),
removeHasManyItem: jest.fn()
}))

const setup = ({
mockQueryAll = jest.fn(),
mockSaveAll = jest.fn(),
contacts = []
} = {}) => {
const mockClient = {
queryAll: mockQueryAll.mockResolvedValue(contacts),
saveAll: mockSaveAll
}

return mockClient
}

describe('cleanRelatedContactsService', () => {
it('should update contacts with related contact deleted', async () => {
const mockSaveAll = jest.fn()
const contacts = [
{
_id: 'contact0',
relationships: {
related: { data: [{ _id: 'contactDeletedId' }] }
}
},
{
_id: 'contact1',
relationships: {
related: { data: [] }
}
}
]
const client = setup({ mockSaveAll, contacts })

getHasManyItem.mockImplementation((contact, relation, id) => {
return contact.relationships[relation].data.find(item => item._id === id)
})

removeHasManyItem.mockImplementation((contact, relation, id) => {
return {
...contact,
relationships: {
[relation]: {
data: contact.relationships.related.data.filter(
item => item._id !== id
)
}
}
}
})

await cleanRelatedContactsService(client, 'contactDeletedId')

await waitFor(() => {
expect(mockSaveAll).toHaveBeenCalledWith([
{
_id: 'contact0',
relationships: {
related: { data: [] }
}
}
])
})
})

it('should not update contacts if no related contact deleted', async () => {
const mockSaveAll = jest.fn()
const contacts = [
{
_id: 'contact0',
relationships: {
related: { data: [{ _id: 'otherId' }] }
}
},
{
_id: 'contact1',
relationships: {
related: { data: [] }
}
}
]
const client = setup({ mockSaveAll, contacts })

getHasManyItem.mockImplementation((contact, relation, id) => {
return contact.relationships[relation].data.find(item => item._id === id)
})

await cleanRelatedContactsService(client, 'contactDeletedId')

await waitFor(() => {
expect(mockSaveAll).not.toHaveBeenCalled()
})
})
})
26 changes: 26 additions & 0 deletions src/targets/services/cleanRelatedContacts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import fetch from 'node-fetch'
import { cleanRelatedContactsService } from 'src/helpers/cleanRelatedContactsService'

import CozyClient from 'cozy-client'
import logger from 'cozy-logger'

import { schema } from '../../helpers/doctypes'

const log = logger.namespace('services/cleanRelatedContacts')

global.fetch = fetch

const cleanRelatedContacts = async () => {
log('info', 'Start cleanRelatedContacts service')
const client = CozyClient.fromEnv(process.env, { schema })
const contactDeleted = JSON.parse(process.env.COZY_COUCH_DOC)

await cleanRelatedContactsService(client, contactDeleted._id)

log('info', 'All contacts successfully updated')
}

cleanRelatedContacts().catch(e => {
log('error', e)
process.exit(1)
})

0 comments on commit e32419e

Please sign in to comment.