add 后清算 收支分离模式

master
luoyang 6 years ago
parent 9b465fe3aa
commit fc653ca1f9

@ -0,0 +1,27 @@
package au.com.royalpay.payment.manage.mappers.system;
import cn.yixblog.support.mybatis.autosql.annotations.AdvanceSelect;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
@AutoMapper(tablename = "log_clearing_distributed_surcharge", pkName = "log_id")
public interface ClearingDistributedSurchargeMapper {
List<JSONObject> findTransactions(@Param("client_id") int clientId);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject transactions);
List<JSONObject> getMonthDetailByClientId(@Param("datefrom") Date datefrom, @Param("dateto") Date dateto);
List<JSONObject> findTransactionsByDate(JSONObject params);
}

@ -0,0 +1,25 @@
package au.com.royalpay.payment.manage.mappers.system;
import cn.yixblog.support.mybatis.autosql.annotations.AdvanceSelect;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@AutoMapper(tablename = "sys_clients_surcharge_accounts", pkName = "client_id")
public interface ClientsSurchargeAccountsMapper {
@AutoSql(type = SqlType.SELECT)
@AdvanceSelect(addonWhereClause = "is_valid=1")
JSONObject find(@Param("client_id") int clientId);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject surchargeAccount);
@AutoSql(type = SqlType.UPDATE)
void update(JSONObject surchargeAccount);
}

@ -0,0 +1,28 @@
package au.com.royalpay.payment.manage.mappers.system;
import cn.yixblog.support.mybatis.autosql.annotations.AutoMapper;
import cn.yixblog.support.mybatis.autosql.annotations.AutoSql;
import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
@AutoMapper(tablename = "financial_surcharge_account_detail", pkName = "detail_id")
public interface FinancialSurchargeAccountDetailMapper {
List<JSONObject> findDetailsByMonth(@Param("settle_month") String settle_month);
List<JSONObject> findDetailsByClientId(@Param("client_id") int client_id);
@AutoSql(type = SqlType.INSERT)
void save(JSONObject detail);
List<JSONObject> listSettlementDatesInMonth(@Param("month") String month);
}

