results = new ArrayList<>();
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/IntervalWindow.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/IntervalWindow.java
new file mode 100644
index 000000000..778e87ea7
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/IntervalWindow.java
@@ -0,0 +1,205 @@
+package org.jeecg.modules.business.domain.job;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+/**
+ * Extends {@code LinkedHashMap} into a fixed sized ordered cache
+ * for allocating and tracking limited resources in intervals. It also
+ * tracks the allocation rate as a moving average.
+ *
+ * The {@code IntervalWindow} is created with a cache that consists of the
+ * present interval and at least one past interval.
+ * As the number of cached intervals exceed the windows size, they are
+ * removed and the moving average updated. The allocation method is
+ * thread-safe to ensure over allocation is avoided.
+ *
+ * @author martinb
+ * @since 2015-08-17
+ */
+public class IntervalWindow extends LinkedHashMap
+{
+ /**
+ * Serial
+ */
+ private static final long serialVersionUID = 201508171315L;
+
+ /**
+ * The upper execution limit per interval
+ */
+ private final int INTERVAL_LIMIT;
+
+ /**
+ * Number of intervals to track
+ */
+ private final int INTERVAL_WINDOW_SIZE;
+
+ /**
+ * The current interval being filled.
+ */
+ private long currentInterval = 0;
+
+ /**
+ * The moving total of slots used in the window
+ */
+ private int slotsUsedInWindow = 0;
+
+ /**
+ * The minimum interval index that can be considered.
+ */
+ private long minimumInterval = 0;
+
+
+ /**
+ * Returns the value in the map, or a default.
+ * Implemented in JSE8
+ *
+ * @param key
+ * @param defaultValue
+ * @return the value
+ */
+ private final int getOrDefault(Long key,
+ Integer defaultValue)
+ {
+ if (get(key) != null)
+ {
+ return get(key);
+ }
+ return defaultValue;
+ }
+
+
+ /**
+ * Decreases the running total by the number of slots used in the
+ * interval leaving the moving window.
+ *
+ * The value in map is the number of free slots left in the interval.
+ *
+ * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
+ */
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ if (INTERVAL_WINDOW_SIZE < size())
+ {
+ slotsUsedInWindow -= (INTERVAL_LIMIT - eldest.getValue());
+ minimumInterval = eldest.getKey();
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Tries to allocate a slot in the given interval within the rate limit.
+ *
+ * @param interval
+ * the interval
+ * @return true is a slot was allocated in the interval
+ */
+ public boolean allocateSlot(long interval)
+ {
+ boolean isSlotAllocated = false;
+ int freeSlots = 0; // Free slots in the interval
+
+ if (interval > minimumInterval)
+ /*
+ * Cheap range check is OK
+ */
+ {
+ synchronized (this)
+ /*
+ * Synchronize allocate on this object to ensure that cache is consistent
+ */
+ {
+ if ((freeSlots = getOrDefault(interval,
+ INTERVAL_LIMIT)) > 0)
+ /*
+ * There are free slots in this interval to execute this thread
+ * Break out of the loop and return.
+ */
+ {
+ if (currentInterval > 0 && currentInterval != interval)
+ /*
+ * Update the running total of slots used in window
+ * with past values only once past the first interval.
+ */
+ {
+ slotsUsedInWindow +=
+ INTERVAL_LIMIT
+ - getOrDefault(currentInterval,
+ 0);
+ }
+
+ put(currentInterval = interval, freeSlots - 1); // Maximum is RATE_LIMIT - 1
+ isSlotAllocated = true;
+ } // if
+ } // synchronized
+ } // if
+
+ return isSlotAllocated;
+ }
+
+
+ /**
+ * Returns the moving average number of slots allocated for work during
+ * the present window but excluding the currently filling interval
+ *
+ * @return the average number of slots used
+ */
+ public float getAverageSlotUsed()
+ {
+ return slotsUsedInWindow / (INTERVAL_WINDOW_SIZE - 1);
+ }
+
+
+ /**
+ * Check window size parameters for range.
+ *
+ * @param intervalWindowSize
+ * the proposed window size
+ * @return the window size
+ */
+ private static int checkWindowSize(int intervalWindowSize)
+ {
+ if (intervalWindowSize < 2)
+ {
+ throw new IllegalArgumentException(
+ "Interval Window Size cannot be smaller than 2");
+ }
+ return intervalWindowSize;
+
+ }
+
+
+ /**
+ * Creates an {@code IntervalWindow} of a window size of two that limits the
+ * number of successful allocations in each interval.
+ *
+ * @param intervalLimit
+ * the maximum number of allocations per interval.
+ */
+ public IntervalWindow(int intervalLimit)
+ {
+ super(2, 1);
+ INTERVAL_WINDOW_SIZE = 2;
+ INTERVAL_LIMIT = intervalLimit;
+ }
+
+
+ /**
+ * Creates an {@code IntervalWindow} of a given window size that limits the
+ * number of successful allocations in each interval.
+ *
+ * @param intervalLimit
+ * the maximum number of allocations per interval.
+ * @param intervalWindow
+ * the number if intervals to track, must be at least two
+ */
+ public IntervalWindow(int intervalLimit, int intervalWindow)
+ {
+ super(checkWindowSize(intervalWindow),
+ 1);
+ INTERVAL_WINDOW_SIZE = intervalWindow;
+ INTERVAL_LIMIT = intervalLimit;
+ }
+
+}
\ No newline at end of file
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ThrottlingExecutorService.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ThrottlingExecutorService.java
new file mode 100644
index 000000000..b30e37511
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ThrottlingExecutorService.java
@@ -0,0 +1,166 @@
+package org.jeecg.modules.business.domain.job;
+
+import static java.lang.Integer.MAX_VALUE;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@code ExecutorService} that throttles the amount of work released
+ * for execution per time period.
+ *
+ * @author martinb
+ * @since 2015-08-17
+ */
+public class ThrottlingExecutorService extends ThreadPoolExecutor {
+ /**
+ * The interval window cache
+ */
+ private final IntervalWindow INTERVAL_WINDOW;
+
+ /**
+ * The rate limit interval in milliseconds
+ */
+ private final long RATE_INTERVAL_MILLISECONDS;
+
+
+ /**
+ * Caching, dynamic rate limiting {@code ExecutorService}
+ *
+ * @param rateLimit
+ * the rate limit
+ * @param unit
+ * the rate limit time unit
+ */
+ private ThrottlingExecutorService(
+ int rateLimit,
+ TimeUnit unit)
+ {
+ /*
+ * Create a CACHING ExecutorService
+ */
+ super(0, MAX_VALUE,
+ 60L, SECONDS,
+ new SynchronousQueue());
+
+ INTERVAL_WINDOW = new IntervalWindow(rateLimit);
+ RATE_INTERVAL_MILLISECONDS = unit.toMillis(1);
+ }
+
+
+ /**
+ * Fixed size rate limiting {@code ExecutorService}
+ *
+ * @param parallelism
+ * @param rateLimit
+ * @param unit
+ */
+ private ThrottlingExecutorService(int parallelism,
+ int rateLimit,
+ TimeUnit unit)
+ {
+ /*
+ * Create a FIXED ExecutorService
+ */
+ super(parallelism, parallelism, 0, MILLISECONDS,
+ new LinkedBlockingQueue());
+
+ INTERVAL_WINDOW = new IntervalWindow(rateLimit);
+ RATE_INTERVAL_MILLISECONDS = unit.toMillis(1);
+ }
+
+
+ /**
+ * Produces a throttling ExecutorService
+ *
+ * Evaluates the parameters and generates an appropriate ExecutorService
+ *
+ * @param parallelism
+ * how many threads
+ * @param rateLimit
+ * work per time unit
+ * @param unit
+ * the time unit
+ * @return the ExecutorService
+ */
+ public static ExecutorService createExecutorService(int parallelism,
+ int rateLimit,
+ TimeUnit unit)
+ {
+ if (parallelism > 0)
+ /*
+ * Fixed ExecutorService
+ */
+ {
+ return new ThrottlingExecutorService(parallelism,
+ rateLimit > 0 ? rateLimit : MAX_VALUE,
+ unit);
+ }
+ else
+ /*
+ * Caching ExecutorService
+ */
+ {
+ return new ThrottlingExecutorService(
+ rateLimit > 0 ? rateLimit : MAX_VALUE,
+ unit);
+ }
+ }
+
+
+ /**
+ * Throttles the execution before executing the task to achieve the desired
+ * rate.
+ *
+ * @see java.util.concurrent.ThreadPoolExecutor#execute(java.lang.Runnable)
+ */
+ @Override
+ public void execute(final Runnable task)
+ {
+ throttle();
+ super.execute(task);
+ }
+
+
+ /**
+ * Throttles if the thread can not be allocated in the current time
+ * interval,
+ * forcing it to wait to the next interval.
+ */
+ private void throttle()
+ {
+ long interval = 0; // The interval index
+ long milliTime = System.currentTimeMillis(); // The current time
+ long offset = milliTime % RATE_INTERVAL_MILLISECONDS; // Interval offset
+
+ while (!INTERVAL_WINDOW.allocateSlot(
+ (interval = (milliTime + offset) / RATE_INTERVAL_MILLISECONDS)))
+ /*
+ * Cannot allocate free slots in this interval.
+ * Calculate the required pause to get to the next interval and sleep
+ */
+ {
+ int pause = (int) (((interval + 1)
+ * RATE_INTERVAL_MILLISECONDS)
+ - milliTime + offset);
+ try
+ /*
+ * Try to sleep the thread for a pause of nanoseconds
+ */
+ {
+ Thread.sleep(pause);
+ }
+ catch (InterruptedException e)
+ {
+ }
+
+ milliTime = System.currentTimeMillis();
+
+ } // while
+ }
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/YPJob.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/YPJob.java
new file mode 100644
index 000000000..0871cbb25
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/YPJob.java
@@ -0,0 +1,126 @@
+package org.jeecg.modules.business.domain.job;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.util.EntityUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.jeecg.modules.business.domain.api.hualei.HLRequest;
+import org.jeecg.modules.business.domain.api.hualei.HLResponse;
+import org.jeecg.modules.business.domain.api.hualei.HLResponseItem;
+import org.jeecg.modules.business.service.IParcelService;
+import org.jeecg.modules.business.service.IPlatformOrderService;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Slf4j
+public class YPJob implements Job {
+
+ @Autowired
+ private IParcelService parcelService;
+ @Autowired
+ private IPlatformOrderService platformOrderService;
+
+ private final static String URL = "http://www.yuanpeng56.com:8082/selectTrack.htm";
+
+ private static final Integer DEFAULT_NUMBER_OF_DAYS = 15;
+ private static final Integer DEFAULT_MAXIMUM_NUMBER_OF_PARCELS_PER_TRANSACTION = 800;
+ private static final List DEFAULT_TRANSPORTERS = Arrays.asList("法国普货小包专线");
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ LocalDate endDate = LocalDate.now();
+ LocalDate startDate = endDate.minusDays(DEFAULT_NUMBER_OF_DAYS);
+ List transporters = DEFAULT_TRANSPORTERS;
+ boolean overrideRestriction = false;
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ JobDataMap jobDataMap = context.getMergedJobDataMap();
+ String parameter = ((String) jobDataMap.get("parameter"));
+ if (parameter != null) {
+ try {
+ JSONObject jsonObject = new JSONObject(parameter);
+ if (!jsonObject.isNull("startDate")) {
+ String startDateStr = jsonObject.getString("startDate");
+ startDate = LocalDate.parse(startDateStr);
+ }
+ if (!jsonObject.isNull("endDate")) {
+ String endDateStr = jsonObject.getString("endDate");
+ endDate = LocalDate.parse(endDateStr);
+ }
+ if (!jsonObject.isNull("transporters")) {
+ JSONArray transporterArray = jsonObject.getJSONArray("transporters");
+ List transporterList = new ArrayList<>();
+ for (int i = 0; i < transporterArray.length(); i++) {
+ transporterList.add(transporterArray.getString(i));
+ }
+ transporters = transporterList;
+ }
+ if (!jsonObject.isNull("override")) {
+ overrideRestriction = jsonObject.getBoolean("override");
+ }
+ } catch (JSONException e) {
+ log.error("Error while parsing parameter as JSON, falling back to default parameters.");
+ }
+ }
+
+ if (!endDate.isAfter(startDate)) {
+ throw new RuntimeException("EndDate must be strictly greater than StartDate !");
+ } else if (endDate.minusDays(30).isAfter(startDate) && !overrideRestriction) {
+ throw new RuntimeException("No more than 30 days can separate startDate and endDate !");
+ }
+
+ log.info("Starting to retrieve parcel traces of {} from {} to {}", transporters, startDate, endDate);
+ List billCodes = platformOrderService.fetchBillCodesOfParcelsWithoutTrace(
+ Date.valueOf(startDate), Date.valueOf(endDate), transporters);
+ log.info("{} parcels without trace in total", billCodes.size());
+ List> billCodeLists = Lists.partition(billCodes, 40);
+ log.info("Requests will be divided in to {} parts", billCodeLists.size());
+ List parcelTraces = new ArrayList<>();
+ List hlRequests = new ArrayList<>();
+ billCodeLists.forEach(billcodeList -> {
+ HLRequest hlRequest = new HLRequest(URL, billcodeList);
+ hlRequests.add(hlRequest);
+ });
+ List results = new ArrayList<>();
+ for (HLRequest request : hlRequests) {
+ boolean success = false;
+ HttpEntity entity = request.send().getEntity();
+ try {
+ // String of the response
+ String responseString = EntityUtils.toString(entity, "UTF-8");
+ // Geniuses at HL decided to put the sole response object in an array....
+ HLResponse[] hlResponseArray = mapper.readValue(responseString, HLResponse[].class);
+ parcelTraces.addAll(hlResponseArray[0].getResponseItems());
+ success = true;
+ } catch (IOException e) {
+ log.error("Error while parsing response into String", e);
+ } finally {
+ results.add(success);
+ }
+ log.info("{} parcel added to the queue to be inserted into DB.", parcelTraces.size());
+ }
+ long nbSuccesses = results.stream().filter(b -> b).count();
+ log.info("{}/{} lots of 40 parcel traces have been retrieved.", nbSuccesses, hlRequests.size());
+
+ List> parcelTraceList = Lists.partition(parcelTraces, DEFAULT_MAXIMUM_NUMBER_OF_PARCELS_PER_TRANSACTION);
+ for (List parcelTracesPerTransaction : parcelTraceList) {
+ parcelService.saveHLParcelAndTraces(parcelTracesPerTransaction);
+ }
+ }
+
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PlatformOrderContent.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PlatformOrderContent.java
index a143e23b2..ece603025 100644
--- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PlatformOrderContent.java
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PlatformOrderContent.java
@@ -19,9 +19,9 @@ import java.util.Objects;
* @Description: 平台订单内容
* @Author: jeecg-boot
* @Date: 2023-11-28
- * @Version: V1.4
+ * @Version: V1.5
*/
-@ApiModel(value = "platform_order对象", description = "平台订单表")
+@ApiModel(value = "platform_order_content对象", description = "平台订单内容")
@Data
@TableName("platform_order_content")
public class PlatformOrderContent implements Serializable {
@@ -133,6 +133,13 @@ public class PlatformOrderContent implements Serializable {
@Excel(name = "海外仓操作费", width = 15)
@ApiModelProperty(value = "海外仓操作费")
private java.math.BigDecimal pickingFee;
+ /**
+ * 商品多属性
+ */
+ @Excel(name = "商品多属性", width = 15)
+ @ApiModelProperty(value = "商品多属性")
+ private java.lang.String customizationData;
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMabangMapper.xml b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMabangMapper.xml
index 684b8c313..351832dff 100644
--- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMabangMapper.xml
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMabangMapper.xml
@@ -189,14 +189,14 @@
INSERT INTO platform_order_content(
id, create_by, create_time,
update_by, update_time, platform_order_id,
- sku_id, quantity, erp_status, product_available)
+ sku_id, quantity, erp_status, product_available, customization_data)
VALUES
(
UUID(), 'Mabang API', NOW(),
'Mabang API', NOW(), #{item.platformOrderId},
skuErpToId(#{item.erpCode}), #{item.quantity}, #{item.erpStatus},
- #{item.productAvailable})
+ #{item.productAvailable}, #{item.specifics})
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/PlatformOrderShippingInvoiceService.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/PlatformOrderShippingInvoiceService.java
index f97b2abb5..0c8fe4820 100644
--- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/PlatformOrderShippingInvoiceService.java
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/PlatformOrderShippingInvoiceService.java
@@ -1,5 +1,7 @@
package org.jeecg.modules.business.service;
+import com.aspose.cells.SaveFormat;
+import com.aspose.cells.Workbook;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
@@ -34,7 +36,10 @@ import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -106,6 +111,11 @@ public class PlatformOrderShippingInvoiceService {
@Value("${jeecg.path.shippingInvoiceDetailDir}")
private String INVOICE_DETAIL_DIR;
+ @Value("${jeecg.path.shippingInvoicePdfDir}")
+ private String INVOICE_PDF_DIR;
+ @Value("${jeecg.path.shippingInvoiceDetailPdfDir}")
+ private String INVOICE_DETAIL_PDF_DIR;
+ private static final String EXTENSION = ".xlsx";
private final static String[] DETAILS_TITLES = {
"Boutique",
@@ -563,6 +573,107 @@ public class PlatformOrderShippingInvoiceService {
return invoiceList;
}
+
+ /** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
+ *
+ * @param dirPath
+ * @param invoiceNumber
+ * @return List of paths for the file but should only find one result
+ */
+ public List getPath(String dirPath, String invoiceNumber) {
+ List pathList = new ArrayList<>();
+ //Recursively list all files
+ //The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
+ try (Stream stream = Files.walk(Paths.get(dirPath))) {
+ pathList = stream.map(Path::normalize)
+ .filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
+ .filter(path -> path.getFileName().toString().contains(invoiceNumber))
+ .filter(path -> path.getFileName().toString().endsWith(EXTENSION))
+ .collect(Collectors.toList());
+ }
+ catch(IOException e) {
+ e.printStackTrace();
+ }
+ return pathList;
+ }
+
+ /** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
+ *
+ * @param dirPath
+ * @param invoiceNumber
+ * @return List of paths for the file but should only find one result
+ */
+ public List getPath(String dirPath, String invoiceNumber, String invoiceEntity) {
+ List pathList = new ArrayList<>();
+ //Recursively list all files
+ //The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
+ try (Stream stream = Files.walk(Paths.get(dirPath))) {
+ pathList = stream.map(Path::normalize)
+ .filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
+ .filter(path -> path.getFileName().toString().contains(invoiceNumber))
+ .filter(path -> path.getFileName().toString().contains(invoiceEntity))
+ .filter(path -> path.getFileName().toString().endsWith(EXTENSION))
+ .collect(Collectors.toList());
+ }
+ catch(IOException e) {
+ e.printStackTrace();
+ }
+ return pathList;
+ }
+
+ /**
+ * Finds the absolute path of invoice file and return the path
+ * @param invoiceNumber
+ * @param filetype if it's an invoice or invoice detail
+ * @return String returns the path of the invoice file
+ */
+ public String getInvoiceList(String invoiceNumber, String filetype) {
+ log.info("Invoice number : " + invoiceNumber);
+ List pathList = new ArrayList<>();
+ if(filetype.equals("invoice")) {
+ log.info("File asked is of type invoice");
+ pathList = getPath(INVOICE_DIR, invoiceNumber);
+ }
+ if(filetype.equals("detail")) {
+ log.info("File asked is of type invoice detail");
+ pathList = getPath(INVOICE_DETAIL_DIR, invoiceNumber);
+ }
+ if(pathList.isEmpty()) {
+ log.error("NO INVOICE FILE FOUND : " + invoiceNumber);
+ return "ERROR";
+ }
+ else {
+ for (Path path : pathList) {
+ log.info(path.toString());
+ }
+ return pathList.get(0).toString();
+ }
+ }
+ public String convertToPdf(String invoiceNumber, String fileType) throws Exception {
+ String excelFilePath = getInvoiceList(invoiceNumber, fileType);// (C:\PATH\filename.xlsx)
+
+ if(!excelFilePath.equals("ERROR")) {
+ String pdfFilePath= INVOICE_PDF_DIR + "/" + invoiceNumber + ".pdf";
+ if(fileType.equals("invoice")){
+ pdfFilePath = INVOICE_PDF_DIR + "/Invoice N°" + invoiceNumber + ".pdf";
+ }
+ if(fileType.equals("detail")) {
+ pdfFilePath = INVOICE_DETAIL_PDF_DIR + "/Détail_calcul_de_facture_" + invoiceNumber + ".pdf";
+ }
+
+ Pattern p = Pattern.compile("^(.*)[\\/\\\\](.*)(\\.[a-z]+)"); //group(1): "C:\PATH" , group(2) : "filename", group(3): ".xlsx"
+ Matcher m = p.matcher(excelFilePath);
+ if (m.matches()) {
+ pdfFilePath = INVOICE_PDF_DIR + "/" + m.group(2) + ".pdf";
+ }
+ // Créé un classeur pour charger le fichier Excel
+ Workbook workbook = new Workbook(excelFilePath);
+ // On enregistre le document au format PDF
+ workbook.save(pdfFilePath, SaveFormat.PDF);
+ return pdfFilePath;
+ }
+ return "ERROR";
+ }
@Transactional
public String zipInvoices(List invoiceList) throws IOException {
log.info("Zipping Invoices ...");
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/EmailServiceImpl.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/EmailServiceImpl.java
index 6af2ec090..f29ab4e43 100644
--- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/EmailServiceImpl.java
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/EmailServiceImpl.java
@@ -1,5 +1,6 @@
package org.jeecg.modules.business.service.impl;
+import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
@@ -118,11 +119,9 @@ public class EmailServiceImpl implements EmailService {
}
@Override
@Transactional
- public FreeMarkerConfigurer freemarkerClassLoaderConfig() throws IOException {
+ public FreeMarkerConfigurer freemarkerClassLoaderConfig() {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
- TemplateLoader templateLoader = new FileTemplateLoader(new File(env.getProperty("jeecg.path.emailTemplateDir"))) {
- };
- configuration.setTemplateLoader(templateLoader);
+ configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), "/templates"));
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setConfiguration(configuration);
return freeMarkerConfigurer;
diff --git a/pom.xml b/pom.xml
index 9bfd92c41..c42e2d69b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
org.jeecgframework.boot
jeecg-boot-parent
- 1.6.0
+ 1.8.1
pom
WIA APP ${project.version}