/** * Utility method create a proposal with the given parameters and triggering the associated work * flow steps * * @param pm Persistence manager instance to use - let open at the end to allow possible object * updates later * @param parameters Parameters produced by the Command line parser or transmitted via the REST * API * @param owner Sale associate who's going to own the created proposal * @param saConsumerRecord Consumer record attached to the sale associate * @return Just created proposal * @throws DataSourceException if the retrieval of the last created proposal or of the location * information fail * @throws ClientException if there's an issue with the given parameters */ public static Proposal createProposal( PersistenceManager pm, JsonObject parameters, SaleAssociate owner, Consumer saConsumerRecord) throws DataSourceException, ClientException { // Data validation & propagation // FIXME: deprecate Demand.REFERENCE in favor of Proposal.DEMAND_KEY, be careful with the // CommandLineParser with uses Demand.REFERENCE if (!parameters.containsKey(Proposal.DEMAND_KEY) && !parameters.containsKey(Demand.REFERENCE)) { throw new InvalidIdentifierException("Missing " + Proposal.DEMAND_KEY + " attribute!"); } if (!parameters.containsKey(Proposal.DEMAND_KEY)) { parameters.put(Proposal.DEMAND_KEY, parameters.getLong(Demand.REFERENCE)); } Long demandKey = parameters.getLong(Proposal.DEMAND_KEY); Demand demand = getDemandOperations().getDemand(pm, demandKey, null); if (!parameters.containsKey(Proposal.CONSUMER_KEY)) { parameters.put(Proposal.CONSUMER_KEY, demand.getOwnerKey()); } else if (!demand.getOwnerKey().equals(parameters.getLong(Proposal.CONSUMER_KEY))) { throw new ClientException( "Proposed " + Proposal.CONSUMER_KEY + " does not match the key of the demand owner!"); } parameters.put(Proposal.LOCATION_KEY, owner.getLocationKey()); // Entity creation Proposal proposal = getProposalOperations().createProposal(pm, parameters, owner); // Related workflow step MaelzelServlet.triggerValidationTask(proposal); return proposal; }
public static List<Long> getProposalKeys( PersistenceManager pm, JsonObject parameters, Long ownerKey, QueryPointOfView pointOfView, Long saleAssociateKey) throws ReservedOperationException, DataSourceException { Map<String, Object> queryParameters = prepareQueryForSelection(parameters); int maximumResults = parameters.containsKey(BaseRestlet.MAXIMUM_RESULTS_PARAMETER_KEY) ? (int) parameters.getLong(BaseRestlet.MAXIMUM_RESULTS_PARAMETER_KEY) : 0; List<Long> output = null; if (QueryPointOfView.CONSUMER.equals(pointOfView)) { queryParameters.put(Proposal.CONSUMER_KEY, ownerKey); output = getProposalOperations().getProposalKeys(pm, queryParameters, maximumResults); throw new RuntimeException("Not yet implemented!"); } else if (QueryPointOfView.SALE_ASSOCIATE.equals(pointOfView)) { if (saleAssociateKey == null) { throw new ReservedOperationException(Action.list, Proposal.class.getName()); } queryParameters.put(Proposal.OWNER_KEY, saleAssociateKey); output = getProposalOperations().getProposalKeys(pm, queryParameters, maximumResults); } else { // if (QueryPointOfView.anonymous.equals(pointOfView)) { throw new ReservedOperationException(Action.list, Proposal.class.getName()); } return output; }
public TransferObject fromJson(JsonObject in, boolean isUserAdmin, boolean isCacheRelated) { if (isCacheRelated) { isUserAdmin = isCacheRelated; } if (!isUserAdmin) { throw new IllegalArgumentException("Reserved operation"); } super.fromJson(in, isUserAdmin, isCacheRelated); if (in.containsKey(CONSUMER_KEY)) { setConsumerKey(in.getLong(CONSUMER_KEY)); } if (in.containsKey(TOKEN_NB)) { setTokenNb(in.getLong(TOKEN_NB)); } return this; }
public static List<Proposal> getProposals( PersistenceManager pm, JsonObject parameters, Long ownerKey, QueryPointOfView pointOfView, Long saleAssociateKey) throws ReservedOperationException, InvalidIdentifierException, DataSourceException { Map<String, Object> queryParameters = prepareQueryForSelection(parameters); int maximumResults = parameters.containsKey(BaseRestlet.MAXIMUM_RESULTS_PARAMETER_KEY) ? (int) parameters.getLong(BaseRestlet.MAXIMUM_RESULTS_PARAMETER_KEY) : 0; List<Proposal> output = null; if (QueryPointOfView.CONSUMER.equals(pointOfView)) { queryParameters.put(Proposal.CONSUMER_KEY, ownerKey); boolean withKeySet = parameters.containsKey(Entity.KEY); if (withKeySet) { JsonArray intialKeys = parameters.getJsonArray(Entity.KEY); List<Long> convertedKeys = new ArrayList<Long>(); int limit = intialKeys.size(); for (int idx = 0; idx < limit; idx++) { convertedKeys.add(Long.valueOf(intialKeys.getString(idx))); } output = getProposalOperations().getProposals(pm, convertedKeys); } else { output = getProposalOperations().getProposals(pm, queryParameters, maximumResults); } } else if (QueryPointOfView.SALE_ASSOCIATE.equals(pointOfView)) { if (saleAssociateKey == null) { throw new ReservedOperationException(Action.list, Proposal.class.getName()); } queryParameters.put(Proposal.OWNER_KEY, saleAssociateKey); output = getProposalOperations().getProposals(pm, queryParameters, maximumResults); } else { // if (QueryPointOfView.anonymous.equals(pointOfView)) { List<Location> locations = LocationSteps.getLocations(pm, parameters, true); output = getProposalOperations().getProposals(pm, queryParameters, locations, maximumResults); } return output; }
/** * Utility method updating the proposal state if the specified user owns the attached demand * * @param pm Persistence manager instance to use - let open at the end to allow possible object * updates later * @param rawCommand Reference of the command which initiated the process, is <code>null</code> if * initiated by a REST API call * @param proposalKey Resource identifier * @param parameters Parameters produced by the Command line parser or transmitted via the REST * API * @param demandOwner Key of the owner of the demand associated to the identified proposal * @return Just updated proposal * @throws DataSourceException if the retrieval of the last created proposal or of the location * information fail * @throws InvalidIdentifierException if there's an issue with the Proposal identifier is invalid * @throws InvalidStateException if the Proposal is not update-able * @throws ReservedOperationException if the Consumer does not own the Demand associated to the * identified Proposal * @throws CommunicationException If the result of the operation cannot be communicated to the * SaleAssociate owning the concerned Proposal */ public static Proposal updateProposal( PersistenceManager pm, RawCommand rawCommand, Long proposalKey, JsonObject parameters, Long demandOwnerKey) throws DataSourceException, InvalidIdentifierException, InvalidStateException, ReservedOperationException, CommunicationException { // Verify the correct parameter sequence if (parameters.size() != 2 && parameters.size() != 3 || !parameters.containsKey(Command.POINT_OF_VIEW) || !parameters.containsKey(Command.STATE) && !parameters.containsKey(Proposal.SCORE) || parameters.containsKey(Command.STATE) && !State.confirmed.toString().equals(parameters.getString(Command.STATE)) && !State.declined.toString().equals(parameters.getString(Command.STATE))) { throw new InvalidStateException("Invalid parameter sequence for the Proposal state update!"); } // Get the proposal and verify its state Proposal proposal = getProposalOperations().getProposal(pm, proposalKey, null, null); // Verify the consumer owns the associated demand and its state Consumer demandOwner = getConsumerOperations().getConsumer(pm, demandOwnerKey); Demand demand = getDemandOperations().getDemand(pm, proposal.getDemandKey(), demandOwnerKey); if (parameters.containsKey(Command.STATE)) { boolean confirmProposal = State.confirmed.toString().equals(parameters.getString(Command.STATE)); State newState = confirmProposal ? State.confirmed : State.declined; // Verify the proposal state State currentState = proposal.getState(); if (!State.published.equals(currentState)) { throw new InvalidStateException( "Invalid Proposal state for a " + (confirmProposal ? "confirmation" : "declination"), currentState.toString(), newState.toString()); } // Verify the demand state if (!State.published.equals(demand.getState())) { throw new InvalidStateException( "Invalid associated Demand state for a " + (confirmProposal ? "confirmation" : "declination"), demand.getState().toString(), newState.toString()); } // Persist the proposal state change proposal.setState(newState); if (!confirmProposal) { proposal.setCancelerKey(demandOwnerKey); } proposal = getProposalOperations().updateProposal(pm, proposal); if (confirmProposal) { // Cancel the other proposals associated to the demand List<Long> proposalKeys = demand.getProposalKeys(); if (1 < proposalKeys.size()) { // Schedule the other proposal cancellation MaelzelServlet.triggerProposalCancellationTask(proposalKeys, demandOwnerKey, proposalKey); // Clean-up the list of associated proposals demand.resetProposalKeys(); demand.addProposalKey(proposalKey); } List<Long> saleAssociateKeys = demand.getSaleAssociateKeys(); if (1 < saleAssociateKeys.size()) { demand.resetSaleAssociateKeys(); demand.addSaleAssociateKey(proposal.getOwnerKey()); } // Persist the demand state change demand.setState(State.confirmed); getDemandOperations().updateDemand(pm, demand); // Echo back the successful confirmation Store store = BaseSteps.getStoreOperations().getStore(pm, proposal.getStoreKey()); Location location = BaseSteps.getLocationOperations().getLocation(pm, store.getLocationKey()); Registrar registrar = getRegistrarOperations().getRegistrar(pm, store.getRegistrarKey()); if (rawCommand != null) { // Means the Consumer did not use the console to !confirm the Proposal Locale locale = demandOwner.getLocale(); MessageGenerator msgGen = new MessageGenerator(rawCommand.getSource(), demand.getHashTags(), locale); msgGen .put("demand>owner>name", demandOwner.getName()) .fetch(proposal) .fetch(store) .fetch(location, "store") .fetch(registrar) .fetch(demand) .put("message>footer", msgGen.getAlternateMessage(MessageId.messageFooter)) .put( "command>footer", LabelExtractor.get(ResourceFileId.fourth, "command_message_footer", locale)); String cancelDemand = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_demand_cancel", msgGen.getParameters(), locale); String closeDemand = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_demand_close", msgGen.getParameters(), locale); String subject = null; if (Source.mail.equals(msgGen.getCommunicationChannel())) { subject = rawCommand.getSubject(); } if (subject == null) { subject = msgGen.getAlternateMessage(MessageId.messageSubject, msgGen.getParameters()); } subject = MailConnector.prepareSubjectAsResponse(subject, locale); msgGen .put("command>threadSubject", BaseConnector.prepareMailToSubject(subject)) .put("command>cancelDemand", BaseConnector.prepareMailToBody(cancelDemand)) .put("command>closeDemand", BaseConnector.prepareMailToBody(closeDemand)); String message = msgGen.getMessage(MessageId.PROPOSAL_CONFIRMATION_OK_TO_CONSUMER); communicateToConsumer( msgGen.getCommunicationChannel(), subject, demandOwner, new String[] {message}); } Long robotKey = RobotResponder.getRobotSaleAssociateKey(pm); if (proposal.getOwnerKey().equals(robotKey)) { // Schedule the automatic Proposal closing by the Robot prepareProposalClosingByTheRobot(pm, proposalKey); } else { // Inform the sale associate of the successful confirmation SaleAssociate saleAssociate = getSaleAssociateOperations().getSaleAssociate(pm, proposal.getOwnerKey()); Consumer saConsumerRecord = getConsumerOperations().getConsumer(pm, saleAssociate.getConsumerKey()); Locale locale = saConsumerRecord.getLocale(); MessageGenerator msgGen = new MessageGenerator( saConsumerRecord.getPreferredConnection(), proposal.getHashTags(), locale); msgGen .put("proposal>owner>name", saConsumerRecord.getName()) .fetch(proposal) .fetch(demand) .put("message>footer", msgGen.getAlternateMessage(MessageId.messageFooter)) .put( "command>footer", LabelExtractor.get(ResourceFileId.fourth, "command_message_footer", locale)); String cancelProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_cancel", msgGen.getParameters(), locale); String closeProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_close", msgGen.getParameters(), locale); String subject = null; if (Source.mail.equals(msgGen.getCommunicationChannel()) && Source.mail.equals(proposal.getSource())) { subject = getRawCommandOperations() .getRawCommand(pm, proposal.getRawCommandId()) .getSubject(); } if (subject == null) { subject = msgGen.getAlternateMessage(MessageId.messageSubject, msgGen.getParameters()); } subject = MailConnector.prepareSubjectAsResponse(subject, locale); msgGen .put( "command>threadSubject", BaseConnector.prepareMailToSubject( MailConnector.prepareSubjectAsResponse(subject, locale))) .put("command>cancelProposal", BaseConnector.prepareMailToBody(cancelProposal)) .put("command>closeProposal", BaseConnector.prepareMailToBody(closeProposal)); communicateToConsumer( msgGen.getCommunicationChannel(), subject, saConsumerRecord, new String[] {msgGen.getMessage(MessageId.PROPOSAL_CONFIRMATION_OK_TO_ASSOCIATE)}); } // Notify CC-ed List<String> cc = demand.getCC(); if (cc != null && 0 < cc.size()) { Locale locale = demandOwner.getLocale(); MessageGenerator msgGen = null; String message = null; String subject = null; for (String coordinate : cc) { try { Source source = getCCedCommunicationChannel(coordinate); if (msgGen == null || !source.equals(msgGen.getCommunicationChannel())) { // // TODO: cache the MessageGenerator instance per Source value to avoid unnecessary // re-creation! // msgGen = new MessageGenerator(source, demand.getHashTags(), locale); msgGen .put("demand>owner>name", demandOwner.getName()) .fetch(proposal) .fetch(store) .fetch(location, "store") .fetch(registrar) .fetch(demand) .put("message>footer", msgGen.getAlternateMessage(MessageId.messageFooter)); message = msgGen.getMessage(MessageId.PROPOSAL_CONFIRMATION_OK_TO_CCED); } if (subject == null) { Map<String, Object> cmdPrm = new HashMap<String, Object>(); cmdPrm.put("demand>key", demand.getKey()); subject = msgGen.getAlternateMessage(MessageId.messageSubject, cmdPrm); subject = MailConnector.prepareSubjectAsForward(subject, locale); } communicateToCCed( msgGen.getCommunicationChannel(), coordinate, subject, message, locale); } catch (CommunicationException e) { // Too bad, cannot contact the CC-ed person... Don't block the next sending! getLogger().warning("Cannot inform cc'ed " + coordinate); } } } } } else { // if (parameters.containsKey(Proposal.SCORE)) { // Persist the proposal attribute change proposal.setScore(Long.valueOf((int) parameters.getLong(Proposal.SCORE))); if (parameters.containsKey(Proposal.COMMENT)) { proposal.setComment(parameters.getString(Proposal.COMMENT)); } proposal = getProposalOperations().updateProposal(pm, proposal); // Echo back the successful rating Store store = BaseSteps.getStoreOperations().getStore(pm, proposal.getStoreKey()); Location location = BaseSteps.getLocationOperations().getLocation(pm, store.getLocationKey()); Registrar registrar = getRegistrarOperations().getRegistrar(pm, store.getRegistrarKey()); if (rawCommand != null) { // Means the Consumer did not use the console to !confirm the Proposal Locale locale = demandOwner.getLocale(); MessageGenerator msgGen = new MessageGenerator(rawCommand.getSource(), demand.getHashTags(), locale); msgGen .put("demand>owner>name", demandOwner.getName()) .fetch(proposal) .fetch(store) .fetch(location, "store") .fetch(registrar) .fetch(demand) .put("message>footer", msgGen.getAlternateMessage(MessageId.messageFooter)) .put( "command>footer", LabelExtractor.get(ResourceFileId.fourth, "command_message_footer", locale)); String confirmProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_confirm", msgGen.getParameters(), locale); String declineProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_decline", msgGen.getParameters(), locale); String cancelDemand = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_demand_cancel", msgGen.getParameters(), locale); String listDemand = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_demand_list", msgGen.getParameters(), locale); String subject = null; if (rawCommand != null) { // Can be only null if its source == api -- see caller context subject = rawCommand.getSubject(); } if (subject == null) { subject = msgGen.getAlternateMessage(MessageId.messageSubject, msgGen.getParameters()); } subject = MailConnector.prepareSubjectAsResponse(subject, locale); msgGen .put("command>threadSubject", BaseConnector.prepareMailToSubject(subject)) .put("command>confirmProposal", BaseConnector.prepareMailToBody(confirmProposal)) .put("command>declineProposal", BaseConnector.prepareMailToBody(declineProposal)) .put("command>cancelDemand", BaseConnector.prepareMailToBody(cancelDemand)) .put("command>listDemand", BaseConnector.prepareMailToBody(listDemand)); String message = msgGen.getMessage(MessageId.PROPOSAL_RATING_OK_TO_CONSUMER); communicateToConsumer( msgGen.getCommunicationChannel(), subject, demandOwner, new String[] {message}); } Long robotKey = RobotResponder.getRobotSaleAssociateKey(pm); if (proposal.getOwnerKey().equals(robotKey)) { // Stay silent } else { // Inform the sale associate of the successful rating SaleAssociate saleAssociate = getSaleAssociateOperations().getSaleAssociate(pm, proposal.getOwnerKey()); Consumer saConsumerRecord = getConsumerOperations().getConsumer(pm, saleAssociate.getConsumerKey()); Locale locale = saConsumerRecord.getLocale(); MessageGenerator msgGen = new MessageGenerator( saConsumerRecord.getPreferredConnection(), proposal.getHashTags(), locale); msgGen .put("proposal>owner>name", saConsumerRecord.getName()) .fetch(proposal) .fetch(demand) .put("message>footer", msgGen.getAlternateMessage(MessageId.messageFooter)) .put( "command>footer", LabelExtractor.get(ResourceFileId.fourth, "command_message_footer", locale)); String cancelProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_cancel", msgGen.getParameters(), locale); String closeProposal = LabelExtractor.get( ResourceFileId.fourth, "command_message_body_proposal_close", msgGen.getParameters(), locale); String subject = null; if (Source.mail.equals(msgGen.getCommunicationChannel()) && Source.mail.equals(proposal.getSource())) { subject = getRawCommandOperations().getRawCommand(pm, proposal.getRawCommandId()).getSubject(); } if (subject == null) { subject = msgGen.getAlternateMessage(MessageId.messageSubject, msgGen.getParameters()); } subject = MailConnector.prepareSubjectAsResponse(subject, locale); msgGen .put( "command>threadSubject", BaseConnector.prepareMailToSubject( MailConnector.prepareSubjectAsResponse(subject, locale))) .put("command>cancelProposal", BaseConnector.prepareMailToBody(cancelProposal)) .put("command>closeProposal", BaseConnector.prepareMailToBody(closeProposal)); communicateToConsumer( msgGen.getCommunicationChannel(), subject, saConsumerRecord, new String[] {msgGen.getMessage(MessageId.PROPOSAL_RATING_OK_TO_ASSOCIATE)}); } } return proposal; }