Merge branch 'hotfix-bttps' into develop

master
yixian 4 years ago
commit 7ab29fa38b

@ -0,0 +1,211 @@
package au.com.royalpay.payment.manage.analysis.beans.ato;
import au.com.royalpay.payment.tools.merchants.beans.BalanceGroup;
import org.joda.time.DateTime;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ConfigurationProperties(prefix = "app.atoreport")
public class ATOCompanyConfig {
private List<ATOCompany> companies;
public List<ATOCompany> getCompanies() {
return companies;
}
public ATOCompanyConfig setCompanies(List<ATOCompany> companies) {
this.companies = companies;
return this;
}
public static class ATOCompany {
private String[] balanceGroups;
private String brand;
private String referencePrefix;
private String company;
private String abn;
private Contact contact;
private Addr address;
public String reference() {
return referencePrefix + DateTime.now().toString("yyyyMMddHHmm");
}
public List<BalanceGroup> balanceGroups() {
return Arrays.stream(balanceGroups).map(BalanceGroup::valueOf).collect(Collectors.toList());
}
public String getReferencePrefix() {
return referencePrefix;
}
public ATOCompany setReferencePrefix(String referencePrefix) {
this.referencePrefix = referencePrefix;
return this;
}
public String[] getBalanceGroups() {
return balanceGroups;
}
public ATOCompany setBalanceGroups(String[] balanceGroups) {
this.balanceGroups = balanceGroups;
return this;
}
public String getBrand() {
return brand;
}
public ATOCompany setBrand(String brand) {
this.brand = brand;
return this;
}
public String getAbn() {
return abn;
}
public ATOCompany setAbn(String abn) {
this.abn = abn;
return this;
}
public Contact getContact() {
return contact;
}
public ContactInfo getContactInfo() {
return contact.convert();
}
public ATOCompany setContact(Contact contact) {
this.contact = contact;
return this;
}
public Addr getAddress() {
return address;
}
public ATOCompany setAddress(Addr address) {
this.address = address;
return this;
}
public AddressInfo getAddressInfo() {
return address.convert();
}
public String getShortCompanyName() {
return company.replace(" PTY LTD", "");
}
public String getCompany() {
return company;
}
public ATOCompany setCompany(String company) {
this.company = company;
return this;
}
}
public static class Contact {
private String name;
private String phone;
private String email;
public ContactInfo convert() {
return new ContactInfo(name, phone, email);
}
public String getName() {
return name;
}
public Contact setName(String name) {
this.name = name;
return this;
}
public String getPhone() {
return phone;
}
public Contact setPhone(String phone) {
this.phone = phone;
return this;
}
public String getEmail() {
return email;
}
public Contact setEmail(String email) {
this.email = email;
return this;
}
}
public static class Addr {
private String address;
private String suburb;
private String state;
private String postcode;
private String country;
public AddressInfo convert() {
return new AddressInfo(address, suburb, state, postcode, country);
}
public String getAddress() {
return address;
}
public Addr setAddress(String address) {
this.address = address;
return this;
}
public String getSuburb() {
return suburb;
}
public Addr setSuburb(String suburb) {
this.suburb = suburb;
return this;
}
public String getState() {
return state;
}
public Addr setState(String state) {
this.state = state;
return this;
}
public String getPostcode() {
return postcode;
}
public Addr setPostcode(String postcode) {
this.postcode = postcode;
return this;
}
public String getCountry() {
return country;
}
public Addr setCountry(String country) {
this.country = country;
return this;
}
}
}

