package in.partake.controller.api.event; import in.partake.app.PartakeApp; import in.partake.base.PartakeException; import in.partake.base.TimeUtil; import in.partake.base.Util; import in.partake.controller.api.AbstractPartakeAPI; import in.partake.controller.base.permission.EventEditPermission; import in.partake.model.IPartakeDAOs; import in.partake.model.UserEx; import in.partake.model.access.Transaction; import in.partake.model.dao.DAOException; import in.partake.model.dao.PartakeConnection; import in.partake.model.dao.access.IEventTicketAccess; import in.partake.model.dto.Event; import in.partake.model.dto.EventTicket; import in.partake.model.dto.auxiliary.TicketAmountType; import in.partake.model.dto.auxiliary.TicketApplicationEnd; import in.partake.model.dto.auxiliary.TicketApplicationStart; import in.partake.model.dto.auxiliary.TicketPriceType; import in.partake.model.dto.auxiliary.TicketReservationEnd; import in.partake.resource.UserErrorCode; import in.partake.service.IEventSearchService; import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.apache.commons.lang.StringUtils; import play.mvc.Result; public class ModifyTicketAPI extends AbstractPartakeAPI { public static Result post() throws DAOException, PartakeException { return new ModifyTicketAPI().execute(); } @Override protected Result doExecute() throws DAOException, PartakeException { UserEx user = ensureLogin(); ensureValidSessionToken(); String eventId = getValidEventIdParameter(); String[] ids = getParameters("id[]"); int N = ids != null ? ids.length : 0; String[] names = ensureParameters("name[]", N, UserErrorCode.INVALID_ARGUMENT); String[] startDateTypes = ensureParameters("applicationStart[]", N, UserErrorCode.INVALID_ARGUMENT); String[] startDateDays = ensureParameters("applicationStartDayBeforeEvent[]", N, UserErrorCode.INVALID_ARGUMENT); String[] customStartDates = ensureParameters("customApplicationStartDate[]", N, UserErrorCode.INVALID_ARGUMENT); String[] endDateTypes = ensureParameters("applicationEnd[]", N, UserErrorCode.INVALID_ARGUMENT); String[] endDateDays = ensureParameters("applicationEndDayBeforeEvent[]", N, UserErrorCode.INVALID_ARGUMENT); String[] customEndDates = ensureParameters("customApplicationEndDate[]", N, UserErrorCode.INVALID_ARGUMENT); String[] reservationEndDateTypes = ensureParameters("reservationEnd[]", N, UserErrorCode.INVALID_ARGUMENT); String[] reservationEndHourBeforeApplications = ensureParameters("reservationEndHourBeforeApplication[]", N, UserErrorCode.INVALID_ARGUMENT); String[] customReservationEndDates = ensureParameters("customReservationEndDate[]", N, UserErrorCode.INVALID_ARGUMENT); String[] priceTypes = ensureParameters("priceType[]", N, UserErrorCode.INVALID_ARGUMENT); String[] prices = ensureParameters("price[]", N, UserErrorCode.INVALID_ARGUMENT); String[] amountTypes = ensureParameters("amountType[]", N, UserErrorCode.INVALID_ARGUMENT); String[] amounts = ensureParameters("amount[]", N, UserErrorCode.INVALID_ARGUMENT); List<EventTicket> tickets = new ArrayList<EventTicket>(); try { for (int i = 0; i < N; ++i) { if (!StringUtils.isBlank(ids[i]) && !Util.isUUID(ids[i])) return renderInvalid(UserErrorCode.INVALID_ARGUMENT); UUID id = StringUtils.isBlank(ids[i]) ? null : UUID.fromString(ids[i]); EventTicket ticket = new EventTicket(id, eventId, i, names[i], TicketApplicationStart.safeValueOf(startDateTypes[i]), Integer.parseInt(startDateDays[i]), TimeUtil.parseForEvent(customStartDates[i]), TicketApplicationEnd.safeValueOf(endDateTypes[i]), Integer.parseInt(endDateDays[i]), TimeUtil.parseForEvent(customEndDates[i]), TicketReservationEnd.safeValueOf(reservationEndDateTypes[i]), Integer.parseInt(reservationEndHourBeforeApplications[i]), TimeUtil.parseForEvent(customReservationEndDates[i]), TicketPriceType.safeValueOf(priceTypes[i]), Integer.parseInt(prices[i]), TicketAmountType.safeValueOf(amountTypes[i]), Integer.parseInt(amounts[i]), TimeUtil.getCurrentDateTime(), TimeUtil.getCurrentDateTime()); if (!ticket.validate()) return renderInvalid(UserErrorCode.INVALID_ARGUMENT); tickets.add(ticket); } } catch (NumberFormatException e) { return renderInvalid(UserErrorCode.INVALID_ARGUMENT); } ModifyTicketTransaction transaction = new ModifyTicketTransaction(user, eventId, tickets); transaction.execute(); Event event = transaction.getEvent(); IEventSearchService searchService = PartakeApp.getEventSearchService(); if (!event.isSearchable()) searchService.remove(eventId); else if (searchService.hasIndexed(eventId)) searchService.update(event, tickets); else searchService.create(event, tickets); return renderOK(); } } class ModifyTicketTransaction extends Transaction<Void> { private UserEx user; private String eventId; private Event event; private List<EventTicket> tickets; public ModifyTicketTransaction(UserEx user, String eventId, List<EventTicket> tickets) { this.user = user; this.eventId = eventId; this.tickets = tickets; } @Override protected Void doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { event = daos.getEventAccess().find(con, eventId); if (event == null) throw new PartakeException(UserErrorCode.INVALID_EVENT_ID); if (!EventEditPermission.check(event, user)) throw new PartakeException(UserErrorCode.FORBIDDEN_EVENT_EDIT); modifyTickets(con, daos, event.isDraft()); return null; } private void modifyTickets(PartakeConnection con, IPartakeDAOs daos, boolean forDraft) throws DAOException, PartakeException { IEventTicketAccess dao = daos.getEventTicketAccess(); List<EventTicket> originalTickets = dao.findEventTicketsByEventId(con, eventId); boolean[] processed = new boolean[originalTickets.size()]; // |tickets| should contain all the original ticket. for (EventTicket ticket : tickets) { EventTicket originalTicket = null; for (int i = 0; i < originalTickets.size(); ++i) { if (!originalTickets.get(i).getId().equals(ticket.getId())) continue; if (processed[i]) throw new PartakeException(UserErrorCode.INVALID_TICKET_DUPLICATE_ID); // Found the original ticket. processed[i] = true; originalTicket = originalTickets.get(i); break; } if (originalTicket == null) { // If new ticket has id, it's strange. Otherwise, add a new ticket id. if (ticket.getId() != null) throw new PartakeException(UserErrorCode.INVALID_PARAMETERS); ticket.setId(daos.getEventTicketAccess().getFreshId(con)); } } // If the event has already been published, all ticket should be preserved. // However, it's OK to remove the ticket that no participants. if (!forDraft) { for (int i = 0; i < processed.length; ++i) { UUID eventTicketId = originalTickets.get(i).getId(); if (!processed[i] && daos.getEnrollmentAccess().countByTicketId(con, eventTicketId) > 0) throw new PartakeException(UserErrorCode.INVALID_TICKET_REMOVAL_ENROLLED); } } // OK. let's save the tickets. dao.removeByEventId(con, eventId); for (EventTicket ticket : tickets) dao.put(con, ticket); } public Event getEvent() { return event; } }