Merge pull request #17 from LQYBill/dev

Release of 1.3.0
pull/6221/head
Qiuyi LI 2023-08-02 18:00:12 +02:00 committed by GitHub
commit 984707043a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 695 additions and 20 deletions

View File

@ -323,9 +323,9 @@ public class InvoiceController {
}
@GetMapping(value = "/downloadInvoiceDetail")
public byte[] downloadInvoiceDetail(@RequestParam("invoiceNumber") String invoiceNumber) throws IOException {
public byte[] downloadInvoiceDetail(@RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("invoiceEntity") String invoiceEntity) throws IOException {
List<FactureDetail> res = shippingInvoiceService.getInvoiceDetail(invoiceNumber);
return shippingInvoiceService.exportToExcel(res, invoiceNumber);
return shippingInvoiceService.exportToExcel(res, invoiceNumber, invoiceEntity);
}
@GetMapping(value = "/breakdown/byShop")

View File

@ -17,8 +17,7 @@ import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.business.entity.Client;
import org.jeecg.modules.business.entity.ShippingInvoice;
import org.jeecg.modules.business.service.EmailService;
import org.jeecg.modules.business.service.IShippingInvoiceService;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.business.vo.ShippingInvoicePage;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
@ -70,6 +69,14 @@ import java.util.stream.Stream;
@RequestMapping("/generated/shippingInvoice")
@Slf4j
public class ShippingInvoiceController {
@Autowired
private IClientService clientService;
@Autowired
private IPlatformOrderContentService platformOrderContentService;
@Autowired
private IPlatformOrderService platformOrderService;
@Autowired
private ISavRefundService savRefundService;
@Autowired
private IShippingInvoiceService shippingInvoiceService;
@Autowired
@ -296,6 +303,30 @@ public class ShippingInvoiceController {
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<Path> getPath(String dirPath, String invoiceNumber, String invoiceEntity) {
List<Path> 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<Path> 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
@ -471,4 +502,55 @@ public class ShippingInvoiceController {
log.info("Found client for invoice {} : {}", invoiceNumber, client.fullName());
return Result.OK(client);
}
/**
* Deletes an invoice
* @param invoiceNumber invoice number to cancel
* @return if update successful
*/
@PostMapping(value = "/cancelInvoice")
public Result<?> cancelInvoice(@RequestParam("id") String id, @RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("clientId") String clientId) {
log.info("Cancelling invoice number : {}", invoiceNumber);
platformOrderContentService.cancelInvoice(invoiceNumber);
platformOrderService.cancelInvoice(invoiceNumber);
savRefundService.cancelInvoice(invoiceNumber);
shippingInvoiceService.delMain(id);
log.info("Deleting invoice files ...");
String invoiceEntity = clientService.getClientEntity(clientId);
List<Path> invoicePathList = getPath(INVOICE_LOCATION, invoiceNumber, invoiceEntity);
List<Path> detailPathList = getPath(INVOICE_DETAIL_LOCATION, invoiceNumber, invoiceEntity);
if(invoicePathList.isEmpty() ||detailPathList.isEmpty()) {
log.error("FILE NOT FOUND : " + invoiceNumber);
return Result.ok("Invoice canceled, but file not found.");
}
else {
for (Path path : invoicePathList) {
log.info(path.toString());
}
for (Path path : detailPathList) {
log.info(path.toString());
}
try {
File invoiceFile = new File(invoicePathList.get(0).toString());
File detailFile = new File(detailPathList.get(0).toString());
if(invoiceFile.delete()) {
log.info("Invoice file {} delete successful.", invoicePathList.get(0).toString());
} else {
log.error("Invoice file delete fail.");
return Result.error("Invoice file delete fail.");
}
if(detailFile.delete()) {
log.info("Detail file {} delete successful.", detailPathList.get(0).toString());
} else {
log.error("Detail file delete fail.");
return Result.error("Detail file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error(e.getMessage());
}
}
log.info("Invoice files deleted.");
return Result.ok("Invoice cancel successful.");
}
}

View File

@ -6,6 +6,7 @@ public enum ScanType {
END_DELIVERED("End Delivered"),
END_DELIVERY("End Delivery"),
END_RECEIVED("End Received"),
END_SEND("End Send"),
END_ARRIVED("End Arrived"),
FLIGHT_ARRIVED("Flight Arrived"),
FLIGHT_DEPARTURE("Flight Departure"),
@ -13,12 +14,15 @@ public enum ScanType {
FACILITY_ARRIVED("Received by Consolidation Warehouse"),
FACILITY_DEPARTURE("Consolidation Center Dispatch"),
FACILITY_OUTBOUND("Consolidation Center Outbound"),
CUSTOMS_CLEARANCE("Customs Clearance"),
CUSTOMS_CLEARANCE_COMPLETED("Customs Clearance Completed"),
ORDER_PLACED("Order Placed"),
WAITING_FOR_DELIVERY("Waiting for Delivery"),
ARRIVED_PORT("Arrived at Port"),
FLIGHT_PREPARING("Flight Preparing"),
CN_CUSTOMS_INSPECTION("Customs Inspection"),
EXPORT_CUSTOMS_DECLARATION("Export Declaration"),
EXPORT_CUSTOMS_DECLARATION_COMPLETED("Export Declaration Completed"),
BAGGING("Bagging");
private final String desc;

View File

@ -0,0 +1,140 @@
package org.jeecg.modules.business.domain.api.hualei;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import static org.jeecg.modules.business.domain.api.ScanType.*;
@Slf4j
@Data
public class HLParcelTraceDetail {
@JSONField(deserialize = false)
private String parcelId;
@JsonProperty("track_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.S")
private String scanTime;
private String scanType;
@JsonProperty("track_kind")
private String trackKind;
@JsonProperty("track_content")
private String descriptionCn;
private String descriptionEn;
@JsonProperty("track_location")
private String location;
private static final String ARRIVAL_AT_RECEPTION_CN = "到达收货点";
private static final String ARRIVAL_AT_RECEPTION = "Parcel has been handed to logistics company";
private static final String DELIVERED = "Package delivered";
private static final String ARRIVAL_LOCAL_DELIVERY = "Arrived at local delivery center";
private static final String OUT_FOR_DELIVERY = "Out for delivery";
private static final String LOCAL_DELIVERY_RECEPTION = "Received by local delivery company";
private static final String DEPART_CUSTOMS = "Departed from customs";
private static final String AWAITING_TRANSIT_TO_FINAL_DELIVERY_OFFICE = "Awaiting for transit to final delivery office";
private static final String DEPARTED_FROM_TRANSIT_COUNTRY = "Departed from transit country/region";
private static final String LEAVING_TRANSIT_COUNTRY = "Leaving transit country/region";
private static final String IMPORT_CUSTOMS_CLEARANCE_COMPLETE = "Import customs clearance complete";
private static final String IMPORT_CUSTOMS_CLEARANCE_STARTED = "Import customs clearance started";
private static final String ARRIVAL_IN_TRANSIT_COUNTRY = "Arrived in transit country/region";
private static final String HANDED_TO_LINEHAUL = "Handed over from linehaul office";
private static final String ARRIVAL_LINEHAUL = "Arrived at linehaul office";
private static final String DEPARTED_FROM_ORIGIN = "Departed from departure country/region";
private static final String LEAVING_FROM_ORIGIN = "Leaving from departure country/region";
private static final String EXPORT_CUSTOMS_CLEARANCE_COMPLETE = "Export customs clearance complete";
private static final String EXPORT_CUSTOMS_CLEARANCE_START = "Export customs clearance started";
private static final String TRANSPORT_HUB_ARRIVAL = "Arrived at departure transport hub";
private static final String SORTING_CENTER_DEPARTURE = "[Fenggang Town] Departed from sorting center";
private static final String SORTING_CENTER_PROCESSING = "[Fenggang Town] Processing at sorting center";
private static final String ORDER_RECEIVED = "货物电子信息已经收到";
private static final String ORDER_RECEIVED_EN = "Order received by logistics company";
public HLParcelTraceDetail() {
}
public HLParcelTraceDetail(String parcelId, String scanTime, String scanType, String trackKind,
String descriptionCn, String descriptionEn, String location) {
this.parcelId = parcelId;
this.scanTime = scanTime;
this.scanType = scanType;
this.trackKind = trackKind;
this.descriptionCn = descriptionCn;
this.descriptionEn = descriptionEn;
this.location = location;
}
/**
* Set parcel ID, and write the scan type into the trace according to description
* @param parcelId Parcel ID to which the trace belongs to
*/
public void parcelTraceProcess(String parcelId) {
setParcelId(parcelId);
switch (descriptionCn) {
case DELIVERED:
setScanType(END_DELIVERED.getDesc());
break;
case ARRIVAL_LOCAL_DELIVERY:
setScanType(END_ARRIVED.getDesc());
break;
case OUT_FOR_DELIVERY:
setScanType(END_DELIVERY.getDesc());
break;
case LOCAL_DELIVERY_RECEPTION:
setScanType(END_RECEIVED.getDesc());
break;
case DEPART_CUSTOMS:
case IMPORT_CUSTOMS_CLEARANCE_COMPLETE:
setScanType(CUSTOMS_CLEARANCE_COMPLETED.getDesc());
break;
case AWAITING_TRANSIT_TO_FINAL_DELIVERY_OFFICE:
setScanType(END_SEND.getDesc());
break;
case DEPARTED_FROM_TRANSIT_COUNTRY:
case LEAVING_TRANSIT_COUNTRY:
case ARRIVAL_IN_TRANSIT_COUNTRY:
setScanType(FLIGHT_ARRIVED.getDesc());
break;
case IMPORT_CUSTOMS_CLEARANCE_STARTED:
setScanType(CUSTOMS_CLEARANCE.getDesc());
break;
case HANDED_TO_LINEHAUL:
setScanType(FLIGHT_DEPARTURE.getDesc());
break;
case ARRIVAL_LINEHAUL:
case DEPARTED_FROM_ORIGIN:
case LEAVING_FROM_ORIGIN:
setScanType(FLIGHT_PREPARING.getDesc());
break;
case EXPORT_CUSTOMS_CLEARANCE_COMPLETE:
setScanType(EXPORT_CUSTOMS_DECLARATION_COMPLETED.getDesc());
break;
case EXPORT_CUSTOMS_CLEARANCE_START:
setScanType(EXPORT_CUSTOMS_DECLARATION.getDesc());
break;
case TRANSPORT_HUB_ARRIVAL:
case SORTING_CENTER_DEPARTURE:
setScanType(FACILITY_DEPARTURE.getDesc());
break;
case SORTING_CENTER_PROCESSING:
setScanType(FACILITY_ARRIVED.getDesc());
break;
case ORDER_RECEIVED:
setDescriptionEn(ORDER_RECEIVED_EN);
setScanType(ORDER_PLACED.getDesc());
break;
case ARRIVAL_AT_RECEPTION_CN:
setDescriptionEn(ARRIVAL_AT_RECEPTION);
setScanType(BAGGING.getDesc());
break;
}
}
}

View File

@ -0,0 +1,68 @@
package org.jeecg.modules.business.domain.api.hualei;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import java.util.ArrayList;
import java.util.List;
/**
* This class contains some key information and necessary procedures
* to send a request body to mabang API, for example target URL,
* correspondent HTTP method, procedure to generate authorization.
*/
@Slf4j
public class HLRequest {
private final static String URL = "http://www.antugj.com:8082/selectTrack.htm";
private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().build();
private final List<String> billCodes;
public HLRequest(List<String> billCodes) {
this.billCodes = billCodes;
}
/**
* Sent request to the mabang API with a request body.
*
* @return the response
*/
public HttpResponse send() {
int attempts = 0;
while (attempts++ < 5) {
try {
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
HttpPost request = new HttpPost(URL);
// adding the form data
request.setEntity(new UrlEncodedFormEntity(generateFormData(), "UTF-8"));
return httpClient.execute(request);
} catch (Exception e) {
log.error("Request failed on attempt n°" + attempts);
}
}
return null;
}
/**
* Convert body's json parameters to json string with the necessary extra parameter to
* send request.
*
* @return json string
*/
private List<NameValuePair> generateFormData() {
List<NameValuePair> pairs = new ArrayList<>();
String billCodesWithComas = String.join(",", billCodes);
pairs.add(new BasicNameValuePair("documentCode", billCodesWithComas));
return pairs;
}
}

View File

@ -0,0 +1,27 @@
package org.jeecg.modules.business.domain.api.hualei;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.business.domain.api.jt.JTResponseItem;
import java.util.List;
@Slf4j
@Data
public class HLResponse {
@JsonProperty("ack")
private Boolean acknowledgment;
@JsonProperty("data")
private List<HLResponseItem> responseItems;
public HLResponse(Boolean acknowledgment, List<HLResponseItem> responseItems) {
this.acknowledgment = acknowledgment;
this.responseItems = responseItems;
}
public HLResponse() {
}
}

View File

@ -0,0 +1,52 @@
package org.jeecg.modules.business.domain.api.hualei;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
@Data
@TableName("parcel")
public class HLResponseItem {
@TableId(type = IdType.ASSIGN_ID)
private String id = IdWorker.getIdStr();
@JsonProperty("trackingNumber")
private String trackingNumber;
@JsonProperty("consigneeCountry")
private String country;
@JsonProperty("productKindName")
private String productCode;
@JsonProperty("business_seqinvoicecode")
private String billCode;
@JsonProperty("referenceNumber")
private String orderNumber;
@JsonProperty("trackDetails")
private List<HLParcelTraceDetail> tracesList;
public HLResponseItem(String id, String trackingNumber, String country, String productCode, String billCode,
String orderNumber, List<HLParcelTraceDetail> tracesList) {
this.id = id;
this.trackingNumber = trackingNumber;
this.country = country;
this.productCode = productCode;
this.billCode = billCode;
this.orderNumber = orderNumber;
this.tracesList = tracesList;
}
public HLResponseItem() {
}
}

View File

@ -20,7 +20,7 @@ public class CreateFulfillmentRequest extends ShopifyRequest {
CANADA_POST("https://www.canadapost-postescanada.ca/track-reperage/en#/search?searchFor=%s", "Canada Post", "(201255|732131)[0-9]{10}"),
SWISS_POST("https://service.post.ch/ekp-web/ui/entry/search/%s", "Swiss Post", "[0-9]{18}"),
EARLY_BIRD("https://earlybird.se/", "Early Bird", "[0-9]{19}"),
DAO("https://www.dao.as/privat/find-din-pakke?stregkode=%s", "DAO", "00057151271[0-9]{9}"),
DAO("https://www.dao.as/privat/find-din-pakke?stregkode=%s", "DAO", "00057151270[0-9]{10}"),
DHL_PACKET("https://www.dhl.de/en/privatkunden/pakete-empfangen/verfolgen.html?piececode=%s", "DHL Packet", "0034[0-9]{16}"),
GLS_NL("https://www.gls-info.nl/tracking", "GLS", "[0-9]{20}"),
GLS_NL_2("https://www.gls-info.nl/tracking", "GLS", "(1437|1000)[0-9]{10}"),

View File

@ -0,0 +1,124 @@
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 HLJob implements Job {
@Autowired
private IParcelService parcelService;
@Autowired
private IPlatformOrderService platformOrderService;
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<String> 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<String> 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<String> 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<String> billCodes = platformOrderService.fetchBillCodesOfParcelsWithoutTrace(
Date.valueOf(startDate), Date.valueOf(endDate), transporters);
log.info("{} parcels without trace in total", billCodes.size());
List<List<String>> billCodeLists = Lists.partition(billCodes, 40);
log.info("Requests will be divided in to {} parts", billCodeLists.size());
List<HLResponseItem> parcelTraces = new ArrayList<>();
List<HLRequest> hlRequests = new ArrayList<>();
billCodeLists.forEach(billcodeList -> {
HLRequest hlRequest = new HLRequest(billcodeList);
hlRequests.add(hlRequest);
});
List<Boolean> 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<List<HLResponseItem>> parcelTraceList = Lists.partition(parcelTraces, DEFAULT_MAXIMUM_NUMBER_OF_PARCELS_PER_TRANSACTION);
for (List<HLResponseItem> parcelTracesPerTransaction : parcelTraceList) {
parcelService.saveHLParcelAndTraces(parcelTracesPerTransaction);
}
}
}

View File

@ -387,7 +387,7 @@ public class ShippingInvoiceFactory {
List<SavRefundWithDetail> savRefunds,
String subject, boolean skipShippingTimeComparing) throws UserException {
log.info("Orders to be invoiced: {}", orderAndContent);
if (orderAndContent == null) {
if (orderAndContent == null || orderAndContent.size() == 0) {
throw new UserException("No platform order in the selected period!");
}
Map<String, BigDecimal> skuRealWeights = new HashMap<>();
@ -397,7 +397,7 @@ public class ShippingInvoiceFactory {
Map<LogisticChannel, List<LogisticChannelPrice>> channelPriceMap;
Map<String, LogisticChannel> logisticChannelMap = logisticChannelMapper.getAll().stream()
.collect(toMap(LogisticChannel::getId, Function.identity()));
if(subject.contains("Pre") || subject.contains("All")) {
if(subject.contains("order time")) {
channelPriceMap = getChannelPriceMap(logisticChannelMap, orderAndContent, skipShippingTimeComparing, "order");
}
else {

View File

@ -50,6 +50,12 @@ public class ShippingInvoice implements Serializable {
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* ID
*/
@Excel(name = "客户", width = 15)
@ApiModelProperty(value = "客户")
private String clientId;
/**
*
*/
@ -103,6 +109,9 @@ public class ShippingInvoice implements Serializable {
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public void setClientI(String clientId) {
this.clientId = clientId;
}
public void setInvoiceNumber(String invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
@ -135,6 +144,7 @@ public class ShippingInvoice implements Serializable {
Date createTime,
String updateBy,
Date updateTime,
String clientId,
String invoiceNumber,
BigDecimal totalAmount,
BigDecimal discountAmount,
@ -145,6 +155,7 @@ public class ShippingInvoice implements Serializable {
this.createTime = createTime;
this.updateBy = updateBy;
this.updateTime = updateTime;
this.clientId = clientId;
this.invoiceNumber = invoiceNumber;
this.totalAmount = totalAmount;
this.discountAmount = discountAmount;
@ -153,12 +164,13 @@ public class ShippingInvoice implements Serializable {
}
public static ShippingInvoice of(
String username,
String clientId,
String invoiceNumber,
BigDecimal totalAmount,
BigDecimal discountAmount,
BigDecimal paidAmount
) {
return new ShippingInvoice(null, username, new Date(), username, new Date(),
return new ShippingInvoice(null, username, new Date(), username, new Date(), clientId,
invoiceNumber, totalAmount, discountAmount, totalAmount.subtract(discountAmount), paidAmount);
}
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.entity.Client;
import org.springframework.stereotype.Repository;
@ -13,4 +14,5 @@ import org.springframework.stereotype.Repository;
@Repository
public interface ClientMapper extends BaseMapper<Client> {
String getClientEntity(@Param("id") String id);
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.domain.api.cmk.CMKParcelTraceData;
import org.jeecg.modules.business.domain.api.equick.EQuickResponse;
import org.jeecg.modules.business.domain.api.hualei.HLResponseItem;
import org.jeecg.modules.business.domain.api.jt.JTParcelTrace;
import org.jeecg.modules.business.domain.api.yd.YDTraceData;
import org.jeecg.modules.business.entity.Parcel;
@ -28,6 +29,7 @@ public interface ParcelMapper extends BaseMapper<Parcel> {
void insertOrIgnoreYDParcels(List<YDTraceData> parcels);
void insertOrIgnoreCMKParcels(List<CMKParcelTraceData> parcels);
void insertOrIgnoreHLParcels(List<HLResponseItem> parcels);
/**
* fetch all parcels from platform order's tracking number, to archive

View File

@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.domain.api.cmk.CMKParcelTrace;
import org.jeecg.modules.business.domain.api.cmk.CMKParcelTraceData;
import org.jeecg.modules.business.domain.api.equick.EQuickTraceData;
import org.jeecg.modules.business.domain.api.hualei.HLParcelTraceDetail;
import org.jeecg.modules.business.domain.api.jt.JTParcelTraceDetail;
import org.jeecg.modules.business.domain.api.yd.YDTraceDetail;
import org.jeecg.modules.business.entity.ParcelTrace;
@ -33,6 +34,8 @@ public interface ParcelTraceMapper extends BaseMapper<ParcelTrace> {
void insertOrIgnoreCMKTraces(@Param("traces") List<CMKParcelTrace> traceDetails);
void insertOrIgnoreHLTraces(@Param("traces") List<HLParcelTraceDetail> tracesToInsert);
/**
* Fetches parcel traces to archive
* @param parcelIDs

View File

@ -73,4 +73,5 @@ public interface PlatformOrderContentMapper extends BaseMapper<PlatformOrderCont
List<PlatformOrderContent> findUninvoicedShippedOrderContents();
List<PlatformOrderContent> fetchPlatformOrderContentsToArchive(@Param("orderIDs") List<String> orderIDs);
void insertPlatformOrderContentsArchives(@Param("orderContents") List<PlatformOrderContent> platformOrderContents);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -181,4 +181,5 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
List<PlatformOrder> fetchOrdersToArchiveBetweenDate(@Param("startDate") String startDate, @Param("endDate") String endDate);
List<PlatformOrder> fetchOrdersToArchiveBeforeDate(@Param("endDate") String endDate);
void insertPlatformOrdersArchives(@Param("orders") List<PlatformOrder> platformOrders);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -17,4 +17,5 @@ import java.util.List;
@Repository
public interface SavRefundMapper extends BaseMapper<SavRefund> {
List<BigDecimal> fetchRefundAmount(@Param("invoiceNumber") String invoiceNumber);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.business.mapper.ClientMapper">
<select id="getClientEntity" parameterType="java.lang.String" resultType="java.lang.String">
SELECT invoice_entity
FROM client
WHERE id = #{id}
</select>
</mapper>

View File

@ -86,6 +86,27 @@
)
</foreach>
</insert>
<insert id="insertOrIgnoreHLParcels" parameterType="list">
INSERT IGNORE INTO parcel(id, create_by, create_time, update_by, update_time, bill_code, country,
third_bill_code, order_no, product_code)
VALUES
<foreach collection="parcels" separator="," open="" close="" item="parcel" index="index">
(
#{parcel.id},
'hl api',
NOW(),
'hl api',
NOW(),
#{parcel.billCode},
#{parcel.country},
#{parcel.trackingNumber},
#{parcel.orderNumber},
#{parcel.productCode}
)
</foreach>
</insert>
<select id="fetchParcelsToArchive" resultType="org.jeecg.modules.business.entity.Parcel">
SELECT *
FROM parcel

View File

@ -100,6 +100,28 @@
)
</foreach>
</insert>
<insert id="insertOrIgnoreHLTraces" parameterType="list">
INSERT IGNORE INTO parcel_trace(id, create_by, create_time, update_by, update_time, parcel_id, scan_time,
description, description_en, trace_location, scan_type)
VALUES
<foreach collection="traces" separator="," open="" close="" item="trace" index="index">
(
UUID(),
'hl api',
NOW(),
'hl api',
NOW(),
#{trace.parcelId},
#{trace.scanTime},
#{trace.descriptionCn},
#{trace.descriptionEn},
#{trace.location},
#{trace.scanType}
)
</foreach>
</insert>
<select id="fetchParcelTracesToArchive" resultType="org.jeecg.modules.business.entity.ParcelTrace">
SELECT *
FROM parcel_trace

View File

@ -279,4 +279,13 @@
)
</foreach>;
</insert>
<update id="cancelInvoice">
UPDATE platform_order_content
SET picking_fee = 0.0,
shipping_fee = NULL,
service_fee = NULL,
vat = NULL,
purchase_fee = 0.0
WHERE platform_order_id IN (SELECT id FROM platform_order WHERE shipping_invoice_number = #{invoiceNumber});
</update>
</mapper>

View File

@ -258,7 +258,6 @@
JOIN shop as s
ON po.shop_id = s.id
WHERE po.shipping_invoice_number IS NULL
AND po.order_time IS NOT NULL
AND po.erp_status IN
<foreach
collection="erpStatuses"
@ -291,7 +290,6 @@
JOIN shop as s
ON po.shop_id = s.id
WHERE po.shipping_invoice_number IS NULL
AND po.order_time IS NOT NULL
AND po.erp_status IN
<foreach
collection="erpStatuses"
@ -464,7 +462,8 @@
SELECT po.id
FROM platform_order po
JOIN logistic_channel lc ON po.logistic_channel_name = lc.zh_name
WHERE po.shop_id IN
WHERE shipping_invoice_number IS NULL
AND po.shop_id IN
<foreach
collection="shops"
separator=","
@ -487,13 +486,15 @@
#{warehouse}
</foreach>
AND po.shipping_time between #{startDate} AND #{endDate}
AND po.shipping_invoice_number IS NULL
AND po.erp_status = 3;
</select>
<select id="fetchUninvoicedShippedOrderIDInShopsAndOrderTime" resultType="org.jeecg.modules.business.entity.PlatformOrder">
SELECT po.id
FROM platform_order po
JOIN logistic_channel lc ON po.logistic_channel_name = lc.zh_name
WHERE po.shop_id IN
WHERE shipping_invoice_number IS NULL
AND po.shop_id IN
<foreach
collection="shops"
separator=","
@ -516,6 +517,7 @@
#{warehouse}
</foreach>
AND po.order_time between #{startDate} AND #{endDate}
AND po.shipping_invoice_number IS NULL
AND po.erp_status IN
<foreach
collection="erpStatuses"
@ -587,4 +589,14 @@
)
</foreach>;
</insert>
<update id="cancelInvoice">
UPDATE platform_order
SET fret_fee = NULL,
order_service_fee = NULL,
shipping_invoice_number = NULL,
picking_fee = 0.0,
packaging_material_fee = 0.0
WHERE shipping_invoice_number = #{invoiceNumber};
</update>
</mapper>

View File

@ -6,4 +6,11 @@
FROM sav_refund s
WHERE s.invoice_number = #{invoiceNumber}
</select>
<update id="cancelInvoice">
UPDATE sav_refund
SET invoice_number = NULL,
refund_date = NULL,
total_refund_amount = 0.0
WHERE invoice_number = #{invoiceNumber};
</update>
</mapper>

View File

@ -37,7 +37,7 @@ public interface IClientService extends IService<Client> {
*
*/
public void delBatchMain (Collection<? extends Serializable> idList);
public String getClientEntity(String id);
/**
* Get current user's client information
* @return client or null if current user's role is not client

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.business.domain.api.cmk.CMKParcelTraceData;
import org.jeecg.modules.business.domain.api.equick.EQuickResponse;
import org.jeecg.modules.business.domain.api.hualei.HLResponseItem;
import org.jeecg.modules.business.domain.api.jt.JTParcelTrace;
import org.jeecg.modules.business.domain.api.yd.YDTraceData;
import org.jeecg.modules.business.entity.Parcel;
@ -48,6 +49,8 @@ public interface IParcelService extends IService<Parcel> {
void saveYDParcelAndTraces(List<YDTraceData> traceData);
void saveCMKParcelAndTraces(List<CMKParcelTraceData> traceData);
void saveHLParcelAndTraces(List<HLResponseItem> parcelTraces);
List<Parcel> fetchParcelsToArchive(List<String> trackingNumbers);
void saveParcelArchive(List<Parcel> parcels);
}

View File

@ -42,4 +42,10 @@ public interface IPlatformOrderContentService extends IService<PlatformOrderCont
*/
List<PlatformOrderContent> fetchPlatformOrderContentsToArchive(List<String> orderIDs);
void savePlatformOrderContentArchive(List<PlatformOrderContent> platformOrderContents);
/**
* Cancels an invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -165,4 +165,10 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
* @param platformOrders list of platform orders
*/
void savePlatformOrderArchive(List<PlatformOrder> platformOrders);
/**
* Cancel Invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -13,5 +13,9 @@ import java.util.List;
* @Version: V1.0
*/
public interface ISavRefundService extends IService<SavRefund> {
List<BigDecimal> getRefundAmount(String invoiceNumber);
List<BigDecimal> getRefundAmount(String invoiceNumber);/**
* Cancel Invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -258,13 +258,14 @@ public class PlatformOrderShippingInvoiceService {
// save to DB
org.jeecg.modules.business.entity.ShippingInvoice shippingInvoiceEntity = org.jeecg.modules.business.entity.ShippingInvoice.of(
username,
invoice.client().getId(),
invoice.code(),
invoice.getTotalAmount(),
invoice.reducedAmount(),
invoice.paidAmount()
);
shippingInvoiceMapper.insert(shippingInvoiceEntity);
return new InvoiceMetaData(filename, invoice.code());
return new InvoiceMetaData(filename, invoice.code(), invoice.client().getInvoiceEntity());
}
/**
@ -317,7 +318,7 @@ public class PlatformOrderShippingInvoiceService {
return factureDetailMapper.selectList(queryWrapper);
}
public byte[] exportToExcel(List<FactureDetail> details, String invoiceNumber) throws IOException {
public byte[] exportToExcel(List<FactureDetail> details, String invoiceNumber, String invoiceEntity) throws IOException {
SheetManager sheetManager = SheetManager.createXLSX();
for (String title : titles) {
sheetManager.write(title);
@ -370,15 +371,16 @@ public class PlatformOrderShippingInvoiceService {
sheetManager.nextRow();
}
Path target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + ".xlsx");
Path target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_(" + invoiceEntity + ").xlsx");
int i = 2;
while (Files.exists(target)) {
target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_" + i + ".xlsx");
target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_(" + invoiceEntity + ")_" + i + ".xlsx");
i++;
}
Files.createFile(target);
sheetManager.export(target);
sheetManager.getWorkbook().close();
System.gc();
return Files.readAllBytes(target);
}
}

View File

@ -117,4 +117,8 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
return clientUserMap.selectClientByUserId(sysUser.getId());
}
@Override
public String getClientEntity(String id) {
return clientMapper.getClientEntity(id);
}
}

View File

@ -7,6 +7,8 @@ import org.jeecg.modules.business.domain.api.cmk.CMKParcelTrace;
import org.jeecg.modules.business.domain.api.cmk.CMKParcelTraceData;
import org.jeecg.modules.business.domain.api.equick.EQuickResponse;
import org.jeecg.modules.business.domain.api.equick.EQuickTraceData;
import org.jeecg.modules.business.domain.api.hualei.HLParcelTraceDetail;
import org.jeecg.modules.business.domain.api.hualei.HLResponseItem;
import org.jeecg.modules.business.domain.api.jt.JTParcelTrace;
import org.jeecg.modules.business.domain.api.jt.JTParcelTraceDetail;
import org.jeecg.modules.business.domain.api.yd.YDTraceData;
@ -272,6 +274,46 @@ public class ParcelServiceImpl extends ServiceImpl<ParcelMapper, Parcel> impleme
}
log.info("Finished inserting {} parcels and their traces into DB.", parcelTraces.size());
}
@Override
@Transactional
public void saveHLParcelAndTraces(List<HLResponseItem> parcelTraces) {
if (parcelTraces.isEmpty()) {
return;
}
log.info("Started inserting {} HL parcels and their traces into DB.", parcelTraces.size() );
List<String> parcelBillCodes = parcelTraces.stream()
.map(HLResponseItem::getBillCode)
.collect(Collectors.toList());
List<Parcel> existingParcels = parcelMapper.searchByBillCode(parcelBillCodes);
Map<String, Parcel> billCodeToExistingParcels = existingParcels.stream().collect(
Collectors.toMap(Parcel::getBillCode, Function.identity())
);
List<HLResponseItem> parcelToInsert = new ArrayList<>();
List<HLParcelTraceDetail> tracesToInsert = new ArrayList<>();
for (HLResponseItem parcelAndTrace : parcelTraces) {
List<HLParcelTraceDetail> traceDetails = parcelAndTrace.getTracesList();
if (traceDetails.isEmpty()) {
break;
}
Parcel existingParcel = billCodeToExistingParcels.get(parcelAndTrace.getBillCode());
if (existingParcel == null) {
parcelToInsert.add(parcelAndTrace);
traceDetails.forEach(trace -> trace.parcelTraceProcess(parcelAndTrace.getId()));
} else {
traceDetails.forEach(trace -> trace.parcelTraceProcess(existingParcel.getId()));
}
tracesToInsert.addAll(traceDetails);
}
log.info("After filtering, {} parcels will be inserted into the DB.", parcelToInsert.size());
if (!parcelToInsert.isEmpty()) {
parcelMapper.insertOrIgnoreHLParcels(parcelToInsert);
}
if (!tracesToInsert.isEmpty()) {
parcelTraceMapper.insertOrIgnoreHLTraces(tracesToInsert);
}
log.info("Finished inserting {} HL parcels and their traces into DB.", parcelTraces.size());
}
@Override
@Transactional
public List<Parcel> fetchParcelsToArchive(List<String> trackingNumbers) {

View File

@ -62,4 +62,8 @@ public class PlatformOrderContentServiceImpl extends ServiceImpl<PlatformOrderCo
public void savePlatformOrderContentArchive(List<PlatformOrderContent> platformOrderContents) {
platformOrderContentMapper.insertPlatformOrderContentsArchives(platformOrderContents);
}
@Override
public void cancelInvoice(String invoiceNumber) {
platformOrderContentMapper.cancelInvoice(invoiceNumber);
}
}

View File

@ -378,4 +378,8 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
public void savePlatformOrderArchive(List<PlatformOrder> platformOrders) {
platformOrderMap.insertPlatformOrdersArchives(platformOrders);
}
@Override
public void cancelInvoice(String invoiceNumber) {
platformOrderMap.cancelInvoice(invoiceNumber);
}
}

View File

@ -32,4 +32,8 @@ public class SavRefundServiceImpl extends ServiceImpl<SavRefundMapper, SavRefund
public List<BigDecimal> getRefundAmount(String invoiceNumber) {
return savRefundMapper.fetchRefundAmount(invoiceNumber);
}
@Override
public void cancelInvoice(String invoiceNumber) {
savRefundMapper.cancelInvoice(invoiceNumber);
}
}

View File

@ -8,4 +8,6 @@ public class InvoiceMetaData {
private final String filename;
private final String invoiceCode;
private final String invoiceEntity;
}

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>1.1.2</version>
<version>1.3.0</version>
<packaging>pom</packaging>
<name>WIA APP ${project.version} </name>