r384 - in trunk: chorem-entities/src/main/java/org/chorem chorem-entities/src/main/java/org/chorem/project chorem-webmotion/src/main/java/org/chorem/webmotion/actions chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project chorem-webmotion/src/main/resources chorem-webmotion/src/main/webapp/WEB-INF/jsp chorem-webmotion/src/main/webapp/js
Author: meynier Date: 2013-08-14 16:17:38 +0200 (Wed, 14 Aug 2013) New Revision: 384 Url: http://chorem.org/projects/chorem/repository/revisions/384 Log: Changed tabulation into spaces and added the adc dashboard page. Added a level of alert \(info\). Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/AdcDashboardAction.java trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardAdc.jsp trunk/chorem-webmotion/src/main/webapp/js/dashboardAdc.js Modified: trunk/chorem-entities/src/main/java/org/chorem/ChoremClient.java trunk/chorem-entities/src/main/java/org/chorem/ChoremUtil.java trunk/chorem-entities/src/main/java/org/chorem/project/AdcCalculation.java trunk/chorem-entities/src/main/java/org/chorem/project/QuotationCalculation.java trunk/chorem-entities/src/main/java/org/chorem/project/TotalQuotationCalculation.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/EmployeeEditAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/GanttAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationData.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/TaskData.java trunk/chorem-webmotion/src/main/resources/mapping trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp trunk/chorem-webmotion/src/main/webapp/js/employeeEdit.js Modified: trunk/chorem-entities/src/main/java/org/chorem/ChoremClient.java =================================================================== --- trunk/chorem-entities/src/main/java/org/chorem/ChoremClient.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-entities/src/main/java/org/chorem/ChoremClient.java 2013-08-14 14:17:38 UTC (rev 384) @@ -389,7 +389,7 @@ WikittyQueryResult<Task> taskResult = findAllByQuery(Task.class, taskQuery); return taskResult.getAll(); } - + /** * Fetch the times from the given task * @param t Task @@ -400,17 +400,17 @@ WikittyQuery timeQuery = new WikittyQueryMaker() .eq(Time.ELEMENT_FIELD_TIME_TASK, t) .end(); - + timeQuery.addSortAscending(Quotation.ELEMENT_FIELD_INTERVAL_BEGINDATE); - + WikittyQueryResult<Time> timeResult = findAllByQuery(Time.class, timeQuery); - + return timeResult.getAll(); } /** * Returns the daily return of the given empoyee - * @param e - * @return + * @param e employee + * @return daily return of employee */ public double getDailyReturn(Employee e) { @@ -419,17 +419,21 @@ if(e.getCompany(false) != null) companyW = restore(e.getCompany(false).getWikittyId()); + double dailyReturn = 0; + if(w.hasExtension(EmployeeHR.EXT_EMPLOYEEHR) && w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN) != 0) { - return w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN); + dailyReturn = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN); } else if(companyW != null && companyW.hasExtension(CompanyHR.EXT_COMPANYHR) && companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN) != 0) { - return companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN); + dailyReturn = companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN); } else { - return this.getConfiguration().getDailyReturn(); + dailyReturn = this.getConfiguration().getDailyReturn(); } + + return dailyReturn; } /** * Returns the daily hours worked of the given empoyee @@ -443,20 +447,24 @@ if(e.getCompany(false) != null) companyW = restore(e.getCompany(false).getWikittyId()); + double dailyHoursWorked = 0; + if(companyW.hasExtension(CompanyHR.EXT_COMPANYHR) && companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR,CompanyHR.FIELD_COMPANYHR_DAILYHOURSWORKED) != 0) { if(w.hasExtension(EmployeeHR.EXT_EMPLOYEEHR) && w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PARTIALTIME) != 0) { - return companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, CompanyHR.FIELD_COMPANYHR_DAILYHOURSWORKED) * + dailyHoursWorked = companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, CompanyHR.FIELD_COMPANYHR_DAILYHOURSWORKED) * (w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PARTIALTIME)/100); } else { - return companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, CompanyHR.FIELD_COMPANYHR_DAILYHOURSWORKED); + dailyHoursWorked = companyW.getFieldAsDouble(CompanyHR.EXT_COMPANYHR, CompanyHR.FIELD_COMPANYHR_DAILYHOURSWORKED); } } else { - return this.getConfiguration().getDailyHoursWorked(); + dailyHoursWorked = this.getConfiguration().getDailyHoursWorked(); } + + return dailyHoursWorked; } Modified: trunk/chorem-entities/src/main/java/org/chorem/ChoremUtil.java =================================================================== --- trunk/chorem-entities/src/main/java/org/chorem/ChoremUtil.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-entities/src/main/java/org/chorem/ChoremUtil.java 2013-08-14 14:17:38 UTC (rev 384) @@ -69,6 +69,12 @@ return getPeriodInSeconds(start, end)/3600; } + /** + * Calculates the number of working days between two dates + * @param begin start date + * @param end end date + * @return number of working days + */ public static int getWorkingDays(Date begin, Date end) { GregorianCalendar gBegin = new GregorianCalendar(); GregorianCalendar gEnd = new GregorianCalendar(); Modified: trunk/chorem-entities/src/main/java/org/chorem/project/AdcCalculation.java =================================================================== --- trunk/chorem-entities/src/main/java/org/chorem/project/AdcCalculation.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-entities/src/main/java/org/chorem/project/AdcCalculation.java 2013-08-14 14:17:38 UTC (rev 384) @@ -19,17 +19,36 @@ import org.nuiton.wikitty.query.WikittyQueryMaker; import org.nuiton.wikitty.query.WikittyQueryResult; - +/** + * Makes the calculation for the adc. + * It can calculate the adc of one or more employee by using the method getAdc or getMultipleAdc + * Usage : construct the object with an employee or a list of employees and call the method + * getAdc() or getMultipleAdc() + * + * @author gwenn + * + */ public class AdcCalculation { + /** Chorme Client*/ protected ChoremClient client; + /** Company of the employee(s) */ protected Company company; + /** Employee */ protected EmployeeHR employee; + /** List of employees */ protected List<EmployeeHR> employees; - + + /** start date of the year*/ protected Date start; + /** end date of the year*/ protected Date end; - + + /** + * Construct the object for calculating the adc of an employee + * @param client chorem client + * @param employee employee withthe adc to calculate + */ public AdcCalculation(ChoremClient client, EmployeeHR employee) { this.employee = employee; this.company = employee.getCompany(false); @@ -37,7 +56,12 @@ this.employees = null; initDate(); } - + + /** + * Construct the object for calculating the adc of a list of employees + * @param client chorem client + * @param employees employees with the adc to calculate + */ public AdcCalculation(ChoremClient client, List<EmployeeHR> employees) { this.employees = employees; this.company = employees.get(0).getCompany(false); @@ -45,31 +69,46 @@ this.employee = null; initDate(); } - - private void initDate() { + + /** + * Initiate the start and end date to the beginning and end of the year + * TODO : Manage this in the configuration of chorem + */ + protected void initDate() { + Calendar cstart = new GregorianCalendar(); + cstart.add(Calendar.YEAR, -1); + cstart.set(Calendar.MONTH, Calendar.JANUARY); + cstart.set(Calendar.DAY_OF_MONTH, 1); + cstart.set(Calendar.HOUR_OF_DAY, 0); + cstart.set(Calendar.MINUTE, 0); + cstart.set(Calendar.SECOND, 0); + cstart.set(Calendar.MILLISECOND, 0); + Calendar cend = new GregorianCalendar(); cend.add(Calendar.YEAR, -1); cend.set(Calendar.MONTH, Calendar.DECEMBER); cend.set(Calendar.DAY_OF_MONTH, 31); + cend.set(Calendar.HOUR_OF_DAY, 23); + cend.set(Calendar.MINUTE, 59); + cend.set(Calendar.SECOND, 59); + cend.set(Calendar.MILLISECOND, 999); + - Calendar cstart = new GregorianCalendar(); - cstart.add(Calendar.YEAR, -1); - cstart.set(Calendar.MONTH, Calendar.JANUARY); - cstart.set(Calendar.DAY_OF_MONTH, 1); - + start = cstart.getTime(); end = cend.getTime(); } - - + + /** * Calculates the total gains made by the company in one year - * @return + * TODO : Use wikitty function for sum. + * @return total expenses */ public double getTotalExpenses() { //Construct the query - //TODO : Use wikitty function for sum. + WikittyQuery expenseQuery = new WikittyQueryMaker() .and() .exteq(FinancialTransaction.EXT_FINANCIALTRANSACTION) //of type financial transaction @@ -117,9 +156,14 @@ return (daysInYear * (partialTime/100) * (productivityRate/100)); } - + + /** + * Returns the real number of procuctive days in year, which is the sum of all the time object by the employee + * @param e + * @return + */ public double getRealNumberOfProductiveDays(EmployeeHR e) { - + //fetch the times of all the employees of the company that have worked between $start an $end WikittyQuery timeQuery = new WikittyQueryMaker() .and() @@ -135,15 +179,17 @@ double total = 0; for(Time t : result.getAll()) { total += ChoremUtil.getPeriodInHours(t.getBeginDate(), t.getEndDate()); - + } return (total/ client.getDailyHoursWorked(e) ) - * (e.getProductivityRate()/100); + * (e.getProductivityRate()/100); } /** - * + * calculates the full time cost in a year + * @param e + * @param real true if the real time is needed * @return */ public double getYearCost(EmployeeHR e, boolean real) { @@ -157,6 +203,11 @@ return result; } + /** + * calculates the full time cost in a year for all the employees in the company + * @param real true if the real time is needed + * @return + */ public double getTotalYearCost(boolean real) { double total = 0; @@ -220,8 +271,8 @@ * @return */ public double getAdc(boolean real) { - + double expenses = getTotalExpenses(); double productiveDays = 0; if(real) { @@ -230,7 +281,7 @@ else { productiveDays = getEstimatedNumberOfProductiveDays(employee); } - + double cost = getYearCost(employee, real); double totalCost = getTotalYearCost(real); @@ -238,13 +289,13 @@ System.out.println("PROD DAYS : " + productiveDays); System.out.println("COST : " + expenses); System.out.println("TOTAL COST : " + expenses); - + double adc = ( (expenses * cost) / totalCost ) / productiveDays; return adc; } - + public double getAdc() { return getAdc(false); } @@ -257,56 +308,55 @@ * @param client * @param employees * @return - */ - public Map<String, Double> getMultipleAdc(boolean real) { - if(employees.size() == 0) - return null; - - Calendar cend = new GregorianCalendar(); + */ + public Map<String, Double> getMultipleAdc(boolean real) { + if(employees.size() == 0) + return null; + + Calendar cend = new GregorianCalendar(); cend.add(Calendar.YEAR, -1); cend.set(Calendar.MONTH, Calendar.DECEMBER); cend.set(Calendar.DAY_OF_MONTH, 31); - + Calendar cstart = new GregorianCalendar(); cstart.add(Calendar.YEAR, -1); cstart.set(Calendar.MONTH, Calendar.JANUARY); cstart.set(Calendar.DAY_OF_MONTH, 1); - + Date start = cstart.getTime(); Date end = cend.getTime(); - //Calculate all the "static" values before + //Calculate all the "static" values before - double expenses = getTotalExpenses(); + double expenses = getTotalExpenses(); double totalCost = getTotalYearCost(real); - //Then, for each employee + //Then, for each employee - HashMap<String, Double> adcs = new HashMap<String, Double>(); - for(EmployeeHR e : employees) { - this.employee = e; - - double productiveDays = 0; - if(real) { - productiveDays = getRealNumberOfProductiveDays(e); - } - else { - productiveDays = getEstimatedNumberOfProductiveDays(e); - } - double cost = getYearCost(e, real); + HashMap<String, Double> adcs = new HashMap<String, Double>(); + for(EmployeeHR e : employees) { + this.employee = e; - Double adc = ( ( (expenses * cost) / totalCost ) / productiveDays); - if(adc.isNaN()) { - adc = 0.0; - } - adcs.put(e.getWikittyId(),adc); - } + double productiveDays = 0; + if(real) { + productiveDays = getRealNumberOfProductiveDays(e); + } + else { + productiveDays = getEstimatedNumberOfProductiveDays(e); + } + double cost = getYearCost(e, real); - return adcs; + Double adc = ( ( (expenses * cost) / totalCost ) / productiveDays); + if(adc.isNaN()) { + adc = 0.0; + } + adcs.put(e.getWikittyId(),adc); + } - } + return adcs; + } @@ -314,4 +364,5 @@ + } Modified: trunk/chorem-entities/src/main/java/org/chorem/project/QuotationCalculation.java =================================================================== --- trunk/chorem-entities/src/main/java/org/chorem/project/QuotationCalculation.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-entities/src/main/java/org/chorem/project/QuotationCalculation.java 2013-08-14 14:17:38 UTC (rev 384) @@ -10,84 +10,88 @@ public class QuotationCalculation extends Calculation<Quotation> { - - private List<Task> tasks = null; - - public QuotationCalculation(Quotation q, ChoremClient client) { - super(q, q.getAmount(), q.getEstimatedDays(), client); - } - @Override - public double realDays() { - double totalTime = 0; - //For each task - for(Task t : client.getTasks(e)) { - //Sum the real days of the tasks objects - totalTime+=new TaskCalculation(t, client).getRealDays(); - } - return totalTime; + private List<Task> tasks = null; - } + public QuotationCalculation(Quotation q, ChoremClient client) { + super(q, q.getAmount(), q.getEstimatedDays(), client); + } - @Override - public HashMap<Employee, Double> getPercentages() { - HashMap<Employee, Double> percentages = new HashMap<Employee, Double>(); - double totalDays = 0; - for(Task t : getTasks()) - totalDays += t.getEstimatedDays(); - - List<Task> tasks = getTasks(); - for(Task t : tasks) { + @Override + public double realDays() { + double totalTime = 0; + //For each task + for(Task t : client.getTasks(e)) { + //Sum the real days of the tasks objects + totalTime+=new TaskCalculation(t, client).getRealDays(); + } + return totalTime; - HashMap<Employee, Double> taskPercentages = new TaskCalculation(t, client).getPercentages(); - for(Employee emp : taskPercentages.keySet()) { - double rate = (t.getEstimatedDays()/totalDays); - if(percentages.containsKey(emp)) { - //We temporaly put the sum in the map. - percentages.put(emp, percentages.get(emp) + taskPercentages.get(emp)*rate); - } - else { - percentages.put(emp, taskPercentages.get(emp)*rate); - } + } - } - } + @Override + public HashMap<Employee, Double> getPercentages() { + HashMap<Employee, Double> percentages = new HashMap<Employee, Double>(); + double totalDays = 0; + for(Task t : getTasks()) + totalDays += t.getEstimatedDays(); - //Caluculate the average for each employee - /*Set<Employee> keySet = percentages.keySet(); + List<Task> tasks = getTasks(); + for(Task t : tasks) { + + HashMap<Employee, Double> taskPercentages = new TaskCalculation(t, client).getPercentages(); + for(Employee emp : taskPercentages.keySet()) { + double rate = (t.getEstimatedDays()/totalDays); + if(percentages.containsKey(emp)) { + //We temporaly put the sum in the map. + percentages.put(emp, percentages.get(emp) + taskPercentages.get(emp)*rate); + } + else { + percentages.put(emp, taskPercentages.get(emp)*rate); + } + + } + } + + //Caluculate the average for each employee + /*Set<Employee> keySet = percentages.keySet(); for(Employee emp : keySet) { percentages.put(emp, percentages.get(emp)/tasks.size()); }*/ - return percentages; - } + return percentages; + } - @Override - public HashMap<Employee, Double> getTimes() { - HashMap<Employee, Double> times = new HashMap<Employee, Double>(); + @Override + public HashMap<Employee, Double> getTimes() { + HashMap<Employee, Double> times = new HashMap<Employee, Double>(); - for(Task t : getTasks()) { + for(Task t : getTasks()) { - HashMap<Employee, Double> taskPercentages = new TaskCalculation(t, client).getTimes(); - for(Employee emp : taskPercentages.keySet()) { - if(times.containsKey(emp)) { - times.put(emp, times.get(emp) + taskPercentages.get(emp)); - } - else { - times.put(emp, taskPercentages.get(emp)); - } + HashMap<Employee, Double> taskPercentages = new TaskCalculation(t, client).getTimes(); + for(Employee emp : taskPercentages.keySet()) { + if(times.containsKey(emp)) { + times.put(emp, times.get(emp) + taskPercentages.get(emp)); + } + else { + times.put(emp, taskPercentages.get(emp)); + } - } + } - } + } - return times; - } - - public List<Task> getTasks() { - if(tasks == null) - tasks = client.getTasks(e); - return tasks; - - } + return times; + } + + /** + * Fetch the tasks of the quotation keep a reference + * @return + */ + public List<Task> getTasks() { + if(tasks == null) + tasks = client.getTasks(e); + return tasks; + + } } Modified: trunk/chorem-entities/src/main/java/org/chorem/project/TotalQuotationCalculation.java =================================================================== --- trunk/chorem-entities/src/main/java/org/chorem/project/TotalQuotationCalculation.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-entities/src/main/java/org/chorem/project/TotalQuotationCalculation.java 2013-08-14 14:17:38 UTC (rev 384) @@ -3,22 +3,38 @@ import java.util.HashMap; import java.util.List; -import org.chorem.ChoremClient; import org.chorem.entities.Employee; import org.chorem.entities.Quotation; -import org.chorem.entities.Task; +/** + * Calculates the total values of the quotation calculations + * Usage : construct the cobject by sending the list of quotation in parameter, then you can get the totals + * by using the total* methdds. + * @author gwenn + * + */ public class TotalQuotationCalculation extends Calculation<Quotation> { - + /** + * List of quotation calculation + */ private List<QuotationCalculation> calculations; + /** + * + * @param calculations list of calculation used to calculate the total. + */ public TotalQuotationCalculation(List<QuotationCalculation> calculations) { super(null, totalAmount(calculations), totalEstimatedDays(calculations), null); //super(q, q.getAmount(), q.getEstimatedDays(), client); this.calculations = calculations; } + /** + * + * @param calculations + * @return total amount + */ private static double totalAmount(List<QuotationCalculation> calculations) { double total = 0; for(QuotationCalculation q : calculations) { @@ -28,6 +44,11 @@ return total; } + /** + * + * @param calculations + * @return + */ private static double totalEstimatedDays(List<QuotationCalculation> calculations) { double total = 0; for(QuotationCalculation q : calculations) { Added: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/AdcDashboardAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/AdcDashboardAction.java (rev 0) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/AdcDashboardAction.java 2013-08-14 14:17:38 UTC (rev 384) @@ -0,0 +1,210 @@ +package org.chorem.webmotion.actions; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.debux.webmotion.server.WebMotionController; +import org.chorem.ChoremClient; +import org.debux.webmotion.server.render.Render; +import org.chorem.entities.ADC; +import org.chorem.entities.Company; +import org.chorem.entities.CompanyImpl; +import org.chorem.entities.Employee; +import org.nuiton.wikitty.entities.Wikitty; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; + +/** + * + * @author meynier + * + */ +public class AdcDashboardAction extends WebMotionController { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(AdcDashboardAction.class); + + /** + * Return a page with an array with the employees of the specified company + * + * @param client + * chorem client + * @param company + * employees will be fetched from this company + * @return + */ + public Render employeeFilter(ChoremClient client, Company company, int from, int to) { + // get all the empoyees from the default company + + List<Company> companies = client.findAllByQuery(Company.class, + new WikittyQueryMaker().exteq("Company").end()).getAll(); + + // Order by name + WikittyQuery employeeQuery = new WikittyQueryMaker().eq( + Employee.ELEMENT_FIELD_EMPLOYEE_COMPANY, company).end(); + + WikittyQueryResult<Employee> employeeResult = client.findAllByQuery( + Employee.class, employeeQuery); + + List<EmployeeData> employees = new ArrayList<EmployeeData>(); + Set<Integer> years = new HashSet<Integer>(); + for (Employee e : employeeResult.getAll()) { + EmployeeData eData = new EmployeeData(e, client, from, to); + employees.add(eData); + years.addAll(eData.getAdcPerYear().keySet()); + } + + Collections.sort(employees); + + + + // simply return them + return renderView("dashboardAdc.jsp", + "employees", employees, + "from", from, + "to", to, + "lastYear", (new GregorianCalendar()).get(Calendar.YEAR) +1, + "companies", companies, + "company", + new CompanyImpl(client.restore(company.getWikittyId())), + "years", years, + "title", "ADC Dashboard"); + } + + /** + * generate a page to manage the adcs + * + * @param client chorem client + * @param companyId + * @param addExtension + * @param call + * @return + */ + public Render requestDashboardAdc(ChoremClient client, String companyId, Integer from, Integer to) { + Company company = null; + + if(from == null) { + from = (new GregorianCalendar()).get(Calendar.YEAR); + from--; + } + if(to == null) { + to = (new GregorianCalendar()).get(Calendar.YEAR); + } + + if (companyId == null) + company = client.getDefaultCompany(); + else { + company = new CompanyImpl(client.restore(companyId)); + } + + + + return employeeFilter(client, company, from , to); + } + + + + + + /** + * Structure used to store information about an employee Used for the AJAX + * request + * + * @author gwenn + * + */ + public class EmployeeJson { + + private String salary; + private double productivityRate; + private double partialTime; + private double dailyReturn; + private double dailyHoursWorked; + private double otherPayments; + + public EmployeeJson(String salary, double productivityRate, + double partialTime, double dailyReturn, + double dailyHoursWorked, double otherPayments) { + this.salary = salary; + this.productivityRate = productivityRate; + this.partialTime = partialTime; + this.dailyReturn = dailyReturn; + this.dailyHoursWorked = dailyHoursWorked; + this.otherPayments = otherPayments; + } + } + + /** + * Structure used to store information about an employee used for the + * standard http request + * + * @author gwenn + * + */ + public class EmployeeData implements Comparable { + + private Employee e; + private double estimatedAdc; + private Map<Integer, Double> adcPerYear; + + public EmployeeData(Employee e, ChoremClient client, int from, int to) { + Wikitty w = client.restore(e.getWikittyId()); + + this.estimatedAdc = client.getDailyReturn(e); + //Simple trick to limit to 2 numbers after digit + int x = (int)(client.getDailyHoursWorked(e)*100); + double y = x/100.0; + + x = (int)(this.estimatedAdc*100); + y = x/100.0; + this.estimatedAdc = y; + + + WikittyQuery adcQuery = new WikittyQueryMaker().and() + .eq(ADC.ELEMENT_FIELD_ADC_EMPLOYEEHR, e) + .bw(ADC.ELEMENT_FIELD_ADC_YEAR, from, to) + .end(); + adcPerYear = new HashMap<Integer, Double>(); + + WikittyQueryResult<ADC> adcResult = client.findAllByQuery( + ADC.class, adcQuery); + + for(ADC a : adcResult.getAll()) { + adcPerYear.put(a.getYear(), a.getValue()); + } + System.out.println("ADC FOR " + e.getPerson(false) + " : " + adcPerYear); + this.e = e; + } + + public Employee getObject() { + return e; + } + + public double getEstimatedAdc() { + return estimatedAdc; + } + + public Map<Integer, Double> getAdcPerYear() { + return adcPerYear; + } + + @Override + public int compareTo(Object o) { + EmployeeData e = (EmployeeData) o; + return this.getObject().getPerson(false).getLastName() + .compareTo(e.getObject().getPerson(false).getLastName()); + } + + } + +} Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/EmployeeEditAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/EmployeeEditAction.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/EmployeeEditAction.java 2013-08-14 14:17:38 UTC (rev 384) @@ -13,6 +13,8 @@ import org.chorem.ChoremUtil; import org.debux.webmotion.server.call.Call; import org.debux.webmotion.server.render.Render; +import org.chorem.entities.ADC; +import org.chorem.entities.ADCImpl; import org.chorem.entities.Company; import org.chorem.entities.CompanyImpl; import org.chorem.entities.Employee; @@ -26,356 +28,398 @@ import org.nuiton.wikitty.query.WikittyQueryResult; /** - * + * Generate a page to edit the calues of the employees + * Also manages ajax requests for calculating the adc or * @author meynier * */ public class EmployeeEditAction extends WebMotionController { - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(EmployeeEditAction.class); + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(EmployeeEditAction.class); - /** - * Return a page with an array with the employees of the specified company - * @param client chorem client - * @param company employees will be fetched from this company - * @return - */ - public Render employeeFilter(ChoremClient client, Company company) { - //get all the empoyees from the default company + /** + * Return a page with an array with the employees of the specified company + * @param client chorem client + * @param company employees will be fetched from this company + * @return + */ + public Render employeeFilter(ChoremClient client, Company company) { + //get all the empoyees from the default company - List<Company> companies = client.findAllByQuery(Company.class, - new WikittyQueryMaker().exteq("Company").end()).getAll(); + List<Company> companies = client.findAllByQuery(Company.class, + new WikittyQueryMaker().exteq("Company").end()).getAll(); - //Order by name - WikittyQuery employeeQuery = new WikittyQueryMaker().eq(Employee.ELEMENT_FIELD_EMPLOYEE_COMPANY, company).end(); + //Order by name + WikittyQuery employeeQuery = new WikittyQueryMaker().eq(Employee.ELEMENT_FIELD_EMPLOYEE_COMPANY, company).end(); - WikittyQueryResult<Employee> employeeResult = client.findAllByQuery(Employee.class, employeeQuery); + WikittyQueryResult<Employee> employeeResult = client.findAllByQuery(Employee.class, employeeQuery); - List<EmployeeData> employees = new ArrayList<EmployeeData>(); - for(Employee e : employeeResult.getAll()) { - employees.add(new EmployeeData(e, client)); - } - - Collections.sort(employees); - //simply return them - return renderView("employeeEdit.jsp", - "employees",employees, - "companies", companies, - "company", new CompanyImpl(client.restore(company.getWikittyId())), - "title", "Employee edit"); - } + List<EmployeeData> employees = new ArrayList<EmployeeData>(); + for(Employee e : employeeResult.getAll()) { + employees.add(new EmployeeData(e, client)); + } + Collections.sort(employees); + //simply return them + return renderView("employeeEdit.jsp", + "employees",employees, + "companies", companies, + "company", new CompanyImpl(client.restore(company.getWikittyId())), + "title", "Employee edit"); + } - /** - * generate a page to edit the employees - * - * @param client choorem client - * @param companyId - * @param addExtension - * @param call - * @return - */ - public Render requestEmployeeEdit(ChoremClient client, String companyId, String addExtension, Call call) { - Company company = null; - if(companyId == null) - company = client.getDefaultCompany(); - else { - company = new CompanyImpl(client.restore(companyId)); - } + /** + * generate a page to edit the employees + * + * @param client choorem client + * @param companyId + * @param addExtension + * @param call + * @return + */ + public Render requestEmployeeEdit(ChoremClient client, String companyId, String addExtension, Call call) { + Company company = null; - if(call != null) { - Wikitty w = client.restore(company.getWikittyId()); - Map<String, Object> params = call.getExtractParameters(); - for(String key : params.keySet()) { - //Prevent false data - if((key.equals("CompanyHR.dailyReturn") - || key.equals("CompanyHR.dailyHoursWorked"))) { - try { - double value = Double.parseDouble(((String[])params.get(key))[0]); - w.setFqField(key, value); - } - catch(java.lang.NumberFormatException e) { - System.err.println(e.getMessage());//TODO : user output - } - - } - } + if(companyId == null) + company = client.getDefaultCompany(); + else { + company = new CompanyImpl(client.restore(companyId)); + } - client.store(w); - } - - if(addExtension != null && addExtension.equals("true")) { - Wikitty w = client.restore(company.getWikittyId()); - w.addExtension(client.restoreExtensionLastVersion("CompanyHR")); - client.store(w); - } + if(call != null) { + Wikitty w = client.restore(company.getWikittyId()); + Map<String, Object> params = call.getExtractParameters(); + for(String key : params.keySet()) { + //Prevent false data + if((key.equals("CompanyHR.dailyReturn") + || key.equals("CompanyHR.dailyHoursWorked"))) { + try { + double value = Double.parseDouble(((String[])params.get(key))[0]); + w.setFqField(key, value); + } + catch(java.lang.NumberFormatException e) { + System.err.println(e.getMessage());//TODO : user output + } - return employeeFilter(client, company); - } + } + } - /** - * Ajax request for the adc calculation - * - * @param client chorme client - * @param employeeId id of the employee that needs an adc calculation - * @return adc - */ - public Render requestAdc(ChoremClient client, String employeeId) { - Wikitty w = client.restore(employeeId); - EmployeeHR e = new EmployeeHRImpl(w); - - double adc = AdcCalculation.getAdc(client, e); - - w.setField("EmployeeHR", "dailyReturn", adc); - client.store(w); - - int iadc = (int)(adc*100); - return renderJSON("adc", (double)(iadc/100.0)); - - - } - /** - * Ajax request for the adc calculation of multiple employees of the same company - * - * @param client chorme client - * @param employeeId id of the employees that needs an adc calculation - * @return adc - */ - public Render requestMultipleAdc(ChoremClient client, String employeeId) { - List<Wikitty> w = client.restore(ChoremUtil.asList(",", employeeId)); - List<EmployeeHR> employees = new ArrayList<EmployeeHR>(); - for(int i = 0; i< w.size(); i++) { - employees.add(new EmployeeHRImpl(w.get(i))); - } - - HashMap<String, Double> adcs = AdcCalculation.getMultipleAdc(client, employees); - for(int i = 0; i< w.size(); i++) { - Wikitty wi = w.get(i); - wi.setField("EmployeeHR", "dailyReturn", adcs.get(wi.getWikittyId())); - client.store(wi); - } - for(String s : adcs.keySet()) { - int iadc = (int)(adcs.get(s)*100); - adcs.put(s, (double)(iadc/100.0)); - } - return renderJSON("adcs", adcs); - } - - - /** - * Ajax requets to modify the employee values - * - * @param client chorme client - * @param employeeId id of the employee to modify - * @param salaryStr new salary in String format - * @param productivityRateStr new prod rate in String format - * @param partialTimeStr new partial time in String format - * @param dailyReturnStr new daily return in String format - * @return - */ - public Render editEmployeeValues(ChoremClient client, String employeeId, String salaryStr - , String productivityRateStr, String partialTimeStr, String dailyReturnStr, String otherPaymentsStr) { - Wikitty employeeWikitty = client.restore(employeeId); - Employee employee = new EmployeeImpl(employeeWikitty); - if(!employeeWikitty.hasExtension(EmployeeHR.EXT_EMPLOYEEHR)) { - employeeWikitty.addExtension(client.restoreExtensionLastVersion(EmployeeHR.EXT_EMPLOYEEHR)); - } + client.store(w); + } - double salary = 0, productivityRate = 0, partialTime = 0, dailyReturn = 0, otherPayments = 0; - - //Try to parse the strings and generates if errors if it fails - List<ErrorJson> errors = new ArrayList<ErrorJson>(); - try { - salary = Double.parseDouble(salaryStr); - } - catch (java.lang.NumberFormatException e) { - errors.add(new ErrorJson("salary", "Salary must be a real number")); - } + if(addExtension != null && addExtension.equals("true")) { + Wikitty w = client.restore(company.getWikittyId()); + w.addExtension(client.restoreExtensionLastVersion("CompanyHR")); + client.store(w); + } - try{ - productivityRate = Double.parseDouble(productivityRateStr); - } - catch (java.lang.NumberFormatException e) { - errors.add(new ErrorJson("productivityRate", "Productivity rate must be a real number")); - } + return employeeFilter(client, company); + } - try { - partialTime = Double.parseDouble(partialTimeStr); - } - catch (java.lang.NumberFormatException e) { - errors.add(new ErrorJson("partialTime", "Partial time must be a real number")); - } - - try { - dailyReturn = Double.parseDouble(dailyReturnStr); - } - catch (java.lang.NumberFormatException e) { - errors.add(new ErrorJson("dailyReturn", "Daily return must be a real number")); - } - - try { - otherPayments = Double.parseDouble(otherPaymentsStr); - } - catch (java.lang.NumberFormatException e) { - errors.add(new ErrorJson("dailyReturn", "Other payments must be a real number")); - } - - //Verify that the percentages are between 0 and 100 - if(productivityRate > 100 || productivityRate < 0) { - errors.add(new ErrorJson("productivityRate", "Productivity rate must be between 0 and 100")); - } - if(partialTime > 100 || partialTime < 0) { - errors.add(new ErrorJson("partialTime", "Partial time must be between 0 and 100")); - } - if(errors.size() != 0) - return renderJSON("data", "error", "errors", errors); + /** + * Ajax request for the adc calculation + * + * @param client chorme client + * @param employeeId id of the employee that needs an adc calculation + * @return adc + */ + public Render requestAdc(ChoremClient client, String employeeId, boolean real) { + Wikitty w = client.restore(employeeId); + EmployeeHR e = new EmployeeHRImpl(w); + double adc = (new AdcCalculation(client, e)).getAdc(real); - if(salary != 0) - employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_SALARY, salary); - employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_PRODUCTIVITYRATE, productivityRate); - employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_PARTIALTIME, partialTime); - employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_DAILYRETURN, dailyReturn); - employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_OTHERPAYMENTS, otherPayments); - client.store(employeeWikitty); + w.setField(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN, adc); + client.store(w); + int iadc = (int)(adc*100); + return renderJSON("adc", (double)(iadc/100.0)); - EmployeeData data = new EmployeeData(new EmployeeImpl(employeeWikitty), client); - EmployeeJson json = new EmployeeJson( - data.getSalary() + "", - data.getProductivityRate(), - data.getPartialTime(), - data.getDailyReturn(), - data.getDailyHoursWorked(), - data.getOtherPayments() - ); + } - return renderJSON("data", json); - } - - /** - * Class used to store an error - * @author gwenn - * - */ - public class ErrorJson { - private String errorMessage; - private String field; - - public ErrorJson (String field, String message) { - this.field = field; - this.errorMessage = message; - } - } + /** + * Ajax request for the adc calculation of multiple employees of the same company + * + * @param client chorme client + * @param employeeId id of the employees that needs an adc calculation + * @param real You must specify this parameter is true if you want the real values from the last year. + * The value will be stored in a new ADC object. + * @param year Year of the adc if it's the real one that needs to be calculated + * @return adc + */ + public Render requestMultipleAdc(ChoremClient client, String employeeId, boolean real, int year) { + List<Wikitty> wemployees = client.restore(ChoremUtil.asList(",", employeeId)); + List<EmployeeHR> employees = new ArrayList<EmployeeHR>(); + System.out.println("real = " + real + ", year = " + year); + for(int i = 0; i< wemployees.size(); i++) { + employees.add(new EmployeeHRImpl(wemployees.get(i))); + } - /** - * Structure used to store information about an employee - * Used for the AJAX request - * - * @author gwenn - * - */ - public class EmployeeJson { + Map<String, Double> adcs = (new AdcCalculation(client, employees)).getMultipleAdc(real); + if(real) { + for(int i = 0; i< wemployees.size(); i++) { + Wikitty wi = wemployees.get(i); - private String salary; - private double productivityRate; - private double partialTime; - private double dailyReturn; - private double dailyHoursWorked; - private double otherPayments; + //Check if the ADC object already exists + WikittyQuery adcQuery = new WikittyQueryMaker().and() + .eq(ADC.ELEMENT_FIELD_ADC_EMPLOYEEHR, employees.get(i)) + .eq(ADC.ELEMENT_FIELD_ADC_YEAR, year) + .end(); - public EmployeeJson(String salary, double productivityRate, double partialTime, - double dailyReturn, double dailyHoursWorked, double otherPayments) { - this.salary = salary; - this.productivityRate = productivityRate; - this.partialTime = partialTime; - this.dailyReturn = dailyReturn; - this.dailyHoursWorked = dailyHoursWorked; - this.otherPayments = otherPayments; - } - } - - /** - * Structure used to store information about an employee - * used for the standard http request - * @author gwenn - * - */ - public class EmployeeData implements Comparable{ - private Employee e; - private String salary; - private double productivityRate; - private double partialTime; - private double dailyReturn; - private double dailyHoursWorked; - private double otherPayments; + WikittyQueryResult<ADC> adcResult = client.findAllByQuery( + ADC.class, adcQuery); + if(adcResult.size() == 0) { + ADC adc = new ADCImpl(); + adc.setEmployeeHR(wi.getWikittyId()); + adc.setYear(year); + adc.setValue(adcs.get(wi.getWikittyId())); + client.store(adc); + } + else { + ADC adc = adcResult.get(0); //There is only one (in theory) + Wikitty wadc =client.restore(adc.getWikittyId()); + wadc.setField(ADC.EXT_ADC, ADC.FIELD_ADC_VALUE, adcs.get(wi.getWikittyId())); + client.store(wadc); - public EmployeeData(Employee e, ChoremClient client) { - Wikitty w = client.restore(e.getWikittyId()); - if(w.hasExtension(EmployeeHR.EXT_EMPLOYEEHR)) { - this.salary = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_SALARY) + ""; - this.productivityRate = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PRODUCTIVITYRATE); - this.partialTime = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PARTIALTIME); - this.otherPayments = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_OTHERPAYMENTS); - } - else { - this.salary = "Non renseigné"; - this.productivityRate = 100; - this.partialTime = 100; - this.otherPayments = 0; - } - this.dailyReturn = client.getDailyReturn(e); - //Simple trick to limit to 2 numbers after digit - int x = (int)(client.getDailyHoursWorked(e)*100); - double y = x/100.0; - this.dailyHoursWorked = y; - - x = (int)(this.dailyReturn*100); - y = x/100.0; - this.dailyReturn = y; + } + } + } + else { + for(int i = 0; i< wemployees.size(); i++) { + Wikitty wi = wemployees.get(i); + wi.setField(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_DAILYRETURN, adcs.get(wi.getWikittyId())); + client.store(wi); + } + } + for(String s : adcs.keySet()) { + int iadc = (int)(adcs.get(s)*100); + adcs.put(s, (double)(iadc/100.0)); + } - this.e = e; - } - public Employee getObject() { - return e; - } + return renderJSON("adcs", adcs); + } - public String getSalary() { - return salary; - } - public double getDailyReturn() { - return dailyReturn; - } - public double getDailyHoursWorked() { - return dailyHoursWorked; - } - public double getProductivityRate() { - return productivityRate; - } - public double getPartialTime() { - return partialTime; - } - public double getOtherPayments() { - return otherPayments; - } + /** + * Ajax requets to modify the employee values + * + * @param client chorme client + * @param employeeId id of the employee to modify + * @param salaryStr new salary in String format + * @param productivityRateStr new prod rate in String format + * @param partialTimeStr new partial time in String format + * @param dailyReturnStr new daily return in String format + * @return + */ + public Render editEmployeeValues(ChoremClient client, String employeeId, String salaryStr + , String productivityRateStr, String partialTimeStr, String dailyReturnStr, String otherPaymentsStr) { + Wikitty employeeWikitty = client.restore(employeeId); + Employee employee = new EmployeeImpl(employeeWikitty); + if(!employeeWikitty.hasExtension(EmployeeHR.EXT_EMPLOYEEHR)) { + employeeWikitty.addExtension(client.restoreExtensionLastVersion(EmployeeHR.EXT_EMPLOYEEHR)); + } - @Override - public int compareTo(Object o) { - EmployeeData e = (EmployeeData)o; - return this.getObject().getPerson(false).getLastName().compareTo(e.getObject().getPerson(false).getLastName()); - } + double salary = 0, productivityRate = 0, partialTime = 0, dailyReturn = 0, otherPayments = 0; + //Try to parse the strings and generates if errors if it fails + List<ErrorJson> errors = new ArrayList<ErrorJson>(); + try { + salary = Double.parseDouble(salaryStr); + } + catch (java.lang.NumberFormatException e) { + errors.add(new ErrorJson("salary", "Salary must be a real number")); + } + try{ + productivityRate = Double.parseDouble(productivityRateStr); + } + catch (java.lang.NumberFormatException e) { + errors.add(new ErrorJson("productivityRate", "Productivity rate must be a real number")); + } - } + try { + partialTime = Double.parseDouble(partialTimeStr); + } + catch (java.lang.NumberFormatException e) { + errors.add(new ErrorJson("partialTime", "Partial time must be a real number")); + } + try { + dailyReturn = Double.parseDouble(dailyReturnStr); + } + catch (java.lang.NumberFormatException e) { + errors.add(new ErrorJson("dailyReturn", "Daily return must be a real number")); + } + + try { + otherPayments = Double.parseDouble(otherPaymentsStr); + } + catch (java.lang.NumberFormatException e) { + errors.add(new ErrorJson("dailyReturn", "Other payments must be a real number")); + } + + //Verify that the percentages are between 0 and 100 + if(productivityRate > 100 || productivityRate < 0) { + errors.add(new ErrorJson("productivityRate", "Productivity rate must be between 0 and 100")); + } + if(partialTime > 100 || partialTime < 0) { + errors.add(new ErrorJson("partialTime", "Partial time must be between 0 and 100")); + } + if(errors.size() != 0) + return renderJSON("data", "error", "errors", errors); + + + if(salary != 0) + employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_SALARY, salary); + employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_PRODUCTIVITYRATE, productivityRate); + employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_PARTIALTIME, partialTime); + employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_DAILYRETURN, dailyReturn); + employeeWikitty.setFqField(EmployeeHR.FQ_FIELD_EMPLOYEEHR_OTHERPAYMENTS, otherPayments); + client.store(employeeWikitty); + + + EmployeeData data = new EmployeeData(new EmployeeImpl(employeeWikitty), client); + + EmployeeJson json = new EmployeeJson( + data.getSalary() + "", + data.getProductivityRate(), + data.getPartialTime(), + data.getDailyReturn(), + data.getDailyHoursWorked(), + data.getOtherPayments() + ); + + return renderJSON("data", json); + + } + + /** + * Class used to store an error + * @author gwenn + * + */ + public class ErrorJson { + private String errorMessage; + private String field; + + public ErrorJson (String field, String message) { + this.field = field; + this.errorMessage = message; + } + } + + /** + * Structure used to store information about an employee + * Used for the AJAX request + * + * @author gwenn + * + */ + public class EmployeeJson { + + private String salary; + private double productivityRate; + private double partialTime; + private double dailyReturn; + private double dailyHoursWorked; + private double otherPayments; + + public EmployeeJson(String salary, double productivityRate, double partialTime, + double dailyReturn, double dailyHoursWorked, double otherPayments) { + this.salary = salary; + this.productivityRate = productivityRate; + this.partialTime = partialTime; + this.dailyReturn = dailyReturn; + this.dailyHoursWorked = dailyHoursWorked; + this.otherPayments = otherPayments; + } + } + + /** + * Structure used to store information about an employee + * used for the standard http request + * @author gwenn + * + */ + public class EmployeeData implements Comparable{ + + private Employee e; + private String salary; + private double productivityRate; + private double partialTime; + private double dailyReturn; + private double dailyHoursWorked; + private double otherPayments; + + + public EmployeeData(Employee e, ChoremClient client) { + Wikitty w = client.restore(e.getWikittyId()); + if(w.hasExtension(EmployeeHR.EXT_EMPLOYEEHR)) { + this.salary = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_SALARY) + ""; + this.productivityRate = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PRODUCTIVITYRATE); + this.partialTime = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_PARTIALTIME); + this.otherPayments = w.getFieldAsDouble(EmployeeHR.EXT_EMPLOYEEHR, EmployeeHR.FIELD_EMPLOYEEHR_OTHERPAYMENTS); + } + else { + this.salary = "Non renseigné"; + this.productivityRate = 100; + this.partialTime = 100; + this.otherPayments = 0; + } + this.dailyReturn = client.getDailyReturn(e); + //Simple trick to limit to 2 numbers after digit + int x = (int)(client.getDailyHoursWorked(e)*100); + double y = x/100.0; + this.dailyHoursWorked = y; + + x = (int)(this.dailyReturn*100); + y = x/100.0; + this.dailyReturn = y; + + this.e = e; + } + + public Employee getObject() { + return e; + } + + public String getSalary() { + return salary; + } + + public double getDailyReturn() { + return dailyReturn; + } + + public double getDailyHoursWorked() { + return dailyHoursWorked; + } + public double getProductivityRate() { + return productivityRate; + } + public double getPartialTime() { + return partialTime; + } + public double getOtherPayments() { + return otherPayments; + } + + @Override + public int compareTo(Object o) { + EmployeeData e = (EmployeeData)o; + return this.getObject().getPerson(false).getLastName().compareTo(e.getObject().getPerson(false).getLastName()); + } + + + + } + } Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/DashboardProjectAction.java 2013-08-14 14:17:38 UTC (rev 384) @@ -34,344 +34,386 @@ import org.nuiton.wikitty.query.WikittyQueryResult; /** - * + * Displays a page that shows one or many quotations, with financial tables and a gantt diagram. * @author meynier * */ public class DashboardProjectAction extends WebMotionController { - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(DashboardProjectAction.class); + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(DashboardProjectAction.class); - /** - * Return the view for a single quotation - * @param client Chorem client - * @param id Project ID (useless here) - * @param quotationFilter Quotation id - * @return - */ - public Render singleQuotationFilter(ChoremClient client, String id, String quotationFilter) { + /** + * Return the view for a single quotation + * @param client Chorem client + * @param id Project ID (useless here) + * @param quotationFilter Quotation id + * @return + */ + public Render singleQuotationFilter(ChoremClient client, String id, String quotationFilter) { + Render render = null; + //Fetch the quotation from the filter + WikittyQuery quotationQuery = new WikittyQueryMaker().ideq(quotationFilter).end(); + WikittyQueryResult<Quotation> quotationResult = client.findAllByQuery(Quotation.class, quotationQuery); - //Fetch the quotation from the filter - WikittyQuery quotationQuery = new WikittyQueryMaker().ideq(quotationFilter).end(); - WikittyQueryResult<Quotation> quotationResult = client.findAllByQuery(Quotation.class, quotationQuery); - - HashMap<Project, List<QuotationData>> projectData = new HashMap<Project, List<QuotationData>>(); + HashMap<Project, List<QuotationData>> projectData = new HashMap<Project, List<QuotationData>>(); - //If some quotation has been found - if(quotationResult != null && quotationResult.size() != 0) { - Quotation quotation = quotationResult.get(0); - - //Fetch the quotation's project - WikittyQuery projectQuery = new WikittyQueryMaker().ideq(quotation.getProject()).end(); - WikittyQueryResult<Project> projectResult = client.findAllByQuery(Project.class, projectQuery); - - List<QuotationData> q = new ArrayList<QuotationData>(); - q.add(new QuotationData(quotation, client)); - projectData.put(projectResult.get(0), q); + //If some quotation has been found + if(quotationResult != null && quotationResult.size() != 0) { + Quotation quotation = quotationResult.get(0); - return renderView("dashboardSingleProject.jsp", - "locale", client.getUserLocale(), - "title", "Tableau de bord projet", - "projects", projectData); + //Fetch the quotation's project + WikittyQuery projectQuery = new WikittyQueryMaker().ideq(quotation.getProject()).end(); + WikittyQueryResult<Project> projectResult = client.findAllByQuery(Project.class, projectQuery); - } - else { - return renderView("dashboardSingleProject.jsp"); - } - } + List<QuotationData> q = new ArrayList<QuotationData>(); + q.add(new QuotationData(quotation, client)); + projectData.put(projectResult.get(0), q); - /** - * Display multiple quotation for one or more projects - * @param client chorem client - * @param id Project id - * @param quotationFilter filter (open quotation or all) - * @return - */ - public Render projectFilter(ChoremClient client, String id, String quotationFilter) { - - WikittyQueryResult<Project> projectResult = null; - WikittyQueryResult<Quotation> quotationResult = null; + render = renderView("dashboardSingleProject.jsp", + "locale", client.getUserLocale(), + "title", "Tableau de bord projet", + "projects", projectData); - - HashMap<Project, List<QuotationData>> projectData = new HashMap<Project, List<QuotationData>>(); - - //Fetch the projects from the id or the filter - WikittyQueryMaker projectQueryMaker = new WikittyQueryMaker(); - if(id != null && !id.equals("")) - projectQueryMaker.ideq(id); - else - projectQueryMaker.exteq(Project.EXT_PROJECT); - WikittyQuery projectQuery = projectQueryMaker.end(); + } + else { + render = renderView("dashboardSingleProject.jsp"); + } + return render; + } - projectResult = client.findAllByQuery(Project.class, projectQuery); - - //Fetch the quotations from the projects - if(projectResult.size() != 0) { - for(Project project : projectResult.getAll()) { - WikittyQuery quotationQuery = null; - WikittyQueryMaker wqm = new WikittyQueryMaker(); + /** + * Display multiple quotation for one or more projects + * @param client chorem client + * @param id Project id + * @param quotationFilter filter (open quotation or all) + * @return + */ + public Render projectFilter(ChoremClient client, String id, String quotationFilter) { + WikittyQueryResult<Project> projectResult = null; + WikittyQueryResult<Quotation> quotationResult = null; - if(quotationFilter.equals("open")) { - wqm.and() - .eq(Quotation.ELEMENT_FIELD_QUOTATION_PROJECT, project) - .extne(Closed.EXT_CLOSED); - } - else if (quotationFilter.equals("all")){ - wqm.eq(Quotation.ELEMENT_FIELD_QUOTATION_PROJECT, project); - } + HashMap<Project, List<QuotationData>> projectData = new HashMap<Project, List<QuotationData>>(); - quotationQuery = wqm.end(); - quotationQuery.setLimit(20); - quotationQuery.addSortDescending(Quotation.ELEMENT_FIELD_INTERVAL_BEGINDATE); - quotationResult = client.findAllByQuery(Quotation.class, quotationQuery); + //Fetch the projects from the id or the filter + WikittyQueryMaker projectQueryMaker = new WikittyQueryMaker(); + if(id != null && !id.equals("")) + projectQueryMaker.ideq(id); + else + projectQueryMaker.exteq(Project.EXT_PROJECT); + WikittyQuery projectQuery = projectQueryMaker.end(); - //Fetch the tasks form the quotations (if there are some) - if(quotationResult != null && quotationResult.size() != 0) { - List<QuotationData> quotation = new ArrayList<QuotationData>(); - for(Quotation quote : quotationResult.getAll()) { - quotation.add(new QuotationData(quote, client)); - } - projectData.put(project, quotation); - } - } - } + projectResult = client.findAllByQuery(Project.class, projectQuery); - return renderView("dashboardSingleProject.jsp", - "locale", client.getUserLocale(), - "title", "Tableau de bord projet", - "projects", projectData); + //Fetch the quotations from the projects + if(projectResult.size() != 0) { + for(Project project : projectResult.getAll()) { + WikittyQuery quotationQuery = null; + WikittyQueryMaker wqm = new WikittyQueryMaker(); - } + if(quotationFilter.equals("open")) { + wqm.and() + .eq(Quotation.ELEMENT_FIELD_QUOTATION_PROJECT, project) + .extne(Closed.EXT_CLOSED); + } + else if (quotationFilter.equals("all")){ + wqm.eq(Quotation.ELEMENT_FIELD_QUOTATION_PROJECT, project); + } - - public Render multiProjectFilter(ChoremClient client, Date from, Date to) { - System.out.println(from + "," + to); - if(from == null || to == null) { - Calendar now = new GregorianCalendar(); - Calendar gFrom = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) - , now.getActualMinimum(Calendar.DAY_OF_MONTH)); - Calendar gTo = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) - , now.getActualMaximum(Calendar.DAY_OF_MONTH)); - from = gFrom.getTime(); - to = gTo.getTime(); + quotationQuery = wqm.end(); + quotationQuery.setLimit(20); + quotationQuery.addSortDescending(Quotation.ELEMENT_FIELD_INTERVAL_BEGINDATE); + quotationResult = client.findAllByQuery(Quotation.class, quotationQuery); - } + //Fetch the tasks form the quotations (if there are some) + if(quotationResult != null && quotationResult.size() != 0) { + List<QuotationData> quotation = new ArrayList<QuotationData>(); + for(Quotation quote : quotationResult.getAll()) { + quotation.add(new QuotationData(quote, client)); + } + projectData.put(project, quotation); + } + } + } + return renderView("dashboardSingleProject.jsp", + "locale", client.getUserLocale(), + "title", "Tableau de bord projet", + "projects", projectData); - WikittyQueryMaker quotationQueryMaker = new WikittyQueryMaker(); - WikittyQuery quotationQuery = quotationQueryMaker.or() - .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) - .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) - .and() - .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) - .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to) - .end(); - WikittyQueryResult<Quotation> result = - client.findAllByQuery(Quotation.class, quotationQuery); + } - Collection<Quotation> quotations = result.getAll(); - HashMap<Quotation, QuotationCalculation> calculations = new HashMap<Quotation, QuotationCalculation>(); - for(Quotation q : quotations) { - QuotationCalculation calc = new QuotationCalculation(q, client); - calc.calculate(); - calculations.put(q, calc); - } - - TotalQuotationCalculation total = new TotalQuotationCalculation( - new ArrayList<QuotationCalculation>(calculations.values())); - - return renderView("dashboardMultiProject.jsp", - "title", "Tableau de bord projets", - "locale", client.getUserLocale(), - "quotations", quotations, - "calculations", calculations, - "total", total); + /** + * Generates the multi-project page + * @param client chorem client + * @param from begin date for the interval + * @param to end date for the interval + * @return + */ + public Render multiProjectFilter(ChoremClient client, Date from, Date to) { + System.out.println(from + "," + to); + if(from == null || to == null) { + Calendar now = new GregorianCalendar(); + Calendar gFrom = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + , now.getActualMinimum(Calendar.DAY_OF_MONTH)); + Calendar gTo = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + , now.getActualMaximum(Calendar.DAY_OF_MONTH)); + from = gFrom.getTime(); + to = gTo.getTime(); + } - } - public Render employeeFilter(ChoremClient client, String id, Date from, Date to, String[] quotationFilters) { - - //If no field has been set, sets the date to the actual month - if(from == null || to == null) { - Calendar now = new GregorianCalendar(); - Calendar gFrom = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) - , now.getActualMinimum(Calendar.DAY_OF_MONTH)); - Calendar gTo = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) - , now.getActualMaximum(Calendar.DAY_OF_MONTH)); - from = gFrom.getTime(); - to = gTo.getTime(); - } - - //Fetch the total list of employee (or just the chosen one - WikittyQueryMaker employeeQueryMaker = new WikittyQueryMaker(); - if(id != null && !id.equals("")) - employeeQueryMaker.ideq(id); - else { - employeeQueryMaker.exteq(Employee.EXT_EMPLOYEE); - } - WikittyQueryResult<Employee> employeeResult = client.findAllByQuery(Employee.class,employeeQueryMaker.end()); - List<Employee> employeeList = employeeResult.getAll(); - - //Fetch all the tasks on the interval - WikittyQueryMaker taskQueryMaker = new WikittyQueryMaker() - .and() - .exteq(Task.EXT_TASK); - - if(quotationFilters!=null) { - taskQueryMaker.or(); - for(String q : quotationFilters) { - taskQueryMaker .eq(Task.FQ_FIELD_TASK_QUOTATION,q); - System.out.println(client.restore(q));} - taskQueryMaker.close(); - } - - taskQueryMaker .or() - .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) - .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) - .and() - .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) - .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to); - - WikittyQuery taskQuery = taskQueryMaker.end(); - System.out.println(taskQuery); - List<Task> taskList = client.findAllByQuery(Task.class,taskQuery).getAll(); - System.out.println("RESULT : " + taskList); - //Fetch the employee's workers on those tasks - - - - //---------------------------------------- - //Fetch the real time spent on each project/quotation - HashMap<Employee, Double> timeTotals = new HashMap<Employee, Double>(); - HashMap<Employee, HashMap<Quotation, Double>> timePerQuotation = new HashMap<Employee, HashMap<Quotation, Double>>(); - for(Task task : taskList) { - - WikittyQueryMaker timeQueryMaker = new WikittyQueryMaker().and() - .eq(Time.ELEMENT_FIELD_TIME_TASK, task); - if(employeeList.size() == 1) - timeQueryMaker.eq(Time.ELEMENT_FIELD_TIME_EMPLOYEE, employeeList.get(0)); - WikittyQuery timeQuery = timeQueryMaker.end(); - WikittyQueryResult<Time> timeResult = client.findAllByQuery(Time.class, timeQuery); - - - - for(Time time : timeResult.getAll()) { - Employee emp = time.getEmployee(false); - - //TOTAL TIMES - if(timeTotals.containsKey(emp)) - timeTotals.put(emp, timeTotals.get(emp) + ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); - else - timeTotals.put(emp, ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); - - HashMap<Quotation, Double> timeQ = null; - //TIME PER QUOTATION - if(timePerQuotation.containsKey(emp)) { - timeQ = timePerQuotation.get(emp); - } - else { - timeQ = new HashMap<Quotation, Double>(); - timePerQuotation.put(emp, timeQ); - } - Quotation qKey = task.getQuotation(false); - if(timeQ.containsKey(qKey)) { - timeQ.put(qKey, timeQ.get(qKey) + - ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); - } - else { - timeQ.put(qKey, - ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); - } - - } - } - Set<Employee> kSet = timePerQuotation.keySet(); - Set<Quotation> quotations = new HashSet<Quotation>(); - for(Employee e : kSet) { - quotations.addAll(timePerQuotation.get(e).keySet()); - } - List<Quotation> allQuotations = new ArrayList<Quotation>(); - WikittyQuery quotationQuery = new WikittyQueryMaker().or() - .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) - .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) - .and() - .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) - .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to).end(); - allQuotations = client.findAllByQuery(Quotation.class, quotationQuery).getAll(); - - HashMap<Employee, HashMap<Quotation, Double>> percentages = new HashMap<Employee, HashMap<Quotation, Double>>(); - - for(Employee e : kSet) { - Set<Quotation> qSet = timePerQuotation.get(e).keySet(); - HashMap<Quotation, Double> p = new HashMap<Quotation, Double>(); - for(Quotation q : qSet) { - - p.put(q, ( timePerQuotation.get(e).get(q) / timeTotals.get(e) ) *100 ); - - } - percentages.put(e, p); - } - - - //Calculates the average working time - - Calendar gFrom = new GregorianCalendar(); - Calendar gTo = new GregorianCalendar(); - gFrom.setTime(from); - gTo.setTime(to); - - return renderView("dashboardEmployee.jsp", - "title", "Tableau de bord employé", - "locale", client.getUserLocale(), - "timePerQuotation", timePerQuotation, - "quotations", quotations, - "percentages", percentages, - "timeTotals", timeTotals, - "allQuotations", allQuotations); - - } + WikittyQueryMaker quotationQueryMaker = new WikittyQueryMaker(); + WikittyQuery quotationQuery = quotationQueryMaker.or() + .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) + .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) + .and() + .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) + .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to) + .end(); + WikittyQueryResult<Quotation> result = + client.findAllByQuery(Quotation.class, quotationQuery); + Collection<Quotation> quotations = result.getAll(); - public Render requestProject(ChoremClient client, String project_name, String project_id, String quotationFilter) { - if(quotationFilter == null) - quotationFilter = "open"; - if(project_name == null || project_name.equals("")) - project_id = ""; - if(quotationFilter.equals("open") || quotationFilter.equals("all")) { - return projectFilter(client, project_id, quotationFilter); - } - else { - return singleQuotationFilter(client, project_id, quotationFilter); - } - } - public Render requestMultiProject(ChoremClient client, Date from, Date to) { - return multiProjectFilter(client, from, to); - } - - public Render requestEmployee(ChoremClient client, String id, Date from, Date to, String[] quotations) { - System.out.println("QUOTATIONS : " + Arrays.toString(quotations)); - return employeeFilter(client, id, from, to, quotations); - } + HashMap<Quotation, QuotationCalculation> calculations = new HashMap<Quotation, QuotationCalculation>(); + for(Quotation q : quotations) { + QuotationCalculation calc = new QuotationCalculation(q, client); + calc.calculate(); + calculations.put(q, calc); + } + TotalQuotationCalculation total = new TotalQuotationCalculation( + new ArrayList<QuotationCalculation>(calculations.values())); - private class IntervalSorter<T extends Interval> implements Comparator { - @Override - public int compare(Object q1, Object q2) { - return ((T)q1).getBeginDate().compareTo(((T)q2).getBeginDate()); - } + return renderView("dashboardMultiProject.jsp", + "title", "Tableau de bord projets", + "locale", client.getUserLocale(), + "quotations", quotations, + "calculations", calculations, + "total", total); - } - - + + } + + /** + * + * @param client + * @param id + * @param from + * @param to + * @param quotationFilters + * @return + */ + public Render employeeFilter(ChoremClient client, String id, Date from, Date to, String[] quotationFilters) { + + //If no field has been set, sets the date to the actual month + if(from == null || to == null) { + Calendar now = new GregorianCalendar(); + Calendar gFrom = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + , now.getActualMinimum(Calendar.DAY_OF_MONTH)); + Calendar gTo = new GregorianCalendar(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + , now.getActualMaximum(Calendar.DAY_OF_MONTH)); + from = gFrom.getTime(); + to = gTo.getTime(); + } + + //Fetch the total list of employee (or just the chosen one + WikittyQueryMaker employeeQueryMaker = new WikittyQueryMaker(); + if(id != null && !id.equals("")) + employeeQueryMaker.ideq(id); + else { + employeeQueryMaker.exteq(Employee.EXT_EMPLOYEE); + } + WikittyQueryResult<Employee> employeeResult = client.findAllByQuery(Employee.class,employeeQueryMaker.end()); + List<Employee> employeeList = employeeResult.getAll(); + + //Fetch all the tasks on the interval + WikittyQueryMaker taskQueryMaker = new WikittyQueryMaker() + .and() + .exteq(Task.EXT_TASK); + + if(quotationFilters!=null) { + taskQueryMaker.or(); + for(String q : quotationFilters) { + taskQueryMaker .eq(Task.FQ_FIELD_TASK_QUOTATION,q); + System.out.println(client.restore(q));} + taskQueryMaker.close(); + } + + taskQueryMaker .or() + .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) + .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) + .and() + .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) + .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to); + + WikittyQuery taskQuery = taskQueryMaker.end(); + System.out.println(taskQuery); + List<Task> taskList = client.findAllByQuery(Task.class,taskQuery).getAll(); + System.out.println("RESULT : " + taskList); + //Fetch the employee's workers on those tasks + + + + //---------------------------------------- + //Fetch the real time spent on each project/quotation + HashMap<Employee, Double> timeTotals = new HashMap<Employee, Double>(); + HashMap<Employee, HashMap<Quotation, Double>> timePerQuotation = new HashMap<Employee, HashMap<Quotation, Double>>(); + for(Task task : taskList) { + + WikittyQueryMaker timeQueryMaker = new WikittyQueryMaker().and() + .eq(Time.ELEMENT_FIELD_TIME_TASK, task); + if(employeeList.size() == 1) + timeQueryMaker.eq(Time.ELEMENT_FIELD_TIME_EMPLOYEE, employeeList.get(0)); + WikittyQuery timeQuery = timeQueryMaker.end(); + WikittyQueryResult<Time> timeResult = client.findAllByQuery(Time.class, timeQuery); + + + + for(Time time : timeResult.getAll()) { + Employee emp = time.getEmployee(false); + + //TOTAL TIMES + if(timeTotals.containsKey(emp)) + timeTotals.put(emp, timeTotals.get(emp) + ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); + else + timeTotals.put(emp, ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); + + HashMap<Quotation, Double> timeQ = null; + //TIME PER QUOTATION + if(timePerQuotation.containsKey(emp)) { + timeQ = timePerQuotation.get(emp); + } + else { + timeQ = new HashMap<Quotation, Double>(); + timePerQuotation.put(emp, timeQ); + } + Quotation qKey = task.getQuotation(false); + if(timeQ.containsKey(qKey)) { + timeQ.put(qKey, timeQ.get(qKey) + + ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); + } + else { + timeQ.put(qKey, + ChoremUtil.getPeriodInHours(time.getBeginDate(), time.getEndDate())); + } + + } + } + Set<Employee> kSet = timePerQuotation.keySet(); + Set<Quotation> quotations = new HashSet<Quotation>(); + for(Employee e : kSet) { + quotations.addAll(timePerQuotation.get(e).keySet()); + } + List<Quotation> allQuotations = new ArrayList<Quotation>(); + WikittyQuery quotationQuery = new WikittyQueryMaker().or() + .bw(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from, to) + .bw(Interval.FQ_FIELD_INTERVAL_ENDDATE, from, to) + .and() + .le(Interval.FQ_FIELD_INTERVAL_BEGINDATE, from) + .ge(Interval.FQ_FIELD_INTERVAL_ENDDATE, to).end(); + allQuotations = client.findAllByQuery(Quotation.class, quotationQuery).getAll(); + + HashMap<Employee, HashMap<Quotation, Double>> percentages = new HashMap<Employee, HashMap<Quotation, Double>>(); + + for(Employee e : kSet) { + Set<Quotation> qSet = timePerQuotation.get(e).keySet(); + HashMap<Quotation, Double> p = new HashMap<Quotation, Double>(); + for(Quotation q : qSet) { + + p.put(q, ( timePerQuotation.get(e).get(q) / timeTotals.get(e) ) *100 ); + + } + percentages.put(e, p); + } + + + //Calculates the average working time + + Calendar gFrom = new GregorianCalendar(); + Calendar gTo = new GregorianCalendar(); + gFrom.setTime(from); + gTo.setTime(to); + + return renderView("dashboardEmployee.jsp", + "title", "Tableau de bord employé", + "locale", client.getUserLocale(), + "timePerQuotation", timePerQuotation, + "quotations", quotations, + "percentages", percentages, + "timeTotals", timeTotals, + "allQuotations", allQuotations); + + } + + /** + * + * @param client + * @param project_name + * @param project_id + * @param quotationFilter + * @return + */ + public Render requestProject(ChoremClient client, String project_name, String project_id, String quotationFilter) { + if(quotationFilter == null) + quotationFilter = "open"; + if(project_name == null || project_name.equals("")) + project_id = ""; + Render render = null; + if(quotationFilter.equals("open") || quotationFilter.equals("all")) { + render = projectFilter(client, project_id, quotationFilter); + } + else { + render = singleQuotationFilter(client, project_id, quotationFilter); + } + return render; + } + /** + * + * @param client + * @param from + * @param to + * @return + */ + public Render requestMultiProject(ChoremClient client, Date from, Date to) { + return multiProjectFilter(client, from, to); + } + + /** + * + * @param client + * @param id + * @param from + * @param to + * @param quotations + * @return + */ + public Render requestEmployee(ChoremClient client, String id, Date from, Date to, String[] quotations) { + System.out.println("QUOTATIONS : " + Arrays.toString(quotations)); + return employeeFilter(client, id, from, to, quotations); + } + + + private class IntervalSorter<T extends Interval> implements Comparator { + + @Override + public int compare(Object q1, Object q2) { + + return ((T)q1).getBeginDate().compareTo(((T)q2).getBeginDate()); + } + + } + + } Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/GanttAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/GanttAction.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/GanttAction.java 2013-08-14 14:17:38 UTC (rev 384) @@ -23,12 +23,23 @@ import org.nuiton.wikitty.query.WikittyQueryMaker; import org.nuiton.wikitty.query.WikittyQueryResult; +/** + * Manage the ajax actions for the gantt diagram on the single-project dashboard + * @author gwenn + * + */ public class GanttAction extends WebMotionController { /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(GanttAction.class); + /** + * Return gantt data under json format + * @param client + * @param id + * @return + */ public Render getGanttInfo(ChoremClient client, String id) { Wikitty wikitty = client.restore(id); WikittyQuery quotationQuery = new WikittyQueryMaker() @@ -48,18 +59,7 @@ for(Task t : taskResult.getAll()) { if(t.getBeginDate() != null && t.getEndDate() != null) { - if(t.getStatus().equalsIgnoreCase("scheduled")) { - customClass = "ganttBlue"; - } - else if(t.getStatus().equalsIgnoreCase("started")) { - customClass = "ganttGreen"; - } - else if(t.getStatus().equalsIgnoreCase("finished")) { - customClass = "ganttRed"; - } - else if(t.getStatus().equalsIgnoreCase("closed")) { - customClass = "ganttGrey"; - } + customClass= "gantt-" + t.getStatus().toLowerCase(); Values[] v = null; if(t.getDayExtension() != 0) Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationData.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationData.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationData.java 2013-08-14 14:17:38 UTC (rev 384) @@ -8,79 +8,97 @@ import org.chorem.ChoremClient; import org.chorem.entities.Task; import org.chorem.entities.Quotation; +import org.chorem.entities.Time; import org.chorem.project.QuotationCalculation; +/** + * Represent a quotation to use it in a jsp page + * @author gwenn + * + */ public class QuotationData extends QuotationCalculation { - private List<TaskData> tasksData; - - public QuotationData(Quotation q, ChoremClient client) { - super(q, client); - tasksData = new ArrayList<TaskData>(); - - for(Task t : this.getTasks()) { - tasksData.add(new TaskData(t, client)); - } - this.calculate(); - getAlerts(); - } - - private void getAlerts() { - Calendar now = new GregorianCalendar(); - for(TaskData td : tasksData) { - Task t = td.getObject(); - if(t.getBeginDate() != null && t.getEndDate() != null) { - String str = "<h4>Warning</h4>"; - boolean alert = false; - //Test if the statuses are correct - if(t.getStatus().equalsIgnoreCase("Scheduled")) { - if(t.getBeginDate().before(now.getTime())) { - alert = true; - str += "Task " + t.getName() + " should be started"; - } - } - else if(t.getStatus().equalsIgnoreCase("Started")) { - if(t.getBeginDate().after(now.getTime())) { - alert = true; - str += "Task " + t.getName() + " has been started in advance"; - } - else if(t.getEndDate().before(now.getTime())) { - alert = true; - str += "Task " + t.getName() + " should have ended by now"; - } - } - else if(t.getStatus().equalsIgnoreCase("Finished")) { - - if(t.getEndDate().after(now.getTime())) { - alert = true; - str += "Task " + t.getName() + " has been finished in advance"; - } - } - if(alert) { - td.setAlert(str); - } - - } + protected List<TaskData> tasksData; - } - - } - - public TaskData getTaskData(Task t) { - for(TaskData td : tasksData) { - if(td.getObject() == t) { - return td; - } - } - return null; - } - - - - public List<TaskData> getTasksData() { - return tasksData; - } - - + public QuotationData(Quotation q, ChoremClient client) { + super(q, client); + tasksData = new ArrayList<TaskData>(); + + for(Task t : this.getTasks()) { + tasksData.add(new TaskData(t, client)); + } + this.calculate(); + addAlerts(tasksData); + } + + /** + * fetch the alerts of each task and stor it in the linked TaskData object + * @param tasksData + */ + protected void addAlerts(List<TaskData> tasksData) { + Calendar now = new GregorianCalendar(); + for(TaskData td : tasksData) { + Task t = td.getObject(); + if(t.getBeginDate() != null && t.getEndDate() != null) { + String alertStr = "<h4>Warning</h4>"; + String infoStr = "<h4>Info</h4>"; + boolean alert = false; + boolean info = false; + //Test if the statuses are correct + if(t.getStatus().equalsIgnoreCase("Scheduled")) { + if(t.getBeginDate().before(now.getTime())) { + alert = true; + alertStr += "Task " + t.getName() + " should be started"; + } + } + else if(t.getStatus().equalsIgnoreCase("Started")) { + + if(t.getEndDate().before(now.getTime())) { + alert = true; + alertStr += "Task " + t.getName() + " should have ended by now"; + } + } + + for(Time time : client.getTimes(t)) { + if(time.getBeginDate().before(t.getBeginDate()) || time.getEndDate().before(t.getBeginDate())) { + info=true; + infoStr = "Times have been added to the task but is is not started"; + } + else if(time.getBeginDate().after(t.getEndDate()) || time.getEndDate().after(t.getEndDate())) { + info=true; + infoStr = "Times have been added to the task but it should be ended"; + } + } + + + if(alert) { + td.setAlert(alertStr); + } + if(info) { + td.setInfo(infoStr); + } + + } + + } + + } + + public TaskData getTaskData(Task t) { + for(TaskData td : tasksData) { + if(td.getObject() == t) { + return td; + } + } + return null; + } + + + + public List<TaskData> getTasksData() { + return tasksData; + } + + } Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/QuotationStatusAction.java 2013-08-14 14:17:38 UTC (rev 384) @@ -11,13 +11,18 @@ import org.chorem.ChoremClient; import org.chorem.ChoremUtil; import org.chorem.webmotion.actions.GenericAction; -import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.call.Call; import org.debux.webmotion.server.render.Render; import org.nuiton.wikitty.entities.Wikitty; import org.nuiton.wikitty.entities.WikittyExtension; import org.nuiton.wikitty.entities.WikittyImpl; +/** + * Currently unsused class managing the ajax request for the quotation status changed. + * May be deprecated with the completion of the transaction funnel. + * @author gwenn + * + */ public class QuotationStatusAction extends GenericAction{ /** to use log facility, just put in your code: log.info(\"...\"); */ Modified: trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/TaskData.java =================================================================== --- trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/TaskData.java 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/project/TaskData.java 2013-08-14 14:17:38 UTC (rev 384) @@ -7,19 +7,28 @@ public class TaskData extends TaskCalculation { - - private String alert; - - public TaskData(Task t, ChoremClient client) { - super(t, client); - this.calculate(); - } - - public void setAlert(String a) { - alert = a; - } - - public String getAlert() { - return alert; - } + + private String alert; + private String info; + + public TaskData(Task t, ChoremClient client) { + super(t, client); + this.calculate(); + } + + public void setAlert(String a) { + alert = a; + } + + public String getAlert() { + return alert; + } + + public void setInfo(String a) { + info = a; + } + + public String getInfo() { + return info; + } } Modified: trunk/chorem-webmotion/src/main/resources/mapping =================================================================== --- trunk/chorem-webmotion/src/main/resources/mapping 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/resources/mapping 2013-08-14 14:17:38 UTC (rev 384) @@ -11,7 +11,7 @@ * /fragment/* DecoratorFilter.decorate wmDecoratorNo=true * /sales/funnel/json/* DecoratorFilter.decorate wmDecoratorNo=true * /project/json/* DecoratorFilter.decorate wmDecoratorNo=true -* /admin/employeeEdit/json/* DecoratorFilter.decorate wmDecoratorNo=true +* /hr/employeeEdit/json/* DecoratorFilter.decorate wmDecoratorNo=true * /ascii/* DecoratorFilter.decorate wmDecoratorNo=true * /rest/* DecoratorFilter.decorate wmDecoratorNo=true GET /* DecoratorFilter.decorate @@ -52,8 +52,6 @@ * /fragment/sales/{method} action:sales.SalesAction.{method} * /admin view:contact.jsp * /admin/importExport view:admin/importExport.jsp -* /admin/employeeEdit action:EmployeeEditAction.requestEmployeeEdit -* /admin/employeeEdit/json/{method}/{employeeId} action:EmployeeEditAction.{method} * /admin/{method} action:AdminAction.{method} * /contact view:contact.jsp * /report view:report.jsp @@ -64,6 +62,9 @@ * /hr/vacationDiv/{ids} action:HrAction.editVacationDiv * /hr/vacationRequest/save action:HrAction.saveVacationRequest * /hr/vacationRequest/delete/{id} action:HrAction.deleteVacationRequest +* /hr/employeeEdit action:EmployeeEditAction.requestEmployeeEdit +* /hr/dashboardAdc action:AdcDashboardAction.requestDashboardAdc +* /hr/employeeEdit/json/{method}/{employeeId} action:EmployeeEditAction.{method} * /salesMenu view:salesReports/menu.jsp * /sales/report/sentQuotation action:sales.SentQuotationsReportAction.sentQuotationPerMonth * /sales/report/acceptedQuotation action:sales.AcceptedQuotationsReportAction.acceptedQuotationPerMonth Added: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardAdc.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardAdc.jsp (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardAdc.jsp 2013-08-14 14:17:38 UTC (rev 384) @@ -0,0 +1,92 @@ +<%-- + #%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="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> +<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> + +<f:setLocale value="${locale}" /> + +<link rel="stylesheet" href="<c:url value='/css/employeeEdit.css'/>" /> + +<h1>${title}</h1> + +<form method="GET" id="companyForm"> + +<select class="filterBox" name="companyId" id="companySelect"> + <option>Choisir une entreprise</option> + <c:forEach var="c" items="${companies}"> + <option value="${c.wikittyId}" + <c:if test="${company.equals(c)}">selected</c:if> + >${c.name}</option> + </c:forEach> + </select> +</form> + +<form class="well form-inline" method="POST" id="company"> +<h4><a href="<c:url value="/wikitty/view/${company.wikittyId}"/>">${company.wikitty}</a></h4> +<input type="hidden" name="companyId" value="${company.wikittyId}"/> + +from : +<input type="text" value="${from}"> +to : +<input type="text" value="${to}"> +</form> +<form style='display:inline;' id='searchForm'>Recherche : <input type="text" id="searchInput"/></form> +<p><button class="btn btn-success" id="calculateBtn" year = "${lastYear}"> + <i class="icon-refresh icon-white"></i> + Calculer les CJMs pour ${lastYear} +</button></p> +<table class="table table-striped table-bordered table-condensed tableEdit"> + <thead> + <th class="headEmployee">Employé</th> + <c:forEach items="${years}" var="year"> + <th class="${year}">${year}</th> + </c:forEach> + <th>CJM estimé</th> + </thead> + <tbody> + <c:set var="count" value="0"/> + <c:forEach items="${employees}" var="employee"> + <tr class="bodyRow row${count}" id="${employee.object.wikittyId}"> + <td class="person bodyEmployee"><w:display wikitty="${employee.object.wikitty}" + fqfield="Employee.person" label="" /> + </td> + <c:forEach items="${years}" var="year"> + <td class="year${year}"> + <c:if test="${not empty employee.adcPerYear[year]}"> + ${employee.adcPerYear[year]} + </c:if> + </td> + </c:forEach> + <td class="estimatedAdc">${employee.estimatedAdc}</td> + + </tr> + <c:set var="count" value="${count + 1}"/> + </c:forEach> + </tbody> +</table> +<script src="<c:url value='/js/employeeEdit.js'/>"></script> +<script src="<c:url value='/js/dashboardAdc.js'/>"></script> + Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/dashboardSingleProject.jsp 2013-08-14 14:17:38 UTC (rev 384) @@ -177,7 +177,10 @@ wikitty="${task.object.wikitty}" fqfield="Task.name" label="" /></a> <c:if test="${not empty task.alert}"> <i class="icon-warning-sign" title="${task.alert}"></i> - </c:if> + </c:if> + <c:if test="${not empty task.info}"> + <i class="icon-info-sign" title="${task.info}"></i> + </c:if> <td><w:display wikitty="${task.object.wikitty}" Modified: trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp =================================================================== --- trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/webapp/WEB-INF/jsp/decorator.jsp 2013-08-14 14:17:38 UTC (rev 384) @@ -193,6 +193,8 @@ <li>Employee HR</li> <li><a href="<c:url value="/wikitty/EmployeeHR/search"/>"><i class="icon-th-list icon-black"></i> All employees HR</a></li> <li><a href="<c:url value="/wikitty/EmployeeHR/edit/new"/>"><i class="icon-plus icon-black"></i> Add employee HR</a> + <li><a href="<c:url value="/hr/employeeEdit"/>">Employee edit</a></li> + <li><a href="<c:url value="/hr/dashboardAdc"/>">Adc Dashboard</a></li> <li>Vacation</li> <li><a href="<c:url value="/wikitty/Vacation/search"/>"><i class="icon-th-list icon-black"></i> All vacations</a></li> <li><a href="<c:url value="/wikitty/Vacation/edit/new"/>"><i class="icon-plus icon-black"></i> Add vacation</a></li> @@ -221,7 +223,7 @@ <li class="divider"></li> <li><a href="<c:url value="/admin/reindex"/>">Reindex</a></li> <li class="divider"></li> - <li><a href="<c:url value="/admin/employeeEdit"/>">Employee edit</a></li> + </ul> </li> </ul> Added: trunk/chorem-webmotion/src/main/webapp/js/dashboardAdc.js =================================================================== --- trunk/chorem-webmotion/src/main/webapp/js/dashboardAdc.js (rev 0) +++ trunk/chorem-webmotion/src/main/webapp/js/dashboardAdc.js 2013-08-14 14:17:38 UTC (rev 384) @@ -0,0 +1,47 @@ + + +$(document).ready(function() { + + + + + $('#calculateBtn').click(function() { + + var rows = $('.bodyRow'); + var str = ""; + var year = $(this).attr('year'); + for(var i = 0; i < rows.length; i++) { + str = str + $(rows[i]).attr('id'); + if(i != (rows.length -1)) { + str= str + ','; + } + + } + $(this).attr('disabled', 'disabled'); + $.get(createUrl("/hr/employeeEdit/json/requestMultipleAdc/",str,'?real=true&year=2012'), + function(ret){ + $('#calculateBtn').removeAttr('disabled'); + var adcs = ret['adcs']; + if($('.' + year).size() != 0) { + for(var i in adcs) { + var row = $('#'+i); + row.find('.year' + year).text(adcs[i]); + } + }else { + $('.headEmployee').after("<th class='"+year+"'>"+year+"</th>"); + for(var i in adcs) { + + var row = $('#'+i); + row.find('.bodyEmployee').after('<td class="year'+year+'">'+adcs[i]+'</td>'); + + } + } + }); + + + }); + + + + +}); \ No newline at end of file Modified: trunk/chorem-webmotion/src/main/webapp/js/employeeEdit.js =================================================================== --- trunk/chorem-webmotion/src/main/webapp/js/employeeEdit.js 2013-08-14 12:14:58 UTC (rev 383) +++ trunk/chorem-webmotion/src/main/webapp/js/employeeEdit.js 2013-08-14 14:17:38 UTC (rev 384) @@ -124,7 +124,7 @@ $('#editAllBtn').attr('disabled', 'disabled'); $('.spinner').show(); } - $.get(createUrl("/admin/employeeEdit/json/editEmployeeValues/",row.attr("id"), "?salaryStr=", + $.get(createUrl("/hr/employeeEdit/json/editEmployeeValues/",row.attr("id"), "?salaryStr=", salaryVal, "&productivityRateStr=", prodVal, "&partialTimeStr=", timeVal, "&dailyReturnStr=", cjmVal, "&otherPaymentsStr=", otherVal), function(ret){ @@ -182,7 +182,7 @@ var cjm = row.find(".dailyReturn"); blockDailyReturn(row); blockEdit(row); - $.get(createUrl("/admin/employeeEdit/json/requestAdc/",row.attr("id")), + $.get(createUrl("/hr/employeeEdit/json/requestAdc/",row.attr("id"),"?real=false"), function(ret){ var adc = ret['adc']; displayDailyReturn(row, adc, true); @@ -205,8 +205,7 @@ } } - console.log(str); - $.get(createUrl("/admin/employeeEdit/json/requestMultipleAdc/",str), + $.get(createUrl("/hr/employeeEdit/json/requestMultipleAdc/",str, "?real=false&year=0"), function(ret){ var adcs = ret['adcs']; for(var i in adcs) {
participants (1)
-
meynier@users.chorem.org