@ -273,6 +273,20 @@ public interface ClientManager {
void setSkipClearing(JSONObject account,String clientMoniker, Boolean skip_clearing,String remark); void setSkipClearing(JSONObject account,String clientMoniker, Boolean skip_clearing,String remark);
void setSurchargeMode(JSONObject account, String clientMoniker, String surcharge_mode);
JSONObject surchargeAccount(JSONObject account, String clientMoniker);
void setAllowSurchargeCredit(JSONObject account,String clientMoniker, Boolean allow_surcharge_credit);
List<JSONObject> getAccountTransactions(JSONObject account,String clientMoniker);
List<JSONObject> getAccountTransactionsByDate(JSONObject account,String clientMoniker, String date);
List<JSONObject> getAccountMonthDetails(JSONObject account,String clientMoniker);
void saveAccountTransaction(JSONObject account,String clientMoniker, JSONObject transaction);
void enableGatewayUpgrade(JSONObject account,String clientMoniker, boolean gatewayUpgrade); void enableGatewayUpgrade(JSONObject account,String clientMoniker, boolean gatewayUpgrade);
void enableGatewayAlipayOnline(JSONObject account,String clientMoniker, boolean gatewayAlipayOnline); void enableGatewayAlipayOnline(JSONObject account,String clientMoniker, boolean gatewayAlipayOnline);

@ -45,25 +45,7 @@ import au.com.royalpay.payment.manage.merchants.core.ClientConfigService;
import au.com.royalpay.payment.manage.merchants.core.ClientInfoCacheSupport; import au.com.royalpay.payment.manage.merchants.core.ClientInfoCacheSupport;
import au.com.royalpay.payment.manage.merchants.core.ClientManager; import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.merchants.core.ClientModifySupport; import au.com.royalpay.payment.manage.merchants.core.ClientModifySupport;
import au.com.royalpay.payment.manage.merchants.entity.impls.ApproveEmailModify; import au.com.royalpay.payment.manage.merchants.entity.impls.*;
import au.com.royalpay.payment.manage.merchants.entity.impls.AuditModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.BDUserModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.ClearDaysModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.CredentialCodeModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.CustomerSurchargeRateModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.DisableModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.EmailModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.GreenChannelModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.MaxOrderAmountModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.OpenStatusModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.OrderExpiryModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.ParentIdModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.PaypadVersionModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.RefundAuditModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.RefundPWDModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.SettleHourModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.SwitchPermissionModify;
import au.com.royalpay.payment.manage.merchants.entity.impls.TimeZoneModify;
import au.com.royalpay.payment.manage.notice.core.MailService; 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.beans.TodoNotice;
import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider; import au.com.royalpay.payment.manage.signin.core.ManagerTodoNoticeProvider;
@ -85,6 +67,7 @@ import au.com.royalpay.payment.tools.exceptions.NotFoundException;
import au.com.royalpay.payment.tools.exceptions.ServerErrorException; import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
import au.com.royalpay.payment.tools.exceptions.event.WechatExceptionEvent; import au.com.royalpay.payment.tools.exceptions.event.WechatExceptionEvent;
import au.com.royalpay.payment.tools.locale.LocaleSupport; import au.com.royalpay.payment.tools.locale.LocaleSupport;
import au.com.royalpay.payment.tools.lock.Locker;
import au.com.royalpay.payment.tools.mail.SendMail; import au.com.royalpay.payment.tools.mail.SendMail;
import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig; import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig;
import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO; import au.com.royalpay.payment.tools.merchants.beans.UpdateSurchargeDTO;
@ -149,14 +132,10 @@ import java.math.RoundingMode;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
import java.util.ArrayList; import java.text.ParseException;
import java.util.Arrays; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.*;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
@ -305,6 +284,14 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
private RiskAttentionMerchantsMapper riskAttentionMerchantsMapper; private RiskAttentionMerchantsMapper riskAttentionMerchantsMapper;
@Resource @Resource
private SysChannelConfigMapper sysChannelConfigMapper; private SysChannelConfigMapper sysChannelConfigMapper;
@Resource
private ClientsSurchargeAccountsMapper clientsSurchargeAccountsMapper;
@Resource
private ClearingDistributedSurchargeMapper clearingDistributedSurchargeMapper;
@Resource
private FinancialSurchargeAccountDetailMapper financialSurchargeAccountDetailMapper;
@Resource
private Locker locker;
@Resource @Resource
@ -3257,6 +3244,131 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
} }
} }
@Override
@Transactional
public void setSurchargeMode(JSONObject account, String clientMoniker, String surcharge_mode) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
clientModifySupport.processClientConfigModify(new SurchargeModeModify(account, clientMoniker, surcharge_mode));
if ("distributed".equals(surcharge_mode)) {
JSONObject surchargeAccount = clientsSurchargeAccountsMapper.find(client.getIntValue("client_id"));
if (surchargeAccount == null) {
JSONObject params = new JSONObject();
params.put("client_id", client.getIntValue("client_id"));
params.put("create_time", new Date());
params.put("is_valid", 1);
params.put("balance", 0);
clientsSurchargeAccountsMapper.save(params);
}
}
}
@Override
public JSONObject surchargeAccount(JSONObject account, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
return clientsSurchargeAccountsMapper.find(client.getIntValue("client_id"));
}
@Override
@Transactional
public void setAllowSurchargeCredit(JSONObject account, String clientMoniker, Boolean allow_surcharge_credit) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
clientModifySupport.processClientConfigModify(new SwitchPermissionModify(account, clientMoniker, "allow_surcharge_credit", allow_surcharge_credit));
}
@Override
public List<JSONObject> getAccountTransactions(JSONObject account, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
List<JSONObject> transactions = clearingDistributedSurchargeMapper.findTransactions(client.getIntValue("client_id"));
transactions.forEach(e->{
if ("Credit".equals(e.getString("type"))) {
JSONObject manager = managerMapper.findDetail(e.getString("operation"));
e.put("operator_displayname", manager.getString("display_name"));
}
});
return transactions;
}
@Override
public List<JSONObject> getAccountTransactionsByDate(JSONObject account, String clientMoniker, String date) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
JSONObject params = new JSONObject();
params.put("client_id", client.getIntValue("client_id"));
params.put("year", date.substring(0, 4));
params.put("month", date.substring(date.length()-2, date.length()));
List<JSONObject> transactions = clearingDistributedSurchargeMapper.findTransactionsByDate(params);
transactions.forEach(e->{
if ("Credit".equals(e.getString("type"))) {
JSONObject manager = managerMapper.findDetail(e.getString("operation"));
e.put("operator_displayname", manager.getString("display_name"));
}
});
return transactions;
}
@Override
public List<JSONObject> getAccountMonthDetails(JSONObject account, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
List<JSONObject> details = financialSurchargeAccountDetailMapper.findDetailsByClientId(client.getIntValue("client_id"));
return details;
}
@Override
@Transactional
public void saveAccountTransaction(JSONObject account, String clientMoniker, JSONObject transaction) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
if (!(ManagerRole.ADMIN.hasRole(account.getIntValue("role")) || ManagerRole.OPERATOR.hasRole(account.getIntValue("role")))) {
throw new ForbiddenException("无法增加充值记录,权限不足");
}
if (!locker.lock(clientMoniker + "_surcharge_account_save", 120_000)) {
throw new ServerErrorException("Processing task, wait for a moment");
}
try {
JSONObject surcharge_account = clientsSurchargeAccountsMapper.find(client.getIntValue("client_id"));
transaction.put("client_id", client.getIntValue("client_id"));
transaction.put("type", "Credit");
transaction.put("total_surcharge", BigDecimal.ZERO);
transaction.put("tax_amount", BigDecimal.ZERO);
transaction.put("post_balance", surcharge_account.getBigDecimal("balance").add(transaction.getBigDecimal("amount")));
transaction.put("operation", account.getString("manager_id"));
transaction.put("create_time", new Date());
clearingDistributedSurchargeMapper.save(transaction);
surcharge_account.put("balance", surcharge_account.getBigDecimal("balance").add(transaction.getBigDecimal("amount")));
clientsSurchargeAccountsMapper.update(surcharge_account);
} finally {
locker.unlock(clientMoniker + "_surcharge_account_save");
}
}
@Override @Override
public void enableGatewayUpgrade(JSONObject account, String clientMoniker, boolean gatewayUpgrade) { public void enableGatewayUpgrade(JSONObject account, String clientMoniker, boolean gatewayUpgrade) {
JSONObject client = getClientInfoByMoniker(clientMoniker); JSONObject client = getClientInfoByMoniker(clientMoniker);

@ -0,0 +1,29 @@
package au.com.royalpay.payment.manage.merchants.entity.impls;
import au.com.royalpay.payment.manage.merchants.entity.ClientConfigModify;
import com.alibaba.fastjson.JSONObject;
/**
* Create by yixian at 2018-04-12 16:43
*/
public class SurchargeModeModify extends ClientConfigModify {
private String surcharge_mode;
public SurchargeModeModify(JSONObject account, String clientMoniker, String surcharge_mode) {
super(account, clientMoniker);
this.surcharge_mode = surcharge_mode;
}
@Override
protected String business() {
return "切换商户清算模式(surcharge_mode)";
}
@Override
protected JSONObject getModifyResult() {
JSONObject modify = new JSONObject();
modify.put("surcharge_mode", surcharge_mode);
return modify;
}
}

@ -370,6 +370,40 @@ public class PartnerManageController {
clientManager.setSkipClearing(manager,clientMoniker, skip_clearing.getBooleanValue("skip_clearing"),skip_clearing.getString("remark")); clientManager.setSkipClearing(manager,clientMoniker, skip_clearing.getBooleanValue("skip_clearing"),skip_clearing.getString("remark"));
} }
@ManagerMapping(value = "/{clientMoniker}/surcharge_mode", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public void updateSurchargeMode(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject surcharge_mode) {
clientManager.setSurchargeMode(manager, clientMoniker, surcharge_mode.getString("surcharge_mode"));
}
@ManagerMapping(value = "/{clientMoniker}/surcharge_account", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public JSONObject surchargeAccount(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return clientManager.surchargeAccount(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/allow_surcharge_credit", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public void allowSurchargeCredit(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject allow_surcharge_credit) {
clientManager.setAllowSurchargeCredit(manager, clientMoniker, allow_surcharge_credit.getBooleanValue("allow_surcharge_credit"));
}
@ManagerMapping(value = "/{clientMoniker}/account/transactions", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public List<JSONObject> accountTransactions(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return clientManager.getAccountTransactions(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/account/transactions/date", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public List<JSONObject> accountTransactionsByDate(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker,@RequestParam String date) {
return clientManager.getAccountTransactionsByDate(manager, clientMoniker, date);
}
@ManagerMapping(value = "/{clientMoniker}/account/save", method = RequestMethod.POST, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public void saveAccountTransaction(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker, @RequestBody JSONObject transaction) {
clientManager.saveAccountTransaction(manager, clientMoniker, transaction);
}
@ManagerMapping(value = "/{clientMoniker}/surcharge_account/month_detail", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR})
public List<JSONObject> surchargeAccountMonthDetail(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return clientManager.getAccountMonthDetails(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/settle_hour", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.FINANCIAL_STAFF}) @ManagerMapping(value = "/{clientMoniker}/settle_hour", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.SERVANT, ManagerRole.FINANCIAL_STAFF})
public void configSettleHour(@PathVariable String clientMoniker, @RequestBody JSONObject config, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) { public void configSettleHour(@PathVariable String clientMoniker, @RequestBody JSONObject config, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.configSettleHour(manager, clientMoniker, config.getInteger("hour")); clientManager.configSettleHour(manager, clientMoniker, config.getInteger("hour"));

@ -164,6 +164,18 @@ public class PartnerViewController {
clientManager.toggleAccountReceiveNotice(account.getString("client_moniker"), account.getString("account_id"), enable.getBooleanValue("enable")); clientManager.toggleAccountReceiveNotice(account.getString("client_moniker"), account.getString("account_id"), enable.getBooleanValue("enable"));
} }
@PartnerMapping(value = "/{clientMoniker}/surcharge_account", method = RequestMethod.GET, roles = {PartnerRole.ADMIN, PartnerRole.MANAGER})
@ResponseBody
public JSONObject surchargeAccount(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return clientManager.surchargeAccount(manager, clientMoniker);
}
@PartnerMapping(value = "/{clientMoniker}/account/transactions", method = RequestMethod.GET, roles = {PartnerRole.ADMIN, PartnerRole.MANAGER})
@ResponseBody
public List<JSONObject> accountTransactions(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return clientManager.getAccountTransactions(manager, clientMoniker);
}
@PartnerMapping(value = "/accounts/{accountId}/audit_refund", method = RequestMethod.PUT, roles = PartnerRole.ADMIN) @PartnerMapping(value = "/accounts/{accountId}/audit_refund", method = RequestMethod.PUT, roles = PartnerRole.ADMIN)
@ResponseBody @ResponseBody
public void toggleAccountAuditRefund(@PathVariable String accountId, @ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestBody JSONObject enable) { public void toggleAccountAuditRefund(@PathVariable String accountId, @ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestBody JSONObject enable) {

@ -0,0 +1,14 @@
package au.com.royalpay.payment.manage.surchargeAccount.core;
import com.alibaba.fastjson.JSONObject;
import java.util.Date;
import java.util.List;
public interface SurchargeAccountService {
void generatorMonthDetail();
List<JSONObject> listSettledDatesInMonth(String mon);
}

@ -0,0 +1,66 @@
package au.com.royalpay.payment.manage.surchargeAccount.core.impl;
import au.com.royalpay.payment.manage.mappers.system.ClearingDistributedSurchargeMapper;
import au.com.royalpay.payment.manage.mappers.system.FinancialSurchargeAccountDetailMapper;
import au.com.royalpay.payment.manage.surchargeAccount.core.SurchargeAccountService;
import au.com.royalpay.payment.manage.system.core.impl.ClientContractServiceImpl;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@Service
public class SurchargeAccountServiceImpl implements SurchargeAccountService{
@Resource
private ClearingDistributedSurchargeMapper clearingDistributedSurchargeMapper;
@Resource
private FinancialSurchargeAccountDetailMapper financialSurchargeAccountDetailMapper;
Logger logger = LoggerFactory.getLogger(ClientContractServiceImpl.class);
@Override
@Transactional
public void generatorMonthDetail(){
Calendar monthCal = Calendar.getInstance();
monthCal.setTime(new Date());
monthCal.set(Calendar.DAY_OF_MONTH, 1);
monthCal.set(Calendar.HOUR_OF_DAY, 0);
monthCal.set(Calendar.MINUTE, 0);
monthCal.set(Calendar.SECOND, 0);
Date dateto = monthCal.getTime();
monthCal.set(Calendar.MONTH, (monthCal.get(Calendar.MONTH) - 1));
Date datefrom = monthCal.getTime();
logger.info("===============Start generator surcharge account month detail===============" + new Date());
List<JSONObject> thisMonthDetail = clearingDistributedSurchargeMapper.getMonthDetailByClientId(datefrom, dateto);
logger.info("this month details : " + thisMonthDetail.toString());
for (JSONObject detail : thisMonthDetail) {
detail.put("send_mail", 0);
detail.put("wx_send", 0);
detail.put("settle_month", DateFormatUtils.format(datefrom, "yyyy-MM"));
detail.put("create_time", new Date());
financialSurchargeAccountDetailMapper.save(detail);
}
logger.info("===============generator OVER===============" + new Date());
}
@Override
public List<JSONObject> listSettledDatesInMonth(String mon) {
List<JSONObject> settledDates = financialSurchargeAccountDetailMapper.listSettlementDatesInMonth(mon);
return settledDates;
}
}

@ -0,0 +1,30 @@
package au.com.royalpay.payment.manage.surchargeAccount.web;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.surchargeAccount.core.SurchargeAccountService;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@RequestMapping("/sys/surcharge_account")
@RestController
public class SurchargeAccountController {
@Resource
private SurchargeAccountService surchargeAccountService;
@ManagerMapping(value = "/month/{month}/settled_dates", role = {ManagerRole.ADMIN,ManagerRole.OPERATOR}, method = RequestMethod.GET)
public List<JSONObject> surchargeAccountSettledDates(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String month) {
return surchargeAccountService.listSettledDatesInMonth(month);
}
}

@ -0,0 +1,27 @@
package au.com.royalpay.payment.manage.task;
import au.com.royalpay.payment.manage.surchargeAccount.core.SurchargeAccountService;
import au.com.royalpay.payment.tools.scheduler.SynchronizedScheduler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@ConditionalOnProperty(value = "app.run-tasks", havingValue = "true")
public class SurchargeAccountMonthTask {
@Resource
private SynchronizedScheduler synchronizedScheduler;
@Resource
private SurchargeAccountService surchargeAccountService;
@Scheduled(cron = "0 30 6 1 * ?")
public void generateSurchargeAccountDetail() {
synchronizedScheduler.executeProcess("manage_task:generateSurchargeAccountMonth", 120_000, () ->
surchargeAccountService.generatorMonthDetail());
}
}

@ -0,0 +1,31 @@
<?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.system.ClearingDistributedSurchargeMapper">
<select id="getMonthDetailByClientId" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT d.client_id,c.client_moniker,c.company_name,
SUM(IF(d.type='Credit',amount,0)) credit_amount,
SUM(IF(d.type='Debit',amount,0)) debit_amount
FROM log_clearing_distributed_surcharge d INNER JOIN sys_clients c ON c.client_id=d.client_id
WHERE d.create_time >=#{datefrom} AND d.create_time < #{dateto}
AND c.is_valid= 1
GROUP BY d.client_id
]]>
</select>
<select id="findTransactions" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT * FROM log_clearing_distributed_surcharge WHERE client_id = #{client_id}
ORDER BY create_time DESC
]]>
</select>
<select id="findTransactionsByDate" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT * FROM log_clearing_distributed_surcharge WHERE client_id = #{client_id}
AND year(create_time) = #{year}
AND month(create_time) = #{month}
ORDER BY create_time DESC
]]>
</select>
</mapper>

@ -0,0 +1,27 @@
<?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.system.FinancialSurchargeAccountDetailMapper">
<select id="findDetailsByMonth" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT d.*,c.client_moniker,c.short_name,c.company_name
FROM financial_surcharge_account_detail d INNER JOIN sys_clients c ON c.client_id=d.client_id
WHERE d.settle_month = #{settle_month}
]]>
</select>
<select id="findDetailsByClientId" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT d.*,c.client_moniker,c.short_name,c.company_name
FROM financial_surcharge_account_detail d INNER JOIN sys_clients c ON c.client_id=d.client_id
WHERE d.client_id = #{client_id} ORDER BY create_time desc
]]>
</select>
<select id="listSettlementDatesInMonth" resultType="com.alibaba.fastjson.JSONObject">
<![CDATA[
SELECT d.*,c.client_moniker,c.short_name,c.company_name,s.balance
FROM financial_surcharge_account_detail d INNER JOIN sys_clients c ON c.client_id=d.client_id
LEFT JOIN sys_clients_surcharge_accounts s ON s.client_id = d.client_id
WHERE d.settle_month= #{month}
ORDER BY s.balance ASC
]]>
</select>
</mapper>

@ -899,6 +899,15 @@ margin-bottom: 10%;"/>
</li> </li>
</ul> </ul>
</li> </li>
<li ng-if="([1,2]|withRole)">
<ul>
<li>
<a ui-sref="surcharge_account">
<!--<i class="fa fa-users" aria-hidden="true"></i> -->Surcharge Account
</a>
</li>
</ul>
</li>
<li ng-if="([1]|withRole)"> <li ng-if="([1]|withRole)">
<ul> <ul>
<li> <li>

@ -472,6 +472,11 @@ margin-bottom: 10%;"/>
<i class="fa fa-money"></i> <span>合同签约情况</span> <i class="fa fa-money"></i> <span>合同签约情况</span>
</a> </a>
</li> </li>
<li ui-sref-active="active">
<a ui-sref="surcharge_account_month">
<i class="fa fa-bell"></i> <span>手续费账户月度统计</span>
</a>
</li>
<li ui-sref-active="active"> <li ui-sref-active="active">
<a ui-sref="rate_warnings"> <a ui-sref="rate_warnings">
<i class="fa fa-bell"></i> <span>签约到期预警</span> <i class="fa fa-bell"></i> <span>签约到期预警</span>

@ -75,6 +75,7 @@ var modules = [
{path: 'static/payment/cashiers/cashier-manage', module: 'cashierManagement', roles: [1, 2, 3]}, {path: 'static/payment/cashiers/cashier-manage', module: 'cashierManagement', roles: [1, 2, 3]},
{path: 'static/application/clientAuthentication', module: 'clientAuthentication', roles: [1]}, {path: 'static/application/clientAuthentication', module: 'clientAuthentication', roles: [1]},
{path: 'static/cashback/partner-cashback', module: 'cashbackApp', roles: [1,2,3]}, {path: 'static/cashback/partner-cashback', module: 'cashbackApp', roles: [1,2,3]},
{path: 'static/payment/surchargeaccount/partner-surcharge-account', module: 'surchargeAccountApp', roles: [1,2,3]},
{path: 'static/integralmall/coupon_cancellation', module: 'couponCancellation', roles: [1,2]}, {path: 'static/integralmall/coupon_cancellation', module: 'couponCancellation', roles: [1,2]},
{path: 'static/invoice/invoice_assistant', module: 'partnerInvoice', roles: [1]}, {path: 'static/invoice/invoice_assistant', module: 'partnerInvoice', roles: [1]},
{path: 'static/payment/billqrcode/bill-qrcode-manage', module: 'billQrCodeManagement', roles: [1,2,3]} {path: 'static/payment/billqrcode/bill-qrcode-manage', module: 'billQrCodeManagement', roles: [1,2,3]}

@ -163,6 +163,15 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
return $stateParams.clientMoniker; return $stateParams.clientMoniker;
}] }]
} }
}).state('partners.detail.surcharge_account', {
url: '/surcharge_account',
templateUrl: '/static/payment/partner/templates/partner_surcharge_account.html',
controller: 'partnerSurchargeAccountCtrl',
resolve: {
clientMoniker: ['$stateParams', function ($stateParams) {
return $stateParams.clientMoniker;
}]
}
}).state('partners.detail.product', { }).state('partners.detail.product', {
url: '/partner_product', url: '/partner_product',
templateUrl: 'static/payment/product/templates/product.html', templateUrl: 'static/payment/product/templates/product.html',
@ -1957,13 +1966,53 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}]); }]);
app.controller('partnerRatesCtrl', ['$scope', '$rootScope', '$http', '$uibModal', 'commonDialog','$sce', function ($scope, $rootScope, $http, $uibModal, commonDialog,$sce) { app.controller('partnerRatesCtrl', ['$scope', '$rootScope', '$http', '$uibModal', 'commonDialog','$sce', function ($scope, $rootScope, $http, $uibModal, commonDialog,$sce) {
$scope.bankCtrl = {edit: true, rate_name: 'Wechat'}; $scope.bankCtrl = {edit: true, rate_name: 'Wechat'};
$scope.init = {skip_clearing:false,tax_in_surcharge:false,customer_tax_free:false}; $scope.init = {skip_clearing:false,tax_in_surcharge:false,customer_tax_free:false,allow_surcharge_credit:false};
$scope.getBankAccount = function () { $scope.getBankAccount = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/bank_account').then(function (resp) { $http.get('/sys/partners/' + $scope.partner.client_moniker + '/bank_account').then(function (resp) {
$scope.bankaccount = resp.data; $scope.bankaccount = resp.data;
$scope.bankCtrl.edit = false; $scope.bankCtrl.edit = false;
}); });
}; };
$scope.switchSurchargeMode = function () {
if ($scope.partner.surcharge_mode == "balance") {
commonDialog.confirm({
title: 'Warning',
content: '启用收支分离模式清算将使消费者支付手续费模式失效,请确认是否切换?'
}).then(function () {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/surcharge_mode', {surcharge_mode:'distributed'}).then(function () {
commonDialog.alert({title: 'Success', content: '已切换为收支分离模式', type: 'success'});
$scope.partner.surcharge_mode = 'distributed';
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
}else {
commonDialog.confirm({
title: 'Warning',
content: '请确认是否切换成净值清算模式?'
}).then(function () {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/surcharge_mode', {surcharge_mode:'balance'}).then(function () {
commonDialog.alert({title: 'Success', content: '已切换为净值清算模式', type: 'success'});
$scope.partner.surcharge_mode = 'balance';
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
}
}
$scope.getBalance = function () {
$scope.surcharge = {};
if ($scope.partner.surcharge_mode != undefined && $scope.partner.surcharge_mode == "distributed") {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/surcharge_account').then(function (resp) {
$scope.surcharge = resp.data;
})
}
};
$scope.getBalance();
$scope.getBankAccount(); $scope.getBankAccount();
$scope.getRates = function () { $scope.getRates = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/rates').then(function (resp) { $http.get('/sys/partners/' + $scope.partner.client_moniker + '/rates').then(function (resp) {
@ -2005,8 +2054,38 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}); });
}) })
} }
};
$scope.surchargeAccountDetail = function () {
$uibModal.open({
templateUrl: '/static/payment/surchargeaccount/templates/partner_surcharge_account_dialog.html',
controller: 'surchargeAccountDetailCtrl',
size: 'lg',
resolve: {
balance: function () {
return $scope.surcharge;
},
partner: function () {
return $scope.partner;
},
transactions: ['$http', function ($http) {
return $http.get('/sys/partners/' + $scope.partner.client_moniker + '/account/transactions');
}]
}
}).result.then(function () {
$scope.getBalance();
}, function () {
$scope.getBalance();
});
};
$scope.allowSurchargeCredit = function (allowSurchargeCredit) {
if (!$scope.init.allow_surcharge_credit) {
$scope.init.allow_surcharge_credit = true;
return;
}
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/allow_surcharge_credit', {allow_surcharge_credit: allowSurchargeCredit}).then(function (resp) {
})
}; };
$scope.taxInSurcharge = function (taxInSurcharge) { $scope.taxInSurcharge = function (taxInSurcharge) {
if (!$scope.init.tax_in_surcharge) { if (!$scope.init.tax_in_surcharge) {
@ -2120,6 +2199,51 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}; };
$scope.complianceChangeCheck(); $scope.complianceChangeCheck();
}]); }]);
app.controller('surchargeAccountDetailCtrl', ['$scope','$http','balance','partner','transactions','commonDialog', function ($scope, $http, balance, partner, transactions,commonDialog) {
$scope.surcharge = angular.copy(balance);
$scope.transactions = angular.copy(transactions.data);
$scope.partner = angular.copy(partner);
$scope.canAddDetail = false;
$scope.params = {};
$scope.getBalance = function () {
if ($scope.partner.surcharge_mode != undefined && $scope.partner.surcharge_mode == "distributed") {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/surcharge_account').then(function (resp) {
$scope.surcharge = resp.data;
})
}
};
$scope.getTransactions = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker + '/account/transactions').then(function (resp) {
$scope.transactions = resp.data;
});
}
$scope.addDetail = function () {
$scope.canAddDetail = true;
};
$scope.cancel = function () {
$scope.canAddDetail = false;
$scope.params = {};
}
$scope.save = function () {
$http.post('/sys/partners/' + $scope.partner.client_moniker + '/account/save', {amount:$scope.params.amount,remark:$scope.params.remark}).then(function (resp) {
$scope.getTransactions();
$scope.getBalance();
$scope.canAddDetail = false;
$scope.params = {};
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
});
}
}]);
app.controller('newRateDialogCtrl', ['$scope', '$http', 'rate', 'sys_common_rate', 'clientMoniker', function ($scope, $http, rate, sys_common_rate, clientMoniker) { app.controller('newRateDialogCtrl', ['$scope', '$http', 'rate', 'sys_common_rate', 'clientMoniker', function ($scope, $http, rate, sys_common_rate, clientMoniker) {
$scope.rate = angular.copy(rate); $scope.rate = angular.copy(rate);
$scope.sysRateConfig = angular.copy(sys_common_rate.data); $scope.sysRateConfig = angular.copy(sys_common_rate.data);
@ -3222,6 +3346,75 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
}; };
$scope.chooseLast7Days(); $scope.chooseLast7Days();
}]); }]);
app.controller('partnerSurchargeAccountCtrl', ['$scope', '$uibModal', '$http', 'clientMoniker', '$filter', function ($scope, $uibModal, $http, clientMoniker, $filter) {
$scope.params = {};
$scope.pagination = {};
$scope.today = new Date();
$scope.chooseToday = function () {
$scope.params.datefrom = $scope.params.dateto = new Date();
$scope.loadSettlementLogs(1);
};
$scope.chooseYesterday = function () {
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
$scope.params.datefrom = $scope.params.dateto = yesterday;
$scope.loadSettlementLogs(1);
};
$scope.chooseLast7Days = function () {
$scope.params.dateto = new Date();
var day = new Date();
day.setDate(day.getDate() - 7);
$scope.params.datefrom = day;
$scope.loadSettlementLogs(1);
};
$scope.thisMonth = function () {
$scope.params.dateto = new Date();
var monthBegin = new Date();
monthBegin.setDate(1);
$scope.params.datefrom = monthBegin;
$scope.loadSettlementLogs(1);
};
$scope.lastMonth = function () {
var monthFinish = new Date();
monthFinish.setDate(0);
$scope.params.dateto = monthFinish;
var monthBegin = new Date();
monthBegin.setDate(0);
monthBegin.setDate(1);
$scope.params.datefrom = monthBegin;
$scope.loadSettlementLogs(1);
};
$scope.loadSettlementLogs = function (page) {
var params = angular.copy($scope.params);
if (params.datefrom) {
params.datefrom = $filter('date')(params.datefrom, 'yyyyMMdd');
}
if (params.dateto) {
params.dateto = $filter('date')(params.dateto, 'yyyyMMdd');
}
params.page = page || $scope.pagination.page || 1;
params.limit = 10;
$http.get('/sys/partners/' + clientMoniker + '/surcharge_account/month_detail').then(function (resp) {
$scope.details = resp.data;
});
};
$scope.getClearingTransactions = function (client_id, detail_id) {
$uibModal.open({
templateUrl: '/static/analysis/templates/settlement_transactions.html',
controller: 'managerSettlementDetailCtrl',
resolve: {
detail: ['$http', '$stateParams', function ($http) {
return $http.get('/analysis/partner_card/' + client_id + '/settlement_logs/' + detail_id);
}],
detail_id:detail_id
},
size: 'lg'
});
};
$scope.chooseLast7Days();
}]);
app.controller('managerSettlementDetailCtrl', ['$scope', 'detail','detail_id','$http', function ($scope, detail,detail_id,$http) { app.controller('managerSettlementDetailCtrl', ['$scope', 'detail','detail_id','$http', function ($scope, detail,detail_id,$http) {
$scope.ctrl = {channel: null}; $scope.ctrl = {channel: null};
$scope.show = true; $scope.show = true;

@ -13,6 +13,37 @@
</a> </a>
</h3> </h3>
<div class="form-horizontal"> <div class="form-horizontal">
<div class="form-group" ng-if="partner.surcharge_mode=='distributed'">
<label class="col-sm-4">手续费账户余额</label>
<div class="col-sm-6" style="font-size: 25px">
<p>{{surcharge.balance|currency:'AUD'}}<i class="fa fa-bars" style="font-size: 15px;color: #3c8dbc;cursor: pointer;padding-left: 15px" ng-click="surchargeAccountDetail()"></i></p>
</div>
</div>
<div class="form-group" ng-if="partner.surcharge_mode=='distributed'">
<label class="col-sm-4">允许手续费账户欠款</label>
<div class="col-sm-6">
<input type="checkbox" ng-model="partner.allow_surcharge_credit" bs-switch
switch-change="allowSurchargeCredit(partner.allow_surcharge_credit)">
</div>
</div>
<div class="form-group">
<label class="col-sm-4">Surcharge Mode</label>
<div class="col-sm-6">
<p>
<span ng-if="partner.surcharge_mode=='balance'">balance
<i class="fa fa-sort" style="color: #3c8dbc;cursor: pointer" ng-click="switchSurchargeMode()"></i>
</span>
<span ng-if="partner.surcharge_mode=='distributed'">distributed
<i class="fa fa-sort" style="color: #3c8dbc;cursor: pointer" ng-click="switchSurchargeMode()"></i>
</span>
<p class="text-info">
<i class="fa fa-info"></i>启用到收支分离(distributed)模式,将使消费者支付手续费模式失效<br>
</p>
</p>
</div>
</div>
<div class="form-group" ng-if="'modify_tax_in_surcharge'|withFunc"> <div class="form-group" ng-if="'modify_tax_in_surcharge'|withFunc">
<label class="col-sm-4">RoyalPay Pay GST</label> <label class="col-sm-4">RoyalPay Pay GST</label>
<div class="col-sm-6"> <div class="col-sm-6">

@ -256,6 +256,11 @@
<li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1"> <li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1">
<a ui-sref=".settlement({clientMoniker:partner.client_moniker})">Settlement</a> <a ui-sref=".settlement({clientMoniker:partner.client_moniker})">Settlement</a>
</li> </li>
<li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1 && partner.surcharge_mode=='distributed'">
<a ui-sref=".surcharge_account({clientMoniker:partner.client_moniker})">Surcharge Account</a>
</li>
<li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1"> <li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1">
<a ui-sref=".product">Product</a> <a ui-sref=".product">Product</a>
</li> </li>

@ -0,0 +1,111 @@
<div class="content">
<div class="row">
<div class="col-md-12">
<div class="box-solid">
<!--<div class="box box-warning">-->
<!--<div class="box-header">-->
<!--<div class="row">-->
<!--<div class="col-sm-12">-->
<!--&lt;!&ndash;<div class="form-horizontal">&ndash;&gt;-->
<!--&lt;!&ndash;<div class="form-group col-xs-12">&ndash;&gt;-->
<!--&lt;!&ndash;<label class="control-label col-xs-4 col-sm-2">Date Range</label>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="col-sm-10 col-xs-8">&ndash;&gt;-->
<!--&lt;!&ndash;<div class="form-control-static form-inline">&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: inline-block">&ndash;&gt;-->
<!--&lt;!&ndash;<input class="form-control" id="date-from-input"&ndash;&gt;-->
<!--&lt;!&ndash;ng-model="params.datefrom"&ndash;&gt;-->
<!--&lt;!&ndash;uib-datepicker-popup size="10" placeholder="From"&ndash;&gt;-->
<!--&lt;!&ndash;is-open="dateBegin.open" ng-click="dateBegin.open=true"&ndash;&gt;-->
<!--&lt;!&ndash;datepicker-options="{maxDate:params.dateto||today}">&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;~&ndash;&gt;-->
<!--&lt;!&ndash;<div style="display: inline-block">&ndash;&gt;-->
<!--&lt;!&ndash;<input class="form-control" id="date-to-input"&ndash;&gt;-->
<!--&lt;!&ndash;ng-model="params.dateto"&ndash;&gt;-->
<!--&lt;!&ndash;uib-datepicker-popup size="10" placeholder="To"&ndash;&gt;-->
<!--&lt;!&ndash;is-open="dateTo.open" ng-click="dateTo.open=true"&ndash;&gt;-->
<!--&lt;!&ndash;datepicker-options="{minDate:params.datefrom,maxDate:today}">&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="btn-group">&ndash;&gt;-->
<!--&lt;!&ndash;<a role="button" class="btn btn-default btn-sm"&ndash;&gt;-->
<!--&lt;!&ndash;ng-click="chooseToday()">Today</a>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="btn-group">&ndash;&gt;-->
<!--&lt;!&ndash;<a role="button" class="btn btn-default btn-sm"&ndash;&gt;-->
<!--&lt;!&ndash;ng-click="chooseYesterday()">Yesterday</a>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="btn-group">&ndash;&gt;-->
<!--&lt;!&ndash;<a role="button" class="btn btn-default btn-sm"&ndash;&gt;-->
<!--&lt;!&ndash;ng-click="chooseLast7Days()">Last 7 Days</a>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="btn-group">&ndash;&gt;-->
<!--&lt;!&ndash;<a role="button" class="btn btn-default btn-sm"&ndash;&gt;-->
<!--&lt;!&ndash;ng-click="thisMonth()">This Month</a>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<div class="btn-group">&ndash;&gt;-->
<!--&lt;!&ndash;<a role="button" class="btn btn-default btn-sm"&ndash;&gt;-->
<!--&lt;!&ndash;ng-click="lastMonth()">Last Month</a>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--&lt;!&ndash;<button class="btn btn-success" type="button" ng-click="loadSettlementLogs(1)">&ndash;&gt;-->
<!--&lt;!&ndash;<i class="fa fa-search"></i> Search&ndash;&gt;-->
<!--&lt;!&ndash;</button>&ndash;&gt;-->
<!--&lt;!&ndash;</div>&ndash;&gt;-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<div class="box box-warning">
<div class="box-header">
<h3 class="box-title">Surcharge Account Details</h3>
</div>
<div class="box-body table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Client Moniker</th>
<th>Settle Date</th>
<th>Credit Amount</th>
<th>Debit Amount</th>
<th>Create_time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="log in details">
<td ng-bind="log.client_moniker"></td>
<td ng-bind="log.settle_month"></td>
<td ng-bind="log.credit_amount|currency:'AUD'"></td>
<td ng-bind="log.debit_amount|currency:'AUD'"></td>
<td ng-bind="log.create_time"></td>
</tr>
</tbody>
</table>
</div>
<div class="panel-footer" ng-if="settlementLogs.length">
<uib-pagination class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadSettlementLogs()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="row">
<div class="col-xs-12">Total Records:{{pagination.totalCount}};Total
Pages:{{pagination.totalPages}}
</div>
</div>
</div>
<!-- /.box-footer -->
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,149 @@
/**
* Created by yishuqian on 01/06/2017.
*/
define(['angular', 'decimal', 'uiBootstrap', 'uiRouter', 'angularEcharts'], function (angular) {
'use strict';
var colors = ['#00c0ef', '#00a65a', '#ff851b', '#f39c12', '#d81b60', '#605ca8', '#dd4b39', '#008080', '#8B008B', '#D2691E', '#708090'];
var app = angular.module('surchargeAccountApp', ['ui.bootstrap', 'ui.router', 'ngEcharts']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('surcharge_account', {
url: '/surcharge_account',
templateUrl: '/static/payment/surchargeaccount/templates/client_surcharge_account.html',
resolve: {
partner: ['$http', function ($http) {
return $http.get('/client/partner_info');
}]
},
controller: 'clientSurchargeAccountCtrl'
}).state('surcharge_account_month', {
url: '/surcharge_account_month',
templateUrl: '/static/payment/surchargeaccount/templates/account_month_logs.html',
controller: 'surchargeAccountMonthCtrl'
})
}]);
app.controller('clientSurchargeAccountCtrl', ['$scope', '$http','$state','$filter', 'commonDialog','partner', function ($scope, $http,$state,$filter, commonDialog, partner) {
$scope.partner = angular.copy(partner.data);
$scope.getBalance = function () {
$scope.surcharge = {};
if ($scope.partner.surcharge_mode != undefined && $scope.partner.surcharge_mode == "distributed") {
$http.get('/client/partner_info/' + $scope.partner.client_moniker + '/surcharge_account').then(function (resp) {
$scope.surcharge = resp.data;
})
}
};
$scope.getTransactions = function () {
$http.get('/client/partner_info/' + $scope.partner.client_moniker + '/account/transactions').then(function (resp) {
$scope.transactions = resp.data;
})
}
$scope.getBalance();
$scope.getTransactions();
}]);
app.controller('surchargeAccountMonthCtrl', ['$scope', '$http', '$filter', '$timeout', '$uibModal', 'commonDialog', 'chartParser',
function ($scope, $http, $filter, $timeout, $uibModal, commonDialog, chartParser) {
$scope.params = {year: new Date().getFullYear()};
$scope.availableYears = [new Date().getFullYear() - 1, new Date().getFullYear()];
$scope.initMonth = function (year) {
$scope.params.year = year;
$scope.months = [];
for (var i = 1; i < 13; i++) {
var mon = '00' + i;
mon = mon.substr(mon.length - 2, 2);
$scope.months.push(year + '-' + mon);
}
};
$scope.initMonth(new Date().getFullYear());
$scope.hasReport = function (mon) {
var start = '2017-02';//todo modify in different country
var end = $filter('date')(new Date().setMonth(new Date().getMonth()-1), 'yyyy-MM');
return start <= mon && end >= mon
};
$scope.loadReport = function (mon) {
$http.get('/sys/surcharge_account/month/' + mon + '/settled_dates').then(function (resp) {
$scope.report = {
month: mon,
details: resp.data
};
})
};
$scope.surchargeAccountDetail = function (client_moniker,mon) {
$uibModal.open({
templateUrl: '/static/payment/surchargeaccount/templates/partner_surcharge_account_dialog.html',
controller: 'accountDetailCtrl',
size: 'lg',
resolve: {
client_moniker: function () {
return client_moniker;
},
month: function () {
return mon;
},
transactions: ['$http', function ($http) {
return $http.get('/sys/partners/' + client_moniker + '/account/transactions/date?date='+mon);
}]
}
}).result.then(function () {
$scope.loadReport($scope.report.month);
}, function () {
$scope.loadReport($scope.report.month);
});
};
}]);
app.controller('accountDetailCtrl', ['$scope','$http','transactions','client_moniker','commonDialog','month', function ($scope, $http, transactions,client_moniker,commonDialog,month) {
$scope.transactions = angular.copy(transactions.data);
$scope.canAddDetail = false;
$scope.params = {};
$scope.month = angular.copy(month);
$scope.getBalance = function () {
$http.get('/sys/partners/' + client_moniker + '/surcharge_account').then(function (resp) {
$scope.surcharge = resp.data;
})
};
$scope.getBalance();
$scope.getTransactions = function () {
$http.get('/sys/partners/' + client_moniker + '/account/transactions/date?date=' + $scope.month).then(function (resp) {
$scope.transactions = resp.data;
});
}
$scope.addDetail = function () {
$scope.canAddDetail = true;
};
$scope.cancel = function () {
$scope.canAddDetail = false;
$scope.params = {};
}
$scope.save = function () {
$http.post('/sys/partners/' + client_moniker + '/account/save', {amount:$scope.params.amount,remark:$scope.params.remark}).then(function (resp) {
$scope.getTransactions();
$scope.getBalance();
$scope.canAddDetail = false;
$scope.params = {};
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
});
}
}]);
return app;
});

@ -0,0 +1,76 @@
<section class="content-header">
<h1>Surcharge Account Detail</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-sitemap"></i> Compliance
</li>
<li class="active">Surcharge Account Detail</li>
</ol>
</section>
<section class="content">
<div class="box box-default">
<div class="box-header">
<!-- <div uib-dropdown>
<button class="btn btn-primary" uib-dropdown-toggle type="button" ng-bind="params.year"></button>
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
<li ng-repeat="year in availableYears" role="menuitem"><a role="button" ng-click="initMonth(year)" ng-bind="year"></a></li>
</ul>
</div>-->
<div ng-repeat="year in availableYears" style="display: inline">
<button class="btn btn-info"
ng-click="initMonth(year)"
ng-bind="year"
ng-class="{'active':year == params.year}"
></button>
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-xs-3" ng-repeat="mon in months">
<a class="text-success" role="button" ng-click="loadReport(mon)" ng-if="hasReport(mon)">
<h2 ng-bind="mon.substring(5,7)"></h2>
</a>
<h2 class="text-gray" ng-bind="mon.substring(5,7)" ng-if="!hasReport(mon)"></h2>
</div>
</div>
</div>
</div>
<div class="box box-warning" ng-if="report">
<div class="box-header">
<span ng-bind="report.month"></span>
</div>
<div class="box-body table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>商户编号</th>
<th>Short Name</th>
<th>充值总额</th>
<th>支出总额</th>
<th>余额</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="details in report.details">
<td ng-bind="details.client_moniker"></td>
<td ng-bind="details.short_name"></td>
<td ng-bind="details.credit_amount|currency:'$'" style="color: green"></td>
<td ng-bind="details.debit_amount|currency:'$'" style="color: red"></td>
<td>
<span ng-if="details.balance>=0" style="color: green">{{details.balance|currency:'$'}}</span>
<span ng-if="details.balance<0" style="color: red">{{details.balance|currency:'$'}}</span>
</td>
<td>
<!-- 等待邮件和微信推送模板 -->
<!--<a style="cursor: pointer" > 催款</a>-->
<!--<a style="cursor: pointer" ng-click="showDetail()">充值</a>-->
<i class="fa fa-bars" style="font-size: 15px;color: #3c8dbc;cursor: pointer;padding-left: 15px" ng-click="surchargeAccountDetail(details.client_moniker,details.settle_month)"></i>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>

@ -0,0 +1,114 @@
<section class="content-header">
<h1>
Client Surcharge Account
</h1>
<ol class="breadcrumb">
<li class="active"><i class="fa fa-dashboard"></i> Surcharge Account</li>
</ol>
</section>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="box-solid">
<div class="box box-warning">
<div class="box-header">
<div class="form-horizontal col-sm-8" style="margin-top: 30px">
<div class="form-group" ng-if="partner.surcharge_mode=='distributed'">
<label class="control-label col-xs-4 col-sm-3">手续费账户余额</label>
<div class="col-sm-6" style="font-size: 25px">
<p>{{surcharge.balance|currency:'AUD'}}</p>
</div>
</div>
<div class="form-group" ng-if="partner.surcharge_mode=='distributed'">
<label class="control-label col-xs-4 col-sm-3">允许手续费账户欠款</label>
<div class="col-sm-6">
<input type="checkbox" ng-model="partner.allow_surcharge_credit" bs-switch
switch-change="allowSurchargeCredit(partner.allow_surcharge_credit)" switch-readonly="true">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-4 col-sm-3" style="padding-top:0px">Surcharge Mode:</label>
<div class="col-xs-8 col-sm-6">
<span class="control-label" ng-bind="partner.surcharge_mode"></span>
<p class="text-info">
<i class="fa fa-info"></i>启用到收支分离(distributed)模式,将使消费者支付手续费模式失效
</p>
</div>
</div>
</div>
<div class="col-sm-4" style="text-align: center" ng-if="code_url">
<a class="thumbnail" download ng-href="{{code_url}}" uib-tooltip="Download">
<img ng-src="{{code_url}}">
</a>
<p>
<a ng-href="{{code_url}}" download><i class="fa fa-download"></i> Download Bill QR
Code Image</a>
</p>
</div>
</div>
</div>
<div class="box">
<div class="box box-default">
<div class="box-header">Credits</div>
<div class="box-body">
<div class="table-responsive col-sm-12">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Num</th>
<th>Create Time</th>
<th>Amount</th>
<th>Remark</th>
<th>Operator</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tr in transactions|propsFilter:{type:'Credit',create_time:ctrl.day}:true">
<td>{{$index+1}}</td>
<td ng-bind="tr.create_time|date:'yyyy-MM-dd HH:mm:ss'"></td>
<td ng-bind="tr.amount|currency:'AUD'"></td>
<td ng-bind="tr.remark"></td>
<td ng-bind="tr.operator_displayname"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="box box-default">
<div class="box-header">Debits</div>
<div class="box-body">
<div class="table-responsive col-sm-12">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Num</th>
<th>Settle Date</th>
<th>Amount</th>
<th>Total Surcharge</th>
<th>Tax Amount</th>
<th>Remark</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tr in transactions|propsFilter:{type:'Debit',create_time:ctrl.day}:true">
<td>{{$index+1}}</td>
<td ng-bind="tr.settle_date|date:'yyyy-MM-dd'"></td>
<td ng-bind="tr.amount|currency:'AUD'"></td>
<td ng-bind="tr.total_surcharge|currency:'AUD'"></td>
<td ng-bind="tr.tax_amount|currency:'AUD'"></td>
<td ng-bind="tr.remark"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,88 @@
<div class="modal-header">
<h4>Surcharge Account Detail{{partner.client_moniker?'('+partner.client_moniker+')':''}}</h4>
</div>
<div class="modal-body">
<div class="box box-warning">
<div class="box-body" style="font-size: 35px;text-align: right">
{{surcharge.balance|currency:'AUD'}}<i class="fa fa-plus-square-o" style="font-size: 15px;padding-left: 15px;cursor: pointer" ng-click="addDetail()"></i>
</div>
</div>
<div class="box box-warning" ng-if="canAddDetail">
<div class="box-body">
<div class="row" style="margin-left: 20px;">
<div class="form-group">
<label>
Amount:
</label>
<input type="number" ng-model="params.amount">
<label>
remark:
</label>
<input type="text" ng-model="params.remark">
<div class="btn-group">
<a class="btn btn-success" role="button" ng-click="save()">Submit</a>
</div>
<div class="btn-group">
<a class="btn btn-danger" ng-click="cancel()" >Cancel</a>
</div>
</div>
</div>
</div>
</div>
<div class="box box-default">
<div class="box-header">Credits</div>
<div class="box-body">
<div class="table-responsive col-sm-12">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Num</th>
<th>Create Time</th>
<th>Amount</th>
<th>Remark</th>
<th>Operator</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tr in transactions|propsFilter:{type:'Credit'}:true">
<td>{{$index+1}}</td>
<td ng-bind="tr.create_time|date:'yyyy-MM-dd HH:mm:ss'"></td>
<td ng-bind="tr.amount|currency:'AUD'"></td>
<td ng-bind="tr.remark"></td>
<td ng-bind="tr.operator_displayname"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="box box-default">
<div class="box-header">Debits</div>
<div class="box-body">
<div class="table-responsive col-sm-12">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Num</th>
<th>Settle Date</th>
<th>Amount</th>
<th>Total Surcharge</th>
<th>Tax Amount</th>
<th>Remark</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="tr in transactions|propsFilter:{type:'Debit'}:true">
<td>{{$index+1}}</td>
<td ng-bind="tr.settle_date|date:'yyyy-MM-dd'"></td>
<td ng-bind="tr.amount|currency:'AUD'"></td>
<td ng-bind="tr.total_surcharge|currency:'AUD'"></td>
<td ng-bind="tr.tax_amount|currency:'AUD'"></td>
<td ng-bind="tr.remark"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Loading…
Cancel
Save