Merge branch 'develop'

# Conflicts:
#	pom.xml
master
yixian 4 years ago
commit d15a505dba

@ -9,7 +9,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>manage</artifactId>
<version>2.3.39</version>
<version>2.3.40</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jib-maven-plugin.version>2.4.0</jib-maven-plugin.version>

@ -1,7 +1,5 @@
package au.com.royalpay.payment.manage.analysis.beans.ato;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@ -1,5 +1,9 @@
package au.com.royalpay.payment.manage.analysis.core;
import com.alibaba.fastjson.JSONObject;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
@ -8,4 +12,10 @@ import java.util.Date;
public interface ATOReportService {
String exportBTTPSFile(Date from, Date to);
void startExportTask(Date from, Date to);
JSONObject taskStatus();
void downloadFile(HttpServletResponse resp) throws IOException;
}

@ -4,26 +4,40 @@ import au.com.royalpay.payment.manage.analysis.beans.ato.*;
import au.com.royalpay.payment.manage.analysis.core.ATOReportService;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
import au.com.royalpay.payment.tools.connections.attachment.core.AttachmentClient;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Create by yixian at 2018-08-31 1:23
@ -38,6 +52,16 @@ public class ATOReportServiceImpl implements ATOReportService {
@Value("classpath:data/category/billbuddyindustry.json")
private org.springframework.core.io.Resource industryResource;
private Map<String, String> industryMap;
private final StringRedisTemplate redisTemplate;
private final String prefix;
private final AttachmentClient client;
private Progress progress;
public ATOReportServiceImpl(StringRedisTemplate redisTemplate, @Value("${app.redis.prefix}") String prefix, AttachmentClient client) {
this.redisTemplate = redisTemplate;
this.prefix = prefix;
this.client = client;
}
@PostConstruct
public void loadIndustryConfiguration() throws IOException {
@ -102,14 +126,90 @@ public class ATOReportServiceImpl implements ATOReportService {
return data.outputBTTPS();
}
private String progressKey() {
return prefix + ":tasks:exporting-bttps";
}
private String reportFileKey() {
return prefix + ":caching:exporting-bttps-file";
}
@Override
public void startExportTask(Date from, Date to) {
if (progress != null && !progress.isFinished()) {
throw new BadRequestException("In Progress");
}
if (redisTemplate.boundValueOps(progressKey()).get() != null) {
throw new BadRequestException("In Progress");
}
new Thread(() -> {
progress = new Progress();
try {
String content = exportBTTPSFile(from, to);
byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
progress.setStatus("Uploading,filesize:" + contentBytes.length);
String filename = "royalpay_ato_report_" + new DateTime(from).toString("yyyyMMdd") + "_to_" + new DateTime(to).toString("yyyyMMdd") + ".bttps";
JSONObject file = client.uploadFile(new ByteArrayInputStream(contentBytes), filename, true);
String fileid = file.getString("fileid");
logger.info("uploaded ATO report to {}", fileid);
progress.setFileid(fileid);
redisTemplate.boundValueOps(reportFileKey()).set(file.toJSONString(), Duration.ofDays(1));
} catch (Exception e) {
progress.setStatus(e.getMessage());
synchronizeProgress();
} finally {
progress.setFinished();
synchronizeProgress();
}
}).start();
}
@Override
public JSONObject taskStatus() {
String status = redisTemplate.boundValueOps(progressKey()).get();
if (status != null) {
JSONObject std = JSON.parseObject(status);
std.remove("fileid");
return std;
} else {
String file = redisTemplate.boundValueOps(reportFileKey()).get();
JSONObject std = new JSONObject();
if (file != null) {
std.put("success", true);
std.put("finished", true);
}
return std;
}
}
@Override
public void downloadFile(HttpServletResponse resp) throws IOException {
String file = redisTemplate.boundValueOps(reportFileKey()).get();
if (file != null) {
JSONObject fileInfo = JSON.parseObject(file);
String filename = StringUtils.substringAfterLast(fileInfo.getString("url"), "/");
resp.setHeader(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.builder("attachment").filename(filename).build().toString());
resp.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
try (OutputStream out = resp.getOutputStream()) {
client.getFileContent(fileInfo.getString("fileid"), out);
out.flush();
}
} else {
throw new BadRequestException("No file available");
}
}
private void loadMonthTransactions(ReportingPartyData reportingParty, DateTime startOfMon, DateTime endOfMon) {
List<Integer> clients = clientMapper.listClientsWithTransactionsSettled(startOfMon.toDate(), endOfMon.toDate());
if (progress != null) {
progress.setMonth(startOfMon, clients);
}
clients.parallelStream().forEach(clientId -> loadClientMonthTransactions(reportingParty, clientId, startOfMon, endOfMon));
}
private void loadClientMonthTransactions(ReportingPartyData reportingParty, Integer clientId, DateTime startOfMon, DateTime endOfMon) {
BusinessData biz = reportingParty.findBusiness(clientId);
logger.debug("Exporting date range for client[{}]:{} ~ {}",clientId,startOfMon.toString("yyyy-MM-dd"), endOfMon.toString("yyyy-MM-dd"));
logger.debug("Exporting date range for client[{}]:{} ~ {}", clientId, startOfMon.toString("yyyy-MM-dd"), endOfMon.toString("yyyy-MM-dd"));
if (biz == null) {
JSONObject cli = clientMapper.findClientIgnoreInvalid(clientId);
AddressInfo addr = new AddressInfo(cli.getString("address"), cli.getString("suburb"), cli.getString("state"), cli.getString("postcode"), cli.getString("country"));
@ -128,5 +228,85 @@ public class ATOReportServiceImpl implements ATOReportService {
for (JSONObject analysis : analysisList) {
biz.addTransaction(new TransactionSummaryData(analysis, startOfMon, endOfMon));
}
if (progress != null) {
progress.markClientFinished(clientId);
}
}
private void synchronizeProgress() {
redisTemplate.boundValueOps(progressKey()).set(JSON.toJSONString(progress), Duration.ofMinutes(5));
}
public static class Progress {
private String currentMonth;
private Map<Integer, Boolean> clientsStatus;
private final String server;
private String fileid;
private boolean finished;
private String status;
public Progress() {
status = "Init";
server = PlatformEnvironment.getEnv().appName();
}
public void setMonth(DateTime start, List<Integer> clients) {
currentMonth = start.toString("yyyy-MM");
clientsStatus = clients.stream().collect(ConcurrentHashMap::new, (map, cid) -> map.put(cid, false), Map::putAll);
}
public String getFileid() {
return fileid;
}
public Progress setFileid(String fileid) {
this.fileid = fileid;
return this;
}
public boolean isFinished() {
return finished;
}
public boolean isSuccess() {
return fileid != null;
}
public void setFinished() {
this.finished = true;
}
public String getStatus() {
return status;
}
public int getProgress() {
if (clientsStatus == null || clientsStatus.isEmpty()) {
return 0;
}
int total = clientsStatus.size();
long finishedCount = clientsStatus.values().stream().filter(success -> success).count();
return (int) finishedCount * 100 / total;
}
public String getCurrentMonth() {
return currentMonth;
}
public String getServer() {
return server;
}
public Progress setStatus(String status) {
this.status = status;
return this;
}
public void markClientFinished(Integer clientId) {
if (clientsStatus != null) {
clientsStatus.put(clientId, true);
}
}
}
}

@ -56,7 +56,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@ -68,10 +67,8 @@ import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -511,17 +508,23 @@ public class TestController {
}
@ManagerMapping(value = "/reports/ato_reports/royalpay_ato_report_{year}.bttps", role = ManagerRole.DEVELOPER, method = RequestMethod.GET)
@ManagerMapping(value = "/reports/ato_reports/royalpay_ato_report_{year}.bttps", role = ManagerRole.DEVELOPER, method = RequestMethod.POST)
@ReadOnlyConnection
public void downloadATOReport(@PathVariable String year, HttpServletResponse resp) throws IOException {
public JSONObject exportATOReport(@PathVariable String year) {
DateTime from = DateTime.parse(year + "-07-01");
DateTime to = from.plusYears(1).plusDays(-1);
String atoReport = atoReportService.exportBTTPSFile(from.toDate(), to.toDate());
resp.setContentType(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
try (OutputStream out = resp.getOutputStream()) {
out.write(atoReport.getBytes(StandardCharsets.UTF_8));
out.flush();
atoReportService.startExportTask(from.toDate(), to.toDate());
return atoReportService.taskStatus();
}
@ManagerMapping(value = "/reports/ato_reports/royalpay_ato_report", role = ManagerRole.DEVELOPER, method = RequestMethod.GET)
public JSONObject exportATOStatus() {
return atoReportService.taskStatus();
}
@ManagerMapping(value = "/reports/ato_reports/royalpay_ato_report.bttps", role = ManagerRole.DEVELOPER, method = RequestMethod.GET)
public void downloadReport(HttpServletResponse response) throws IOException {
atoReportService.downloadFile(response);
}
@ManagerMapping(value = "/custom_declare_check/{reportId}/detail", method = RequestMethod.GET, role = ManagerRole.DEVELOPER)

@ -8,7 +8,7 @@ import java.util.List;
public interface PriorityListManager {
List<JSONObject> listPriorityMerchants();
void setMerchantPriority(String clientMoniker, JSONObject manager);
JSONObject setMerchantPriority(String clientMoniker, JSONObject manager);
void removePriorityMerchant(String clientMoniker, JSONObject manager);

@ -3,6 +3,7 @@ package au.com.royalpay.payment.manage.management.clearing.core.impl;
import au.com.royalpay.payment.manage.management.clearing.beans.PriorityModifyLog;
import au.com.royalpay.payment.manage.management.clearing.core.PriorityListManager;
import au.com.royalpay.payment.manage.mappers.system.SysSettlePlanMapper;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.NotFoundException;
import au.com.royalpay.payment.tools.merchants.core.MerchantInfoProvider;
import au.com.royalpay.payment.tools.utils.id.IdUtil;
@ -47,8 +48,8 @@ public class PriorityListManagerImpl implements PriorityListManager {
}
@Override
public void setMerchantPriority(String clientMoniker, JSONObject manager) {
JSONObject client = mchInfoProvider.getClientInfoByMoniker(clientMoniker);
public JSONObject setMerchantPriority(String clientMoniker, JSONObject manager) {
JSONObject client = MonikerStringUtils.getSimplifiedClientsInfo(mchInfoProvider, clientMoniker);
if (client == null) {
throw new NotFoundException("Client " + clientMoniker + " not found");
}
@ -57,7 +58,7 @@ public class PriorityListManagerImpl implements PriorityListManager {
List<String> monikerList = MonikerStringUtils.splitStringArray(clientMonikers).collect(Collectors.toList());
if (monikerList.stream().anyMatch(moniker -> moniker.equalsIgnoreCase(clientMoniker))) {
logger.debug("{} exists,ignore", clientMoniker);
return;
throw new BadRequestException("Client exists");
}
monikerList.add(clientMoniker.toUpperCase());
String joinedMonikers = String.join(",", monikerList);
@ -74,6 +75,7 @@ public class PriorityListManagerImpl implements PriorityListManager {
mongoTemplate.insert(log);
} catch (Exception ignore) {
}
return client;
}
@Override

@ -49,8 +49,8 @@ public class SettleTasksController {
}
@PutMapping("/priority_merchants/{clientMoniker}")
public void setMerchantPriority(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
priorityListManager.setMerchantPriority(clientMoniker, manager);
public JSONObject setMerchantPriority(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return priorityListManager.setMerchantPriority(clientMoniker, manager);
}
@DeleteMapping("/priority_merchants/{clientMoniker}")

@ -152,7 +152,7 @@ define(['angular', 'uiBootstrap', 'uiRouter'], function (angular) {
tasks.push(submitTask)
}
$http.post('/sys/settle_tasks', tasks).then(function (resp) {
commonDialog.alert({type: 'success', title: 'Success', content: resp.data.message})
commonDialog.alert({type: 'success', title: 'Success', content: 'Task submitted'})
ctrl.update_task = $interval(function () {
$scope.checkProgressStatus()
}, 5000);
@ -198,18 +198,29 @@ define(['angular', 'uiBootstrap', 'uiRouter'], function (angular) {
if (!$scope.input.moniker) {
return;
}
$http.put('/sys/settle_tasks/priority_merchants/' + $scope.input.moniker).then(function () {
$http.put('/sys/settle_tasks/priority_merchants/' + $scope.input.moniker).then(function (res) {
commonDialog.alert({
type: 'success',
title: 'Client Added',
content: res.data.client_moniker + ' added into priority list'
});
$scope.loadPriorities();
}, function (res) {
commonDialog.alert({type: 'error', title: 'Error', content: res.data.message})
})
};
$scope.dropPriorityClient = function (client) {
commonDialog.confirm({
title: 'Disable client priority',
content: 'Disabling ' + client.client_moniker + ' in priority list, confirm?'
}).then(function () {
$http['delete']('/sys/settle_tasks/priority_merchants/' + client.client_moniker).then(function () {
$scope.loadPriorities();
}, function (res) {
commonDialog.alert({type: 'error', title: 'Error', content: res.data.message})
})
})
};
$scope.listHistory = function () {
$uibModal.open({

@ -306,7 +306,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6" ng-class="{'has-error':partnerForm.address.$invalid && partnerForm.address.$dirty}">

@ -244,7 +244,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">

@ -177,7 +177,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">

@ -993,7 +993,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6"

@ -851,7 +851,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6" ng-class="{'has-error':partnerForm.address.$invalid && partnerForm.address.$dirty}">

@ -506,7 +506,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
@ -1157,7 +1157,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">

@ -618,7 +618,7 @@
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6">

@ -1082,7 +1082,7 @@
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">

@ -901,7 +901,7 @@
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-heading">Address Information(<span style="color: red">Registered address on your business license.</span>)</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6">

@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets;
* Create by yixian at 2018-08-31 14:40
*/
@SpringBootTest
@ActiveProfiles({"proxy", "wechat","alipay","bestpay","rpay","jd","yeepay"})
@ActiveProfiles({"proxy", "wechat", "alipay", "common", "rppaysvc", "rpay"})
@TestPropertySource(properties = {"spring.datasource.username=root", "spring.datasource.password=ZOIBhellor0yalpay"})
@RunWith(SpringRunner.class)
public class ExportATOReport {
@ -28,7 +28,7 @@ public class ExportATOReport {
@Test
public void export() throws IOException {
String content = atoReportService.exportBTTPSFile(DateTime.parse("2018-07-01").toDate(), DateTime.parse("2019-06-30").toDate());
FileUtils.write(new File("C:\\Users\\davep\\Documents\\royalpay2018070120190630.bttps"), content, StandardCharsets.US_ASCII);
String content = atoReportService.exportBTTPSFile(DateTime.parse("2019-07-01").toDate(), DateTime.parse("2020-06-30").toDate());
FileUtils.write(new File("/Users/yixian/documents/royalpay2019070120200630.bttps"), content, StandardCharsets.US_ASCII);
}
}

Loading…
Cancel
Save