r306 - in trunk/chorem-webmotion/src/main: java/org/chorem/webmotion java/org/chorem/webmotion/actions java/org/chorem/webmotion/actions/crm java/org/chorem/webmotion/actions/sales java/org/chorem/webmotion/render resources webapp/WEB-INF/jsp webapp/WEB-INF/jsp/crm webapp/WEB-INF/jsp/salesReports webapp/css webapp/js
Author: jcouteau Date: 2013-02-14 14:19:54 +0100 (Thu, 14 Feb 2013) New Revision: 306 Url: http://chorem.org/projects/chorem/repository/revisions/306 Log: fixes #862 : Introduce a sales module refs #882 : Introduce a CRM module Sales Module : Add funnel and power it with jquery Beginning of CRM module implementation with account page Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/AccountAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Company.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Project.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/QuotationAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/render/ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/render/RenderWikittyJson.java trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/account.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/company.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/editQuotation.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/project.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp trunk/chorem-webmotion/src/main/webapp/css/chorem-crm.css trunk/chorem-webmotion/src/main/webapp/css/chorem-sales.css Removed: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationAccepted.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationDraft.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationLead.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationSent.jsp Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesReportHelper.java trunk/chorem-webmotion/src/main/resources/mapping trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp trunk/chorem-webmotion/src/main/webapp/js/chorem.js Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/GenericAction.java 2013-02-14 13:19:54 UTC (rev 306) @@ -23,25 +23,6 @@ package org.chorem.webmotion.actions; import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimaps; -import java.io.ByteArrayInputStream; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpSession; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; @@ -55,9 +36,7 @@ import org.debux.webmotion.server.call.UploadFile; import org.debux.webmotion.server.mapping.Config; import org.debux.webmotion.server.render.Render; -import org.nuiton.wikitty.WikittyUtil; import org.nuiton.wikitty.entities.Element; -import org.nuiton.wikitty.entities.ElementField; import org.nuiton.wikitty.entities.Wikitty; import org.nuiton.wikitty.entities.WikittyExtension; import org.nuiton.wikitty.entities.WikittyImpl; @@ -66,8 +45,24 @@ import org.nuiton.wikitty.query.WikittyQueryMaker; import org.nuiton.wikitty.query.WikittyQueryParser; import org.nuiton.wikitty.query.WikittyQueryResult; -import org.nuiton.wikitty.query.conditions.True; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; +import java.io.ByteArrayInputStream; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + /** * * @author poussin @@ -553,6 +548,26 @@ public Render save(ChoremClient client, String id, String[] extension, Call call) { + Wikitty w = saveInternal(client, id, extension, call); + getContext().addInfoMessage("message", "Object saved"); + return renderURL("/wikitty/view/"+w.getWikittyId()); + } + + public Render saveJson(ChoremClient client, String id, String[] extension, Call call) { + Wikitty w = saveInternal(client, id, extension, call); + return renderJSON(w); + } + + /** + * Method used by save and saveJson to actually perform the save action + * @param client + * @param id + * @param extension + * @param call + * @return the saved wikitty + */ + protected Wikitty saveInternal(ChoremClient client, String id, String[] extension, Call call) { + log.debug("save: " + id); Wikitty w = client.restore(id); @@ -566,9 +581,7 @@ String error = setWikittyField(w, "", params); client.store(w); - getContext().addInfoMessage("message", "Object saved" + error); - - return renderURL("/wikitty/view/"+w.getWikittyId()); + return w; } Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/AccountAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/AccountAction.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/AccountAction.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,86 @@ +package org.chorem.webmotion.actions.crm; + +import org.chorem.ChoremClient; +import org.chorem.entities.Accepted; +import org.chorem.entities.Attachment; +import org.chorem.entities.ContactDetails; +import org.chorem.entities.Employee; +import org.chorem.entities.Note; +import org.chorem.entities.Quotation; +import org.chorem.entities.Rejected; +import org.debux.webmotion.server.WebMotionController; +import org.debux.webmotion.server.render.Render; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class AccountAction extends WebMotionController { + + public Render view(ChoremClient client, String id) { + //Recuperation du compte client + Employee account = client.restore(Employee.class, id, + "Employee.person"); + + //recuperation des contact details + WikittyQuery contactDetailsQuery = new WikittyQueryMaker().and() + .exteq(ContactDetails.EXT_CONTACTDETAILS) + .or() + .eq(ContactDetails.FQ_FIELD_CONTACTDETAILS_TARGET, account) + .eq(ContactDetails.FQ_FIELD_CONTACTDETAILS_TARGET, account.getPerson()) + .eq(ContactDetails.FQ_FIELD_CONTACTDETAILS_TARGET, account.getCompany()) + .end().setLimit(WikittyQuery.MAX); + WikittyQueryResult<ContactDetails> contacts = + client.findAllByQuery(ContactDetails.class, + contactDetailsQuery); + + //recuperation des notes + WikittyQuery notesQuery = new WikittyQueryMaker().and() + .exteq(Note.EXT_NOTE) + .eq(Note.FQ_FIELD_NOTE_TARGET, account) + .end().setLimit(WikittyQuery.MAX) + .addSortDescending(Note.ELEMENT_FIELD_NOTE_DATE); + WikittyQueryResult<Note> notes = + client.findAllByQuery(Note.class, notesQuery); + + //recuperation des collègues + WikittyQuery colleaguesQuery = new WikittyQueryMaker().and() + .exteq(Employee.EXT_EMPLOYEE) + .eq(Employee.ELEMENT_FIELD_EMPLOYEE_COMPANY, account.getCompany()) + .ne(Employee.ELEMENT_FIELD_EMPLOYEE_PERSON, account.getPerson()) + .end().setLimit(WikittyQuery.MAX); + WikittyQueryResult<Employee> colleagues = + client.findAllByQuery(Employee.class, colleaguesQuery); + + + //recuperation des documents + WikittyQuery documentsQuery = new WikittyQueryMaker().and() + .exteq(Attachment.EXT_ATTACHMENT) + .eq(Attachment.ELEMENT_FIELD_ATTACHMENT_TARGET, account) + .end().setLimit(WikittyQuery.MAX); + WikittyQueryResult<Attachment> documents = + client.findAllByQuery(Attachment.class, documentsQuery); + + //recuperation des devis en cours + WikittyQuery quotationsQuery = new WikittyQueryMaker().and() + .exteq(Quotation.EXT_QUOTATION) + .extne(Accepted.EXT_ACCEPTED) + .extne(Rejected.EXT_REJECTED) + .eq(Quotation.FQ_FIELD_QUOTATION_CUSTOMER, account) + .end().setLimit(WikittyQuery.MAX); + WikittyQueryResult<Quotation> quotations = + client.findAllByQuery(Quotation.class, + quotationsQuery); + + return renderView("crm/account.jsp", + "account", account, + "contacts", contacts.getAll(), + "quotations", quotations.getAll(), + "documents", documents.getAll(), + "colleagues", colleagues.getAll(), + "notes", notes.getAll() + ); + } +} Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Company.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Company.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Company.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,7 @@ +package org.chorem.webmotion.actions.crm; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class Company { +} Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Project.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Project.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/Project.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,7 @@ +package org.chorem.webmotion.actions.crm; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class Project { +} Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/QuotationAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/QuotationAction.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/QuotationAction.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,49 @@ +package org.chorem.webmotion.actions.crm; + +import org.apache.commons.lang3.StringUtils; +import org.chorem.ChoremClient; +import org.chorem.entities.Quotation; +import org.chorem.entities.QuotationImpl; +import org.debux.webmotion.server.WebMotionController; +import org.debux.webmotion.server.call.Call; +import org.debux.webmotion.server.render.Render; + +import java.util.Map; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class QuotationAction extends WebMotionController { + + public Render edit(ChoremClient client, String id, Call call) { + // on preload rien, le preload sera fait a la fin + Quotation quotation = client.restore(Quotation.class, id, ""); + + // si on ne retrouve pas la quotation demandée, on en crée une nouvelle + if (quotation == null) { + quotation = new QuotationImpl(); + } + + //récupère les paramètres (customer ou autre) et on les ajoute au devis + Map<String, Object> params = call.getExtractParameters(); + for (Map.Entry<String, Object> param : params.entrySet()) { + + String[] fqn = StringUtils.split(param.getKey(), "."); + + String[] values = (String[])param.getValue(); + + if (values.length == 1) { + quotation.setField(fqn[0], fqn[1], values[0]); + } else { + quotation.setField(fqn[0], fqn[1], values); + } + + //client.preload(Collections.singleton(quotation), ".*"); + + } + + return renderView("crm/editQuotation.jsp", "quotation", quotation); + } + + //view +} Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/FunnelAction.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,92 @@ +package org.chorem.webmotion.actions.sales; + +import org.chorem.ChoremClient; +import org.chorem.entities.Accepted; +import org.chorem.entities.Draft; +import org.chorem.entities.Quotation; +import org.chorem.entities.Rejected; +import org.chorem.entities.Sent; +import org.debux.webmotion.server.WebMotionController; +import org.debux.webmotion.server.render.Render; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class FunnelAction extends WebMotionController { + + /** + * Rend le tunnel de commande + * + * @param client + * @return + */ + public Render funnel(ChoremClient client) { + + // recuperation des quotations en statut lead + WikittyQuery leadQuotationQuery = new WikittyQueryMaker().and() + .exteq(Quotation.EXT_QUOTATION) + .extne(Draft.EXT_DRAFT) + .end().setLimit(WikittyQuery.MAX); + + WikittyQueryResult<Quotation> leads = + client.findAllByQuery(Quotation.class, leadQuotationQuery); + + // calcul des montants totaux lead + double leadAmount = 0; + double leadAmountHope = 0; + for (Quotation q : leads) { + leadAmount += q.getAmount(); + leadAmountHope += q.getAmount() * q.getConversionHope() / 100.0; + } + + // recuperation des quotations en statut draft + WikittyQuery draftQuotationQuery = new WikittyQueryMaker().and() + .exteq(Draft.EXT_DRAFT) + .extne(Sent.EXT_SENT) + .end().setLimit(WikittyQuery.MAX); + + WikittyQueryResult<Quotation> drafts = + client.findAllByQuery(Quotation.class, draftQuotationQuery); + + // calcul des montants totaux drafts + double draftAmount = 0; + double draftAmountHope = 0; + for (Quotation q : drafts) { + draftAmount += q.getAmount(); + draftAmountHope += q.getAmount() * q.getConversionHope() / 100.0; + } + + // recuperation des quotations en statut sent + WikittyQuery sentQuotationQuery = new WikittyQueryMaker().and() + .exteq(Sent.EXT_SENT) + .extne(Accepted.EXT_ACCEPTED) + .extne(Rejected.EXT_REJECTED) + .end().setLimit(WikittyQuery.MAX); + + WikittyQueryResult<Quotation> sents = + client.findAllByQuery(Quotation.class, sentQuotationQuery); + + // calcul des montants totaux + double sentAmount = 0; + double sentAmountHope = 0; + for (Quotation q : sents) { + sentAmount += q.getAmount(); + sentAmountHope += q.getAmount() * q.getConversionHope() / 100.0; + } + + return renderView( "salesReports/salesFunnel.jsp", + "leads", leads.getAll(), + "leadAmount", leadAmount, + "leadAmountHope", leadAmountHope, + "drafts", drafts.getAll(), + "draftAmount", draftAmount, + "draftAmountHope", draftAmountHope, + "sents", sents.getAll(), + "sentAmount", sentAmount, + "sentAmountHope", sentAmountHope); + + } +} Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesAction.java 2013-02-14 13:19:54 UTC (rev 306) @@ -26,15 +26,12 @@ import org.chorem.ChoremClient; import org.chorem.entities.Accepted; import org.chorem.entities.Draft; -import org.chorem.entities.Quotation; import org.chorem.entities.Rejected; import org.chorem.entities.Sent; import org.chorem.entities.Started; +import org.chorem.webmotion.render.RenderWikittyJson; import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.render.Render; -import org.nuiton.wikitty.query.WikittyQuery; -import org.nuiton.wikitty.query.WikittyQueryMaker; -import org.nuiton.wikitty.query.WikittyQueryResult; import java.util.Date; @@ -48,156 +45,37 @@ */ public class SalesAction extends WebMotionController { - /** - * Rend le tableau des leads - * - * @param client - * @return - */ - public Render lead(ChoremClient client) { - // recuperation des quotations en statut lead - WikittyQuery quotationQuery = new WikittyQueryMaker().and() - .exteq(Quotation.EXT_QUOTATION) - .extne(Draft.EXT_DRAFT) - .end().setLimit(WikittyQuery.MAX); - - WikittyQueryResult<Quotation> result = - client.findAllByQuery(Quotation.class, quotationQuery); - - // calcul des montants totaux - double amount = 0; - double amountHope = 0; - for (Quotation q : result) { - amount += q.getAmount(); - amountHope += q.getAmount() * q.getConversionHope() / 100.0; - } - - return renderView( "dashboardQuotationLead.jsp", - "quotations", result.getAll(), - "amount", amount, - "amountHope", amountHope); - - } - - /** - * Rend le tableau des propositions en statut draft (en cours de réponse) - * - * @param client - * @return - */ - public Render draft(ChoremClient client) { - // recuperation des quotations en statut draft - WikittyQuery quotationQuery = new WikittyQueryMaker().and() - .exteq(Draft.EXT_DRAFT) - .extne(Sent.EXT_SENT) - .end().setLimit(WikittyQuery.MAX); - - WikittyQueryResult<Quotation> result = - client.findAllByQuery(Quotation.class, quotationQuery); - - // calcul des montants totaux - double amount = 0; - double amountHope = 0; - for (Quotation q : result) { - amount += q.getAmount(); - amountHope += q.getAmount() * q.getConversionHope() / 100.0; - } - - return renderView("dashboardQuotationDraft.jsp", - "quotations", result.getAll(), - "amount", amount, - "amountHope", amountHope); - } - - /** - * Rend le tableau des propositions en attente de réponse - * - * @param client - * @return - */ - public Render sent(ChoremClient client) { - // recuperation des quotations en statut sent - WikittyQuery quotationQuery = new WikittyQueryMaker().and() - .exteq(Sent.EXT_SENT) - .extne(Accepted.EXT_ACCEPTED) - .extne(Rejected.EXT_REJECTED) - .end().setLimit(WikittyQuery.MAX); - - WikittyQueryResult<Quotation> result = - client.findAllByQuery(Quotation.class, quotationQuery); - - // calcul des montants totaux - double amount = 0; - double amountHope = 0; - for (Quotation q : result) { - amount += q.getAmount(); - amountHope += q.getAmount() * q.getConversionHope() / 100.0; - } - - return renderView("dashboardQuotationSent.jsp", - "quotations", result.getAll(), - "amount", amount, - "amountHope", amountHope); - } - - /** - * Rend le tableau des propositions acceptées mais non commencées - * - * @param client - * @return - */ - public Render accepted(ChoremClient client) { - // recuperation des quotations en statut accepted - WikittyQuery quotationQuery = new WikittyQueryMaker().and() - .exteq(Accepted.EXT_ACCEPTED) - .extne(Started.EXT_STARTED) - .end().setLimit(WikittyQuery.MAX); - - WikittyQueryResult<Quotation> result = - client.findAllByQuery(Quotation.class, quotationQuery); - - // calcul des montants totaux - double amount = 0; - for (Quotation q : result) { - amount += q.getAmount(); - } - - return renderView("dashboardQuotationAccepted.jsp", - "quotations", result.getAll(), - "amount", amount); - } - public Render send(ChoremClient client, String id) { Sent sent = client.restore(Sent.class, id); sent.setPostedDate(new Date()); - client.store(sent); - - return renderLastPage(); + sent = client.store(sent); + return new RenderWikittyJson(sent); } public Render accept(ChoremClient client, String id) { Accepted accepted = client.restore(Accepted.class, id); accepted.setAcceptedDate(new Date()); client.store(accepted); + return new RenderWikittyJson(accepted); + } - return renderLastPage(); + public Render reject(ChoremClient client, String id) { + Rejected rejected = client.restore(Rejected.class, id); + rejected.setRejectedDate(new Date()); + client.store(rejected); + return new RenderWikittyJson(rejected); } public Render start(ChoremClient client, String id) { - Started started = client.restore(Started.class, id); started.setStartedDate(new Date()); client.store(started); - - return renderLastPage(); - + return new RenderWikittyJson(started); } public Render answer(ChoremClient client, String id) { - Draft draft = client.restore(Draft.class, id); - client.store(draft); - - return renderLastPage(); - + Draft draft = client.restore(Draft.class, id,".*"); + draft = client.store(draft); + return new RenderWikittyJson(draft); } } Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesReportHelper.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesReportHelper.java 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/sales/SalesReportHelper.java 2013-02-14 13:19:54 UTC (rev 306) @@ -88,8 +88,6 @@ Date firstYear = client.findByQuery(Date.class, firstYearQuery); - System.out.println(firstYear); - Calendar c = Calendar.getInstance(); c.setTime(firstYear); return c.get(Calendar.YEAR); Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/render/RenderWikittyJson.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/render/RenderWikittyJson.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/render/RenderWikittyJson.java 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,86 @@ +package org.chorem.webmotion.render; + +import com.google.gson.Gson; +import org.apache.commons.lang3.StringUtils; +import org.debux.webmotion.server.call.Call; +import org.debux.webmotion.server.call.HttpContext; +import org.debux.webmotion.server.mapping.Mapping; +import org.debux.webmotion.server.render.Render; +import org.nuiton.wikitty.WikittyUtil; +import org.nuiton.wikitty.entities.BusinessEntity; +import org.nuiton.wikitty.entities.Wikitty; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +/** + * @author jcouteau <couteau@codelutin.com> + */ +public class RenderWikittyJson extends Render { + protected Map<String, Object> model; + + public RenderWikittyJson(Wikitty wikitty) { + this.model = createModel(wikitty); + } + + public RenderWikittyJson(BusinessEntity entity) { + this(WikittyUtil.getWikitty(entity)); + } + + public Map<String, Object> getModel() { + return model; + } + + @Override + public void create(Mapping mapping, Call call) throws IOException, ServletException { + HttpContext context = call.getContext(); + HttpServletResponse response = context.getResponse(); + + Object object = model; + if (model != null && model.size() == 1 + && model.keySet().contains(DEFAULT_MODEL_NAME)) { + object = model.values().toArray()[0]; + } + + response.setContentType("application/json"); + + Gson gson = new Gson(); + String json = gson.toJson(object); + PrintWriter out = context.getOut(); + out.print(json); + } + + Map<String,Object> getMeta(Wikitty wikitty){ + Map<String,Object> meta = new HashMap<String,Object>(); + meta.put("id", wikitty.getWikittyId()); + meta.put("version", wikitty.getWikittyVersion()); + meta.put("extensions", StringUtils.join(wikitty.getExtensionNames(), ",")); + return meta; + } + + Map<String,Object> getData(Wikitty wikitty){ + return wikitty.getFieldValue(); + } + + Map<String,Object> getPreloaded(Wikitty wikitty){ + Map<String,Object> preloadedModels = new HashMap<String, Object>(); + Map<String,Wikitty> preloaded = wikitty.getPreloaded(); + for (Map.Entry<String, Wikitty> entry : preloaded.entrySet()) { + preloadedModels.put(entry.getKey(),createModel(entry.getValue())); + } + return preloadedModels; + } + + Map<String,Object> createModel(Wikitty wikitty){ + Map<String,Object> model = new HashMap<String,Object>(); + model.put("meta", getMeta(wikitty)); + model.put("data", getData(wikitty)); + model.put("preloaded", getPreloaded(wikitty)); + return model; + } + +} Modified: trunk/chorem-webmotion/src/main/resources/mapping =================================================================== --- trunk/chorem-webmotion/src/main/resources/mapping 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/resources/mapping 2013-02-14 13:19:54 UTC (rev 306) @@ -9,7 +9,8 @@ #GET /wikitty/{extension}/view/* DecoratorFilter.decorate slotEntityFooter={extension}Footer.jsp * /wikitty-json/* DecoratorFilter.decorate wmDecoratorNo=true * /fragment/* DecoratorFilter.decorate wmDecoratorNo=true -GET /* DecoratorFilter.decorate +* /sales/funnel/json/* DecoratorFilter.decorate wmDecoratorNo=true +GET /* DecoratorFilter.decorate * /* AuthenticationFilter.check ##### #/!\# @@ -39,6 +40,7 @@ * /wikitty-json/search?q={query} action:GenericAction.searchJson * /wikitty-json/search?term={query} action:GenericAction.searchJson * /wikitty-json/get/{id} action:GenericAction.getById +* /wikitty-json/save action:GenericAction.saveJson * /fragment/dashboard/{method} action:DashboardAction.{method} * /fragment/dashboardHR/{method} action:DashboardHRAction.{method} * /fragment/sales/{method} action:sales.SalesAction.{method} @@ -51,7 +53,6 @@ * /hr/vacationDiv/{ids} action:HrAction.editVacationDiv * /hr/vacationRequest/save action:HrAction.saveVacationRequest * /hr/vacationRequest/delete/{id} action:HrAction.deleteVacationRequest -* /sales redirect:/report/sentQuotation * /salesMenu view:salesReports/menu.jsp * /sales/report/sentQuotation action:sales.SentQuotationsReportAction.sentQuotationPerMonth * /sales/report/acceptedQuotation action:sales.AcceptedQuotationsReportAction.acceptedQuotationPerMonth @@ -60,3 +61,8 @@ * /sales/report/salesPerProject/{project} action:sales.ProjectSalesReportAction.sales * /sales/report/salesPerAccount action:sales.SalesPerAccountReportAction.sales * /sales/report/salesPerAccount/{account} action:sales.AccountSalesReportAction.sales +* /sales/funnel action:sales.FunnelAction.funnel +* /sales/funnel/json/{method} action:sales.SalesAction.{method} +* /sales/funnel/json/{method}/{id} action:sales.SalesAction.{method} +* /crm/account/{id} action:crm.AccountAction.view +* /crm/quotation/edit/{id} action:crm.QuotationAction.edit Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/account.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/account.jsp (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/account.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,114 @@ +<%-- + #%L + Chorem webmotion + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2011 - 2012 CodeLutin + %% + This program 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. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --%> +<%@page contentType="text/html" pageEncoding="UTF-8"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> +<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> + +<head> + <link rel="stylesheet/less" href="<c:url value='/css/chorem-crm.css'/>"> +</head> + +<body> +<div class="row-fluid"> + + <h1>${account.getPerson(false).firstName} ${account.getPerson(false).lastName}</h1> + <h6><a href="<c:url value="/wikitty/view/${account.company}"/>">${account.getCompany(false).name}</a></h6> + <div class="elementId">${account.wikittyId}</div> + + <div class="contactDetails"> + <c:forEach var="contact" items="${contacts}"> + <p> + <c:if test="${contact.type=='adresse'}"> + <i class="icon-envelope"></i> + </c:if> + <c:if test="${contact.type=='telephone' || contact.type=='phone'}"> + <i class="icon-phone">tel</i> + </c:if> + <c:if test="${contact.type=='mail' || contact.type=='email'}"> + <i class="icon-laptop">@</i> + </c:if> + : <span wikittyId="${contact.wikittyId}" class="value">${contact.value}</span> + <i class="icon-edit contactDetail-edit-inline"></i> + </p> + </c:forEach> + </div> + + <!-- Left column --> + <div class="span3"> + <h6><i class="icon-user"></i> Collègues</h6> + <ul class="unstyled"> + <c:forEach var="colleague" items="${colleagues}"> + <li> + <small><a href="<c:url value="/crm/account/${colleague.wikittyId}"/>">${colleague.getPerson(false).firstName} ${colleague.getPerson(false).lastName}</a></small><br/> + </li> + </c:forEach> + </ul> + + </div> + + <!-- Center column --> + <div class="span5"> + <form class="add-note"> + Titre : <input type="text" name="title" id="note-title"/> + <textarea name="content" rows=5 cols=70 id="note-content"></textarea> + <input type="submit" class="btn btn-success" value="Nouvelle note"/> + </form> + <ul class="unstyled notes"> + <c:forEach var="note" items="${notes}"> + <li> + <h6 class="pull-left"><i class="icon-comment"></i> ${note.title}</h6> + <small class="pull-right note-date"><f:formatDate value="${note.date}" pattern="dd-MM-yyyy" /></small> + <div style="clear:both;"/> + <small>${note.content}</small> + </li> + </c:forEach> + </ul> + </div> + + <!-- Right column --> + <div class="span3"> + <h6><i class="icon-fire"></i> Devis</h6> + <ul class="unstyled"> + <c:forEach var="q" items="${quotations}"> + <li class="quotationsItem"> + <small><a href="<c:url value="/wikitty/view/${q.wikittyId}"/>">${q.description}</a></small><br/> + <small>${q.amount} € - status</small> + </li> + </c:forEach> + </ul> + + <h6><i class="icon-file"></i> Documents</h6> + <ul class="unstyled"> + <c:forEach var="document" items="${documents}"> + <li> + <small><a href="<c:url value="/wikitty/view/${document.wikittyId}/Attachment/content"/>">${document.name}</a></small><br/> + </li> + </c:forEach> + </ul> + </div> + +</div> + +<div style="clear:both;"/> +</body> \ No newline at end of file Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/company.jsp =================================================================== Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/editQuotation.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/editQuotation.jsp (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/editQuotation.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,40 @@ +<%-- + #%L + Chorem webmotion + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2011 - 2012 CodeLutin + %% + This program 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. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --%> +<%@page contentType="text/html" pageEncoding="UTF-8"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> +<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> + +<head> + <link rel="stylesheet/less" href="<c:url value='/css/chorem-crm.css'/>"> +</head> + +<body> +<div class="row-fluid"> + + <h1>${quotation.customer}</h1> + +</div> + +<div style="clear:both;"/> +</body> \ No newline at end of file Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/project.jsp =================================================================== Deleted: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationAccepted.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationAccepted.jsp 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationAccepted.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -1,67 +0,0 @@ -<%-- - #%L - Chorem webmotion - $Id:$ - $HeadURL:$ - %% - Copyright (C) 2011 - 2012 CodeLutin - %% - This program 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. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - #L% - --%> -<%@page contentType="text/html" pageEncoding="UTF-8"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> -<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> - -<h1>Projets acceptés, non commencés</h1> - -<table class="table table-striped table-bordered table-condensed"> - <thead> - <tr> - <th>Projet</th> - <th>Catégorie</th> - <th>Description</th> - <th>Client</th> - <th>Fournisseur</th> - <th>Chiffrage jours</th> - <th>Prix jour moyen</th> - <th>Montant</th> - <th>Date d'acceptation</th> - <th>Actions</th> - </tr> - </thead> - <c:forEach var="q" items="${quotations}"> - <tbody> - <tr> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/></td> - <td><w:display wikitty="${q.wikitty}" toString="%Quotation.description$s" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.supplier" label=""/></td> - <td class="number"><w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/></td> - <td class="currency"><f:formatNumber type="currency" value="${q.amount / q.estimatedDays}"/></td> - <td class="currency"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Accepted.acceptedDate" label=""/></td> - <td><a class="btn btn-success" href="<c:url value="/sales/start/${q.wikittyId}"/>">Start</a></td> - </tr> - </tbody> - </c:forEach> -</table> - - - -<dl class="dl-horizontal"> - <dt>Total</dt><dd><f:formatNumber type="currency" value="${amount}"/></dd> -</dl> \ No newline at end of file Deleted: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationDraft.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationDraft.jsp 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationDraft.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -1,70 +0,0 @@ -<%-- - #%L - Chorem webmotion - $Id:$ - $HeadURL:$ - %% - Copyright (C) 2011 - 2012 CodeLutin - %% - This program 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. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - #L% - --%> -<%@page contentType="text/html" pageEncoding="UTF-8"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> -<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> - -<h1>Propositions en cours de réponse</h1> - -<table class="table table-striped table-bordered table-condensed"> - <thead> - <tr> - <th>Projet</th> - <th>Catégorie</th> - <th>Description</th> - <th>Client</th> - <th>Fournisseur</th> - <th>Chiffrage jours</th> - <th>Taux de conversion</th> - <th>Prix jour moyen</th> - <th>Montant</th> - <th>Date limite d'envoi</th> - <th>Action</th> - </tr> - </thead> - <c:forEach var="q" items="${quotations}"> - <tbody> - <tr> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/></td> - <td><w:display wikitty="${q.wikitty}" toString="%Quotation.description$s" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.supplier" label=""/></td> - <td class="number"><w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/></td> - <td class="percent"><w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></td> - <td class="currency"><f:formatNumber type="currency" value="${q.amount / q.estimatedDays}"/></td> - <td class="currency"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Draft.sendingDate" label=""/></td> - <td><a class="btn btn-success" href="<c:url value="/sales/send/${q.wikittyId}"/>">Send</a></td> - </tr> - </tbody> - </c:forEach> -</table> - - - -<dl class="dl-horizontal"> - <dt>Total</dt><dd><f:formatNumber type="currency" value="${amount}"/></dd> - <dt>Hope</dt><dd><f:formatNumber type="currency" value="${amountHope}"/></dd> -</dl> \ No newline at end of file Deleted: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationLead.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationLead.jsp 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationLead.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -1,63 +0,0 @@ -<%-- - #%L - Chorem webmotion - $Id:$ - $HeadURL:$ - %% - Copyright (C) 2011 - 2012 CodeLutin - %% - This program 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. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - #L% - --%> -<%@page contentType="text/html" pageEncoding="UTF-8"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> -<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> - -<h1>Les leads</h1> - -<table class="table table-striped table-bordered table-condensed"> - <thead> - <tr> - <th>Projet</th> - <th>Catégorie</th> - <th>Description</th> - <th>Client</th> - <th>Fournisseur</th> - <th>Taux de conversion</th> - <th>Montant</th> - <th>Actions</th> - </tr> - </thead> - <c:forEach var="q" items="${quotations}"> - <tbody> - <tr> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/></td> - <td><w:display wikitty="${q.wikitty}" toString="%Quotation.description$s" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.supplier" label=""/></td> - <td class="percent"><w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></td> - <td class="currency"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></td> - <td><a class="btn btn-success" href="<c:url value="/sales/answer/${q.wikittyId}"/>">Answer</a></td> - </tr> - </tbody> - </c:forEach> -</table> - - -<dl class="dl-horizontal"> - <dt>Total</dt><dd><f:formatNumber type="currency" value="${amount}"/></dd> - <dt>Hope</dt><dd><f:formatNumber type="currency" value="${amountHope}"/></dd> -</dl> \ No newline at end of file Deleted: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationSent.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationSent.jsp 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardQuotationSent.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -1,70 +0,0 @@ -<%-- - #%L - Chorem webmotion - $Id:$ - $HeadURL:$ - %% - Copyright (C) 2011 - 2012 CodeLutin - %% - This program 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. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - #L% - --%> -<%@page contentType="text/html" pageEncoding="UTF-8"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> -<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> - -<h1>Propositions en attente de réponse</h1> - -<table class="table table-striped table-bordered table-condensed"> - <thead> - <tr> - <th>Projet</th> - <th>Catégorie</th> - <th>Description</th> - <th>Client</th> - <th>Fournisseur</th> - <th>Chiffrage jours</th> - <th>Taux de conversion</th> - <th>Prix jour moyen</th> - <th>Montant</th> - <th>Date d'envoi</th> - <th>Actions</th> - </tr> - </thead> - <c:forEach var="q" items="${quotations}"> - <tbody> - <tr> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/></td> - <td><w:display wikitty="${q.wikitty}" toString="%Quotation.description$s" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Quotation.supplier" label=""/></td> - <td class="number"><w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/></td> - <td class="percent"><w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></td> - <td class="currency"><f:formatNumber type="currency" value="${q.amount / q.estimatedDays}"/></td> - <td class="currency"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></td> - <td><w:display wikitty="${q.wikitty}" fqfield="Sent.postedDate" label=""/></td> - <td><a class="btn btn-success" href="<c:url value="/sales/accept/${q.wikittyId}"/>">Accept</a></td> - </tr> - </tbody> - </c:forEach> -</table> - - - -<dl class="dl-horizontal"> - <dt>Total</dt><dd><f:formatNumber type="currency" value="${amount}"/></dd> - <dt>Hope</dt><dd><f:formatNumber type="currency" value="${amountHope}"/></dd> -</dl> \ No newline at end of file Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -33,6 +33,10 @@ <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> <meta charset="UTF-8"/> + <link href="<c:url value='/css/chorem-crm.css'/>" rel="stylesheet" type="text/css"/> + <link href="<c:url value='/css/chorem-sales.css'/>" rel="stylesheet" type="text/css"/> + + <link rel="stylesheet/less" href="<c:url value='/css/chorem.less '/>"> <%-- import via nuiton-js to add js or css show WEB-INF/wro.xml --%> <link href="<c:url value='/nuiton-js/chorem.css'/>" rel="stylesheet" type="text/css"/> @@ -114,15 +118,13 @@ </li> <li class="dropdown nav-group"> <!-- around sales --> - <a href="<c:url value="/sales"/>">Commercial</a> + <a>Commercial</a> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <b class="caret"></b> </a> <ul class="dropdown-menu"> - <li><a href="<c:url value="/sales/lead"/>"><i class="icon-th-list icon-black"></i> Leads</a></li> - <li><a href="<c:url value="/sales/draft"/>"><i class="icon-th-list icon-black"></i> En cours</a></li> - <li><a href="<c:url value="/sales/sent"/>"><i class="icon-th-list icon-black"></i> Attente réponse</a></li> - <li><a href="<c:url value="/sales/accepted"/>"><i class="icon-th-list icon-black"></i> Acceptés</a></li> + <li><a href="<c:url value="/sales/funnel"/>"><i class="icon-tasks icon-black"></i> Tunnel de commande</a></li> + <li><a href="<c:url value="/sales/report/sales"/>"><i class="icon-th-list icon-black"></i> Rapports</a></li> </ul> </li> <li class="dropdown nav-group"> Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/salesReports/salesFunnel.jsp 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,137 @@ +<%-- + #%L + Chorem webmotion + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2011 - 2012 CodeLutin + %% + This program 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. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --%> +<%@page contentType="text/html" pageEncoding="UTF-8"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> +<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> + +<head> + <link rel="stylesheet/less" href="<c:url value='/css/chorem-sales.css'/>"> +</head> + +<body> +<div class="row-fluid"> + + <ul id="funnelTabs" class="nav nav-tabs" data-tabs="funnelTabs"> + <li class="active" > + <a href="#lead" data-toggle="tab">Leads</a> + </li> + <li> + <a href="#draft" data-toggle="tab">Draft</a> + </li> + <li> + <a href="#sent" data-toggle="tab">Sent</a> + </li> + </ul> + + <div id="funnelTabsContent" class="tab-content"> + + <!-- LEADS TAB --> + <div class="tab-pane active" id="lead"> + <ul class="unstyled leads"> + <c:forEach var="q" items="${leads}"> + <li class="salesFunnelItem"> + <div class="pull-left"> + <a href="<c:url value="/wikitty/edit/${q.wikittyId}"/>"> + <i class="icon-edit"></i> + </a> + <small> + <a href="<c:url value="/wikitty/Employee/view/${q.customer}"/>"> + <w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/> + </a> + </small> + <p> + <span class="salesFunnelItemTitle"> + <a class="name-link" href="<c:url value="/wikitty/Project/view/${q.project}"/>"> + <w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/> + </a> + </span> - <small> + <w:display wikitty="${q.wikitty}" fqfield="Quotation.description" label=""/> + </small> + </p> + </div> + <a class="btn btn-success pull-right salesFunnelItemButton lead" wikittyId="${q.wikittyId}">Répondre</a> + <div class="pull-right salesFunnelItemPrice"> + <p class="salesFunnelItemTitle"> + <w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/> + </p> + <small> + <w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/> - + <w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/>j + </small> + </div> + <div style="clear:both;"/> + </li> + </c:forEach> + </ul> + </div> + + <!-- DRAFT TAB --> + <div class="tab-pane" id="draft"> + <ul class="unstyled drafts"> + <c:forEach var="q" items="${drafts}"> + <li class="salesFunnelItem draft"> + <div class="pull-left"> + <a href="<c:url value="/wikitty/edit/${q.wikittyId}"/>"><i class="icon-edit"></i></a> + <small><a href="<c:url value="/wikitty/Employee/view/${q.customer}"/>"><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></a></small> + <p><span class="salesFunnelItemTitle"><a class="name-link" href="<c:url value="/wikitty/Project/view/${q.project}"/>"><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></a></span> - <small><w:display wikitty="${q.wikitty}" fqfield="Quotation.description" label=""/></small></p> + </div> + <a class="btn btn-success pull-right salesFunnelItemButton draft" wikittyId="${q.wikittyId}">Envoyer</a> + <div class="pull-right salesFunnelItemPrice"> + <p class="salesFunnelItemTitle"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></p> + <small><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/> - <w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/>j - <w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></small> + </div> + <div style="clear:both;"/> + </li> + </c:forEach> + </ul> + </div> + + <!-- SENT TAB --> + <div class="tab-pane" id="sent"> + <ul class="unstyled sents"> + <c:forEach var="q" items="${sents}"> + <li class="salesFunnelItem sent"> + <div class="pull-left"> + <a href="<c:url value="/wikitty/edit/${q.wikittyId}"/>"><i class="icon-edit"></i></a> + <small><a href="<c:url value="/wikitty/Employee/view/${q.customer}"/>"><w:display wikitty="${q.wikitty}" fqfield="Quotation.customer" label=""/></a></small> + <p><span class="salesFunnelItemTitle"><a class="name-link" href="<c:url value="/wikitty/Project/view/${q.project}"/>"><w:display wikitty="${q.wikitty}" fqfield="Quotation.project" label=""/></a></span> - <small><w:display wikitty="${q.wikitty}" fqfield="Quotation.description" label=""/></small></p> + </div> + <a class="btn btn-success pull-right salesFunnelItemButton sent toAccepted" wikittyId="${q.wikittyId}">Accepté</a> + <a class="btn btn-danger pull-right salesFunnelItemButton sent toRejected" wikittyId="${q.wikittyId}">Rejeté</a> + <div class="pull-right salesFunnelItemPrice"> + <p class="salesFunnelItemTitle"><w:display wikitty="${q.wikitty}" fqfield="Quotation.amount" label=""/></p> + <small><w:display wikitty="${q.wikitty}" fqfield="Quotation.category" label=""/> - <w:display wikitty="${q.wikitty}" fqfield="Quotation.estimatedDays" label=""/>j - <w:display wikitty="${q.wikitty}" fqfield="Quotation.conversionHope" label=""/></small> + </div> + <div style="clear:both;"/> + </li> + </c:forEach> + </ul> + </div> + + </div> + +</div> + +<div style="clear:both;"/> +</body> \ No newline at end of file Added: trunk/chorem-webmotion/src/main/webapp/css/chorem-crm.css =================================================================== --- trunk/chorem-webmotion/src/main/webapp/css/chorem-crm.css (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/css/chorem-crm.css 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,29 @@ +.contactDetails, .quotationsItem{ + background-color: #F5F5F5; + border: 1px solid #E3E3E3; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05) inset; + margin-bottom: 10px; + min-height: 20px; + margin-left:0; + padding: 5px; +} + +.quotationsItem{ + background-color: #F5F5F5; + border: 1px solid #E3E3E3; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05) inset; + margin-bottom: 5px; + min-height: 20px; + margin-left:0; + padding: 1px; +} + +.note-date{ + margin: 10px 0; +} + +.elementId{ + display: none; +} \ No newline at end of file Added: trunk/chorem-webmotion/src/main/webapp/css/chorem-sales.css =================================================================== --- trunk/chorem-webmotion/src/main/webapp/css/chorem-sales.css (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/css/chorem-sales.css 2013-02-14 13:19:54 UTC (rev 306) @@ -0,0 +1,22 @@ +.salesFunnelItem{ + background-color: #F5F5F5; + border: 1px solid #E3E3E3; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05) inset; + margin-bottom: 10px; + min-height: 20px; + padding: 5px; +} + +.salesFunnelItemTitle{ + font-size: 21px; + font-weight: 200; +} + +.salesFunnelItemPrice { + margin-right:10px; +} + +.salesFunnelItemButton { + margin-top:10px; +} \ No newline at end of file Modified: trunk/chorem-webmotion/src/main/webapp/js/chorem.js =================================================================== --- trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-01-26 10:23:12 UTC (rev 305) +++ trunk/chorem-webmotion/src/main/webapp/js/chorem.js 2013-02-14 13:19:54 UTC (rev 306) @@ -127,3 +127,293 @@ }) }); + +$(document).ready(function($) { + + // ******************************************************************** + // * ACCOUNT EDITING * + // ******************************************************************** + + //Edition inline des ContactDetails + $(".contactDetail-edit-inline").click(function() { + var button = $(this); + var span = button.parent().children("span[wikittyId].value"); + var value = span.text(); + var id = span.attr('wikittyId'); + var input = $("<input type='text' value='"+value+"'></input>"); + input.keyup(function (e) { + if (e.keyCode == 13) { + value = input.val(); + $.get("/chorem/wikitty-json/save?id="+id+"&extension=ContactDetails&ContactDetails.value="+value, function(){ + //success + span.text(value); + input.replaceWith(span); + //ajoute un logo ok + var okIcon = $("<i class='icon-ok'></i>"); + button.after(okIcon); + //timeout 3s + setTimeout(function() { okIcon.remove(); }, 3000); + }).fail(function(){ + //fail + input.replaceWith(span); + //ajoute un logo erreur + var errorIcon = $("<i class='icon-exclamation-sign'></i>"); + button.after(errorIcon); + //timeout 3s + setTimeout(function() { errorIcon.remove(); }, 3000); + + }); + + } else if (e.keyCode == 27) { + input.replaceWith(span); + } + }); + input.blur(function() { + input.replaceWith(span); + }); + + span.replaceWith(input); + }); + + //Ajout d'une note sur un compte client + $(".add-note").submit(function() { + var form = $(this).get(0); + var title = $("#note-title").val(); + var content = $("#note-content").val(); + var id = $(".elementId").html(); + var date = $.datepicker.formatDate('dd/mm/yy', new Date()); + + $.get("/chorem/wikitty-json/save?extension=Note&Note.target=" + id + + "&Note.title=" + title + + "&Note.content=" + content + + "&Note.date="+date,function(data){ + //success + var note; + $.each(data, function(key, val) { + if (key=="fieldValue"){ + var savedDate = new Date(val["Note.date"]); + + note = $('<li><h6 class="pull-left"><i class="icon-comment"></i> ' + + val["Note.title"] +'</h6><small class="pull-right note-date">' + + $.datepicker.formatDate('dd-mm-yy', savedDate) + + '</small><div style="clear:both;"/><small>' + + val["Note.content"] + '</small></li>'); + } + }); + var notes = $(".notes"); + notes.prepend(note); + form.reset(); + }).fail(function(){ + //fail + //TODO JC20130210 retour utilisateur + + }); + + return false; + }); + + // ******************************************************************** + // * SALES FUNNEL * + // ******************************************************************** + + function leadToDraft() { + var id = $(this).attr('wikittyId'); + var oldQuotation = $(this).parent(); + $.get("/chorem/sales/funnel/json/answer/" + id,function(data){ + //success + + var wikitty = data.data; + + var li = $("<li></li>").addClass("salesFunnelItem draft"); + + //leftDiv + var leftDiv = $("<div></div>").addClass("pull-left"); + var aIconEdit = $("<a></a>") + .attr("href","/chorem/wikitty/edit/" + data.meta.id); + var iconEdit = $("<i></i>").addClass("icon-edit"); + aIconEdit.append(iconEdit); + leftDiv.append(aIconEdit); + var smallAccount = $("<small></small>"); + if (wikitty["Quotation.customer"]!=null){ + var customer = data.preloaded[wikitty["Quotation.customer"]]; + var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"]; + var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"]; + var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"]; + } + var aAccount = $("<a></a>") + .text(firstName + " " + lastName + " (" + company + ")") + .attr("href","/chorem/wikitty/Employee/view/" + wikitty["Quotation.customer"]); + smallAccount.append(aAccount); + leftDiv.append(smallAccount); + var leftP = $("<p> - </p>"); + var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle'); + + if (wikitty["Quotation.project"]!=null) { + var aProject = $("<a/>") + .addClass("nameLink") + .attr("href" , "/chorem/wikitty/Project/view/" + wikitty["Quotation.project"]) + .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]); + } + itemTitleSpan.append(aProject); + var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]); + leftP.append(descriptionSmall); + leftP.prepend(itemTitleSpan); + leftDiv.append(leftP); + + //button + var aSend = $('<a/>') + .addClass("btn btn-success pull-right salesFunnelItemButton draft") + .text("Envoyer") + .click(draftToSent); + + //rightDiv + var rightDiv = $("<div>").addClass("pull-right"); + var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €"); + if (wikitty["Quotation.category"] != null) { + var smallInfo = $("<small>") + .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"] + + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' + + wikitty["Quotation.conversionHope"] + "%"); + } + rightDiv.append(rightP); + rightDiv.append(smallInfo); + + //clear:both + var clearBoth=$("<div style='clear:both;'/>") + + li.append(leftDiv); + li.append(aSend); + li.append(rightDiv); + li.append(clearBoth); + + var drafts = $(".drafts"); + drafts.append(li); + oldQuotation.slideUp(); + + }).fail(function(){ + //fail + //TODO JC20130212 retour utilisateur + }); + } + + function draftToSent() { + var id = $(this).attr('wikittyId'); + var oldQuotation = $(this).parent(); + $.get("/chorem/sales/funnel/json/send/" + id,function(data){ + //success + + var wikitty = data.data; + + var li = $("<li></li>").addClass("salesFunnelItem draft"); + + //leftDiv + var leftDiv = $("<div></div>").addClass("pull-left"); + var aIconEdit = $("<a></a>") + .attr("href","/chorem/wikitty/edit/" + data.meta.id); + var iconEdit = $("<i></i>").addClass("icon-edit"); + aIconEdit.append(iconEdit); + leftDiv.append(aIconEdit); + var smallAccount = $("<small></small>"); + if (wikitty["Quotation.customer"]!=null){ + var customer = data.preloaded[wikitty["Quotation.customer"]]; + var firstName = customer.preloaded[customer.data["Employee.person"]].data["Person.firstName"]; + var lastName = customer.preloaded[customer.data["Employee.person"]].data["Person.lastName"]; + var company = customer.preloaded[customer.data["Employee.company"]].data["Company.name"]; + } + var aAccount = $("<a></a>") + .text(firstName + " " + lastName + " (" + company + ")") + .attr("href","/chorem/wikitty/Employee/view/" + wikitty["Quotation.customer"]); + smallAccount.append(aAccount); + leftDiv.append(smallAccount); + var leftP = $("<p> - </p>"); + var itemTitleSpan = $('<span></span>').addClass('salesFunnelItemTitle'); + + if (wikitty["Quotation.project"]!=null) { + var aProject = $("<a/>") + .addClass("nameLink") + .attr("href" , "/chorem/wikitty/Project/view/" + wikitty["Quotation.project"]) + .text(data.preloaded[wikitty["Quotation.project"]].data["Project.name"]); + } + itemTitleSpan.append(aProject); + var descriptionSmall = $('<small/>').text(wikitty["Quotation.description"]); + leftP.append(descriptionSmall); + leftP.prepend(itemTitleSpan); + leftDiv.append(leftP); + + //button + var aAccepted = $('<a/>') + .addClass("btn btn-success pull-right salesFunnelItemButton sent toAccepted") + .text("Accepté") + .click(sentToAccepted); + var aRejected = $('<a/>') + .addClass("btn btn-danger pull-right salesFunnelItemButton sent toRejected") + .text("Rejeté") + .click(sentToRejected); + + //rightDiv + var rightDiv = $("<div>").addClass("pull-right"); + var rightP = $("<p>").addClass("salesFunnelItemTitle").text(wikitty["Quotation.amount"] +" €"); + if (wikitty["Quotation.category"] != null) { + var smallInfo = $("<small>") + .text(data.preloaded[wikitty["Quotation.category"]].data["WikittyTreeNode.name"] + + ' - ' + wikitty["Quotation.estimatedDays"] + 'j - ' + + wikitty["Quotation.conversionHope"] + "%"); + } + rightDiv.append(rightP); + rightDiv.append(smallInfo); + + //clear:both + var clearBoth=$("<div style='clear:both;'/>") + + li.append(leftDiv); + li.append(aAccepted); + li.append(aRejected); + li.append(rightDiv); + li.append(clearBoth); + + var sents = $(".sents"); + sents.append(li); + oldQuotation.slideUp(); + + }).fail(function(){ + //fail + //TODO JC20130212 retour utilisateur + }); + } + + function sentToRejected(){ + var id = $(this).attr('wikittyId'); + var oldQuotation = $(this).parent(); + $.get("/chorem/sales/funnel/json/reject/" + id,function(){ + //success + oldQuotation.slideUp(); + }).fail(function(){ + //fail + //TODO JC20130212 retour utilisateur + }); + } + + function sentToAccepted(){ + var id = $(this).attr('wikittyId'); + var oldQuotation = $(this).parent(); + $.get("/chorem/sales/funnel/json/accept/" + id,function(){ + //success + oldQuotation.slideUp(); + }).fail(function(){ + //fail + //TODO JC20130212 retour utilisateur + }); + } + + //Passage d'un lead -> draft + $("a.lead").click(leadToDraft); + + //Passage d'un draft -> sent + $("a.draft").click(draftToSent); + + //Passage d'un sent vers accepted + $("a.toAccepted").click(sentToAccepted); + + //Passage d'un sent vers rejected + $("a.toRejected").click(sentToRejected); +}); \ No newline at end of file
participants (1)
-
jcouteau@users.chorem.org