diff --git a/pom.xml b/pom.xml
index 85e39c8b..f6feedfc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,11 +192,11 @@
-
- net.tanesha.recaptcha4j
- recaptcha4j
- 0.0.7
-
+
+ net.tanesha.recaptcha4j
+ recaptcha4j
+ 0.0.7
+
@@ -208,6 +208,19 @@
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.2
+
+ true
+ true
+
+
+
+
org.apache.maven.plugins
@@ -255,6 +268,6 @@
https://github.com/gaetancollaud/fablab-manager
scm:git:git://github.com/gaetancollaud/fablab-manager.git
scm:git:git@github.com:gaetancollaud/fablab-manager.git
- HEAD
-
+ HEAD
+
\ No newline at end of file
diff --git a/src/main/java/net/collaud/fablab/manager/data/UserEO.java b/src/main/java/net/collaud/fablab/manager/data/UserEO.java
index 4a066960..75712ba3 100644
--- a/src/main/java/net/collaud/fablab/manager/data/UserEO.java
+++ b/src/main/java/net/collaud/fablab/manager/data/UserEO.java
@@ -31,6 +31,8 @@
import lombok.Setter;
import lombok.ToString;
import net.collaud.fablab.manager.data.type.Gender;
+import net.collaud.fablab.manager.export.CsvExport;
+import net.collaud.fablab.manager.export.CsvField;
/**
*
@@ -43,6 +45,7 @@
@ToString
@NoArgsConstructor
@AllArgsConstructor
+@CsvExport(fileName = "users")
public class UserEO extends AbstractDataEO implements Serializable {
private static final long serialVersionUID = 1L;
@@ -64,26 +67,33 @@ public class UserEO extends AbstractDataEO implements Serializable {
@JsonProperty
private String passwordNew;
+ @CsvField(headerName="Firstname")
@Column(name = "firstname", nullable = false)
private String firstname;
+ @CsvField(headerName="Lastname")
@Column(name = "lastname", nullable = false)
private String lastname;
+ @CsvField(headerName="Email")
@Column(name = "email", nullable = false, unique = true)
private String email;
+ @CsvField(headerName="Inscription date")
@Column(name = "date_inscr", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date dateInscr;
+ @CsvField(headerName="Rfid")
@Column(name = "rfid", nullable = true)
private String rfid;
+ @CsvField(headerName="birthdate")
@Column(name = "birthdate", nullable = true)
@Temporal(TemporalType.DATE)
private Date birthdate;
+ @CsvField(headerName="Gender")
@Column(name = "gender", nullable = true)
@Enumerated(EnumType.ORDINAL)
private Gender gender;
@@ -92,12 +102,15 @@ public class UserEO extends AbstractDataEO implements Serializable {
@Column(name = "enabled", nullable = false)
private boolean enabled;
+ @CsvField(headerName="Phone")
@Column(name = "phone", nullable = true)
private String phone;
+ @CsvField(headerName="Address")
@Column(name = "address", nullable = true)
private String address;
+ @CsvField(headerName="Comment")
@Column(name = "comment", nullable = true)
private String comment;
diff --git a/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntry.java b/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntry.java
index fc3af4aa..886f71d0 100644
--- a/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntry.java
+++ b/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntry.java
@@ -9,6 +9,8 @@
import net.collaud.fablab.manager.data.UsageEO;
import net.collaud.fablab.manager.data.UserEO;
import net.collaud.fablab.manager.data.type.HistoryEntryType;
+import net.collaud.fablab.manager.export.CsvExport;
+import net.collaud.fablab.manager.export.CsvField;
/**
*
@@ -17,14 +19,21 @@
@Getter
@Setter
@EqualsAndHashCode(of = {"id", "type"})
+@CsvExport(fileName = "accounting")
public class HistoryEntry implements Comparable {
private final int id;
+ @CsvField(headerName = "type")
private final HistoryEntryType type;
+ @CsvField(headerName = "comment")
private final String comment;
+ @CsvField(headerName = "date")
private final Date date;
+ @CsvField(headerName = "amount")
private final double amount;
+ @CsvField(headerName = "detail")
private final String detail;
+ @CsvField(headerName = "user")
private final HistoryEntryUser user;
public HistoryEntry(PaymentEO payment) {
diff --git a/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntryUser.java b/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntryUser.java
index 6fc80da7..7ba124ec 100644
--- a/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntryUser.java
+++ b/src/main/java/net/collaud/fablab/manager/data/virtual/HistoryEntryUser.java
@@ -21,4 +21,9 @@ public HistoryEntryUser(UserEO user){
this.firstname = user.getFirstname();
}
+ @Override
+ public String toString() {
+ return firstname+" "+lastname;
+ }
+
}
diff --git a/src/main/java/net/collaud/fablab/manager/export/CsvExport.java b/src/main/java/net/collaud/fablab/manager/export/CsvExport.java
new file mode 100644
index 00000000..3c2e879a
--- /dev/null
+++ b/src/main/java/net/collaud/fablab/manager/export/CsvExport.java
@@ -0,0 +1,17 @@
+package net.collaud.fablab.manager.export;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Gaetan Collaud
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface CsvExport {
+ public String fileName();
+
+}
diff --git a/src/main/java/net/collaud/fablab/manager/export/CsvExporter.java b/src/main/java/net/collaud/fablab/manager/export/CsvExporter.java
new file mode 100644
index 00000000..dbf1b4f3
--- /dev/null
+++ b/src/main/java/net/collaud/fablab/manager/export/CsvExporter.java
@@ -0,0 +1,81 @@
+package net.collaud.fablab.manager.export;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BinaryOperator;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ *
+ * @author Gaetan Collaud
+ */
+@Slf4j
+public class CsvExporter {
+
+ public static final String FIELD_SEPARATOR = ";";
+ public static final String LINE_SEPARATOR = "\n";
+ public static final String ESCAPE_CHAR = "\"";
+
+ private final Map fields;
+ private final CsvExport classAnnotation;
+ private final StringBuilder builder;
+
+ public CsvExporter(Class type) {
+ fields = new LinkedHashMap<>();
+ builder = new StringBuilder();
+ classAnnotation = Optional.ofNullable(type.getAnnotation(CsvExport.class))
+ .orElseThrow(() -> new IllegalArgumentException("Class " + type.getSimpleName() + " has no CsvExport annotation"));
+ Arrays.stream(type.getDeclaredFields())
+ .filter(f -> f.getAnnotation(CsvField.class) != null)
+ .forEach(f -> fields.put(f, f.getAnnotation(CsvField.class)));
+ }
+
+ public CsvExporter writeHeader() {
+ return writeLine(fields.values().stream()
+ .map(f -> f.headerName())
+ .reduce(reduce())
+ .orElse(""));
+ }
+
+ public CsvExporter writeRow(T obj) {
+ return writeLine(fields.keySet().stream()
+ .map(f -> getFieldValue(obj, f))
+ .reduce(reduce())
+ .orElse(""));
+ }
+
+ private BinaryOperator reduce() {
+ return (l, r) ->l + FIELD_SEPARATOR + r ;
+ }
+
+ @Override
+ public String toString() {
+ return builder.toString();
+ }
+
+ public String getFileName() {
+ return classAnnotation.fileName();
+ }
+
+ private String getFieldValue(T obj, Field f) {
+ try {
+ f.setAccessible(true);
+ return Optional.ofNullable(f.get(obj))
+ .map(v -> v.toString())
+ .orElse("");
+ } catch (IllegalAccessException ex) {
+ log.error("Cannot access field " + f.getName(), ex);
+ return "";
+ }
+ }
+
+ private CsvExporter writeLine(String l) {
+ builder.append(l);
+ builder.append(LINE_SEPARATOR);
+ return this;
+ }
+
+}
diff --git a/src/main/java/net/collaud/fablab/manager/export/CsvField.java b/src/main/java/net/collaud/fablab/manager/export/CsvField.java
new file mode 100644
index 00000000..eb1b2860
--- /dev/null
+++ b/src/main/java/net/collaud/fablab/manager/export/CsvField.java
@@ -0,0 +1,16 @@
+package net.collaud.fablab.manager.export;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Gaetan Collaud
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface CsvField {
+ public String headerName();
+}
diff --git a/src/main/java/net/collaud/fablab/manager/rest/v1/AccoutingWS.java b/src/main/java/net/collaud/fablab/manager/rest/v1/AccoutingWS.java
index 902f072a..4459c9f6 100644
--- a/src/main/java/net/collaud/fablab/manager/rest/v1/AccoutingWS.java
+++ b/src/main/java/net/collaud/fablab/manager/rest/v1/AccoutingWS.java
@@ -1,6 +1,11 @@
package net.collaud.fablab.manager.rest.v1;
+import java.util.Date;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
import net.collaud.fablab.manager.annotation.JavascriptAPIConstant;
+import net.collaud.fablab.manager.data.virtual.HistoryEntry;
+import net.collaud.fablab.manager.export.CsvExporter;
import net.collaud.fablab.manager.rest.v1.criteria.PeriodSearchCriteria;
import net.collaud.fablab.manager.rest.v1.model.BaseModel;
import net.collaud.fablab.manager.rest.v1.model.DataModel;
@@ -10,6 +15,8 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -29,4 +36,21 @@ public BaseModel search(@Validated @RequestBody PeriodSearchCriteria search) {
return new DataModel(paymentService.getPaymentEntries(search));
}
+ @RequestMapping(value = "export", method = RequestMethod.GET, produces = "text/csv")
+ @ResponseBody
+ public String export(@RequestParam("dateFrom") Long dateFrom,@RequestParam("dateTo") Long dateTo, HttpServletResponse response) {
+ response.setContentType("text/csv");
+ Date from = new Date(dateFrom*1000);
+ Date to = new Date(dateTo*1000);
+ final List list = paymentService.getPaymentEntries(new PeriodSearchCriteria(from, to));
+ if (list.isEmpty()) {
+ return "";
+ }
+ CsvExporter exporter = new CsvExporter<>(list.get(0).getClass());
+ response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s.csv\"",exporter.getFileName()));
+ exporter.writeHeader();
+ list.forEach(l -> exporter.writeRow(l));
+ return exporter.toString();
+ }
+
}
diff --git a/src/main/java/net/collaud/fablab/manager/rest/v1/base/ReadRestWebservice.java b/src/main/java/net/collaud/fablab/manager/rest/v1/base/ReadRestWebservice.java
index 486de5fe..5f7cdd89 100644
--- a/src/main/java/net/collaud/fablab/manager/rest/v1/base/ReadRestWebservice.java
+++ b/src/main/java/net/collaud/fablab/manager/rest/v1/base/ReadRestWebservice.java
@@ -1,9 +1,11 @@
package net.collaud.fablab.manager.rest.v1.base;
import java.util.List;
+import javax.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.Setter;
import net.collaud.fablab.manager.data.AbstractDataEO;
+import net.collaud.fablab.manager.export.CsvExporter;
import net.collaud.fablab.manager.rest.v1.model.BaseModel;
import net.collaud.fablab.manager.rest.v1.model.DataModel;
import net.collaud.fablab.manager.service.global.ReadService;
@@ -19,11 +21,11 @@
* @param repository
*/
abstract public class ReadRestWebservice> {
-
+
@Setter
@Getter
private SERVICE service;
-
+
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public BaseModel list() {
@@ -32,6 +34,22 @@ public BaseModel list() {
return model;
}
+ @RequestMapping(value = "/export", method = RequestMethod.GET, produces = "text/csv")
+ @ResponseBody
+ public String export(HttpServletResponse response) {
+ response.setContentType("text/csv");
+
+ List list = service.findAll();
+ if (list.isEmpty()) {
+ return "";
+ }
+ CsvExporter exporter = new CsvExporter<>(list.get(0).getClass());
+ response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s.csv\"",exporter.getFileName()));
+ exporter.writeHeader();
+ list.forEach(l -> exporter.writeRow(l));
+ return exporter.toString();
+ }
+
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public BaseModel get(@PathVariable("id") Integer id) {
diff --git a/src/main/webapp/components/accounting/accounting-list-ctrl.js b/src/main/webapp/components/accounting/accounting-list-ctrl.js
index 51d3a7bb..09713099 100644
--- a/src/main/webapp/components/accounting/accounting-list-ctrl.js
+++ b/src/main/webapp/components/accounting/accounting-list-ctrl.js
@@ -52,32 +52,35 @@
$scope.updateAccounting();
};
- var computeInAndOut = function(){
+ var computeInAndOut = function () {
var moneyIn = 0;
var sell = 0;
- angular.forEach($scope.history, function(h){
- if(h.amount>0){
+ angular.forEach($scope.history, function (h) {
+ if (h.amount > 0) {
moneyIn += h.amount;
- }else{
+ } else {
sell -= h.amount;
}
});
$scope.results = {
- moneyIn : moneyIn,
+ moneyIn: moneyIn,
sell: sell,
- delta : moneyIn-sell
+ delta: moneyIn - sell
};
};
$scope.updateAccounting = function () {
- AccountingService.search($scope.criteria.dateFrom, $scope.criteria.dateTo, function(data){
+ AccountingService.search($scope.criteria.dateFrom, $scope.criteria.dateTo, function (data) {
$scope.history = data;
computeInAndOut();
});
};
-
- $scope.export = function(){
- alert('todo');
+
+ $scope.export = function () {
+ var format = 'DD-MM-YYYY hh:mm:ss'
+ var from = moment($scope.criteria.dateFrom).format('X');
+ var to = moment($scope.criteria.dateTo).format('X');
+ window.location = App.API.ACCOUNTING_API + "/export?dateFrom=" + from + "&dateTo=" + to;
};
$scope.periodPreset($scope.intervals[2]);//this month
diff --git a/src/main/webapp/components/user/list-ctrl.js b/src/main/webapp/components/user/list-ctrl.js
index 7500197d..7e47ad65 100644
--- a/src/main/webapp/components/user/list-ctrl.js
+++ b/src/main/webapp/components/user/list-ctrl.js
@@ -43,6 +43,10 @@ angular.module('Fablab').controller('UserListController', function ($scope, $fil
NotificationService.notify("success", "TODO Mailing list mise à jour");
});
};
+
+ $scope.export = function(){
+ window.location=App.API.USER_API+"/export";
+ }
updateUserList();
diff --git a/src/main/webapp/components/user/list-view.html b/src/main/webapp/components/user/list-view.html
index 00164d29..8a368d75 100644
--- a/src/main/webapp/components/user/list-view.html
+++ b/src/main/webapp/components/user/list-view.html
@@ -2,7 +2,7 @@