/*
jBilling - The Enterprise Open Source Billing System
Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde
This file is part of jbilling.
jbilling is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
jbilling is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with jbilling. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sapienter.jbilling.server.user;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.naming.NamingException;
import com.sapienter.jbilling.server.util.audit.EventLogger;
import org.apache.log4j.Logger;
import com.sapienter.jbilling.common.SessionInternalError;
import com.sapienter.jbilling.server.invoice.InvoiceBL;
import com.sapienter.jbilling.server.system.event.EventManager;
import com.sapienter.jbilling.server.user.contact.db.ContactDAS;
import com.sapienter.jbilling.server.user.contact.db.ContactDTO;
import com.sapienter.jbilling.server.user.contact.db.ContactFieldDAS;
import com.sapienter.jbilling.server.user.contact.db.ContactFieldDTO;
import com.sapienter.jbilling.server.user.contact.db.ContactFieldTypeDAS;
import com.sapienter.jbilling.server.user.contact.db.ContactFieldTypeDTO;
import com.sapienter.jbilling.server.user.contact.db.ContactMapDAS;
import com.sapienter.jbilling.server.user.contact.db.ContactMapDTO;
import com.sapienter.jbilling.server.user.contact.db.ContactTypeDAS;
import com.sapienter.jbilling.server.user.contact.db.ContactTypeDTO;
import com.sapienter.jbilling.server.user.event.NewContactEvent;
import com.sapienter.jbilling.server.util.Constants;
import com.sapienter.jbilling.server.util.Context;
import com.sapienter.jbilling.server.util.db.JbillingTableDAS;
import java.util.ArrayList;
public class ContactBL {
private static final Logger LOG = Logger.getLogger(ContactBL.class);
// contact types in synch with the table contact_type
static public final Integer ENTITY = new Integer(1);
// private methods
private ContactDAS contactDas = null;
private ContactFieldDAS contactFieldDas = null;
private ContactDTO contact = null;
private Integer entityId = null;
private JbillingTableDAS jbDAS = null;
private EventLogger eLogger = null;
public ContactBL(Integer contactId)
throws NamingException {
init();
contact = contactDas.find(contactId);
}
public ContactBL() {
init();
}
public void set(Integer userId) {
contact = contactDas.findPrimaryContact(userId);
//LOG.debug("Found " + contact + " for " + userId);
setEntityFromUser(userId);
}
private void setEntityFromUser(Integer userId) {
// id the entity
if (userId != null) {
try {
entityId = new UserBL().getEntityId(userId);
} catch (Exception e) {
LOG.error("Finding the entity", e);
}
}
}
public void set(Integer userId, Integer contactTypeId) {
contact = contactDas.findContact(userId, contactTypeId);
setEntityFromUser(userId);
}
public void setEntity(Integer entityId) {
this.entityId = entityId;
contact = contactDas.findEntityContact(entityId);
}
public boolean setInvoice(Integer invoiceId) {
boolean retValue = false;
contact = contactDas.findInvoiceContact(invoiceId);
InvoiceBL invoice = new InvoiceBL(invoiceId);
if (contact == null) {
set(invoice.getEntity().getBaseUser().getUserId());
} else {
entityId = invoice.getEntity().getBaseUser().getCompany().getId();
retValue = true;
}
return retValue;
}
public Integer getPrimaryType(Integer entityId) {
return new ContactTypeDAS().findPrimary(entityId).getId();
}
/**
* Rather confusing considering the previous method, but necessary
* to follow the convention
* @return
*/
public ContactDTO getEntity() {
return contact;
}
public ContactDTOEx getVoidDTO(Integer myEntityId) {
entityId = myEntityId;
ContactDTOEx retValue = new ContactDTOEx();
retValue.setFieldsTable(initializeFields());
return retValue;
}
public ContactDTOEx getDTO() {
ContactDTOEx retValue = new ContactDTOEx(
contact.getId(),
contact.getOrganizationName(),
contact.getAddress1(),
contact.getAddress2(),
contact.getCity(),
contact.getStateProvince(),
contact.getPostalCode(),
contact.getCountryCode(),
contact.getLastName(),
contact.getFirstName(),
contact.getInitial(),
contact.getTitle(),
contact.getPhoneCountryCode(),
contact.getPhoneAreaCode(),
contact.getPhoneNumber(),
contact.getFaxCountryCode(),
contact.getFaxAreaCode(),
contact.getFaxNumber(),
contact.getEmail(),
contact.getCreateDate(),
contact.getDeleted(),
contact.getInclude());
LOG.debug("ContactDTO: getting custom fields");
try {
retValue.setFieldsTable(initializeFields());
for (ContactFieldDTO field: contact.getFields()) {
// now find the field of this type
ContactFieldDTO dto = (ContactFieldDTO) retValue
.getFieldsTable().get(String.valueOf(field.getType().getId()));
if (field != null && dto != null) {
dto.setContent(field.getContent() == null ? "" : field.getContent());
dto.setId(field.getId());
}
}
} catch (Exception e) {
LOG.error("Error initializing fields", e);
}
LOG.debug("Returning dto with " + retValue.getFieldsTable().size() +
" fields");
return retValue;
}
public List<ContactDTOEx> getAll(Integer userId) {
List<ContactDTOEx> retValue = new ArrayList<ContactDTOEx>();
UserBL user = new UserBL(userId);
entityId = user.getEntityId(userId);
for (ContactTypeDTO type: user.getEntity().getEntity().getContactTypes()) {
contact = contactDas.findContact(userId, type.getId());
if (contact != null) {
ContactDTOEx dto = getDTO();
dto.setType(type.getId());
retValue.add(dto);
}
}
return retValue;
}
/**
* Create a Hashtable with the key beign the field type for the
* entity
* @return
*/
private Hashtable<String, ContactFieldDTO> initializeFields() {
// now go over the entity specific fields
Hashtable<String, ContactFieldDTO> fields = new Hashtable<String, ContactFieldDTO>();
EntityBL entity = new EntityBL(entityId);
for (ContactFieldTypeDTO field: entity.getEntity().getContactFieldTypes()) {
ContactFieldDTO fieldDto = new ContactFieldDTO();
fieldDto.setType(field);
fieldDto.setContent(new String()); // can't be null
// the key HAS to be a String if we want struts to be able to
// read the Hashtabe
fields.put(String.valueOf(field.getId()), fieldDto);
}
return fields;
}
private void init() {
contactDas = new ContactDAS();
contactFieldDas = new ContactFieldDAS();
jbDAS = (JbillingTableDAS) Context.getBean(Context.Name.JBILLING_TABLE_DAS);
eLogger = EventLogger.getInstance();
}
public Integer createPrimaryForUser(ContactDTOEx dto, Integer userId, Integer entityId)
throws SessionInternalError {
// find which type id is the primary for this entity
try {
Integer retValue;
ContactTypeDTO type = new ContactTypeDAS().findPrimary(entityId);
retValue = createForUser(dto, userId, type.getId());
// this is the primary contact, the only one with a user_id
// denormilized for performance
contact.setUserId(userId);
return retValue;
} catch (Exception e) {
throw new SessionInternalError(e);
}
}
/**
* Finds what is the next contact type and creates a new
* contact with it
* @param dto
*/
public boolean append(ContactDTOEx dto, Integer userId)
throws SessionInternalError {
UserBL user = new UserBL(userId);
for (ContactTypeDTO type: user.getEntity().getEntity().getContactTypes()) {
set(userId, type.getId());
if (contact == null) {
// this one is available
createForUser(dto, userId, type.getId());
return true;
}
}
return false; // no type was avaiable
}
public Integer createForUser(ContactDTOEx dto, Integer userId,
Integer typeId) throws SessionInternalError {
try {
return create(dto, Constants.TABLE_BASE_USER, userId, typeId);
} catch (Exception e) {
LOG.debug("Error creating contact for " +
"user " + userId);
throw new SessionInternalError(e);
}
}
public Integer createForInvoice(ContactDTOEx dto, Integer invoiceId) {
return create(dto, Constants.TABLE_INVOICE, invoiceId, new Integer(1));
}
/**
*
* @param dto
* @param table
* @param foreignId
* @param typeId Use 1 if it is not for a user (like and entity or invoice)
* @return
* @throws NamingException
*/
public Integer create(ContactDTOEx dto, String table,
Integer foreignId, Integer typeId) {
// first thing is to create the map to the user
ContactMapDTO map = new ContactMapDTO();
map.setJbillingTable(jbDAS.findByName(table));
map.setContactType(new ContactTypeDAS().find(typeId));
map.setForeignId(foreignId);
map = new ContactMapDAS().save(map);
// now the contact itself
dto.setCreateDate(new Date());
dto.setDeleted(0);
dto.setVersionNum(0);
dto.setId(0);
contact = contactDas.save(new ContactDTO(dto)); // it won't take the Ex
contact.setContactMap(map);
map.setContact(contact);
updateCreateFields(dto.getFieldsTable(), false);
LOG.debug("created " + contact);
// do an event if this is a user contact (invoices, companies, have
// contacts too)
if (table.equals(Constants.TABLE_BASE_USER)) {
NewContactEvent event = new NewContactEvent(contact, entityId);
EventManager.process(event);
eLogger.auditBySystem(entityId,
contact.getUserId(),
Constants.TABLE_CONTACT,
contact.getId(),
EventLogger.MODULE_USER_MAINTENANCE,
EventLogger.ROW_CREATED, null, null, null);
}
return contact.getId();
}
public void updatePrimaryForUser(ContactDTOEx dto, Integer userId) {
contact = contactDas.findPrimaryContact(userId);
update(dto);
}
public void createUpdatePrimaryForUser(ContactDTOEx dto, Integer userId, Integer entityId) {
contact = contactDas.findPrimaryContact(userId);
if (contact == null) {
createPrimaryForUser(dto, userId, entityId);
} else {
update(dto);
}
}
public void updateForUser(ContactDTOEx dto, Integer userId,
Integer contactTypeId) throws SessionInternalError {
contact = contactDas.findContact(userId, contactTypeId);
if (contact != null) {
if (entityId == null) {
setEntityFromUser(userId);
}
update(dto);
} else {
try {
createForUser(dto, userId, contactTypeId);
} catch (Exception e1) {
throw new SessionInternalError(e1);
}
}
}
private void update(ContactDTOEx dto) {
contact.setAddress1(dto.getAddress1());
contact.setAddress2(dto.getAddress2());
contact.setCity(dto.getCity());
contact.setCountryCode(dto.getCountryCode());
contact.setEmail(dto.getEmail());
contact.setFaxAreaCode(dto.getFaxAreaCode());
contact.setFaxCountryCode(dto.getFaxCountryCode());
contact.setFaxNumber(dto.getFaxNumber());
contact.setFirstName(dto.getFirstName());
contact.setInitial(dto.getInitial());
contact.setLastName(dto.getLastName());
contact.setOrganizationName(dto.getOrganizationName());
contact.setPhoneAreaCode(dto.getPhoneAreaCode());
contact.setPhoneCountryCode(dto.getPhoneCountryCode());
contact.setPhoneNumber(dto.getPhoneNumber());
contact.setPostalCode(dto.getPostalCode());
contact.setStateProvince(dto.getStateProvince());
contact.setTitle(dto.getTitle());
contact.setInclude(dto.getInclude());
if (entityId == null) {
setEntityFromUser(contact.getUserId());
}
NewContactEvent event = new NewContactEvent(contact, entityId);
EventManager.process(event);
eLogger.auditBySystem(entityId,
contact.getUserId(),
Constants.TABLE_CONTACT,
contact.getId(),
EventLogger.MODULE_USER_MAINTENANCE,
EventLogger.ROW_UPDATED, null, null, null);
updateCreateFields(dto.getFieldsTable(), true);
}
private void updateCreateFields(Hashtable fields, boolean isUpdate) {
if (fields == null) {
// if the fields are not there, do nothing
return;
}
// now the per-entity fields
for (Iterator it = fields.keySet().iterator(); it.hasNext();) {
String type = (String) it.next();
ContactFieldDTO field = (ContactFieldDTO) fields.get(type);
// we can't create or update custom fields with null value
if (field.getContent() == null) {
continue;
}
if (isUpdate) {
if (field.getId() != 0) {
contactFieldDas.find(field.getId()).setContent(field.getContent());
} else {
// it is un update, but don't know the field id
ContactFieldDTO aField = contactFieldDas.findByType(Integer.valueOf(type), contact.getId());
if (aField != null) {
aField.setContent(field.getContent());
} else {
// not there yet. It's ok
createContactField(Integer.valueOf(type), field.getContent());
}
}
} else {
// create the new field
createContactField(Integer.valueOf(type), field.getContent());
}
}
}
private void createContactField(Integer type, String content) {
ContactFieldDTO newField = new ContactFieldDTO();
newField.setType(new ContactFieldTypeDAS().find(type));
newField.setContent(content);
newField.setContact(contact);
newField = new ContactFieldDAS().save(newField);
contact.getFields().add(newField);
}
public void delete() {
if (contact == null) return;
LOG.debug("Deleting contact " + contact.getId());
// delete the map first
new ContactMapDAS().delete(contact.getContactMap());
// now the fields
for(ContactFieldDTO field: contact.getFields()) {
new ContactFieldDAS().delete(field);
}
contact.getFields().clear();
// for the logger
Integer entityId = this.entityId;
Integer userId = contact.getUserId();
Integer contactId = contact.getId();
// the contact goes last
contactDas.delete(contact);
contact = null;
// log event
eLogger.auditBySystem(entityId,
userId,
Constants.TABLE_CONTACT,
contactId,
EventLogger.MODULE_USER_MAINTENANCE,
EventLogger.ROW_DELETED, null, null, null);
}
/**
* Sets this contact object to that on the parent, taking the children id
* as a parameter.
* @param customerId
*/
public void setFromChild(Integer userId) {
UserBL customer = new UserBL(userId);
set(customer.getEntity().getCustomer().getParent().getBaseUser().getUserId());
}
}