Merge remote-tracking branch 'origin/develop' into develop

master
yuan 6 years ago
commit 82a00fe302

@ -574,3 +574,10 @@ CREATE TABLE `sys_mail_unsub` (
alter table sys_clients add column ali_sub_merchant_id varchar(20) DEFAULT NULL;
update sys_clients set ali_sub_merchant_id = client_moniker;
ALTER TABLE `log_clearing_detail`
ADD COLUMN `settle_bank` varchar(10) NULL DEFAULT NULL COMMENT '清算来源银行(RoyalPay)' AFTER `account_name`;
update log_clearing_detail set settle_bank='CBA';
ALTER TABLE `log_clearing`
ADD COLUMN `editable` tinyint(1) NULL DEFAULT 1 COMMENT '是否可编辑' AFTER `balance`;

@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Date;
import java.util.List;
@ -259,7 +260,7 @@ public class AreaMerchantTradeAnalysisImpl implements AreaMerchantTradeAnalysis{
}
}
if(thisAmount.getBigDecimal("total").compareTo(BigDecimal.ZERO)>0 && thisAmount.getBigDecimal("old_total").compareTo(BigDecimal.ZERO)>0) {
lastTotal = (thisAmount.getBigDecimal("total").subtract(thisAmount.getBigDecimal("old_total"))).divide(thisAmount.getBigDecimal("old_total"), 4, BigDecimal.ROUND_HALF_UP);
lastTotal = (thisAmount.getBigDecimal("total").subtract(thisAmount.getBigDecimal("old_total"))).divide(thisAmount.getBigDecimal("old_total"), 4, RoundingMode.HALF_UP);
}
}else {
if(thisAmount.getBigDecimal("total").compareTo(BigDecimal.ZERO) == 0){
@ -274,7 +275,7 @@ public class AreaMerchantTradeAnalysisImpl implements AreaMerchantTradeAnalysis{
}
}
if(thisAmount.getBigDecimal("alipay_total").compareTo(BigDecimal.ZERO)>0 && thisAmount.getBigDecimal("old_alipay_total").compareTo(BigDecimal.ZERO)>0){
alipayTotal = (thisAmount.getBigDecimal("alipay_total").subtract(thisAmount.getBigDecimal("old_alipay_total"))).divide(thisAmount.getBigDecimal("old_alipay_total"),4,BigDecimal.ROUND_HALF_UP);
alipayTotal = (thisAmount.getBigDecimal("alipay_total").subtract(thisAmount.getBigDecimal("old_alipay_total"))).divide(thisAmount.getBigDecimal("old_alipay_total"),4,RoundingMode.HALF_UP);
}
}else {
if(thisAmount.getBigDecimal("alipay_total").compareTo(BigDecimal.ZERO) == 0){
@ -290,7 +291,7 @@ public class AreaMerchantTradeAnalysisImpl implements AreaMerchantTradeAnalysis{
}
}
if(thisAmount.getBigDecimal("wechat_toatl").compareTo(BigDecimal.ZERO)>0 && thisAmount.getBigDecimal("old_wechat_toatl").compareTo(BigDecimal.ZERO)>0){
wechatToatl = (thisAmount.getBigDecimal("wechat_toatl").subtract(thisAmount.getBigDecimal("old_wechat_toatl"))).divide(thisAmount.getBigDecimal("old_wechat_toatl"),4,BigDecimal.ROUND_HALF_UP);
wechatToatl = (thisAmount.getBigDecimal("wechat_toatl").subtract(thisAmount.getBigDecimal("old_wechat_toatl"))).divide(thisAmount.getBigDecimal("old_wechat_toatl"),4,RoundingMode.HALF_UP);
}
}else {
if(thisAmount.getBigDecimal("wechat_toatl").compareTo(BigDecimal.ZERO) == 0){

@ -27,6 +27,7 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -303,9 +304,9 @@ public class DashboardServiceImpl implements DashboardService,DashboardAnalysisT
res.put("today",today);
res.put("yes",yes);
res.put("not_settled", new BigDecimal(transactionAnalysisMapper.analysisNotSettled(params)));
res.put("trade_amount_rise",yes.getBigDecimal("trade_amount").compareTo(BigDecimal.ZERO)>0 ? (today.getBigDecimal("trade_amount").subtract(yes.getBigDecimal("trade_amount"))).divide(yes.getBigDecimal("trade_amount"), 4, BigDecimal.ROUND_HALF_UP):BigDecimal.ZERO);
res.put("trade_count_rise", yes.getIntValue("trade_count") > 0 ? (today.getBigDecimal("trade_count").subtract(yes.getBigDecimal("trade_count"))).divide(yes.getBigDecimal("trade_count"), 4, BigDecimal.ROUND_HALF_UP) : 0);
res.put("customers_rise", yes.getIntValue("customers") > 0 ? (today.getBigDecimal("customers").subtract(yes.getBigDecimal("customers"))).divide(yes.getBigDecimal("customers"), 4, BigDecimal.ROUND_HALF_UP) : 0);
res.put("trade_amount_rise",yes.getBigDecimal("trade_amount").compareTo(BigDecimal.ZERO)>0 ? (today.getBigDecimal("trade_amount").subtract(yes.getBigDecimal("trade_amount"))).divide(yes.getBigDecimal("trade_amount"), 4, RoundingMode.HALF_UP):BigDecimal.ZERO);
res.put("trade_count_rise", yes.getIntValue("trade_count") > 0 ? (today.getBigDecimal("trade_count").subtract(yes.getBigDecimal("trade_count"))).divide(yes.getBigDecimal("trade_count"), 4, RoundingMode.HALF_UP) : 0);
res.put("customers_rise", yes.getIntValue("customers") > 0 ? (today.getBigDecimal("customers").subtract(yes.getBigDecimal("customers"))).divide(yes.getBigDecimal("customers"), 4, RoundingMode.HALF_UP) : 0);
params.remove("begin");
params.remove("end");
List<JSONObject> logs = transactionMapper.listSettlementLogTotal(params);

@ -11,10 +11,7 @@ import au.com.royalpay.payment.manage.cashback.core.CashbackService;
import au.com.royalpay.payment.manage.customers.core.CouponValidateService;
import au.com.royalpay.payment.manage.fund.core.impls.XPlanFundConfigServiceImpl;
import au.com.royalpay.payment.manage.management.clearing.core.CleanService;
import au.com.royalpay.payment.manage.mappers.log.AppMessageLogMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailAnalysisMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailMapper;
import au.com.royalpay.payment.manage.mappers.log.LogSettleMailMapper;
import au.com.royalpay.payment.manage.mappers.log.*;
import au.com.royalpay.payment.manage.mappers.notice.NoticePartnerMapper;
import au.com.royalpay.payment.manage.mappers.payment.OrderMapper;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
@ -79,6 +76,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -166,6 +164,8 @@ public class RetailAppServiceImp implements RetailAppService {
private ClientMapper clientMapper;
@Resource
private ClientModifySupport clientModifySupport;
@Resource
private ClearingLogMapper clearingLogMapper;
private Map<String, AppMsgSender> senderMap = new HashMap<>();
private final String fileName[] = { "client_bank_file", "client_id_file", "client_company_file" };
@ -550,18 +550,18 @@ public class RetailAppServiceImp implements RetailAppService {
PageList<JSONObject> logs = clearingDetailMapper.listClientSettlementLog(params,
new PageBounds(appQueryBean.getPage(), appQueryBean.getLimit(), Order.formString("report_date.desc")));
logs.forEach(log -> log.put("total_charge", log.getBigDecimal("total_charge").add(log.getBigDecimal("tax_amount"))));
JSONObject result = PageListUtils.buildPageListResult(logs);
if (appQueryBean.getPage() == 1) {
if (!logs.isEmpty() && logs.size() > 0) {
JSONObject sendMailLog = logSettleMailMapper.findByDate(logs.get(0).getDate("report_date"));
if (sendMailLog == null) {
logs.remove(0);
}else if (sendMailLog != null && sendMailLog.getIntValue("mail_status") != 1) {
logs.remove(0);
JSONObject clearingDetail = clearingDetailMapper.findByDetailId(logs.get(0).getIntValue("clearing_order"));
if (clearingDetail!=null){
JSONObject clearingLog = clearingLogMapper.findById(clearingDetail.getIntValue("clearing_id"));
if(clearingLog.getBooleanValue("editable")){
result.put("padding", true);
}
}
}
}
JSONObject result = PageListUtils.buildPageListResult(logs);
return result;
}
@ -1016,7 +1016,7 @@ public class RetailAppServiceImp implements RetailAppService {
@Override
public void sendCleanMessage(JSONObject log_clearing_detail, int client_id) {
String clearing_amount = log_clearing_detail.getBigDecimal("clearing_amount").setScale(2, BigDecimal.ROUND_HALF_DOWN).toString();
String clearing_amount = log_clearing_detail.getBigDecimal("clearing_amount").setScale(2, RoundingMode.HALF_DOWN).toString();
String settle_date_from = DateFormatUtils.format(log_clearing_detail.getDate("settle_date_from"), "MM/dd/yyyy");
String settle_date_to = DateFormatUtils.format(log_clearing_detail.getDate("settle_date_to"), "MM/dd/yyyy");
logger.debug("sendCleanMessage-" + log_clearing_detail.getString("client_moniker") + "- " + PlatformEnvironment.getEnv().getForeignCurrency() + " "

@ -5,6 +5,7 @@ import au.com.royalpay.payment.tools.CommonConsts;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@ -49,25 +50,25 @@ public class AgentCommissionAnalysis {
Date tradeDate = dayAnalysis.getDate("trade_date");
BigDecimal grossAmount = dayAnalysis.getBigDecimal("total");
BigDecimal dayRate = dayAnalysis.getBigDecimal(channel+"_rate_value");
BigDecimal agentCharge = grossAmount.multiply(dayRate.divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP));
BigDecimal agentCharge = grossAmount.multiply(dayRate.divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP));
BigDecimal orgCharge = BigDecimal.ZERO;
BigDecimal orgNetCharge = BigDecimal.ZERO;
switch (channel){
case "alipay":
orgCharge = grossAmount.multiply(org.getBigDecimal("alipay_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("alipay_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP)));
orgCharge = grossAmount.multiply(org.getBigDecimal("alipay_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("alipay_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP)));
break;
case "wechat":
orgCharge = grossAmount.multiply(org.getBigDecimal("wechat_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("wechat_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP)));
orgCharge = grossAmount.multiply(org.getBigDecimal("wechat_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("wechat_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP)));
break;
case "jd":
orgCharge = grossAmount.multiply(org.getBigDecimal("jd_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("jd_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP)));
orgCharge = grossAmount.multiply(org.getBigDecimal("jd_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("jd_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP)));
break;
case "alipayonline":
orgCharge = grossAmount.multiply(org.getBigDecimal("alipayonline_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("alipayonline_rate_value").divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP)));
orgCharge = grossAmount.multiply(org.getBigDecimal("alipayonline_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP));
orgNetCharge = orgCharge.subtract(grossAmount.multiply(parentOrg.getBigDecimal("alipayonline_rate_value").divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP)));
break;
default:
break;

@ -6,6 +6,7 @@ import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
/**
@ -67,9 +68,9 @@ public class CityPartnerCommissionAnalysis {
Date tradeDate = dayAnalysis.getDate("trade_date");
BigDecimal total = dayAnalysis.getBigDecimal("total");
BigDecimal dayRate = dayAnalysis.getBigDecimal(channel + "_rate_value");
BigDecimal dayCharge = total.multiply(dayRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal dayCharge = total.multiply(dayRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
BigDecimal royalpayCharge = total.multiply(rate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal royalpayCharge = total.multiply(rate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
BigDecimal thirdPartyPaymentCharge = getThirdPartyCharge(channel, total);
BigDecimal netCharge = royalpayCharge.subtract(thirdPartyPaymentCharge);
@ -161,13 +162,13 @@ public class CityPartnerCommissionAnalysis {
Date tradeDate = dayAnalysis.getDate("trade_date");
BigDecimal total = dayAnalysis.getBigDecimal("total");
BigDecimal dayRate = dayAnalysis.getBigDecimal(channel + "_rate_value");
BigDecimal dayCharge = total.multiply(dayRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal dayCharge = total.multiply(dayRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
BigDecimal royalpayCharge = total.multiply(rate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal royalpayCharge = total.multiply(rate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
BigDecimal thirdPartyPaymentCharge = getThirdPartyCharge(channel, total);
BigDecimal netCharge = royalpayCharge.subtract(thirdPartyPaymentCharge);
BigDecimal orgCharge = netCharge.multiply(orgRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal orgCharge = netCharge.multiply(orgRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
totalGrossAmount = totalGrossAmount.add(total);
totalChargeSum = totalChargeSum.add(dayCharge);
totalRoyalPayCharge = totalRoyalPayCharge.add(royalpayCharge);
@ -216,16 +217,16 @@ public class CityPartnerCommissionAnalysis {
BigDecimal thirdPartyPaymentCharge = BigDecimal.ZERO;
switch (channel) {
case "alipay":
thirdPartyPaymentCharge = total.multiply(alipayChargeRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
thirdPartyPaymentCharge = total.multiply(alipayChargeRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
break;
case "wechat":
thirdPartyPaymentCharge = total.multiply(wechatChargeRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
thirdPartyPaymentCharge = total.multiply(wechatChargeRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
break;
case "jd":
thirdPartyPaymentCharge = total.multiply(jdChargeRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
thirdPartyPaymentCharge = total.multiply(jdChargeRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
break;
case "alipayonline":
thirdPartyPaymentCharge = total.multiply(alipayonlineChargeRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
thirdPartyPaymentCharge = total.multiply(alipayonlineChargeRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
break;
default:
break;

@ -4,6 +4,7 @@ import au.com.royalpay.payment.tools.CommonConsts;
import com.alibaba.fastjson.JSONObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
/**
@ -34,7 +35,7 @@ public class ReferrerCommissionAnalysis {
}
BigDecimal total = dayAnalysis.getBigDecimal("total");
BigDecimal orgCharge = total.multiply(referrerRate).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal orgCharge = total.multiply(referrerRate).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP);
Date tradeDate = dayAnalysis.getDate("trade_date");
totalGrossAmount = totalGrossAmount.add(total);

@ -24,6 +24,7 @@ import com.github.miemiedev.mybatis.paginator.domain.PageList;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -113,15 +114,15 @@ public class XPlanFundConfigServiceImpl implements XPlanFundConfigService {
}
public static BigDecimal calculateInterest(BigDecimal interestRate, BigDecimal amount) {
return amount.multiply(interestRate.divide(CommonConsts.HUNDRED, 4, BigDecimal.ROUND_DOWN)).divide(BigDecimal.valueOf(365), 2, BigDecimal.ROUND_HALF_UP);
return amount.multiply(interestRate.divide(CommonConsts.HUNDRED, 4, BigDecimal.ROUND_DOWN)).divide(BigDecimal.valueOf(365), 2, RoundingMode.HALF_UP);
}
private JSONObject getClient(String clientMoniker) {
JSONObject client = clientManager.getClientInfoByMoniker(clientMoniker);
client.putAll(clientConfigService.find(client.getIntValue("client_id")));
if (client == null) {
throw new InvalidShortIdException();
}
client.putAll(clientConfigService.find(client.getIntValue("client_id")));
return client;
}

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.management.clearing.core;
import au.com.royalpay.payment.manage.support.abafile.ABAFile;
import au.com.royalpay.payment.manage.tradelog.beans.ClearingLogQuery;
import com.alibaba.fastjson.JSONObject;
import org.springframework.transaction.annotation.Transactional;
@ -42,9 +43,9 @@ public interface CleanService {
void settlementXlsx(Date date, HttpServletResponse response) throws IOException;
List<JSONObject> getXlsx(Date date) throws IOException;
List<JSONObject> getXlsx(Date dt, String bank) throws IOException;
List<JSONObject> getAba(Date dt) throws IOException;
List<ABAFile> getAba(Date dt, String bank) throws IOException;
void settlementAba(Date date, HttpServletResponse response) throws IOException;
@ -82,5 +83,11 @@ public interface CleanService {
JSONObject findLogSettleByDate(Date date);
JSONObject validTransactions(Date dt, boolean fix, boolean b, boolean b1);
JSONObject validTransactions(Date date, boolean fix, boolean b, boolean b1);
void distributeBank(Date date, int clearingId, JSONObject bankDistribution);
void lockClearingLog(Date date, int clearingId);
void undoSettle(Date date, int clearingId);
}

@ -4,11 +4,8 @@ import au.com.royalpay.payment.core.PaymentApi;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.core.tasksupport.SettlementSupport;
import au.com.royalpay.payment.manage.management.clearing.core.CleanService;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailAnalysisMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingLogMapper;
import au.com.royalpay.payment.manage.mappers.log.LogSettleMailMapper;
import au.com.royalpay.payment.manage.mappers.log.ValidationLogMapper;
import au.com.royalpay.payment.manage.mappers.log.*;
import au.com.royalpay.payment.manage.mappers.payment.TaskManualSettleMapper;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.system.CalendarMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientRateMapper;
@ -19,7 +16,9 @@ import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.notice.core.MailService;
import au.com.royalpay.payment.manage.signin.beans.TodoNotice;
import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider;
import au.com.royalpay.payment.manage.support.abafile.ABAConfig;
import au.com.royalpay.payment.manage.support.abafile.ABAFile;
import au.com.royalpay.payment.manage.support.abafile.ABATemplate;
import au.com.royalpay.payment.manage.tradelog.beans.ClearingLogQuery;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApi;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApiProvider;
@ -34,14 +33,12 @@ import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.tasksupport.TaskFinishNotifyEvent;
import au.com.royalpay.payment.tools.utils.PageListUtils;
import au.com.royalpay.payment.tools.utils.TimeZoneUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.Order;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
@ -50,12 +47,7 @@ import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.joda.time.Days;
@ -67,18 +59,15 @@ import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.format.number.CurrencyStyleFormatter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring4.SpringTemplateEngine;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
@ -90,9 +79,6 @@ import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import static au.com.royalpay.payment.manage.permission.utils.OrgCheckUtils.checkOrgPermission;
/**
@ -112,6 +98,8 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
@Resource
private ClearingDetailAnalysisMapper clearingDetailAnalysisMapper;
@Resource
private TaskManualSettleMapper taskManualSettleMapper;
@Resource
private ValidationLogMapper validationLogMapper;
@Resource
private ManagerMapper managerMapper;
@ -145,7 +133,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
@Value("${app.redis.settle.check-code.prefix}")
private String reidsCheckCodeKey;
private final String[] open_ids = { "o32MzuEeb5ZT_DJQYbzZf6VCu1HQ", "o32MzuIsa3OBOkvC9pL90h9pgHPg", "o32MzuCpqGQJTlvTK7VQ7m_LVXiQ" };
private final String[] open_ids = {"o32MzuEeb5ZT_DJQYbzZf6VCu1HQ", "o32MzuIsa3OBOkvC9pL90h9pgHPg", "o32MzuCpqGQJTlvTK7VQ7m_LVXiQ"};
private ApplicationEventPublisher publisher;
// private final String[] open_ids = { "o32MzuO4s8c7iFOVxnxejkbhMoEc" };
@ -226,8 +214,25 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
addBigDecimal(total, log, "wechat_charge");
addBigDecimal(total, log, "royalpay_charge");
addBigDecimal(total, log, "net_amount");
details.addAll(clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id")));
int clearingId = log.getIntValue("clearing_id");
List<JSONObject> logDetails = clearingDetailMapper.listReportsOfSettlement(clearingId);
details.addAll(logDetails);
List<String> banks = logDetails.stream().map(detail -> detail.getString("settle_bank")).distinct().collect(Collectors.toList());
List<JSONObject> bankStatistics = banks.stream().map(bank -> {
JSONObject data = new JSONObject();
data.put("bank", bank);
data.put("total_settle", logDetails.stream()
.filter(detail -> bank.equals(detail.getString("settle_bank")))
.map(detail -> detail.getBigDecimal("clearing_amount"))
.reduce(BigDecimal::add)
);
return data;
}).collect(Collectors.toList());
log.put("bank_statistics", bankStatistics);
log.put("editable", DateUtils.isSameDay(log.getDate("settle_date"), new Date()) && log.getBooleanValue("editable"));
log.put("channel_analysis", clearingDetailAnalysisMapper.analysisChannelReport(clearingId));
}
total.put("logs", logs);
total.put("details", details);
List<JSONObject> channels = clearingDetailAnalysisMapper.analysisChannelReportDaily(settleDate);
total.put("channel_analysis", channels);
@ -260,7 +265,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
}
@Override
public Map<String,JSONObject> getDayAndChannelOfAnalysisMap(int detailId,String channel,JSONObject manager) {
public Map<String, JSONObject> getDayAndChannelOfAnalysisMap(int detailId, String channel, JSONObject manager) {
JSONObject cleanLog = clearingDetailMapper.findByDetailId(detailId);
if (cleanLog == null) {
throw new NotFoundException();
@ -269,7 +274,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
Assert.notNull(client, "Client ID invalid");
checkOrgPermission(manager, client);
return getDayAnalysisMap(String.valueOf(detailId),channel,client);
return getDayAnalysisMap(String.valueOf(detailId), channel, client);
}
@Override
@ -340,7 +345,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String filename = "Merchant_Settlement_Info_" + dateString + RandomStringUtils.random(8, false, true) + ".xlsx";
zos.putNextEntry(new ZipEntry(filename));
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"));
byte[] xlsx = generateSettleXlsxFile(dt, details);
byte[] xlsx = generateSettleXlsxFile(dt, details, null);
IOUtils.write(xlsx, zos);
}
zos.flush();
@ -348,7 +353,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
}
@Override
public List<JSONObject> getXlsx(Date dt) throws IOException {
public List<JSONObject> getXlsx(Date dt, String bank) throws IOException {
List<JSONObject> logs = clearingLogMapper.findByDate(dt);
if (logs.isEmpty()) {
throw new NotFoundException();
@ -360,7 +365,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String filename = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + "_" + fileIndex + ".xlsx";
JSONObject file = new JSONObject();
file.put("name", filename);
file.put("byteArr", generateSettleXlsxFile(dt, clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"))));
file.put("byteArr", generateSettleXlsxFile(dt, clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id")), bank));
result.add(file);
fileIndex++;
}
@ -369,7 +374,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String filename = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + ".xlsx";
JSONObject file = new JSONObject();
file.put("name", filename);
file.put("byteArr", generateSettleXlsxFile(dt, clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"))));
file.put("byteArr", generateSettleXlsxFile(dt, clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id")), bank));
result.add(file);
}
}
@ -378,37 +383,20 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
}
@Override
public List<JSONObject> getAba(Date dt) throws IOException {
public List<ABAFile> getAba(Date dt, String bank) {
List<JSONObject> logs = clearingLogMapper.findByDate(dt);
if (logs.isEmpty()) {
throw new NotFoundException();
}
List<JSONObject> result = new ArrayList<>();
int index = 1;
if (logs.size() > 1) {
// todo email edit
for (JSONObject log : logs) {
JSONObject file = new JSONObject();
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"));
String filename = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + "_" + index + ".aba";
file.put("name", filename);
file.put("byteArr", generateSettleAbaFile(dt, details, index++));
result.add(file);
}
} else {
for (JSONObject log : logs) {
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"));
String filename = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + ".aba";
JSONObject file = new JSONObject();
file.put("name", filename);
file.put("byteArr", generateSettleAbaFile(dt, details, index++));
result.add(file);
}
List<ABAFile> files = new ArrayList<>();
for (JSONObject log : logs) {
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"));
files.addAll(generateSettleAbaFiles(dt, details, log.getDate("operate_time")));
}
return result;
return files.stream().filter(file -> bank.equals(file.bank())).collect(Collectors.toList());
}
private byte[] generateSettleXlsxFile(Date dt, List<JSONObject> settlements) throws IOException {
private byte[] generateSettleXlsxFile(Date dt, List<JSONObject> settlements, String bank) throws IOException {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMM"));
int rowNum = 0;
@ -416,6 +404,9 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
if (settle.getBigDecimal("clearing_amount").compareTo(BigDecimal.ZERO) == 0) {
continue;
}
if (bank != null && !Objects.equals(settle.getString("settle_bank"), bank)) {
continue;
}
Row row = sheet.createRow(rowNum++);
row.createCell(0, Cell.CELL_TYPE_STRING).setCellValue(settle.getString("bsb_no"));
row.createCell(1, Cell.CELL_TYPE_STRING).setCellValue(settle.getString("account_no"));
@ -434,34 +425,56 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
if (logs.isEmpty()) {
throw new NotFoundException();
}
String zipName = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + RandomStringUtils.random(8, false, true) + "_aba.zip";
resp.setContentType("application/octet-stream;");
resp.addHeader("Content-Disposition", "attachment; filename=" + zipName);
OutputStream ous = resp.getOutputStream();
ZipOutputStream zos = new ZipOutputStream(ous);
int index = 1;
List<ABAFile> files = new ArrayList<>();
for (JSONObject log : logs) {
String dateString = DateFormatUtils.format(log.getDate("operate_time"), "yyyyMMddHHmmss");
String filename = "Merchant_Settlement_Info_" + dateString + RandomStringUtils.random(8, false, true) + ".aba";
zos.putNextEntry(new ZipEntry(filename));
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(log.getIntValue("clearing_id"));
byte[] file = generateSettleAbaFile(dt, details, index++);
IOUtils.write(file, zos);
files.addAll(generateSettleAbaFiles(dt, details, log.getDate("operate_time")));
}
zos.flush();
IOUtils.closeQuietly(zos);
OutputStream ous = resp.getOutputStream();
if (files.size() == 1) {
ABAFile file = files.get(0);
resp.setContentType("application/octet-stream;");
resp.addHeader("Content-Disposition", "attachment; filename=" + file.filename());
ous.write(file.output(1));
ous.flush();
IOUtils.closeQuietly(ous);
} else {
String zipName = "Merchant_Settlement_Info_" + DateFormatUtils.format(dt, "yyyyMMdd") + RandomStringUtils.random(8, false, true) + "_aba.zip";
resp.setContentType("application/octet-stream;");
resp.addHeader("Content-Disposition", "attachment; filename=" + zipName);
ZipOutputStream zos = new ZipOutputStream(ous);
Map<String, Integer> bankCounts = new HashMap<>();
for (ABAFile file : files) {
String filename = file.filename();
zos.putNextEntry(new ZipEntry(filename));
int serializeNo = bankCounts.get(file.bank()) == null ? 1 : bankCounts.get(file.bank()) + 1;
bankCounts.put(file.bank(), serializeNo);
IOUtils.write(file.output(serializeNo), zos);
}
zos.flush();
IOUtils.closeQuietly(zos);
}
}
private List<ABAFile> generateSettleAbaFiles(Date dt, List<JSONObject> settlements, Date operateTime) {
List<String> banks = settlements.stream().map(detail -> detail.getString("settle_bank")).distinct().collect(Collectors.toList());
return banks.stream().map(bank -> generateSettleAbaFile(bank, dt, settlements)).peek(file -> file.setOperateTime(operateTime)).collect(Collectors.toList());
}
private byte[] generateSettleAbaFile(Date dt, List<JSONObject> settlements, int index) {
ABAFile aba = new ABAFile(dt, index);
private ABAFile generateSettleAbaFile(String bank, Date dt, List<JSONObject> settlements) {
ABAFile aba = ABATemplate.getConfig().initFile(bank, dt);
for (JSONObject settle : settlements) {
if (!bank.equals(settle.getString("settle_bank"))) {
continue;
}
if (settle.getBigDecimal("clearing_amount").compareTo(BigDecimal.ZERO) == 0) {
continue;
}
aba.addSettleMerchant(settle.getString("bsb_no"), settle.getString("account_no"), settle.getString("account_name"),
settle.getBigDecimal("clearing_amount"));
}
return aba.output();
return aba;
}
private byte[] generateSettleCSVFile(Date settleDate, List<JSONObject> details) throws IOException {
@ -474,12 +487,12 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
if (detail.getDoubleValue("clearing_amount") == 0) {
continue;
}
String grossAmount = detail.getBigDecimal("gross_amount").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + " @ "
+ detail.getBigDecimal("rate").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%";
String totalCharge = detail.getBigDecimal("total_charge").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
String clearingAmount = detail.getBigDecimal("clearing_amount").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
String[] values = { detail.getString("client_moniker"), "AUD", grossAmount, totalCharge, clearingAmount, detail.getString("bsb_no"),
detail.getString("account_no"), detail.getString("account_name"), settlementDate };
String grossAmount = detail.getBigDecimal("gross_amount").setScale(2, RoundingMode.HALF_UP).toPlainString() + " @ "
+ detail.getBigDecimal("rate").setScale(2, RoundingMode.HALF_UP).toPlainString() + "%";
String totalCharge = detail.getBigDecimal("total_charge").setScale(2, RoundingMode.HALF_UP).toPlainString();
String clearingAmount = detail.getBigDecimal("clearing_amount").setScale(2, RoundingMode.HALF_UP).toPlainString();
String[] values = {detail.getString("client_moniker"), "AUD", grossAmount, totalCharge, clearingAmount, detail.getString("bsb_no"),
detail.getString("account_no"), detail.getString("account_name"), settlementDate};
csv.printRecord((Object[]) values);
}
csv.flush();
@ -497,12 +510,12 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String transactionTime = DateFormatUtils.format(transaction.getDate("transaction_time"), "dd/MM/yyyy h:mm:ss a", Locale.ENGLISH);
int multiply = "Credit".equals(transaction.getString("transaction_type")) ? 1 : -1;
BigDecimal transactionAmount = transaction.getBigDecimal("transaction_amount").multiply(BigDecimal.valueOf(multiply)).setScale(2,
BigDecimal.ROUND_HALF_DOWN);
RoundingMode.HALF_DOWN);
BigDecimal clearingAmount = transaction.getBigDecimal("clearing_amount").multiply(BigDecimal.valueOf(multiply)).setScale(2,
BigDecimal.ROUND_HALF_DOWN);
String[] values = { transaction.getString("system_transaction_id"), transaction.getString("order_id"), transaction.getString("client_id"),
RoundingMode.HALF_DOWN);
String[] values = {transaction.getString("system_transaction_id"), transaction.getString("order_id"), transaction.getString("client_id"),
transaction.getString("device_id"), transaction.getString("transaction_currency"), transactionAmount.toPlainString(),
transaction.getString("clearing_currency"), clearingAmount.toPlainString(), transaction.getString("channel"), transactionTime, "0" };
transaction.getString("clearing_currency"), clearingAmount.toPlainString(), transaction.getString("channel"), transactionTime, "0"};
csv.printRecord((Object[]) values);
}
csv.flush();
@ -650,7 +663,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String timezone_client = client.getString("timezone");
if (timezone_client != null) {
transactions.parallelStream().forEach(p -> {
TimeZoneUtils.switchTimeZone(p, timezone_client, "transaction_time");
TimeZoneUtils.switchTimeZone(p, timezone_client, "transaction_time");
});
}
clearClient.put("report", transactions);
@ -665,7 +678,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
}
@Override
public Map<String,JSONObject> channelAndDayOfAnalysis(int client_id, String clearingDetailId,String channel,JSONObject partner) {
public Map<String, JSONObject> channelAndDayOfAnalysis(int client_id, String clearingDetailId, String channel, JSONObject partner) {
JSONObject client = clientManager.getClientInfo(client_id);
Assert.notNull(client, "Client not exists");
int parent_client_id = client.getIntValue("parent_client_id");
@ -673,15 +686,15 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
if (client_id != partner.getIntValue("client_id") && parent_client_id != partner.getIntValue("client_id")) {
throw new ForbiddenException("No Permission");
}
return getDayAnalysisMap(clearingDetailId,channel,client);
return getDayAnalysisMap(clearingDetailId, channel, client);
}
private Map<String,JSONObject> getDayAnalysisMap(String clearingDetailId,String channel,JSONObject client){
private Map<String, JSONObject> getDayAnalysisMap(String clearingDetailId, String channel, JSONObject client) {
List<JSONObject> transactions = transactionMapper.listTransactionsOfClearingOrder(Integer.parseInt(clearingDetailId),
new PageBounds(Order.formString("order_id.asc")));
String timezone_client = client.getString("timezone");
if(!channel.equals("null")){
transactions = transactions.stream().filter(t->t.getString("channel").equals(channel)).collect(Collectors.toList());
if (!channel.equals("null")) {
transactions = transactions.stream().filter(t -> t.getString("channel").equals(channel)).collect(Collectors.toList());
}
List<String> dateKeysList = new ArrayList<>();
dateKeysList.add("transaction_time");
@ -689,35 +702,36 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
transactions.parallelStream().forEach(p -> {
TimeZoneUtils.switchTimeZone(p, timezone_client, "transaction_time");
});
TimeZoneUtils.switchTimeZoneToString(transactions,timezone_client,TimeZoneUtils.PATTERN_DATE,dateKeysList);
TimeZoneUtils.switchTimeZoneToString(transactions, timezone_client, TimeZoneUtils.PATTERN_DATE, dateKeysList);
}
Map<String,List<JSONObject>> dayTransactionsMap = transactions.stream().collect(Collectors.groupingBy(x -> x.getString("transaction_time").substring(0,10)));
Map<String,JSONObject> dayAnalysisMap = new TreeMap<>();
for (Map.Entry<String, List<JSONObject>> entry : dayTransactionsMap.entrySet()){
Map<String, List<JSONObject>> dayTransactionsMap = transactions.stream().collect(Collectors.groupingBy(x -> x.getString("transaction_time").substring(0, 10)));
Map<String, JSONObject> dayAnalysisMap = new TreeMap<>();
for (Map.Entry<String, List<JSONObject>> entry : dayTransactionsMap.entrySet()) {
JSONObject analysis = new JSONObject();
List<JSONObject> transactionsOfDay = entry.getValue();
BigDecimal total_credit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Credit")).filter(t->t.containsKey("clearing_amount")).map(t-> t.getBigDecimal("clearing_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_debit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Debit")).filter(t->t.containsKey("clearing_amount")).map(t-> t.getBigDecimal("clearing_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_charge_credit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Credit")).filter(t->t.containsKey("total_surcharge")).map(t-> t.getBigDecimal("total_surcharge")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_charge_debit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Debit")).filter(t->t.containsKey("total_surcharge")).map(t-> t.getBigDecimal("total_surcharge")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal net_amount_credit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Credit")).filter(t->t.containsKey("settle_amount")).map(t-> t.getBigDecimal("settle_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal net_amount_debit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Debit")).filter(t->t.containsKey("settle_amount")).map(t-> t.getBigDecimal("settle_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax_amount_credit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Credit")).filter(t->t.containsKey("tax_amount")).map(t-> t.getBigDecimal("tax_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax_amount_debit = transactionsOfDay.stream().filter(t->t.getString("transaction_type").equals("Debit")).filter(t->t.containsKey("tax_amount")).map(t-> t.getBigDecimal("tax_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_credit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Credit")).filter(t -> t.containsKey("clearing_amount")).map(t -> t.getBigDecimal("clearing_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_debit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Debit")).filter(t -> t.containsKey("clearing_amount")).map(t -> t.getBigDecimal("clearing_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_charge_credit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Credit")).filter(t -> t.containsKey("total_surcharge")).map(t -> t.getBigDecimal("total_surcharge")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total_charge_debit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Debit")).filter(t -> t.containsKey("total_surcharge")).map(t -> t.getBigDecimal("total_surcharge")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal net_amount_credit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Credit")).filter(t -> t.containsKey("settle_amount")).map(t -> t.getBigDecimal("settle_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal net_amount_debit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Debit")).filter(t -> t.containsKey("settle_amount")).map(t -> t.getBigDecimal("settle_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax_amount_credit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Credit")).filter(t -> t.containsKey("tax_amount")).map(t -> t.getBigDecimal("tax_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax_amount_debit = transactionsOfDay.stream().filter(t -> t.getString("transaction_type").equals("Debit")).filter(t -> t.containsKey("tax_amount")).map(t -> t.getBigDecimal("tax_amount")).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax_amount = tax_amount_credit.subtract(tax_amount_debit);
analysis.put("total_credit",total_credit.setScale(2,BigDecimal.ROUND_HALF_UP));
analysis.put("total_debit",total_debit.setScale(2,BigDecimal.ROUND_HALF_UP));
analysis.put("net_amount",net_amount_credit.subtract(net_amount_debit).setScale(2,BigDecimal.ROUND_HALF_UP));
analysis.put("tax_amount",tax_amount.setScale(2,BigDecimal.ROUND_HALF_UP));
analysis.put("total_charge",total_charge_credit.subtract(total_charge_debit).add(tax_amount).setScale(2,BigDecimal.ROUND_HALF_UP));
analysis.put("gross_amount",total_credit.subtract(total_debit).setScale(2,BigDecimal.ROUND_HALF_UP));
dayAnalysisMap.put(entry.getKey(),analysis);
analysis.put("total_credit", total_credit.setScale(2, RoundingMode.HALF_UP));
analysis.put("total_debit", total_debit.setScale(2, RoundingMode.HALF_UP));
analysis.put("net_amount", net_amount_credit.subtract(net_amount_debit).setScale(2, RoundingMode.HALF_UP));
analysis.put("tax_amount", tax_amount.setScale(2, RoundingMode.HALF_UP));
analysis.put("total_charge", total_charge_credit.subtract(total_charge_debit).add(tax_amount).setScale(2, RoundingMode.HALF_UP));
analysis.put("gross_amount", total_credit.subtract(total_debit).setScale(2, RoundingMode.HALF_UP));
dayAnalysisMap.put(entry.getKey(), analysis);
}
return dayAnalysisMap;
}
@Override
public void exportListClearingTransactions(int client_id, String clearingDetailId, JSONObject partner, HttpServletResponse resp) {
OutputStream ous = null;
@ -738,9 +752,9 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
Sheet sheet = wb.createSheet("Merchant_Settlement_Info_" + DateFormatUtils.format(reportDate, "yyyyMMdd"));
int rowNum = 0;
Row row = sheet.createRow(rowNum);
String[] title = { "order Id", "Client Order Id", "Transaction Time", "Channel", "Gateway", "Exchange Rate", "Transaction Type", "Currency",
"Input Amount", "Total Amount", "Clearing Amount", "Sruchange Rate", "Settle Amount", "Remark" };
String[] analysis = { "Total Credit", "Total Debit", "Gross Amount", "Total Charge", "Net Amount" };
String[] title = {"order Id", "Client Order Id", "Transaction Time", "Channel", "Gateway", "Exchange Rate", "Transaction Type", "Currency",
"Input Amount", "Total Amount", "Clearing Amount", "Sruchange Rate", "Settle Amount", "Remark"};
String[] analysis = {"Total Credit", "Total Debit", "Gross Amount", "Total Charge", "Net Amount"};
for (int i = 0; i < title.length; i++) {
row.createCell(i, Cell.CELL_TYPE_STRING).setCellValue(title[i]);
}
@ -755,7 +769,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
row.createCell(0, Cell.CELL_TYPE_STRING).setCellValue(settle.getString("order_id"));
row.createCell(1, Cell.CELL_TYPE_STRING).setCellValue(settle.getString("client_order_id"));
Calendar calendar = (Calendar) settle.get("transaction_time");
row.createCell(2, Cell.CELL_TYPE_STRING).setCellValue(DateFormatUtils.format(calendar, "yyyy-MM-dd HH:mm:ss",calendar.getTimeZone()));
row.createCell(2, Cell.CELL_TYPE_STRING).setCellValue(DateFormatUtils.format(calendar, "yyyy-MM-dd HH:mm:ss", calendar.getTimeZone()));
row.createCell(3, Cell.CELL_TYPE_STRING).setCellValue(settle.getString("channel"));
if (settle.getInteger("gateway") != null) {
row.createCell(4, Cell.CELL_TYPE_STRING).setCellValue(TradeType.fromGatewayNumber(settle.getIntValue("gateway")).getTradeType());
@ -925,7 +939,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
String fileName1 = "Merchant_Settlement_Info_xlsx_" + DateFormatUtils.format(date, "yyyyMMdd");
List<JSONObject> attachList = new ArrayList<>();
JSONObject attach1 = new JSONObject();
List<JSONObject> xlsxFileList = getXlsx(date);
List<JSONObject> xlsxFileList = getXlsx(date, "CBA");
if (xlsxFileList.size() > 1) {
fileName1 += ".zip";
attach1.put("content", Base64.encodeBase64String(getZipByteArr(xlsxFileList)));
@ -937,15 +951,23 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
attachList.add(attach1);
JSONObject attach2 = new JSONObject();
List<JSONObject> abaFileList = getAba(date);
List<ABAFile> abaFileList = getAba(date, "CBA");
String fileName2 = "Merchant_Settlement_Info_aba_" + DateFormatUtils.format(date, "yyyyMMdd");
if (abaFileList.size() > 1) {
fileName2 += ".zip";
attach2.put("content", Base64.encodeBase64String(getZipByteArr(abaFileList)));
List<JSONObject> entities = new ArrayList<>();
int index = 0;
for (ABAFile file : abaFileList) {
JSONObject entity = new JSONObject();
entity.put("name", file.filename());
entity.put("byteArr", file.output(index++));
entities.add(entity);
}
attach2.put("content", Base64.encodeBase64String(getZipByteArr(entities)));
} else {
fileName2 += ".aba";
attach2.put("content", Base64.encodeBase64String((byte[]) abaFileList.get(0).get("byteArr")));
attach2.put("content", Base64.encodeBase64String(abaFileList.get(0).output(1)));
}
attach2.put("name", fileName2);
attachList.add(attach2);
@ -987,6 +1009,7 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
}
}
sendTaskFinishMessages(ManagerRole.FINANCIAL_STAFF, "清算文件已发送清算方", "发送清算通知");
clearingLogMapper.lockSettlements(date);
} catch (IOException e) {
logger.error("生成excel字节数组发生错误");
} catch (URISyntaxException e) {
@ -1059,6 +1082,81 @@ public class CleanServiceImpl implements CleanService, ManagerTodoNoticeProvider
return report;
}
@Override
@Transactional
public void distributeBank(Date date, int clearingId, JSONObject bankDistribution) {
if (!DateUtils.isSameDay(date, new Date())) {
throw new ForbiddenException("Only today's settlement file can be modified");
}
JSONObject log = clearingLogMapper.findById(clearingId);
if (log == null || !DateUtils.isSameDay(log.getDate("settle_date"), date)) {
throw new NotFoundException("Settlement log not found");
}
if (!log.getBooleanValue("editable")) {
throw new ForbiddenException("Settlement log has been sent and unable to edit");
}
ABAConfig config = ABATemplate.getConfig();
String defaultBank = config.getRemainsTo();
clearingDetailMapper.updateAllBanks(defaultBank, clearingId);
List<JSONObject> details = clearingDetailMapper.listReportsOfSettlement(clearingId);
details.sort((log1, log2) -> log2.getBigDecimal("clearing_amount").compareTo(log1.getBigDecimal("clearing_amount")));
bankDistribution.remove(defaultBank);
for (String bank : bankDistribution.keySet()) {
List<String> detailIds = new ArrayList<>();
ABAConfig.ABABase base = config.getBankBase(bank);
if (base == null) {
throw new BadRequestException("Invalid bank code:" + bank);
}
BigDecimal bankAmount = bankDistribution.getBigDecimal(bank);
for (JSONObject detail : details) {
String detailBank = detail.getString("settle_bank");
if (defaultBank.equals(detailBank)) {
BigDecimal amount = detail.getBigDecimal("clearing_amount");
if (amount.compareTo(BigDecimal.ZERO) > 0 && bankAmount.compareTo(amount) > 0) {
detailIds.add(detail.getString("clear_detail_id"));
bankAmount = bankAmount.subtract(amount);
detail.put("settle_bank", bank);
}
}
}
clearingDetailMapper.updateBanks(bank, detailIds);
}
}
@Override
public void lockClearingLog(Date date, int clearingId) {
if (!DateUtils.isSameDay(date, new Date())) {
throw new ForbiddenException("Only today's settlement file can be modified");
}
JSONObject log = clearingLogMapper.findById(clearingId);
if (log == null || !DateUtils.isSameDay(log.getDate("settle_date"), date)) {
throw new NotFoundException("Settlement log not found");
}
clearingLogMapper.setLogEditable(false, clearingId);
}
@Override
@Transactional
public void undoSettle(Date date, int clearingId) {
if (!DateUtils.isSameDay(date, new Date())) {
throw new ForbiddenException("Only today's settlement file can be modified");
}
JSONObject log = clearingLogMapper.findById(clearingId);
if (log == null || !DateUtils.isSameDay(log.getDate("settle_date"), date)) {
throw new NotFoundException("Settlement log not found");
}
if (!log.getBooleanValue("editable")) {
throw new ForbiddenException("Settlement log has been sent and unable to edit");
}
transactionMapper.deleteSettlementTransaction(clearingId);
transactionMapper.removeSettleRemark(clearingId);
clearingDetailAnalysisMapper.clearAnalysis(clearingId);
taskManualSettleMapper.rollbackExecutedTask(clearingId);
clearingDetailMapper.deleteSettleLogs(clearingId);
clearingLogMapper.deleteSettleLogs(clearingId);
}
private byte[] getZipByteArr(List<JSONObject> fileByteArrWithName) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(bos);

@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -258,7 +259,7 @@ public class SettleDelayConfigurerImpl implements SettleDelayConfigurer {
}
totalSurcharge = totalSurcharge.add(surcharge);
}
BigDecimal cashbackAmount = CurrencyAmountUtils.scale(totalSurcharge.multiply(attend.getBigDecimal("surcharge_discount")).divide(CommonConsts.HUNDRED, 2, BigDecimal.ROUND_HALF_UP), PlatformEnvironment.getEnv().getForeignCurrency());
BigDecimal cashbackAmount = CurrencyAmountUtils.scale(totalSurcharge.multiply(attend.getBigDecimal("surcharge_discount")).divide(CommonConsts.HUNDRED, 2, RoundingMode.HALF_UP), PlatformEnvironment.getEnv().getForeignCurrency());
String remark = "Surcharge cashback for " + saturday.toString("dd/MMM/yyyy", Locale.ENGLISH) + " ~ " + sunday.toString("dd/MMM/yyyy", Locale.ENGLISH);
if (cashbackAmount.compareTo(BigDecimal.ZERO) > 0) {
cashbackService.saveSurchargeDiscountCashback(clientId, clientMoniker, transactionOrderId, cashbackAmount, date, remark);

@ -2,6 +2,8 @@ package au.com.royalpay.payment.manage.management.clearing.web;
import au.com.royalpay.payment.manage.management.clearing.core.CleanService;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.permission.manager.RequireManager;
import au.com.royalpay.payment.manage.support.abafile.ABATemplate;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
@ -49,6 +51,46 @@ public class SettlementDevController {
}
}
@GetMapping("/available_banks")
public JSONObject getAvailableBanks() {
List<String> banks = ABATemplate.getConfig().availableBanks();
JSONObject res = new JSONObject();
res.put("remains_to", ABATemplate.getConfig().getRemainsTo());
res.put("banks", banks);
return res;
}
@PutMapping("/reports/{date}/clearings/{clearingId}/bank_distribution")
public void modifyClearingBank(@PathVariable String date, @PathVariable int clearingId, @RequestBody JSONObject bankDistribution) {
try {
Date dt = dateFormat.parse(date);
cleanService.distributeBank(dt, clearingId, bankDistribution);
} catch (ParseException e) {
throw new BadRequestException("error.payment.valid.invalid_date_format");
}
}
@PutMapping("/reports/{date}/clearings/{clearingId}/lock")
public void lockClearingLog(@PathVariable String date, @PathVariable int clearingId) {
try {
Date dt = dateFormat.parse(date);
cleanService.lockClearingLog(dt, clearingId);
} catch (ParseException e) {
throw new BadRequestException("error.payment.valid.invalid_date_format");
}
}
@DeleteMapping("/reports/{date}/clearings/{clearingId}")
@RequireManager(role = ManagerRole.DEVELOPER)
public void undoSettle(@PathVariable String date, @PathVariable int clearingId) {
try {
Date dt = dateFormat.parse(date);
cleanService.undoSettle(dt, clearingId);
} catch (ParseException e) {
throw new BadRequestException("error.payment.valid.invalid_date_format");
}
}
@RequestMapping("/reports/{date}/settlement_csv")
public void getSettlementCsv(@PathVariable String date, HttpServletResponse resp) throws IOException {
try {
@ -79,23 +121,23 @@ public class SettlementDevController {
}
}
@ManagerMapping(value = "/reports/{date}/send_settlement_xlsx/{checkCode}",role = {ManagerRole.FINANCIAL_STAFF})
@ManagerMapping(value = "/reports/{date}/send_settlement_xlsx/{checkCode}", role = {ManagerRole.FINANCIAL_STAFF})
public JSONObject sendSettlementMail(@PathVariable("date") String date, @PathVariable("checkCode") String checkCode) {
Date dt = null;
try {
dt = dateFormat.parse(date);
} catch (ParseException e) {
}
return cleanService.sendSettlementMail(dt,checkCode);
return cleanService.sendSettlementMail(dt, checkCode);
}
@ManagerMapping(value = "/reports/send_checkcode",role = {ManagerRole.FINANCIAL_STAFF})
public void sendCheckCode(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager){
cleanService.sendCheckCode(new Date(),manager);
@ManagerMapping(value = "/reports/send_checkcode", role = {ManagerRole.FINANCIAL_STAFF})
public void sendCheckCode(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
cleanService.sendCheckCode(new Date(), manager);
}
@RequestMapping(value = "/reports/{date}/send_status")
public JSONObject sendStatus(@PathVariable String date){
public JSONObject sendStatus(@PathVariable String date) {
Date dt = null;
try {
dt = dateFormat.parse(date);

@ -26,4 +26,6 @@ public interface ClearingDetailAnalysisMapper {
List<JSONObject> listReportChannels(@Param("clearing_detail_id") String clearDetailId);
BigDecimal getSysCleaingAmount(@Param("settle_date") String settle_date, @Param("channel") String channel);
void clearAnalysis(@Param("clearing_id") int clearingId);
}

@ -40,4 +40,12 @@ public interface ClearingDetailMapper {
JSONObject listReportByDate(@Param("report_date") Date date, @Param("client_id") int clientId);
PageList<JSONObject> listClientSettlementLog(JSONObject params, PageBounds pagination);
void updateAllBanks(@Param("settle_bank") String bank, @Param("clearing_id") int clearingId);
@AutoSql(type = SqlType.UPDATE)
void updateBanks(@Param("settle_bank") String bank,@Param("clear_detail_id") List<String> clearingDetailIds);
@AutoSql(type = SqlType.DELETE)
void deleteSettleLogs(@Param("clearing_id") int clearingId);
}

@ -31,11 +31,22 @@ public interface ClearingLogMapper {
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject update);
List<JSONObject> getSettlementChannelsMonthReport(@Param("year") int year, @Param("month") int month);
List<JSONObject> getSettlementChannelsMonthReport(@Param("year") int year, @Param("month") int month);
List<JSONObject> getMondayClearing(@Param("begin") Date begin, @Param("end") Date end);
List<JSONObject> getSettlementChannelsDailyReport(@Param("date") Date date);
JSONObject getSettleDataDailyReport(@Param("date") Date date);
void lockSettlements(@Param("date") Date date);
@AutoSql(type = SqlType.SELECT)
JSONObject findById(@Param("clearing_id") int clearingId);
@AutoSql(type = SqlType.UPDATE)
void setLogEditable(@Param("editable") boolean editable, @Param("clearing_id") int clearingId);
@AutoSql(type = SqlType.DELETE)
void deleteSettleLogs(@Param("clearing_id") int clearingId);
}

@ -31,4 +31,6 @@ public interface TaskManualSettleMapper {
List<JSONObject> getEveryLatestRecord();
void rollbackExecutedTask(@Param("clearing_id") int clearingId);
}

@ -133,4 +133,7 @@ public interface TransactionMapper {
List<JSONObject> listClientUnsettleDataByDate(@Param("client_id") int clientId, @Param("max_settle_to") Date maxSettleTo);
void deleteSettlementTransaction(@Param("clearing_id") int clearingId);
void removeSettleRemark(@Param("clearing_id") int clearingId);
}

@ -14,9 +14,7 @@ import au.com.royalpay.payment.manage.appclient.beans.AppClientBean;
import au.com.royalpay.payment.manage.application.core.SimpleClientApplyService;
import au.com.royalpay.payment.manage.device.core.DeviceManager;
import au.com.royalpay.payment.manage.mappers.financial.FinancialBDConfigMapper;
import au.com.royalpay.payment.manage.mappers.log.ClientsOperationLogMapper;
import au.com.royalpay.payment.manage.mappers.log.LogClientSubMerchantIdMapper;
import au.com.royalpay.payment.manage.mappers.log.LogSettleMailMapper;
import au.com.royalpay.payment.manage.mappers.log.*;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.redpack.ActClientInvitationCodeMapper;
import au.com.royalpay.payment.manage.mappers.system.*;
@ -129,6 +127,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
@ -259,6 +258,11 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
private MailGunService mailGunService;
@Resource
private MailSendMapper mailSendMapper;
@Resource
private ClearingDetailMapper clearingDetailMapper;
@Resource
private ClearingLogMapper clearingLogMapper;
private static final String SOURCE_AGREE_FILE = "source_agree_file";
private static final String CLIENT_BANK_FILE = "client_bank_file";
@ -2185,7 +2189,6 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}
@Override
@Transactional
public void getNewAggregateAgreeFile(String clientMoniker, JSONObject manager, boolean renewal) throws Exception {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
@ -2647,17 +2650,18 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
params.put("client_id", client_id);
PageList<JSONObject> logs = transactionMapper.listSettlementLog(params,
new PageBounds(query.getPage(), query.getLimit(), Order.formString("clearing_time.desc")));
JSONObject result = PageListUtils.buildPageListResult(logs);
if (query.getPage() == 1) {
if (!logs.isEmpty() && logs.size() > 0) {
JSONObject sendMailLog = logSettleMailMapper.findByDate(logs.get(0).getDate("clearing_time"));
if (sendMailLog == null) {
logs.remove(0);
}else if (sendMailLog != null && sendMailLog.getIntValue("mail_status") != 1) {
logs.remove(0);
JSONObject clearingDetail = clearingDetailMapper.findByDetailId(logs.get(0).getIntValue("clearing_order"));
if (clearingDetail!=null){
JSONObject clearingLog = clearingLogMapper.findById(clearingDetail.getIntValue("clearing_id"));
if(clearingLog.getBooleanValue("editable")){
result.put("padding", true);
}
}
}
}
JSONObject result = PageListUtils.buildPageListResult(logs);
return result;
}
@ -3040,7 +3044,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
if (appClientBean.getCustomerSurchargeRate() <= 0) {
throw new ForbiddenException("customerSurchargeRate is 0");
}
BigDecimal customerSurchargeRate = new BigDecimal(appClientBean.getCustomerSurchargeRate()).setScale(2, BigDecimal.ROUND_HALF_DOWN);
BigDecimal customerSurchargeRate = new BigDecimal(appClientBean.getCustomerSurchargeRate()).setScale(2, RoundingMode.HALF_DOWN);
setCustomerSurchargeRate(account, client.getString("client_moniker"), customerSurchargeRate);
}
clientInfoCacheSupport.clearClientCache(client_id);

@ -34,6 +34,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -119,7 +120,7 @@ public class ActRedPackServiceImpl implements ActRedPackService {
if ("CNY".equals(currency)) {
JSONObject income = transactionService.findIncomeByOrderId(orderId);
BigDecimal exchange = income.getBigDecimal("exchange_rate");
currencyAmount = exchange.multiply(currencyAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
currencyAmount = exchange.multiply(currencyAmount).setScale(2, RoundingMode.HALF_UP);
}
if (ruleOrderTotal != null) {
if (!(currencyAmount.compareTo(ruleOrderTotal) >= 0)) {

@ -0,0 +1,127 @@
package au.com.royalpay.payment.manage.support.abafile;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.*;
/**
* Create by yixian at 2018-06-25 17:39
*/
@ConfigurationProperties("settle.abafile")
public class ABAConfig {
private Map<String, ABABase> bank = new HashMap<>();
private String defaultBank;
private String remainsTo;
public ABAFile initFile(String bank, Date settleDate) {
ABABase base = this.bank.get(bank);
if (base == null) {
throw new BadRequestException("Invalid bank:" + bank);
}
return base.initFile(settleDate);
}
public String getDefaultBank() {
return defaultBank;
}
public ABAConfig setDefaultBank(String defaultBank) {
this.defaultBank = defaultBank;
return this;
}
public Map<String, ABABase> getBank() {
return bank;
}
public ABABase getBankBase(String bank) {
return this.bank.get(bank);
}
public ABAConfig setBank(Map<String, ABABase> bank) {
this.bank = bank;
return this;
}
public String getRemainsTo() {
return remainsTo;
}
public ABAConfig setRemainsTo(String remainsTo) {
this.remainsTo = remainsTo;
return this;
}
public List<String> availableBanks() {
return new ArrayList<>(bank.keySet());
}
public static class ABABase {
private boolean manualSending = false;
private String bank;
private String apca;
private String bsb;
private String accountNo;
private String accountName;
public ABAFile initFile(Date settleDate) {
return new ABAFile(this, settleDate);
}
public boolean isManualSending() {
return manualSending;
}
public ABABase setManualSending(boolean manualSending) {
this.manualSending = manualSending;
return this;
}
public String getBank() {
return bank;
}
public ABABase setBank(String bank) {
this.bank = bank;
return this;
}
public String getApca() {
return apca;
}
public ABABase setApca(String apca) {
this.apca = apca;
return this;
}
public String getBsb() {
return bsb;
}
public ABABase setBsb(String bsb) {
this.bsb = bsb;
return this;
}
public String getAccountNo() {
return accountNo;
}
public ABABase setAccountNo(String accountNo) {
this.accountNo = accountNo;
return this;
}
public String getAccountName() {
return accountName;
}
public ABABase setAccountName(String accountName) {
this.accountName = accountName;
return this;
}
}
}

@ -15,21 +15,17 @@ import java.util.List;
public class ABAFile {
private final String baseLine = StringUtils.repeat(" ", 120);
private int sequenceNo = 1;
private String bank = "CBA";
private String company = "Tunnel Show Pty Ltd";
private String selfBSB = "063109";
private String selfAccountNo = "11655861";
private String apca = "301500";
private final ABAConfig.ABABase base;
private final Date settleDate;
private List<SettleMerchantInfo> settlements;
private BigDecimal totalSettleAmount;
private Date operateTime;
public ABAFile(Date settleDate, int index) {
public ABAFile(ABAConfig.ABABase base, Date settleDate) {
this.base = base;
this.settleDate = settleDate;
settlements = new ArrayList<>();
totalSettleAmount = BigDecimal.ZERO;
sequenceNo = index;
}
public void addSettleMerchant(String bsbNo, String accountNo, String accountName, BigDecimal settleAmount) {
@ -37,11 +33,19 @@ public class ABAFile {
totalSettleAmount = totalSettleAmount.add(settleAmount);
}
public byte[] output() {
public boolean manualSending() {
return base.isManualSending();
}
public String bank() {
return base.getBank();
}
public byte[] output(int serializeNo) {
StringWriter out = new StringWriter();
PrintWriter writer = new PrintWriter(out);
writer.print(generateTopLine() + "\r\n");
writer.print(generateTopLine(serializeNo) + "\r\n");
for (SettleMerchantInfo info : settlements) {
String line = info.settleLine();
writer.print(line + "\r\n");
@ -66,27 +70,27 @@ public class ABAFile {
private String generateBalanceLine() {
StringBuilder lineBuilder = new StringBuilder(baseLine);
lineBuilder.replace(0, 1, "1");
lineBuilder.replace(1, 8, bsbNo(selfBSB));
lineBuilder.replace(8, 17, StringUtils.leftPad(selfAccountNo, 9));
lineBuilder.replace(1, 8, bsbNo(base.getBsb()));
lineBuilder.replace(8, 17, StringUtils.leftPad(base.getAccountNo(), 9));
lineBuilder.replace(18, 20, "13");
lineBuilder.replace(20, 30, amountString(totalSettleAmount, 10));
lineBuilder.replace(30, 62, StringUtils.rightPad(StringUtils.substring(company, 0, 32), 32));
lineBuilder.replace(30, 62, StringUtils.rightPad(StringUtils.substring(base.getAccountName(), 0, 32), 32));
lineBuilder.replace(62, 80, StringUtils.rightPad(DateFormatUtils.format(settleDate, "yyyyMMdd"), 18));
lineBuilder.replace(80, 87, bsbNo(selfBSB));
lineBuilder.replace(87, 96, StringUtils.leftPad(selfAccountNo, 9));
lineBuilder.replace(96, 112, StringUtils.left(StringUtils.rightPad(company, 16), 16));
lineBuilder.replace(80, 87, bsbNo(base.getBsb()));
lineBuilder.replace(87, 96, StringUtils.leftPad(base.getAccountNo(), 9));
lineBuilder.replace(96, 112, StringUtils.left(StringUtils.rightPad(base.getAccountName(), 16), 16));
lineBuilder.replace(112, 120, StringUtils.leftPad("0", 8, "0"));
return lineBuilder.toString();
}
private String generateTopLine() {
private String generateTopLine(int serializeNo) {
StringBuilder topLineBuilder = new StringBuilder(baseLine);
topLineBuilder.replace(0, 1, "0");
topLineBuilder.replace(18, 20, StringUtils.leftPad("1", 2, "0"));
Assert.isTrue(bank.length() == 3, "Invalid Bank Code:" + bank);
topLineBuilder.replace(20, 23, bank);
topLineBuilder.replace(30, 56, StringUtils.rightPad(company, 26));
topLineBuilder.replace(56, 62, StringUtils.leftPad(apca, 6, "0"));
Assert.isTrue(base.getBank().length() == 3, "Invalid Bank Code:" + base.getBank());
topLineBuilder.replace(20, 23, base.getBank());
topLineBuilder.replace(30, 56, StringUtils.rightPad(base.getAccountName(), 26));
topLineBuilder.replace(56, 62, StringUtils.leftPad(base.getApca(), 6, "0"));
topLineBuilder.replace(62, 74, StringUtils.rightPad(DateFormatUtils.format(settleDate, "yyyyMMdd"), 12));
topLineBuilder.replace(74, 80, DateFormatUtils.format(settleDate, "ddMMyy"));
return topLineBuilder.toString();
@ -102,6 +106,22 @@ public class ABAFile {
return StringUtils.leftPad("" + amount, size, "0");
}
public void setOperateTime(Date operateTime) {
this.operateTime = operateTime;
}
public String getOperateTimeString() {
return operateTime == null ? "" : DateFormatUtils.format(operateTime, "yyyyMMddHHmmss");
}
public Date getOperateTime() {
return operateTime;
}
public String filename() {
return "Merchant_Settlement_Info_" + bank() + "_" + getOperateTimeString() + ".aba";
}
private class SettleMerchantInfo {
private final String bsbNo;
private final String accountNo;
@ -124,9 +144,9 @@ public class ABAFile {
lineBuilder.replace(20, 30, getSettleAmount());
lineBuilder.replace(30, 62, getAccountName());
lineBuilder.replace(62, 80, StringUtils.rightPad("RoyalPay" + DateFormatUtils.format(settleDate, "yyyyMMdd"), 18));
lineBuilder.replace(80, 87, bsbNo(selfBSB));
lineBuilder.replace(87, 96, StringUtils.leftPad(selfAccountNo, 9));
lineBuilder.replace(96, 112, StringUtils.left(StringUtils.rightPad(company, 16), 16));
lineBuilder.replace(80, 87, bsbNo(base.getBsb()));
lineBuilder.replace(87, 96, StringUtils.leftPad(base.getAccountNo(), 9));
lineBuilder.replace(96, 112, StringUtils.left(StringUtils.rightPad(base.getAccountName(), 16), 16));
lineBuilder.replace(112, 120, StringUtils.leftPad("0", 8, "0"));
return lineBuilder.toString();
}

@ -0,0 +1,27 @@
package au.com.royalpay.payment.manage.support.abafile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* Create by yixian at 2018-06-25 17:16
*/
@Component
@EnableConfigurationProperties(ABAConfig.class)
public class ABATemplate {
private static ABATemplate tpl;
@Autowired
private ABAConfig config;
@PostConstruct
public void init() {
tpl = this;
}
public static ABAConfig getConfig() {
return tpl.config;
}
}

@ -12,6 +12,7 @@ import au.com.royalpay.payment.core.exceptions.ParamInvalidException;
import au.com.royalpay.payment.manage.mappers.client.ClientCustomersMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailAnalysisMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingDetailMapper;
import au.com.royalpay.payment.manage.mappers.log.ClearingLogMapper;
import au.com.royalpay.payment.manage.mappers.log.LogSettleMailMapper;
import au.com.royalpay.payment.manage.mappers.payment.AustracDataMapper;
import au.com.royalpay.payment.manage.mappers.payment.OrderMapper;
@ -132,6 +133,8 @@ public class TradeLogServiceImpl implements TradeLogService {
private ClientCustomersMapper clientCustomersMapper;
@Resource
LogSettleMailMapper logSettleMailMapper;
@Resource
private ClearingLogMapper clearingLogMapper;
@Resource
private OrgManager orgManager;
@ -830,12 +833,12 @@ public class TradeLogServiceImpl implements TradeLogService {
result.put("analysis", transactionMapper.getClientAmountAnalysis(params));
if (query.getPage() == 1) {
if (!logs.isEmpty() && logs.size() > 0) {
JSONObject sendMailLog = logSettleMailMapper.findByDate(logs.get(0).getDate("clearing_time"));
if (sendMailLog == null) {
result.put("padding", true);
}
if (sendMailLog != null && sendMailLog.getIntValue("mail_status") != 1) {
result.put("padding", true);
JSONObject clearingDetail = clearingDetailMapper.findByDetailId(logs.get(0).getIntValue("clearing_order"));
if (clearingDetail!=null){
JSONObject clearingLog = clearingLogMapper.findById(clearingDetail.getIntValue("clearing_id"));
if(clearingLog.getBooleanValue("editable")){
result.put("padding", true);
}
}
}
}

@ -0,0 +1,7 @@
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.schema-name=rppaymentdev
spring.datasource.host=119.28.3.196:3310
spring.datasource.url=jdbc:mysql://${spring.datasource.host}/${spring.datasource.schema-name}?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=readonly
spring.datasource.password=read0nly

@ -111,3 +111,21 @@ mail.mailgun.default.merchantlist=merchants@mail.royalpay.com.au
##############
royalpay.sms.appid=1400094878
royalpay.sms.appkey=43390d81e20c5191c278fbf4cd275be2
#清算银行配置
settle.abafile.default-bank=CBA
settle.abafile.remains-to=ANZ
settle.abafile.bank.CBA.bank=CBA
settle.abafile.bank.CBA.apca=301500
settle.abafile.bank.CBA.bsb=063109
settle.abafile.bank.CBA.account-no=11655861
settle.abafile.bank.CBA.account-name=Tunnel Show Pty Ltd
settle.abafile.bank.ANZ.manual-sending=true
settle.abafile.bank.ANZ.bank=ANZ
settle.abafile.bank.ANZ.apca=514624
settle.abafile.bank.ANZ.bsb=013006
settle.abafile.bank.ANZ.account-no=837022519
settle.abafile.bank.ANZ.account-name=Tunnel Show Pty Ltd

@ -1,6 +1,11 @@
<?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="au.com.royalpay.payment.manage.mappers.log.ClearingDetailAnalysisMapper">
<delete id="clearAnalysis">
DELETE a FROM log_clearing_detail_analysis a
inner JOIN log_clearing_detail d on d.clear_detail_id = a.clearing_detail_id
where d.clearing_id = #{clearing_id}
</delete>
<select id="analysisChannelReport" resultType="com.alibaba.fastjson.JSONObject">
SELECT
a.channel,

@ -1,6 +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="au.com.royalpay.payment.manage.mappers.log.ClearingDetailMapper">
<update id="updateAllBanks">
update log_clearing_detail set settle_bank=#{settle_bank} where clearing_id=#{clearing_id}
</update>
<select id="listReports" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT

@ -1,6 +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="au.com.royalpay.payment.manage.mappers.log.ClearingLogMapper">
<update id="lockSettlements">
update log_clearing set editable=0 where settle_date=#{date}
</update>
<select id="findByDate" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT *

@ -1,14 +1,24 @@
<?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="au.com.royalpay.payment.manage.mappers.payment.TaskManualSettleMapper">
<update id="rollbackExecutedTask">
UPDATE task_client_manual_settle s
INNER JOIN log_clearing_detail d ON d.clear_detail_id = s.clearing_order
SET s.finish_time = NULL, s.clearing_order = NULL
WHERE d.clearing_id = #{clearing_id}
</update>
<select id="getEveryLatestRecord" resultType="com.alibaba.fastjson.JSONObject">
SELECT
s.request_time,c.client_id,c.client_moniker
SELECT
s.request_time,
c.client_id,
c.client_moniker
FROM
task_client_manual_settle s
right join sys_clients c on s.client_id = c.client_id
inner join sys_client_config cc on cc.client_id = c.client_id
where (s.request_time=(select max(B.request_time) from task_client_manual_settle B where s.client_id =B.client_id) or s.request_time is null)
and cc.manual_settle = 1
task_client_manual_settle s
right join sys_clients c on s.client_id = c.client_id
inner join sys_client_config cc on cc.client_id = c.client_id
where (s.request_time = (select max(B.request_time)
from task_client_manual_settle B
where s.client_id = B.client_id) or s.request_time is null)
and cc.manual_settle = 1
</select>
</mapper>

@ -1,6 +1,17 @@
<?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="au.com.royalpay.payment.manage.mappers.payment.TransactionMapper">
<update id="removeSettleRemark">
UPDATE pmt_transactions AS t
INNER JOIN log_clearing_detail d ON d.clear_detail_id = t.clearing_order
SET clearing_status = 0, clearing_order = NULL, clearing_time = NULL
WHERE d.clearing_id = #{clearing_id}
</update>
<delete id="deleteSettlementTransaction">
DELETE t FROM pmt_transactions t
INNER JOIN log_clearing_detail d ON d.clear_detail_id = t.clearing_order
WHERE d.clearing_id = #{clearing_id} AND t.transaction_type = 'Debit' AND t.refund_id IS NULL and t.channel='Settlement'
</delete>
<select id="listTransFlowPage" resultType="com.alibaba.fastjson.JSONObject">
SELECT t.*,if(t.refund_id is not null,'refund',if(t.transaction_type='Debit' AND
t.system_generate=0,'clearing','payment')) trans_type,

@ -241,70 +241,187 @@ define(['angular', 'decimal', 'uiBootstrap', 'uiRouter', 'angularEcharts'], func
})
}
}]);
app.controller('settlementDetailCtrl', ['$scope', '$stateParams', '$http','$uibModal','$filter','detail','commonDialog', function ($scope, $stateParams,$http,$uibModal,$filter, detail,commonDialog) {
$scope.detail = detail.data;
$scope.hasSentMail = false;
$scope.sendNotice = false;
$scope.noticeResend = false;
app.controller('settlementDetailCtrl', ['$scope', '$stateParams', '$http', '$uibModal', '$filter', '$state', 'detail', 'commonDialog',
function ($scope, $stateParams, $http, $uibModal, $filter, $state, detail, commonDialog) {
$scope.detail = detail.data;
$scope.hasSentMail = false;
$scope.sendNotice = false;
$scope.noticeResend = false;
$scope.analysisFilter = {};
$scope.currentAnalysis = $scope.detail;
$scope.pageCtrl = {visible:{}};
$scope.settleAnalysis = [
{settleDays: 1, clients: 0, settleAmount: 0, settles: []},
{settleDays: 2, clients: 0, settleAmount: 0, settles: []},
{settleDays: 3, clients: 0, settleAmount: 0, settles: []}
];
angular.forEach($scope.detail.details, function (settleItem) {
var settleDays = settleItem.clear_days;
var analysisItem = $scope.settleAnalysis[Math.min(settleDays - 1, 2)];
analysisItem.settles.push(settleItem);
analysisItem.clients++;
analysisItem.settleAmount = Decimal.add(analysisItem.settleAmount, settleItem.clearing_amount).toFixed(2, Decimal.ROUND_FLOOR)
});
var nowStr = $filter('date')(new Date(), "yyyy-MM-dd");
$scope.datePattern = $stateParams.date;
if($scope.datePattern == nowStr){
$scope.sendNotice = true;
}
$scope.displaySendCheckCode = function () {
$uibModal.open({
templateUrl: '/static/analysis/templates/settlement_send_check_code.html',
controller: 'settlementSendCheckCodeCtrl',
size: 'sm'
});
};
function getAnalysisTemplate() {
return [
{settleDays: 1, clients: 0, settleAmount: 0, settles: []},
{settleDays: 2, clients: 0, settleAmount: 0, settles: []},
{settleDays: 3, clients: 0, settleAmount: 0, settles: []}
];
}
$scope.settleAnalysis = getAnalysisTemplate();
$scope.batchAnalysis = {
'All': $scope.settleAnalysis
};
angular.forEach($scope.detail.logs, function (batch) {
$scope.batchAnalysis[batch.clearing_id + ''] = getAnalysisTemplate();
});
$http.get('/sys/settlement/reports/'+$stateParams.date+'/send_status/').then(function (resp) {
if(resp.data!=null && resp.data.mail_status ==1){
$scope.hasSentMail = true;
angular.forEach($scope.detail.details, function (settleItem) {
var settleDays = settleItem.clear_days;
attachAnalysis($scope.settleAnalysis[Math.min(settleDays - 1, 2)]);
attachAnalysis($scope.batchAnalysis[settleItem.clearing_id + ''][Math.min(settleDays - 1, 2)]);
function attachAnalysis(analysisItem) {
analysisItem.settles.push(settleItem);
analysisItem.clients++;
analysisItem.settleAmount = Decimal.add(analysisItem.settleAmount, settleItem.clearing_amount).toFixed(2, Decimal.ROUND_FLOOR);
}
});
var nowStr = $filter('date')(new Date(), "yyyy-MM-dd");
$scope.datePattern = $stateParams.date;
if ($scope.datePattern == nowStr) {
$scope.sendNotice = true;
}
})
$scope.$on("sendMailSuccess",
function (event, msg) {
$scope.hasSentMail = true;
});
$scope.displaySendCheckCode = function () {
$uibModal.open({
templateUrl: '/static/analysis/templates/settlement_send_check_code.html',
controller: 'settlementSendCheckCodeCtrl',
size: 'sm'
});
};
$scope.confirmSendSettlementMail = function () {
commonDialog.confirm({
title: 'Confirm to send notice',
content: '请确认账户已扣款后再发送清算通知',
choises : [{label: 'Send', className: 'btn-success', key: '1'},
{label: 'Cancel', className: 'btn-danger', key: '2', dismiss: true}]
}).then(function () {
$scope.noticeResend=true;
$http.post('/sys/settlement/settlement_notice').then(function () {
commonDialog.alert({title: 'Success', content: '发送成功', type: 'success'});
$scope.noticeResend=false;
},function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
$scope.noticeResend=false;
$scope.switchSettleBatch = function (batch) {
if (batch == null) {
$scope.currentAnalysis = $scope.detail;
$scope.analysisFilter.clearing_id = null;
} else {
$scope.analysisFilter.clearing_id = batch.clearing_id;
$scope.currentAnalysis = batch;
}
};
$scope.getCurrentLog = function () {
return $scope.detail.logs.filter(function (log) {
return log.clearing_id === $scope.analysisFilter.clearing_id
})[0];
};
$http.get('/sys/settlement/reports/' + $stateParams.date + '/send_status/').then(function (resp) {
if (resp.data != null && resp.data.mail_status == 1) {
$scope.hasSentMail = true;
}
});
$scope.$on("sendMailSuccess",
function (event, msg) {
$scope.hasSentMail = true;
});
})
};
}]);
$scope.confirmSendSettlementMail = function () {
commonDialog.confirm({
title: 'Confirm to send notice',
content: '请确认账户已扣款后再发送清算通知',
choises: [{label: 'Send', className: 'btn-success', key: '1'},
{label: 'Cancel', className: 'btn-danger', key: '2', dismiss: true}]
}).then(function () {
$scope.noticeResend = true;
$http.post('/sys/settlement/settlement_notice').then(function () {
commonDialog.alert({title: 'Success', content: '发送成功', type: 'success'});
$scope.noticeResend = false;
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
$scope.noticeResend = false;
});
})
};
$scope.lockSettleLog = function (clearingId) {
commonDialog.confirm({title: '确认操作', content: '当前操作将标记本批次清算已发送,无法撤回,确认操作?'}).then(function () {
$http.put('/sys/settlement/reports/' + $stateParams.date + '/clearings/' + clearingId + '/lock').then(function () {
$scope.detail.logs.filter(function (log) {
return log.clearing_id === clearingId
}).forEach(function (log) {
log.editable = 0
});
commonDialog.alert({title: 'Success', content: 'Operation success', type: 'success'});
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.distributeBankDialog = function () {
var log = $scope.getCurrentLog();
$uibModal.open({
templateUrl: '/static/analysis/templates/settlement_bank_distribution_dialog.html',
controller: 'bankDistributionDialogCtrl',
resolve: {
clearingBatch: function () {
return log;
},
banksConfig: ['$http', function ($http) {
return $http.get('/sys/settlement/available_banks')
}],
settleDate: function () {
return $stateParams.date;
}
}
}).result.then(function () {
$state.reload();
})
};
$scope.rollbackSettlement = function () {
var log = $scope.getCurrentLog();
commonDialog.confirm({
title: '确认操作',
content: '回滚当前清算id=' + log.clearing_id + ',确认?'
}).then(function () {
$http.delete('/sys/settlement/reports/' + $stateParams.date + '/clearings/' + log.clearing_id).then(function () {
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
}
}]);
app.controller('settlementTransactionsCtrl', ['$scope', '$stateParams', 'detail', function ($scope, $stateParams, detail) {
$scope.ctrl = {channel: null};
$scope.report = detail.data;
}]);
app.controller('bankDistributionDialogCtrl', ['$scope', '$http', 'clearingBatch', 'banksConfig', 'settleDate',
function ($scope, $http, clearingBatch, banksConfig, settleDate) {
$scope.banksConfig = banksConfig.data;
$scope.bankData = [];
angular.forEach($scope.banksConfig.banks, function (bank) {
if (bank !== $scope.banksConfig.remains_to) {
$scope.bankData.push({bank: bank, amount: 0});
}
});
$scope.remainingAmount = function () {
var total = clearingBatch.net_amount;
angular.forEach($scope.bankData, function (config) {
total = Decimal.sub(total, config.amount);
});
return Decimal.max(0, total).toFixed(2, Decimal.ROUND_DOWN);
};
$scope.submitDistribution = function () {
$scope.errmsg = null;
var data = {};
angular.forEach($scope.bankData, function (config) {
data[config.bank] = config.amount;
});
$http.put('/sys/settlement/reports/' + settleDate + '/clearings/' + clearingBatch.clearing_id + '/bank_distribution', data).then(function () {
$scope.$close();
}, function (resp) {
$scope.errmsg = resp.data.message;
})
}
}]);
app.controller('settleDateConfigCtrl', ['$scope', '$http', '$filter', 'commonDialog', function ($scope, $http, $filter, commonDialog) {
$scope.loadMonthPlan = function (mon) {
$http.get('/sysconfig/clear_days/months/' + $filter('date')(mon, 'yyyyMM')).then(function (resp) {
@ -341,7 +458,7 @@ define(['angular', 'decimal', 'uiBootstrap', 'uiRouter', 'angularEcharts'], func
};
}]);
app.controller('settlementSendCheckCodeCtrl',['$scope', '$http','$rootScope','$stateParams', function ($scope, $http,$rootScope,$stateParams) {
app.controller('settlementSendCheckCodeCtrl', ['$scope', '$http', '$rootScope', '$stateParams', function ($scope, $http, $rootScope, $stateParams) {
$scope.sendCheckCodeButton = false;
$scope.sendMailButton = false;
$scope.check_code = '';
@ -354,15 +471,15 @@ define(['angular', 'decimal', 'uiBootstrap', 'uiRouter', 'angularEcharts'], func
$scope.sendSettlementMail = function () {
$scope.error_msg = '正在发送,请稍后。';
if($scope.check_code =='' || $scope.check_code == null){
if ($scope.check_code == '' || $scope.check_code == null) {
$scope.error_msg = '请输入验证码';
return;
}
$scope.sendMailButton= true;
$http.get('/sys/settlement/reports/'+$stateParams.date+'/send_settlement_xlsx/'+$scope.check_code).then(function (resp) {
$scope.error_msg =resp.data.msg;
$scope.sendMailButton= false;
if(resp.data.result==0){
$scope.sendMailButton = true;
$http.get('/sys/settlement/reports/' + $stateParams.date + '/send_settlement_xlsx/' + $scope.check_code).then(function (resp) {
$scope.error_msg = resp.data.msg;
$scope.sendMailButton = false;
if (resp.data.result == 0) {
$scope.sendMailButton = true;
$rootScope.$broadcast("sendMailSuccess", '123');
}

@ -0,0 +1,24 @@
<div class="modal-header">
<h4>Distribute Bank</h4>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group" ng-repeat="cfg in bankData">
<label class="control-label col-xs-2" ng-bind="cfg.bank"></label>
<div class="col-xs-9">
<input class="form-control" type="number" ng-model="cfg.amount">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2" ng-bind="banksConfig.remains_to"></label>
<div class="col-xs-9">
<p class="form-control-static" ng-bind="remainingAmount()"></p>
</div>
</div>
</div>
<div class="alert alert-danger" ng-if="errmsg" ng-bind="errmsg"></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="submitDistribution()">Submit</button>
<button class="btn btn-danger" ng-click="$dismiss()">Cancel</button>
</div>

@ -28,85 +28,124 @@
class="btn btn-primary">
<i class="fa fa-download"></i> Settlement.aba
</a>
<button type="button" class="btn btn-warning " ng-if="(('1000'|withRole) && !hasSentMail)&&sendNotice" data-toggle="modal" ng-click="displaySendCheckCode()">
Send Settlement Mail
<button type="button" class="btn btn-warning " ng-if="(('1000'|withRole) && !hasSentMail)&&sendNotice"
data-toggle="modal" ng-click="displaySendCheckCode()">
Send Settlement Mail
</button>
<button class="btn btn-success" ng-if="hasSentMail" disabled="true">
<i class="fa fa-check" aria-hidden="true"></i>
Mail Has Sent
</button>
<button class="btn btn-warning" ng-if="hasSentMail && sendNotice" ng-click="confirmSendSettlementMail()" ng-disabled="noticeResend">
<button class="btn btn-warning" ng-if="hasSentMail && sendNotice" ng-click="confirmSendSettlementMail()"
ng-disabled="noticeResend">
Send Settlement Notice
</button>
</div>
</div>
<div class="box box-default">
<div class="box-header">Settlement Batches [{{datePattern}}]</div>
<div class="box-body">
<div class="row margin-bottom">
<div class="col-xs-12">
<div class="btn-group">
<button class="btn btn-default" ng-click="switchSettleBatch(null)"
ng-class="{active:analysisFilter.clearing_id==null}">All
</button>
<button class="btn btn-default" ng-repeat="log in detail.logs"
ng-click="switchSettleBatch(log)"
ng-class="{active:analysisFilter.clearing_id==log.clearing_id}">
<i class="fa fa-lock" ng-if="!log.editable"></i>
<span ng-bind="log.operate_time"></span>
</button>
</div>
</div>
</div>
<div class="row" ng-if="analysisFilter.clearing_id!=null && getCurrentLog().editable">
<div class="col-xs-12">
<button class="btn btn-danger" ng-click="lockSettleLog(analysisFilter.clearing_id)">
Mark as send
</button>
<button class="btn btn-primary" ng-click="distributeBankDialog()">
Distribute Bank
</button>
<button class="btn btn-primary pull-right" ng-if="'undo_settle'|withFunc"
ng-click="rollbackSettlement()">
Undo Settlement
</button>
</div>
</div>
</div>
</div>
<div class="row" ng-if="analysisFilter.clearing_id!=null">
<div class="col-xs-12">
<ul class="list-group">
<li class="list-group-item">
<span class="list-group-item-heading">Bank Statistics</span>
</li>
<li class="list-group-item" ng-repeat="bank in getCurrentLog().bank_statistics">
<div class="row">
<span class="col-xs-1 text-bold" ng-bind="bank.bank"></span>
<span class="col-xs-11" ng-bind="bank.total_settle|currency:''"></span>
</div>
</li>
</ul>
</div>
</div>
<div class="box box-default">
<div class="box-header">Settlement analysis at {{datePattern}}</div>
<div class="box-header">Settlement analysis</div>
<div class="box-body">
<div class="row">
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Total Credit</span>
<span class="col-xs-6" ng-bind="detail.total_credit|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.total_credit|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Total Debit</span>
<span class="col-xs-6" ng-bind="detail.total_debit|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.total_debit|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Gross Amount</span>
<span class="col-xs-6" ng-bind="detail.gross_amount|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.gross_amount|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Net Amount</span>
<span class="col-xs-6" ng-bind="detail.net_amount|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.net_amount|currency:''"></span>
</div>
</div>
<div class="row">
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Total Charge</span>
<span class="col-xs-6"
ng-bind="(detail.wechat_charge+detail.royalpay_charge)|currency:''"></span>
ng-bind="(currentAnalysis.wechat_charge+currentAnalysis.royalpay_charge)|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Channel Charge</span>
<span class="col-xs-6" ng-bind="detail.wechat_charge|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.wechat_charge|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">RoyalPay Charge</span>
<span class="col-xs-6" ng-bind="detail.royalpay_charge|currency:''"></span>
<span class="col-xs-6" ng-bind="currentAnalysis.royalpay_charge|currency:''"></span>
</div>
<div class="col-xs-6 col-sm-3">
<span class="col-xs-6 text-bold">Operate Time</span>
<span class="col-xs-6" ng-bind="detail.operate_time|date:'dd/MMM/yyyy HH:mm:ss'"></span>
<span class="col-xs-6"
ng-bind="currentAnalysis.operate_time|date:'dd/MMM/yyyy HH:mm:ss'"></span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<ul class="list-group">
<li class="list-group-item" ng-repeat="group in settleAnalysis">
<div class="row">
<span class="col-sm-2 col-xs-4 text-center">T+{{group.settleDays}}</span>
<span class="col-sm-10 col-xs-8 text-right">
Clients:{{group.clients}}, Amount:{{group.settleAmount|currency:''}}
</span>
</div>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<ul class="list-group">
<li class="list-group-item" ng-repeat="channel in detail.channel_analysis" ng-if="channel.channel!='System'">
<li class="list-group-item" ng-repeat="channel in currentAnalysis.channel_analysis"
ng-if="channel.channel!='System'">
<div class="row">
<span class="col-xs-2"><img ng-src="{{channel.channel|channel_image}}" class="channel-icon-lg"></span>
<span class="col-xs-2"><img ng-src="{{channel.channel|channel_image}}"
class="channel-icon-lg"></span>
<span class="col-xs-10">Gross Amount:{{ channel.gross_amount|currency:''}}</span>
<span class="col-xs-10">RoyalPay Charge:{{channel.royalpay_charge|currency:''}}</span>
@ -115,10 +154,16 @@
</ul>
</div>
</div>
<div class="box box-default" ng-repeat="group in settleAnalysis">
<div class="box-header">T+{{group.settleDays}}: Clients:{{group.clients}} Amount:{{group.settleAmount|currency:''}}</div>
<div class="box-body table-responsive">
<table class="table table-bordered table-striped table-hover">
<div class="box box-success settle-result-box"
ng-repeat="group in batchAnalysis[analysisFilter.clearing_id==null?'All':analysisFilter.clearing_id+'']">
<div class="box-header" ng-click="pageCtrl.visible[group.settleDays]=!pageCtrl.visible[group.settleDays]">
T+{{group.settleDays}}: Clients:{{group.clients}}
Amount:{{group.settleAmount|currency:''}}
<span class="pull-right">Click to hide</span>
</div>
<div class="box-body table-responsive" ng-hide="pageCtrl.visible[group.settleDays]">
<table class="table table-bordered table-striped table-hover settle-result-table">
<thead>
<tr>
<th>Client Moniker</th>
@ -134,7 +179,10 @@
</thead>
<tbody>
<tr ng-repeat="settleItem in group.settles">
<td ng-bind="settleItem.client_moniker"></td>
<td>
<img ng-src="/static/images/bank/{{settleItem.settle_bank|uppercase}}.png" class="bank-logo" title="{{settleItem.settle_bank}}">
<span ng-bind="settleItem.client_moniker"></span>
</td>
<td>
{{settleItem.settle_date_from|limitTo:10}}
~

@ -549,21 +549,21 @@
position: relative;
}
.active-rate-view:after{
content:'';
clear:both;
display:block;
.active-rate-view:after {
content: '';
clear: both;
display: block;
}
.active-rate-view .client-names {
width:100px;
width: 100px;
overflow-x: hidden;
float: left;
border-right: 2px solid #bbb;
display: block;
}
.active-rate-view .client-name{
.active-rate-view .client-name {
width: 100%;
text-align: left;
font-weight: bold;
@ -571,245 +571,244 @@
border-bottom: 1px solid #bbb;
}
.active-rate-view .client-row{
.active-rate-view .client-row {
height: 30px;
line-height: 30px;
white-space: nowrap;
}
.active-rate-view .analysis-box{
.active-rate-view .analysis-box {
overflow-x: auto;
display: block;
float: left;
padding-bottom: 5px;
}
.active-rate-view .analysis-item{
.active-rate-view .analysis-item {
width: 35px;
height: 100%;
display: inline-block;
text-align:center;
line-height:30px;
text-align: center;
line-height: 30px;
overflow: hidden;
border-right:1px solid #bbb;
border-bottom:1px solid #bbb;
border-right: 1px solid #bbb;
border-bottom: 1px solid #bbb;
}
.selectRow,.table-striped>tbody>tr.selectRow:nth-of-type(odd){
.selectRow, .table-striped > tbody > tr.selectRow:nth-of-type(odd) {
background-color: #E0EEE0;
}
.fountainGBox{
position:relative;
width:108px;
height:13px;
.fountainGBox {
position: relative;
width: 108px;
height: 13px;
margin: auto auto 20px;
}
.fountainG{
position:absolute;
top:0;
background-color:rgb(0,0,0);
width:13px;
height:13px;
animation-name:bounce_fountainG;
-o-animation-name:bounce_fountainG;
-ms-animation-name:bounce_fountainG;
-webkit-animation-name:bounce_fountainG;
-moz-animation-name:bounce_fountainG;
animation-duration:1.5s;
-o-animation-duration:1.5s;
-ms-animation-duration:1.5s;
-webkit-animation-duration:1.5s;
-moz-animation-duration:1.5s;
animation-iteration-count:infinite;
-o-animation-iteration-count:infinite;
-ms-animation-iteration-count:infinite;
-webkit-animation-iteration-count:infinite;
-moz-animation-iteration-count:infinite;
animation-direction:normal;
-o-animation-direction:normal;
-ms-animation-direction:normal;
-webkit-animation-direction:normal;
-moz-animation-direction:normal;
transform:scale(.3);
-o-transform:scale(.3);
-ms-transform:scale(.3);
-webkit-transform:scale(.3);
-moz-transform:scale(.3);
border-radius:9px;
-o-border-radius:9px;
-ms-border-radius:9px;
-webkit-border-radius:9px;
-moz-border-radius:9px;
}
.fountainG.fountainG_1{
left:0;
animation-delay:0.6s;
-o-animation-delay:0.6s;
-ms-animation-delay:0.6s;
-webkit-animation-delay:0.6s;
-moz-animation-delay:0.6s;
}
.fountainG.fountainG_2{
left:13px;
animation-delay:0.75s;
-o-animation-delay:0.75s;
-ms-animation-delay:0.75s;
-webkit-animation-delay:0.75s;
-moz-animation-delay:0.75s;
}
.fountainG.fountainG_3{
left:27px;
animation-delay:0.9s;
-o-animation-delay:0.9s;
-ms-animation-delay:0.9s;
-webkit-animation-delay:0.9s;
-moz-animation-delay:0.9s;
}
.fountainG.fountainG_4{
left:40px;
animation-delay:1.05s;
-o-animation-delay:1.05s;
-ms-animation-delay:1.05s;
-webkit-animation-delay:1.05s;
-moz-animation-delay:1.05s;
}
.fountainG.fountainG_5{
left:54px;
animation-delay:1.2s;
-o-animation-delay:1.2s;
-ms-animation-delay:1.2s;
-webkit-animation-delay:1.2s;
-moz-animation-delay:1.2s;
}
.fountainG.fountainG_6{
left:67px;
animation-delay:1.35s;
-o-animation-delay:1.35s;
-ms-animation-delay:1.35s;
-webkit-animation-delay:1.35s;
-moz-animation-delay:1.35s;
}
.fountainG.fountainG_7{
left:81px;
animation-delay:1.5s;
-o-animation-delay:1.5s;
-ms-animation-delay:1.5s;
-webkit-animation-delay:1.5s;
-moz-animation-delay:1.5s;
}
.fountainG.fountainG_8{
left:94px;
animation-delay:1.64s;
-o-animation-delay:1.64s;
-ms-animation-delay:1.64s;
-webkit-animation-delay:1.64s;
-moz-animation-delay:1.64s;
}
@keyframes bounce_fountainG{
0%{
transform:scale(1);
background-color:rgb(0,0,0);
.fountainG {
position: absolute;
top: 0;
background-color: rgb(0, 0, 0);
width: 13px;
height: 13px;
animation-name: bounce_fountainG;
-o-animation-name: bounce_fountainG;
-ms-animation-name: bounce_fountainG;
-webkit-animation-name: bounce_fountainG;
-moz-animation-name: bounce_fountainG;
animation-duration: 1.5s;
-o-animation-duration: 1.5s;
-ms-animation-duration: 1.5s;
-webkit-animation-duration: 1.5s;
-moz-animation-duration: 1.5s;
animation-iteration-count: infinite;
-o-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-direction: normal;
-o-animation-direction: normal;
-ms-animation-direction: normal;
-webkit-animation-direction: normal;
-moz-animation-direction: normal;
transform: scale(.3);
-o-transform: scale(.3);
-ms-transform: scale(.3);
-webkit-transform: scale(.3);
-moz-transform: scale(.3);
border-radius: 9px;
-o-border-radius: 9px;
-ms-border-radius: 9px;
-webkit-border-radius: 9px;
-moz-border-radius: 9px;
}
.fountainG.fountainG_1 {
left: 0;
animation-delay: 0.6s;
-o-animation-delay: 0.6s;
-ms-animation-delay: 0.6s;
-webkit-animation-delay: 0.6s;
-moz-animation-delay: 0.6s;
}
.fountainG.fountainG_2 {
left: 13px;
animation-delay: 0.75s;
-o-animation-delay: 0.75s;
-ms-animation-delay: 0.75s;
-webkit-animation-delay: 0.75s;
-moz-animation-delay: 0.75s;
}
.fountainG.fountainG_3 {
left: 27px;
animation-delay: 0.9s;
-o-animation-delay: 0.9s;
-ms-animation-delay: 0.9s;
-webkit-animation-delay: 0.9s;
-moz-animation-delay: 0.9s;
}
.fountainG.fountainG_4 {
left: 40px;
animation-delay: 1.05s;
-o-animation-delay: 1.05s;
-ms-animation-delay: 1.05s;
-webkit-animation-delay: 1.05s;
-moz-animation-delay: 1.05s;
}
.fountainG.fountainG_5 {
left: 54px;
animation-delay: 1.2s;
-o-animation-delay: 1.2s;
-ms-animation-delay: 1.2s;
-webkit-animation-delay: 1.2s;
-moz-animation-delay: 1.2s;
}
.fountainG.fountainG_6 {
left: 67px;
animation-delay: 1.35s;
-o-animation-delay: 1.35s;
-ms-animation-delay: 1.35s;
-webkit-animation-delay: 1.35s;
-moz-animation-delay: 1.35s;
}
.fountainG.fountainG_7 {
left: 81px;
animation-delay: 1.5s;
-o-animation-delay: 1.5s;
-ms-animation-delay: 1.5s;
-webkit-animation-delay: 1.5s;
-moz-animation-delay: 1.5s;
}
.fountainG.fountainG_8 {
left: 94px;
animation-delay: 1.64s;
-o-animation-delay: 1.64s;
-ms-animation-delay: 1.64s;
-webkit-animation-delay: 1.64s;
-moz-animation-delay: 1.64s;
}
@keyframes bounce_fountainG {
0% {
transform: scale(1);
background-color: rgb(0, 0, 0);
}
100%{
transform:scale(.3);
background-color:rgb(255,255,255);
100% {
transform: scale(.3);
background-color: rgb(255, 255, 255);
}
}
@-o-keyframes bounce_fountainG{
0%{
-o-transform:scale(1);
background-color:rgb(0,0,0);
@-o-keyframes bounce_fountainG {
0% {
-o-transform: scale(1);
background-color: rgb(0, 0, 0);
}
100%{
-o-transform:scale(.3);
background-color:rgb(255,255,255);
100% {
-o-transform: scale(.3);
background-color: rgb(255, 255, 255);
}
}
@-ms-keyframes bounce_fountainG{
0%{
-ms-transform:scale(1);
background-color:rgb(0,0,0);
@-ms-keyframes bounce_fountainG {
0% {
-ms-transform: scale(1);
background-color: rgb(0, 0, 0);
}
100%{
-ms-transform:scale(.3);
background-color:rgb(255,255,255);
100% {
-ms-transform: scale(.3);
background-color: rgb(255, 255, 255);
}
}
@-webkit-keyframes bounce_fountainG{
0%{
-webkit-transform:scale(1);
background-color:rgb(0,0,0);
@-webkit-keyframes bounce_fountainG {
0% {
-webkit-transform: scale(1);
background-color: rgb(0, 0, 0);
}
100%{
-webkit-transform:scale(.3);
background-color:rgb(255,255,255);
100% {
-webkit-transform: scale(.3);
background-color: rgb(255, 255, 255);
}
}
@-moz-keyframes bounce_fountainG{
0%{
-moz-transform:scale(1);
background-color:rgb(0,0,0);
@-moz-keyframes bounce_fountainG {
0% {
-moz-transform: scale(1);
background-color: rgb(0, 0, 0);
}
100%{
-moz-transform:scale(.3);
background-color:rgb(255,255,255);
100% {
-moz-transform: scale(.3);
background-color: rgb(255, 255, 255);
}
}
.analysis-nav ul li{
.analysis-nav ul li {
margin-right: 10px;
margin-bottom: 10px;
background-color: white;
}
.analysis-nav .nav-pills li a:hover,.analysis-nav .nav-pills li a:focus,.analysis-nav .nav-pills li.active a{
.analysis-nav .nav-pills li a:hover, .analysis-nav .nav-pills li a:focus, .analysis-nav .nav-pills li.active a {
background-color: #f06101;
border-top-color:#f06101;
border-top-color: #f06101;
}
.channel-icon{
.channel-icon {
width: 16px;
height: 16px;
}
.channel-icon-lg{
.channel-icon-lg {
width: 48px;
height: 48px;
}
.settle-forecast .rc-box .week .day{
height:120px;
.settle-forecast .rc-box .week .day {
height: 120px;
}
.dashboard-page .tooltip .tooltip-inner{
.dashboard-page .tooltip .tooltip-inner {
max-width: 600px;
text-align: center;
}
.partner-settlement_page .tooltip .tooltip-inner{
max-width: 600px;
}
.partner-settlement_page .tooltip .tooltip-inner {
max-width: 600px;
}
.partner_list_style {
position: relative;
@ -824,8 +823,17 @@
color: #ffffff;
}
.check-i{
.check-i {
color: #00a65a;
float: right;
margin-top: 8px;
}
.settle-result-box .box-header {
cursor: pointer;
}
.settle-result-box .settle-result-table .bank-logo {
width: 24px;
vertical-align: middle;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -1,27 +0,0 @@
package au.com.royalpay.payment.manage.apps.core.impls;
import au.com.royalpay.payment.manage.apps.core.CustomerImpressionService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* Created by wangning on 08/01/2018.
*/
@SpringBootTest
@ActiveProfiles({"local","alipay","wechat","jd","bestpay"})
@RunWith(SpringRunner.class)
public class CustomerImpressionServiceImplTest {
@Resource
private CustomerImpressionService customerImpressionService;
@Test
public void generate() throws Exception {
customerImpressionService.generate(9);
}
}
Loading…
Cancel
Save