Contact request – leverage CSR ticket framework

Objectives

– Leverage ticket framework for customer requests
– Typical use case is a simple contact request


Customizations/Considerations

– Addition of contact form fields in the [ext]core-items.xml (extend CsTicket model, autocreate and generate equal false)

<itemtype code=”CsTicket” autocreate=”false” generate=”false”>
<attributes>
<attribute type=”java.lang.String” qualifier=”topic”>
<persistence type=”property” />
</attribute>
<attribute type=”java.lang.String” qualifier=”subtopic”>
<persistence type=”property” />
</attribute>
<attribute type=”java.lang.String” qualifier=”firstName”>
<persistence type=”property” />
</attribute>
<attribute type=”java.lang.String” qualifier=”lastName”>
<persistence type=”property” />
</attribute>
</attributes>
</itemtype>

– Custom service to use for handling the tickets/contact requests
– In [ext]core-spring.xml, code snippet to come on demand

– In facades custom extension, create bean for CsTicketData
– See below for code snippet
– Register the facade, converter and populator in the [ext]facades-spring.xml

– Create WsDTO beans for web service layer
– in [ext]webservice/resources/xxxwebservice-beans.xml, see below for example
– create contact us form simple class, see snippet below
– create a ticket controller for external interaction, in web/v2/controller, see snippet below
– update the dto-level-mappings-v2-spring.xml accordingly, see snippet below

– Localization in [ext]backoffice-locales.properties and [ext]backoffice-locales.properties_en (or other). In client backoffice extensions, resources folder.

– type.CsTicket.topic.name=TOPIC
– type.CsTicket.comment.name=COMMENT
– type.CsTicket.FirstName.name=FIRST NAME
– type.CsTicket.lastName.name=LAST NAME
– type.CsTicket.contactType.name=CONTACT TYPE
– type.CsTicket.email.name=EMAIL orderNumber
– type.CsTicket.orderNumber.name=ORDER NUMBER
– type.CsTicket.phoneNumber.name=PHONE NUMBER
– type.CsTicket.isMyMobileNumber.name=IS MYMOBILE NUMBER

– Configuration of the contact form fields in [ext]backoffice-backoffice-config.xml. In client backoffice extensions, resources folder.
Code snippets

Below are code snippet and references. This is by no mean the complete code required to have the functionality enabled, but it should provide most of the insights, in no particular order.

Facade
L1
public interface ExampleTicketFacade
{
List getTicketsForCustomer(UserModel customer);
List getTicketsForState(CsTicketState… state);
CsTicketData createTicket(CsTicketData data);
}

L2
public class DefaultExampleTicketFacade implements ExampleTicketFacade
{

private TicketService ticketService;
private WhirlpoolTicketBusinessService exampleTicketBusinessService;
private Converter<CsTicketModel, CsTicketData> ticketConverter;
private ModelService modelService;

@Override
public List getTicketsForCustomer(final UserModel customer)
{
final List tickets = getTicketService().getTicketsForCustomer(customer);
final List ticketsdata = new ArrayList();
for (final CsTicketModel ticket : tickets)
{
ticketsdata.add(getTicketConverter().convert(ticket));
}
return ticketsdata;
}

@Override
public List getTicketsForState(final CsTicketState… state)
{
final List tickets = getTicketService().getTicketsForState(state);
final List ticketsdata = new ArrayList();
for (final CsTicketModel ticket : tickets)
{
ticketsdata.add(getTicketConverter().convert(ticket));
}
return ticketsdata;
}

@Override
public CsTicketData createTicket(final CsTicketData data)
{
final String handLine = data.getComment();
final String comment = data.getComment();
CsInterventionType enterventionType = CsInterventionType.EMAIL;
CsTicketPriority ticketPriority = CsTicketPriority.HIGH;
CsTicketCategory ticketCategory = CsTicketCategory.PROBLEM;
if (StringUtils.isNotEmpty(data.getContactType()))
{
enterventionType = CsInterventionType.valueOf(data.getContactType());
}
if (StringUtils.isNotEmpty(data.getPriority()))
{
ticketPriority = CsTicketPriority.valueOf(data.getPriority());
}
if (StringUtils.isNotEmpty(data.getCategory()))
{
ticketCategory = CsTicketCategory.valueOf(data.getCategory());
}
final CsTicketModel ticket = (CsTicketModel) this.getModelService().create(CsTicketModel.class);
ticket.setTopic(data.getTopic());
ticket.setSubtopic(data.getSubtopic());
ticket.setFirstName(data.getFirstName());
ticket.setLastName(data.getLastName());
ticket.setEmail(data.getEmail());
ticket.setConfirmEmail(data.getConfirmEmail());
ticket.setNation(data.getNation());
ticket.setCountry(data.getCountry());
ticket.setCity(data.getCity());
ticket.setPhoneNumber(data.getPhoneNumber());
ticket.setIsMyMobileNumber(data.getIsMyMobileNumber());
ticket.setIsAccept(data.getIsAccept());
return getTicketConverter().convert(getExampleTicketBusinessService().createTicket(ticket, null, ticketCategory,
ticketPriority, null, null, handLine, enterventionType, CsEventReason.FIRSTCONTACT, comment));
}
}

