package com.sap.opportunity.ui.server; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.sap.opportunity.ui.client.ExpectedSalesDTO; import com.sap.opportunity.ui.client.OpportunityDTO; import com.sap.opportunity.ui.client.OpportunityService; import com.sap.opportunity.ui.client.SalesByMonthDTO; import com.sap.runlet.interpreter.rucola.Entity; import com.sap.runlet.interpreter.rucola.Function; import com.sap.runlet.interpreter.rucola.Rucola; import com.sap.runlet.interpreter.rucola.RucolaObject; import com.sap.runlet.interpreter.rucola.Value; import com.sap.runlet.tomcat.Activator; /** * The server side implementation of the RPC service. */ public class OpportunityServiceImpl extends RemoteServiceServlet implements OpportunityService { private static final long serialVersionUID = -3807719400704313470L; List<Value> months = new ArrayList<Value>(4); List<String> phases = new ArrayList<String>(3); public void init(ServletConfig config) throws ServletException { super.init(config); // init months list GregorianCalendar cal = new GregorianCalendar(); Rucola rucola = new Rucola(Activator.createConnection("com.sap.runlet.apps.opportunitymanagement"), Activator.getDefault().getRunletDataStore()); Map<String, Object> mmap = new HashMap<String, Object>(); for (int i = 0; i < 4; i++) { mmap.put("year", cal.get(Calendar.YEAR)); mmap.put("month", cal.get(Calendar.MONTH)); months.add(rucola.value("MonthAndYear", mmap)); mmap.clear(); cal.add(Calendar.MONTH, 1); } // init phase list phases.add("Initial"); phases.add("Decision Making"); phases.add("Final Phase"); } /** * Creates a new {@link Rucola} connector with a new {@link RiverInterpreter} but based * on the data store obtained from the surrounding servlet container. */ private Rucola createRucola() { return new Rucola(Activator.createConnection("com.sap.runlet.apps.opportunitymanagement"), Activator.getDefault().getRunletDataStore()); } public List<OpportunityDTO> getOpportunities() { Rucola rucola = createRucola(); Value reports = rucola.value("Reports"); Entity allOpportunities = (Entity) reports.call("getAllOpportunities"); List<OpportunityDTO> opps = new ArrayList<OpportunityDTO>(); for (RucolaObject opportunity : allOpportunities) { Entity opportunityEntity = opportunity.asEntity(); OpportunityDTO o = createOpportunityDTO(opportunityEntity); opps.add(o); } return opps; } @Override public List<OpportunityDTO> getOpportunities(int minRevenue) { List<OpportunityDTO> opps = getOpportunities(); filterByRevenue(minRevenue, opps); return opps; } @Override public List<OpportunityDTO> getOpportunities(String phase) { List<OpportunityDTO> opps = getOpportunities(); filterByPhase(phase, opps); return opps; } @Override public List<OpportunityDTO> getOpportunities(int minRevenue, String phase) { List<OpportunityDTO> opps = getOpportunities(); filterByPhase(phase, opps); filterByRevenue(minRevenue, opps); return opps; } @Override public List<OpportunityDTO> getHistoricOpportunities(Date transactionTime) { Rucola rucola = createRucola(); Value reports = rucola.value("Reports"); Entity allOpportunities = reports.call("getAllOpportunitiesAt", transactionTime).asEntity(); List<OpportunityDTO> opps = new ArrayList<OpportunityDTO>(); for (RucolaObject opportunity : allOpportunities) { Entity opportunityEntity = opportunity.asEntity(); OpportunityDTO o = createOpportunityDTO(opportunityEntity); opps.add(o); } return opps; } @Override public List<OpportunityDTO> getHistoricOpportunities(Date transactionTime, int minRevenue) { List<OpportunityDTO> opps = getHistoricOpportunities(transactionTime); filterByRevenue(minRevenue, opps); return opps; } @Override public List<OpportunityDTO> getHistoricOpportunities(Date transactionTime, String phase) { List<OpportunityDTO> opps = getHistoricOpportunities(transactionTime); filterByPhase(phase, opps); return opps; } @Override public List<OpportunityDTO> getHistoricOpportunities(Date transactionTime, int minRevenue, String phase) { List<OpportunityDTO> opps = getHistoricOpportunities(transactionTime); filterByPhase(phase, opps); filterByRevenue(minRevenue, opps); return opps; } private OpportunityDTO createOpportunityDTO(Entity opportunityEntity) { OpportunityDTO o = new OpportunityDTO(opportunityEntity.getId(), opportunityEntity.get("description").asString(), opportunityEntity.get("prospect").asEntity().get("name").asString(), opportunityEntity.get("phase").asString(), formatCompetitors(opportunityEntity.get("competitors").asEntity()), opportunityEntity.get("expectedCloseDate").asDate(), opportunityEntity.get("responsible").asEntity().get("name").asString(), opportunityEntity.get("expectedSalesVolume").asValue().get("val").asInt(), opportunityEntity.get("probability").asFraction().asFloat()); return o; } private String formatCompetitors(Entity competitors) { StringBuilder result = new StringBuilder(); boolean needComma = false; for (RucolaObject businessPartner : competitors) { Entity businessPartnerEntity = businessPartner.asEntity(); if (needComma) { result.append(", "); } else { needComma = true; } result.append(businessPartnerEntity.get("name").asString()); } return result.toString(); } @Override public void updateOpportunities(List<OpportunityDTO> dtos) { // TODO only update properties that really changed Rucola rucola = createRucola(); Value reports = rucola.value("Reports"); for (OpportunityDTO oDto : dtos) { Entity opportunity; if (oDto.id != null) { opportunity = rucola.getEntityById(oDto.id); } else { opportunity = rucola.newEntity("Opportunity"); rucola.store(opportunity); } opportunity.set("prospect", reports.call("findOrCreateBusinessPartner", oDto.prospect)); opportunity.set("description", oDto.description); opportunity.set("phase", oDto.phase); opportunity.set("expectedCloseDate", oDto.closeDate); opportunity.set("responsible", reports.call("findOrCreateEmployee", oDto.responsibleEmployee)); opportunity.call("competitors-=", opportunity.get("competitors")); for (String competitor : oDto.competitors.split(",")) { opportunity.call("competitors+=", reports.call("findOrCreateBusinessPartner", competitor.trim())); } Map<String, Object> currencyInit = new HashMap<String, Object>(); currencyInit.put("code", "USD"); Value currency = rucola.value("Currency", currencyInit); Map<String, Object> amountInit = new HashMap<String, Object>(); amountInit.put("val", oDto.expectedSalesVolume); amountInit.put("currency", currency); Value amount = rucola.value("Amount", amountInit); opportunity.set("expectedSalesVolume", amount); opportunity.set("probability", oDto.probability); } rucola.commit(); } @Override public List<SalesByMonthDTO> getChartData() { Rucola rucola = createRucola(); Value reports = rucola.value("Reports"); Entity opps = (Entity) reports.call("getAllOpportunities"); return retrieveChartData(reports, opps); } @Override public List<SalesByMonthDTO> getChartData(Date transactionTime) { Rucola rucola = createRucola(); Value reports = rucola.value("Reports"); Entity opps = (Entity) reports.call("getAllOpportunitiesAt", transactionTime); return retrieveChartData(reports, opps); } private List<SalesByMonthDTO> retrieveChartData(Value reports, Entity opps) { System.out.println("Chart: found opportunities: " + opps.size()); Function f = reports.call("getExpectedRevenueByMonthAndPhaseCube").asFunction(); List<SalesByMonthDTO> sbm = new ArrayList<SalesByMonthDTO>(4); for (Value month : months) { SalesByMonthDTO sales = new SalesByMonthDTO(); sales.month = month.get("month").asInt() + " / " + month.get("year").asInt(); System.out.println(" > month: " + sales.month); sales.sales = new ArrayList<ExpectedSalesDTO>(3); for (String phase : phases) { ExpectedSalesDTO es = new ExpectedSalesDTO(); Value amount = f.call(opps, month, phase).asValue(); es.phase = phase; es.expectedVolume = amount.get("val").asInt(); System.out.println(amount); System.out.println(" > phase: " + es.phase); System.out.println(" > val : " + es.expectedVolume); sales.sales.add(es); } sbm.add(sales); } return sbm; } private void filterByPhase(String phase, List<OpportunityDTO> opps) { for (Iterator<OpportunityDTO> it = opps.iterator(); it.hasNext();) { OpportunityDTO dto = it.next(); if (!dto.phase.equals(phase)) { it.remove(); } } } private void filterByRevenue(int minRevenue, List<OpportunityDTO> opps) { for (Iterator<OpportunityDTO> it = opps.iterator(); it.hasNext();) { OpportunityDTO dto = it.next(); if (dto.expectedSalesVolume < minRevenue) { it.remove(); } } } }