yakworks.rally.orgs.repo.ContactRepo.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rally-domain Show documentation
Show all versions of rally-domain Show documentation
gorm domain models for core app and testing
/*
* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package yakworks.rally.orgs.repo
import groovy.transform.CompileStatic
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.dao.DataRetrievalFailureException
import gorm.tools.databinding.BindAction
import gorm.tools.repository.GormRepository
import gorm.tools.repository.PersistArgs
import gorm.tools.repository.events.AfterBindEvent
import gorm.tools.repository.events.AfterPersistEvent
import gorm.tools.repository.events.BeforeRemoveEvent
import gorm.tools.repository.events.RepoListener
import gorm.tools.repository.model.LongIdGormRepo
import gorm.tools.utils.GormUtils
import grails.gorm.transactions.Transactional
import yakworks.api.problem.data.DataProblemCodes
import yakworks.commons.map.Maps
import yakworks.rally.activity.model.ActivityContact
import yakworks.rally.orgs.model.Contact
import yakworks.rally.orgs.model.ContactEmail
import yakworks.rally.orgs.model.ContactFlex
import yakworks.rally.orgs.model.ContactPhone
import yakworks.rally.orgs.model.ContactSource
import yakworks.rally.orgs.model.Location
import yakworks.rally.orgs.model.Org
import yakworks.rally.tag.model.TagLink
import yakworks.security.gorm.model.AppUser
@GormRepository
@CompileStatic
class ContactRepo extends LongIdGormRepo {
private static final String IS_PRIMARY = "isPrimary"
@Autowired LocationRepo locationRepo
@Autowired ContactSourceRepo contactSourceRepo
@RepoListener
void beforeValidate(Contact contact) {
setupNameProps(contact)
}
@RepoListener
void beforeRemove(Contact contact, BeforeRemoveEvent e) {
AppUser user = contact.user
String hasRefName
if (user) {
hasRefName = 'User'
}
if (Org.query(contact: contact).count()) {
hasRefName = 'Org primary contact'
}
if (ActivityContact.repo.count(contact)) {
hasRefName = 'ActivityContact'
}
if(hasRefName){
Map refArgs = [stamp: "Contact: ${contact.name}, id: ${contact.id}", other: hasRefName]
throw DataProblemCodes.ReferenceKey.withArgs(refArgs).toException()
}
TagLink.remove(contact)
// ContactSource.query(contact: contact).deleteAll() - deleted with cascade as per domain mapping.
Location.query(contact: contact).deleteAll()
ContactSource.query(contactId: contact.id).deleteAll()
//NOTE: This was here for CED but it was removed as logic is faulty to keep the location around for the contact if the contact is deleted.
// I think the idea was to keep its location info even if contact was removed since contacts could be some kind of job.
//Location.executeUpdate("update Location set contact = null where contact = :contact", [contact: contact]) //set contact to null
}
@Override
void doBeforePersistWithData(Contact contact, PersistArgs args) {
Map data = args.data
if (args.bindAction == BindAction.Create) {
setupSource(contact, data)
}
// we do primary location and contact here before persist so we persist org only once with contactId it is created
if(data.location) createOrUpdateLocation(contact, data.location as Map)
}
/**
* Create and setup source on contact
*/
void setupSource(Contact contact, Map data) {
if(!contact.id) contact.id = generateId()
//the ContactSource will be persisted in createSource
contact.source = ContactSource.repo.createSource(contact, data)
}
/**
* lookup by num or ContactSource
* This is called from findWithData and is used to locate contact for updates and associtaions
*/
@Override
Contact lookup(Map data) {
Contact contact
if (data == null) data = [:] //if null then make it empty map so it can cycle down and blow error
String sourceId = data.sourceId
//For convience, it allows specifying sourceId directly at top level along with other contact fields.
if(data.source == null && sourceId) data.source = [sourceId: sourceId]
if (data.source && data.source['sourceId']) {
Long cid = contactSourceRepo.findContactIdBySourceId(Maps.value(data, "source.sourceId") as String)
if(cid) return get(cid)
}
else if (data.num) {
String num = data.num
List contactForNum = Contact.findAllWhere(num: num)
if(contactForNum?.size() == 1) {
contact = contactForNum[0]
} else if (contactForNum.size() > 1){
throw new DataRetrievalFailureException("Multiple Contacts found for num: ${data.num}, lookup key must return a unique Contact")
}
}
return contact
}
@RepoListener
void afterBind(Contact contact, Map data, AfterBindEvent e) {
assignOrg(contact, data)
}
@RepoListener
void afterPersist(Contact contact, AfterPersistEvent e) {
if (contact.location?.hasChanged()) contact.location.persist()
syncChangesToUser(contact)
}
/**
* Called from doAfterPersist and before afterPersist event
* if its had a bind action (create or update) and it has data
* creates or updates One-to-Many associations for this entity.
*/
@Override
void doAfterPersistWithData(Contact contact, PersistArgs args) {
Map data = args.data
if(data.getBoolean(IS_PRIMARY)) {
Org org = Org.get(contact.orgId)
org.contact = contact
org.persist()
}
if(data.locations) super.persistToManyData(contact, Location.repo, data.locations as List