L1
public interface ExampleTicketBusinessService extends TicketBusinessService
{
CsTicketModel createTicket(CsTicketModel ticket, UserModel customer, CsTicketCategory category, CsTicketPriority priority,
EmployeeModel assignedAgent, CsAgentGroupModel assignedGroup, String headline, CsInterventionType interventionType,
CsEventReason reason, String creationNotes);
}
L2
ticket = this.populateTicketDetails(ticket, customer, (AbstractOrderModel) null, category, priority, assignedAgent,
assignedGroup, headline);
final CsCustomerEventModel creationEvent = exampleTicketEventStrategy.createCreationEventForTicket(ticket, reason,
interventionType, creationNotes);
return super.createTicketInternal(ticket, creationEvent);
L3
protected CsTicketModel populateTicketDetails(final CsTicketModel ticket, final UserModel customer,
final AbstractOrderModel abstractOrder, final CsTicketCategory category, final CsTicketPriority priority,
final EmployeeModel assignedAgent, final CsAgentGroupModel assignedGroup, final String headline)
{
ticket.setCustomer(customer);
ticket.setOrder(abstractOrder);
ticket.setCategory(category);
ticket.setPriority(priority);
ticket.setAssignedAgent(assignedAgent);
ticket.setAssignedGroup(assignedGroup);
ticket.setHeadline(headline);
final BaseSiteModel currentBaseSite = this.getBaseSiteService().getCurrentBaseSite();
if (currentBaseSite != null)
{
ticket.setBaseSite(currentBaseSite);
}

return ticket;
}

“/>

WsDTO


ContactUsForm.java snippet

/**
* used for ticket
*/
public class ExampleContactUsForm
{
private String topic;
private String subtopic;
private String comment;
private String firstName;
private String lastName;
private String contactType;
private String email;
private String nation;
private String country;
private String city;
private String confirmEmail;
private String orderNumber;
private String phoneNumber;
private boolean isMyMobileNumber;
private boolean isAccept;

Ticket controller v2

@Controller
@RequestMapping(value = “/{baseSiteId}/ticket”)
public class TicketController extends BaseController
{
@Resource(name = “userService”)
private UserService userService;

@Resource(name = “ticketFacade”)
private WhirlpoolTicketFacade ticketFacade;

@RequestMapping(value = “/getTicketsForUser”, method = RequestMethod.GET)
@ResponseBody
public TicketListWsDTO getTicketsforUser(@RequestParam final String userId,
@RequestParam(defaultValue = DEFAULT_FIELD_SET) final String fields)
{
final UserModel user = getUserService().getUserForUID(userId);
final List ticketsData = getTicketFacade().getTicketsForCustomer(user);
final CsTicketDataList ticketDataList = new CsTicketDataList();
ticketDataList.setTickets(ticketsData);
return getDataMapper().map(ticketDataList, TicketListWsDTO.class);
}

@RequestMapping(value = “/getTicketsForState”, method = RequestMethod.GET)
@ResponseBody
public TicketListWsDTO getTicketsforState(@RequestParam(defaultValue = DEFAULT_FIELD_SET) final String fields,
@RequestParam final CsTicketState… state) throws JsonProcessingException
{
final List ticketsData = getTicketFacade().getTicketsForState(state);
final CsTicketDataList ticketDataList = new CsTicketDataList();
ticketDataList.setTickets(ticketsData);
return getDataMapper().map(ticketDataList, TicketListWsDTO.class);
}

@RequestMapping(value = “/createTicket”, method = RequestMethod.POST, consumes =
{ MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public TicketWsDTO createTicket(@RequestBody final ExampleContactUsForm form,
@RequestParam(defaultValue = DEFAULT_FIELD_SET) final String fields)
throws IllegalAccessException, InvocationTargetException
{
final CsTicketData csTicketData = new CsTicketData();
BeanUtils.copyProperties(csTicketData, form);
getTicketFacade().createTicket(csTicketData);
return getDataMapper().map(getTicketFacade().createTicket(csTicketData), TicketWsDTO.class);
}

local_offerevent_note November 10, 2016

account_box Mickael