@ -4,15 +4,16 @@ package au.com.royalpay.payment.manage.analysis.beans.ato;
* Create by yixian at 2018-08-30 21:17
*/
public class AddressInfo {
private String address;
private String suburb;
private String state;
private String postCode;
private String country;
private final String address;
private final String suburb;
private final String state;
private final String postCode;
private final String country;
public AddressInfo(String address, String suburb, String state, String postCode, String country) {
this.address = address;
this.suburb = suburb;
postCode = postCode.replaceAll("\\D", "");
if (!postCode.matches("^\\d{4}$")) {
postCode = "9999";
country = "OTH";
@ -24,7 +25,11 @@ public class AddressInfo {
postCode = "9999";
}
this.postCode = postCode;
this.state = state;
if (state != null) {
this.state = state.toUpperCase();
} else {
this.state = null;
}
this.country = country;
}

@ -6,10 +6,10 @@ import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
* Create by yixian at 2018-08-30 21:19
*/
public class ContactInfo {
private String contactName;
private final String contactName;
private int phoneAreaCode;
private String phoneNumber;
private String email;
private final String email;
public ContactInfo(String contactName, String phoneNumber, String email) {
this.contactName = contactName;

@ -2,26 +2,28 @@ package au.com.royalpay.payment.manage.analysis.beans.ato;
import org.apache.commons.lang3.time.DateUtils;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Create by yixian at 2018-08-30 21:13
*/
public class ReportingPartyData implements ATOBulkLine {
private final String identifier = "RPDR";
private Date periodStart;
private Date periodEnd;
private String abn;
private String branchNumber;
private String registerName;
private static final String IDENTIFIER = "RPDR";
private final Date periodStart;
private final Date periodEnd;
private final String abn;
private final String branchNumber;
private final String registerName;
private String tradingName;
private AddressInfo address;
private AddressInfo postalAddress;
private ContactInfo contactInfo;
private String softwareProductType;
private final String softwareProductType;
private Map<Integer, BusinessData> businesses = new ConcurrentHashMap<>();
private final Map<Integer, BusinessData> businesses = new ConcurrentHashMap<>();
public ReportingPartyData(Date periodStart, Date periodEnd, String abn, String branchNumber, String registerName, String softwareProductType) {
this.periodStart = DateUtils.truncate(periodStart, Calendar.DATE);
@ -56,7 +58,7 @@ public class ReportingPartyData implements ATOBulkLine {
public StringBuilder buildLine(StringBuilder builder) {
StringBuilder line = new StringBuilder();
appendNParam(line, 1400, 4);
appendAParam(line, identifier, 4);
appendAParam(line, IDENTIFIER, 4);
appendDParam(line, periodStart, 8);
appendDParam(line, periodEnd, 8);
appendNParam(line, abn, 11);

@ -0,0 +1,7 @@
package au.com.royalpay.payment.manage.analysis.core;
import java.io.IOException;
public interface ATOReportFinishedConsumer {
void accept(String brand, String content) throws IOException;
}

@ -11,7 +11,7 @@ import java.util.Date;
*/
public interface ATOReportService {
String exportBTTPSFile(Date from, Date to);
void exportBTTPSFile(Date from, Date to, ATOReportFinishedConsumer resultConsumer);
void startExportTask(Date from, Date to);

@ -1,6 +1,8 @@
package au.com.royalpay.payment.manage.analysis.core.impls;
import au.com.royalpay.payment.core.PaymentApi;
import au.com.royalpay.payment.manage.analysis.beans.ato.*;
import au.com.royalpay.payment.manage.analysis.core.ATOReportFinishedConsumer;
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;
@ -14,11 +16,11 @@ import org.apache.commons.codec.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
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.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
@ -36,17 +38,22 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* Create by yixian at 2018-08-31 1:23
*/
@Service
@EnableConfigurationProperties(ATOCompanyConfig.class)
public class ATOReportServiceImpl implements ATOReportService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private TransactionMapper transactionMapper;
@Resource
private ClientMapper clientMapper;
@Resource
private PaymentApi paymentApi;
private final ATOCompanyConfig atoCompanies;
@Value("classpath:data/category/billbuddyindustry.json")
private org.springframework.core.io.Resource industryResource;
private Map<String, String> industryMap;
@ -54,9 +61,10 @@ public class ATOReportServiceImpl implements ATOReportService {
private final String prefix;
private Progress progress;
public ATOReportServiceImpl(StringRedisTemplate redisTemplate, @Value("${app.redis.prefix}") String prefix) {
public ATOReportServiceImpl(StringRedisTemplate redisTemplate, @Value("${app.redis.prefix}") String prefix, ATOCompanyConfig atoCompanies) {
this.redisTemplate = redisTemplate;
this.prefix = prefix;
this.atoCompanies = atoCompanies;
}
@PostConstruct
@ -87,22 +95,27 @@ public class ATOReportServiceImpl implements ATOReportService {
}
@Override
public String exportBTTPSFile(Date from, Date to) {
String reference = "RPAY" + DateFormatUtils.format(new Date(), "yyyyMMddHHmm");
String abn = "16601619685";
String registerCompanyName = "Tunnel Show Pty Ltd";
AddressInfo companyAddr = new AddressInfo("Level 11, 15 William St", "Melbourne", "VIC", "3000", "AUS");
ContactInfo companyContact = new ContactInfo("Locky", "+61394488865", "info@royalpay.com.au");
ATOBulkData.IntermediaryData intermediary = new ATOBulkData.IntermediaryData(abn, registerCompanyName, reference)
.setAddress(companyAddr)
.setContactInfo(companyContact);
public void exportBTTPSFile(Date from, Date to, ATOReportFinishedConsumer resultConsumer) {
atoCompanies.getCompanies().forEach(company -> exportBTTPS(company, from, to, resultConsumer));
}
private void exportBTTPS(ATOCompanyConfig.ATOCompany company, Date from, Date to, ATOReportFinishedConsumer resultConsumer) {
if (progress != null) {
progress.setStatus("Init task");
progress.setBrand(company.getBrand());
synchronizeProgress();
}
ATOBulkData.IntermediaryData intermediary = new ATOBulkData.IntermediaryData(company.getAbn(), company.getCompany(), company.reference())
.setAddress(company.getAddressInfo())
.setContactInfo(company.getContactInfo());
ATOBulkData data = new ATOBulkData(intermediary);
ReportingPartyData reportingParty = new ReportingPartyData(from, to, abn, "001", registerCompanyName, "INHOUSE Tunnel Show")
.setAddress(companyAddr)
.setPostalAddress(companyAddr)
.setContactInfo(companyContact)
.setTradingName("RoyalPay");
ReportingPartyData reportingParty = new ReportingPartyData(from, to, company.getAbn(), "001", company.getCompany(), "INHOUSE " + company.getShortCompanyName())
.setAddress(company.getAddressInfo())
.setPostalAddress(company.getAddressInfo())
.setContactInfo(company.getContactInfo())
.setTradingName(company.getBrand());
intermediary.addReportingParty(reportingParty);
DateTime fromDateTime = new DateTime(from).withTimeAtStartOfDay();
@ -111,15 +124,19 @@ public class ATOReportServiceImpl implements ATOReportService {
DateTime endOfMon = new DateTime(fromDateTime.plusMonths(1).withDayOfMonth(1));
while (endOfMon.isBefore(toDateTime)) {
logger.debug("Exporting date range:{} ~ {}", startOfMon.toString("yyyy-MM-dd"), endOfMon.toString("yyyy-MM-dd"));
loadMonthTransactions(reportingParty, startOfMon, endOfMon);
loadMonthTransactions(company, reportingParty, startOfMon, endOfMon);
startOfMon = new DateTime(endOfMon);
endOfMon = new DateTime(endOfMon.plusMonths(1));
}
endOfMon = new DateTime(toDateTime);
logger.debug("Exporting date range:{} ~ {}", startOfMon.toString("yyyy-MM-dd"), endOfMon.toString("yyyy-MM-dd"));
loadMonthTransactions(reportingParty, startOfMon, endOfMon);
loadMonthTransactions(company, reportingParty, startOfMon, endOfMon);
logger.info("output BTTPS file");
return data.outputBTTPS();
try {
resultConsumer.accept(company.getBrand(), data.outputBTTPS());
} catch (IOException e) {
throw new ServerErrorException("Failed to export bttps file", e);
}
}
private String progressKey() {
@ -142,16 +159,18 @@ public class ATOReportServiceImpl implements ATOReportService {
progress = new Progress();
synchronizeProgress();
try {
String content = exportBTTPSFile(from, to);
exportBTTPSFile(from, to, (brand, content) -> {
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";
progress.setStatus(brand + " Uploading,filesize:" + contentBytes.length);
String filename = brand + "_ato_report_" + new DateTime(from).toString("yyyyMMdd") + "_to_" + new DateTime(to).toString("yyyyMMdd") + ".bttps";
File saveFile = new File("/var/log/payment/" + filename);
FileUtils.writeByteArrayToFile(saveFile, contentBytes);
String path = saveFile.getAbsolutePath();
logger.info("uploaded ATO report to {}", path);
progress.setFileid(path);
redisTemplate.boundValueOps(reportFileKey()).set(path, Duration.ofDays(1));
});
} catch (Exception e) {
progress.setStatus(e.getMessage());
logger.error("output bttps file failed", e);
@ -198,16 +217,17 @@ public class ATOReportServiceImpl implements ATOReportService {
}
}
private void loadMonthTransactions(ReportingPartyData reportingParty, DateTime startOfMon, DateTime endOfMon) {
List<Integer> clients = clientMapper.listClientsWithTransactionsSettled(startOfMon.toDate(), endOfMon.toDate());
private void loadMonthTransactions(ATOCompanyConfig.ATOCompany company, ReportingPartyData reportingParty, DateTime startOfMon, DateTime endOfMon) {
List<String> channels = company.balanceGroups().stream().flatMap(group -> paymentApi.channelsInGroup(group).stream()).distinct().collect(Collectors.toList());
List<Integer> clients = clientMapper.listClientsWithTransactionsSettled(channels, startOfMon.toDate(), endOfMon.toDate());
if (progress != null) {
progress.setMonth(startOfMon, clients);
synchronizeProgress();
}
clients.parallelStream().forEach(clientId -> loadClientMonthTransactions(reportingParty, clientId, startOfMon, endOfMon));
clients.parallelStream().forEach(clientId -> loadClientMonthTransactions(channels, reportingParty, clientId, startOfMon, endOfMon));
}
private void loadClientMonthTransactions(ReportingPartyData reportingParty, Integer clientId, DateTime startOfMon, DateTime endOfMon) {
private void loadClientMonthTransactions(List<String> channels, 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"));
if (biz == null) {
@ -224,7 +244,7 @@ public class ATOReportServiceImpl implements ATOReportService {
.setContactInfo(contact);
reportingParty.addBusiness(clientId, biz);
}
List<JSONObject> analysisList = transactionMapper.analysisForATOReport(clientId, startOfMon.toDate(), endOfMon.toDate());
List<JSONObject> analysisList = transactionMapper.analysisForATOReport(clientId, channels, startOfMon.toDate(), endOfMon.toDate());
for (JSONObject analysis : analysisList) {
biz.addTransaction(new TransactionSummaryData(analysis, startOfMon, endOfMon));
}
@ -240,6 +260,7 @@ public class ATOReportServiceImpl implements ATOReportService {
public static class Progress {
private static final Logger logger = LoggerFactory.getLogger(ATOReportService.class);
private String brand;
private String currentMonth;
private Map<Integer, Boolean> clientsStatus;
private final String server;
@ -253,6 +274,15 @@ public class ATOReportServiceImpl implements ATOReportService {
server = PlatformEnvironment.getEnv().appName();
}
public String getBrand() {
return brand;
}
public Progress setBrand(String brand) {
this.brand = brand;
return this;
}
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);

@ -130,7 +130,7 @@ public interface TransactionMapper {
List<JSONObject> getHfClearAmount(JSONObject params);
List<JSONObject> analysisForATOReport(@Param("clientId") int clientId, @Param("from") Date startOfMon, @Param("to") Date endOfMon);
List<JSONObject> analysisForATOReport(@Param("clientId") int clientId, @Param("channels") List<String> channels, @Param("from") Date startOfMon, @Param("to") Date endOfMon);
/**
* 退退

@ -116,7 +116,7 @@ public interface ClientMapper {
List<JSONObject> listBySubMerchantId(@Param("sub_merchant_id") String sub_merchant_id);
List<Integer> listClientsWithTransactionsSettled(@Param("from") Date fromDate, @Param("to") Date toDate);
List<Integer> listClientsWithTransactionsSettled(@Param("channels") List<String> channels, @Param("from") Date fromDate, @Param("to") Date toDate);
@AutoSql(SqlType.SELECT)
List<JSONObject> AllClients();

@ -28,6 +28,41 @@ app:
enable: true
tax:
type: GST
atoreport:
companies:
- brand: RoyalPay
reference-prefix: RPAY
abn: 16601619685
company: TUNNEL SHOW PTY LTD
balance-groups:
- NORMAL_CROSS_BORDER
contact:
name: Locky
phone: +61394488865
email: info@royalpay.com.au
address:
address: Level 11, 15 William St
suburb: Melbourne
state: VIC
postcode: 3000
country: AUS
- brand: UPay
reference-prefix: UPAY
abn: 62627588514
company: UPAY PTY LTD
balance-groups:
- RPAY_SVC_CARD
- RPAY_SVC_DIRECTDEBIT
contact:
name: Locky
phone: +61394488865
email: info@royalpay.com.au
address:
address: Level 11, 15 William St
suburb: Melbourne
state: VIC
postcode: 3000
country: AUS
logging:
level:
au:

@ -1304,7 +1304,8 @@
and t.system_generate = 0
and t.clearing_status = 1
and t.transaction_time between #{from} and #{to}
and t.channel != 'Settlement'
and t.channel in
<foreach collection="channels" item="channel" open="(" close=")" separator=",">#{channel}</foreach>
group by cd.bsb_no, cd.account_no
order by period_start
</select>

@ -664,6 +664,8 @@
where t.clearing_status = 1
and t.system_generate = 0
and t.transaction_time between #{from} and #{to}
and t.channel in
<foreach collection="channels" open="(" close=")" item="channel" separator=",">#{channel}</foreach>
</select>
<select id="findByhfPayUrlNotNull" resultType="com.alibaba.fastjson.JSONObject">

@ -28,7 +28,7 @@ public class ExportATOReport {
@Test
public void export() throws IOException {
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);
atoReportService.exportBTTPSFile(DateTime.parse("2019-07-01").toDate(), DateTime.parse("2020-06-30").toDate(), (brand, content) -> FileUtils.write(new File("/Users/yixian/documents/royalpay2019070120200630.bttps"), content, StandardCharsets.US_ASCII));
}
}

Loading…
Cancel
Save