Merge branch 'develop_T1249' into develop

# Conflicts:
#	src/main/java/au/com/royalpay/payment/manage/merchants/core/impls/ClientManagerImpl.java
master
luoyang 5 years ago
commit 8b02624f62

@ -5,6 +5,7 @@ import au.com.royalpay.payment.manage.appclient.beans.AppPaymentConfigBean;
import au.com.royalpay.payment.manage.appclient.beans.AppQueryBean;
import au.com.royalpay.payment.manage.appclient.beans.RetailAppMessage;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientUpdateInfo;
import au.com.royalpay.payment.manage.notice.beans.NoticeInfo;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
@ -216,6 +217,8 @@ public interface RetailAppService {
JSONObject getClientAuthFileStatus(JSONObject device);
JSONObject getClientAuthFileStatusAggregate(JSONObject device);
void getCBBankAggregateFile(JSONObject device, HttpServletResponse httpResponse);
JSONObject getSourceAggregateFile(JSONObject device);
@ -224,10 +227,14 @@ public interface RetailAppService {
List<JSONObject> uploadGreenChannelAuthFiles(JSONObject device, ClientAuthFilesInfo filesInfo);
List<JSONObject> uploadKycAuthFiles(JSONObject device, ClientKycFilesInfo filesInfo);
void deleteGreenChannelAuthFiles(JSONObject device, String filesInfo);
void commitAuthFilesToCompliance(JSONObject device, JSONObject photoInfo);
void commitAuthFilesToKyc(JSONObject device);
JSONObject getClientSubManage(JSONObject device);
JSONObject getCustomerInfo(JSONObject device);

@ -15,6 +15,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.device.core.DeviceManager;
import au.com.royalpay.payment.manage.fund.core.impls.XPlanFundConfigServiceImpl;
import au.com.royalpay.payment.manage.kyc.core.KycService;
import au.com.royalpay.payment.manage.management.clearing.core.CleanService;
import au.com.royalpay.payment.manage.mappers.client.AuthAppMessageMapper;
import au.com.royalpay.payment.manage.mappers.log.*;
@ -23,6 +24,7 @@ import au.com.royalpay.payment.manage.mappers.payment.OrderMapper;
import au.com.royalpay.payment.manage.mappers.payment.TransactionMapper;
import au.com.royalpay.payment.manage.mappers.system.*;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientUpdateInfo;
import au.com.royalpay.payment.manage.merchants.core.ClientConfigService;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
@ -83,6 +85,7 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.MessageSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -210,6 +213,12 @@ public class RetailAppServiceImp implements RetailAppService {
@Resource
private MpClientAppWechatApiProvider mpClientAppWechatApiProvider;
@Resource
private KycService kycService;
@Resource
private ClientComplianceCompanyMapper clientComplianceCompanyMapper;
@Resource
private MessageSource messageSource;
@Resource
private DeviceManager deviceManager;
private final String CBBANK_AGGREGATE_FILE = "https://file.royalpay.com.au/open/2019/08/05/1564972204689_uwZvpTBjtLUMcN8c540xcZvux1Rd3O.pdf";
private final String IMG_AGGREGATE_FILE = "https://file.royalpay.com.au/open/2019/10/22/1571723034726_5xK6A0FGv5aQPbMIDJzXJrUPKHFutv.pdf";
@ -2492,6 +2501,76 @@ public class RetailAppServiceImp implements RetailAppService {
return authFileStatus;
}
@Override
public JSONObject getClientAuthFileStatusAggregate(JSONObject device) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
JSONObject client = clientMapper.findClient(device.getIntValue("client_id"));
JSONObject account = clientAccountMapper.findById(device.getString("account_id"));
JSONObject authFileStatus = new JSONObject();
authFileStatus.put("title", messageSource.getMessage("client.auth.file.aggregate.title", null, RequestEnvironment.getLocale()));
authFileStatus.put("content", messageSource.getMessage("client.auth.file.title", null, RequestEnvironment.getLocale()));
List<JSONObject> supplement_array = new ArrayList<>();
JSONObject complianceFilesNotice = complianceFilesNotice(client,account);
JSONObject kycFilesNotice = kycFilesNotice(client,account);
if (PartnerRole.getRole(account.getIntValue("role")) == PartnerRole.CASHIER) {
return null;
}
if(complianceFilesNotice != null){
supplement_array.add(complianceFilesNotice);
}
if(kycFilesNotice != null){
supplement_array.add(kycFilesNotice);
}
authFileStatus.put("supplement_array",supplement_array);
return authFileStatus;
}
public JSONObject complianceFilesNotice(JSONObject client,JSONObject account){
JSONObject complianceFilesNotice = new JSONObject();
JSONObject complianceFileStatus = signInAccountService.checkAuthFileStatus(client);
if(!complianceFileStatus.getBoolean("client_less_file")){
return null;
}
JSONObject compliance = clientComplianceCompanyMapper.findFileByClientId(account.getIntValue("client_id"));
complianceFilesNotice.put("type", messageSource.getMessage("client.auth.file.compliance.type", null, RequestEnvironment.getLocale()));
complianceFilesNotice.put("deadline", messageSource.getMessage("client.auth.file.aggregate.deadline", null, RequestEnvironment.getLocale()));
complianceFilesNotice.put("root_url","111");
complianceFilesNotice.put("client_less_file",complianceFileStatus.getBoolean("client_less_file"));
if(compliance != null){
complianceFilesNotice.put("refused_reason",compliance.getString("description"));
complianceFilesNotice.put("status",compliance.getString("status"));
}
return complianceFilesNotice;
}
public JSONObject kycFilesNotice(JSONObject client,JSONObject account){
JSONObject kycFilesNotice = new JSONObject();
JSONObject kycFileStatus = signInAccountService.checkKycFileStatusForApp(client,account);
JSONObject compliance = clientComplianceCompanyMapper.findKycFileByClientId(account.getIntValue("client_id"));
if(!kycFileStatus.getBoolean("client_less_file")){
return null;
}
kycFilesNotice.put("type", messageSource.getMessage("client.auth.file.kyc.type", null, RequestEnvironment.getLocale()));
kycFilesNotice.put("deadline", messageSource.getMessage("client.auth.file.aggregate.deadline", null, RequestEnvironment.getLocale()));
kycFilesNotice.put("root_url","111");
kycFilesNotice.put("client_less_file",kycFileStatus.getBoolean("client_less_file"));
if(compliance != null){
kycFilesNotice.put("refused_reason",compliance.getString("description"));
kycFilesNotice.put("status",compliance.getString("status"));
}
return kycFilesNotice;
}
@Override
public JSONObject getSourceAggregateFile(JSONObject device) {
String clientType = device.getString("client_type");
@ -2604,6 +2683,17 @@ public class RetailAppServiceImp implements RetailAppService {
return clientManager.uploadAuthFilesForWaitCompliance(account, client.getString("client_moniker"), clientAuthFilesInfo);
}
@Override
public List<JSONObject> uploadKycAuthFiles(JSONObject device, ClientKycFilesInfo clientKycFilesInfo) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
JSONObject client = clientManager.getClientInfo(device.getIntValue("client_id"));
JSONObject account = clientAccountMapper.findById(device.getString("account_id"));
clientKycFilesInfo.setAuthStatus(0);
return clientManager.uploadKycFilesForWaitCompliance(account, client.getString("client_moniker"), clientKycFilesInfo);
}
@Override
public void deleteGreenChannelAuthFiles(JSONObject device, String fileId) {
String clientType = device.getString("client_type");
@ -2621,6 +2711,15 @@ public class RetailAppServiceImp implements RetailAppService {
clientManager.commitAuthFilesToCompliance(client.getString("client_moniker"), account, "App");
}
@Override
public void commitAuthFilesToKyc(JSONObject device) {
String clientType = device.getString("client_type");
deviceSupport.findRegister(clientType);
JSONObject client = clientManager.getClientInfo(device.getIntValue("client_id"));
JSONObject account = clientAccountMapper.findById(device.getString("account_id"));
kycService.commitAuthKycFilesToCompliance(client.getString("client_moniker"), account, "App");
}
public JSONObject getClientSubManage(JSONObject device) {
JSONObject result = new JSONObject();
String clientType = device.getString("client_type");

@ -15,6 +15,7 @@ import au.com.royalpay.payment.manage.bill.bean.QueryBillOrderBean;
import au.com.royalpay.payment.manage.bill.core.BillOrderService;
import au.com.royalpay.payment.manage.bill.core.BillService;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientUpdateInfo;
import au.com.royalpay.payment.manage.riskbusiness.bean.RiskEventQuery;
import au.com.royalpay.payment.manage.riskbusiness.core.RiskBusinessService;
@ -828,6 +829,11 @@ public class RetailAppController {
return retailAppService.getClientAuthFileStatus(device);
}
@GetMapping("/client/auth_file/status/aggregate")
public JSONObject getClientAuthFileStatusAggregate(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device) {
return retailAppService.getClientAuthFileStatusAggregate(device);
}
/**
*
*
@ -893,6 +899,26 @@ public class RetailAppController {
retailAppService.commitAuthFilesToCompliance(device, photoInfo);
}
/**
* KYC
*
* @param device
*/
@PutMapping("/client/kyc_auth_file")
public List<JSONObject> uploadKycAuthFiles(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device, @RequestBody ClientKycFilesInfo filesInfo) {
return retailAppService.uploadKycAuthFiles(device, filesInfo);
}
/**
* Kyc
*
* @param device
*/
@PostMapping("/client/auth_file/commit_to_kyc")
public void commitToKycAuthFiles(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device) {
retailAppService.commitAuthFilesToKyc(device);
}
@GetMapping("/client/sub_manage")
public JSONObject getClientSubManage(@ModelAttribute(CommonConsts.RETAIL_DEVICE) JSONObject device) {
return retailAppService.getClientSubManage(device);

@ -13,12 +13,16 @@ public class ClientComplianceQuery {
private int page = 1;
private String status;
private String client_moniker;
private String type = "1";
public JSONObject toJson(){
JSONObject jason = new JSONObject();
if(StringUtils.isNotEmpty(status)){
jason.put("status",status);
}
if(StringUtils.isNotEmpty(type)){
jason.put("type",type);
}
if(StringUtils.isNotEmpty(client_moniker)){
jason.put("client_moniker",client_moniker);
}
@ -56,4 +60,12 @@ public class ClientComplianceQuery {
public void setClient_moniker(String client_moniker) {
this.client_moniker = client_moniker;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

@ -16,6 +16,10 @@ public interface ClientComplianceApply {
void passComplianceFile(JSONObject manager,int clientId,JSONObject passInfo);
void passKycFile(JSONObject manager,int clientId,JSONObject passInfo);
void refuseComplianceFile(JSONObject manager,int clientId,JSONObject refuseInfo);
void refuseKycFile(JSONObject manager,int clientId,JSONObject refuseInfo);
}

@ -4,10 +4,12 @@ package au.com.royalpay.payment.manage.complianceAudit.core.impl;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.manage.complianceAudit.bean.ClientComplianceQuery;
import au.com.royalpay.payment.manage.complianceAudit.core.ClientComplianceApply;
import au.com.royalpay.payment.manage.kyc.enums.FilesAuthEnum;
import au.com.royalpay.payment.manage.mappers.system.ClientComplianceCompanyMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientFilesMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.signin.core.SignInAccountService;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.utils.PageListUtils;
@ -16,9 +18,7 @@ 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.lang3.StringUtils;
import org.omg.CORBA.SystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@ -38,6 +38,8 @@ public class ClientComplianceApplyImpl implements ClientComplianceApply
private ClientManager clientManager;
@Resource
private ClientMapper clientMapper;
@Resource
private SignInAccountService signInAccountService;
@Override
public JSONObject listClientComplianceApply(JSONObject manager, ClientComplianceQuery applyQuery) {
@ -94,7 +96,10 @@ public class ClientComplianceApplyImpl implements ClientComplianceApply
complianceDetail.put("status",1);
complianceDetail.put("description",' ');
clientComplianceCompanyMapper.update(complianceDetail);
clientFilesMapper.passCompliance(clientId);
clientFilesMapper.updateFilesAuthStatus(clientId,
FilesAuthEnum.PASS_OPR.getAfterStatus(),
FilesAuthEnum.PASS_OPR.getBeforeStatus(),
FilesAuthEnum.PASS_OPR.getAuthType("compliance"));
JSONObject client = clientManager.getClientInfo(clientId);
boolean clientChanged = false;
@ -115,6 +120,29 @@ public class ClientComplianceApplyImpl implements ClientComplianceApply
}
}
@Override
public void passKycFile(JSONObject manager, int clientId, JSONObject passInfo) {
JSONObject complianceDetail = clientComplianceCompanyMapper.findKycFileByClientId(clientId);
if (complianceDetail == null) {
throw new BadRequestException("无此记录");
}
if (complianceDetail.getIntValue("status") == 1) {
throw new BadRequestException("审核已通过,请避免重复操作");
}
complianceDetail.put("operator_id", manager.getString("manager_id"));
complianceDetail.put("status",1);
complianceDetail.put("description",' ');
clientComplianceCompanyMapper.update(complianceDetail);
clientFilesMapper.updateFilesAuthStatus(clientId,
FilesAuthEnum.PASS_OPR.getAfterStatus(),
FilesAuthEnum.PASS_OPR.getBeforeStatus(),
FilesAuthEnum.PASS_OPR.getAuthType("kyc"));
String[] unrepeatFiles = {"client_bank_file","client_id_file"};
for(String fileName : unrepeatFiles){
clientFilesMapper.updateRepeatFilesAfterCommit(clientId,fileName);
}
}
@Override
public void refuseComplianceFile(JSONObject manager, int clientId, JSONObject refuseInfo) {
JSONObject complianceDetail = clientComplianceCompanyMapper.findFileByClientId(clientId);
@ -123,12 +151,34 @@ public class ClientComplianceApplyImpl implements ClientComplianceApply
}
if (complianceDetail.getIntValue("status") == 2) {
throw new BadRequestException("已打回,请避免重复操作");
}
complianceDetail.put("description",refuseInfo.getString("description"));
complianceDetail.put("operator_id", manager.getString("manager_id"));
complianceDetail.put("status",2);
clientComplianceCompanyMapper.update(complianceDetail);
clientFilesMapper.updateFilesAuthStatus(clientId,
FilesAuthEnum.REFUSE_OPR.getAfterStatus(),
FilesAuthEnum.REFUSE_OPR.getBeforeStatus(),
FilesAuthEnum.REFUSE_OPR.getAuthType("compliance"));
}
@Override
public void refuseKycFile(JSONObject manager, int clientId, JSONObject refuseInfo) {
JSONObject complianceDetail = clientComplianceCompanyMapper.findKycFileByClientId(clientId);
if (complianceDetail == null) {
throw new BadRequestException("无此记录");
}
if (complianceDetail.getIntValue("status") == 2) {
throw new BadRequestException("已打回,请避免重复操作");
}
complianceDetail.put("description",refuseInfo.getString("description"));
complianceDetail.put("operator_id", manager.getString("manager_id"));
complianceDetail.put("status",2);
clientComplianceCompanyMapper.update(complianceDetail);
clientFilesMapper.refuseCompliance(clientId);
clientFilesMapper.updateFilesAuthStatus(clientId,
FilesAuthEnum.REFUSE_OPR.getAfterStatus(),
FilesAuthEnum.REFUSE_OPR.getBeforeStatus(),
FilesAuthEnum.REFUSE_OPR.getAuthType("kyc"));
}
}

@ -1,5 +1,6 @@
package au.com.royalpay.payment.manage.complianceAudit.web;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.manage.complianceAudit.bean.ClientComplianceQuery;
import au.com.royalpay.payment.manage.complianceAudit.core.ClientComplianceApply;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
@ -38,16 +39,36 @@ public class ComplianceAuditController
clientComplianceApply.passComplianceFile(manager,clientId,passInfo);
}
@ManagerMapping(value = "/{clientId}/pass/kycFile", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void passKycAudit(@PathVariable int clientId, @RequestBody JSONObject passInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientComplianceApply.passKycFile(manager,clientId,passInfo);
}
@ManagerMapping(value = "/{clientId}/refuse/complianceFile", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void refuseComplianceAudit(@PathVariable int clientId, @RequestBody JSONObject refuseInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientComplianceApply.refuseComplianceFile(manager,clientId,refuseInfo);
}
@ManagerMapping(value = "/{clientId}/refuse/kycFile", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void refuseKycAudit(@PathVariable int clientId, @RequestBody JSONObject refuseInfo, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientComplianceApply.refuseKycFile(manager,clientId,refuseInfo);
}
@RequestMapping(value = "/compliance/clientViewFiles/{clientMoniker}",method = RequestMethod.GET)
@RequireManager(role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT})
public JSONObject searchCompliances(@PathVariable String clientMoniker) {
JSONObject client = clientMapper.findClientByMoniker(clientMoniker);
return clientManager.getComplianceFilesForBD(client);
return clientManager.getComplianceFilesForClient(client);
}
@RequestMapping(value = "/kyc/clientViewFiles/{clientMoniker}", method = RequestMethod.GET)
@RequireManager(role = {ManagerRole.ADMIN, ManagerRole.BD_USER, ManagerRole.OPERATOR, ManagerRole.SERVANT})
public JSONObject searchKycFiles(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
JSONObject client = clientMapper.findClientByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
return clientManager.getKycFilesForBD(client, manager, "operator");
}
}

@ -0,0 +1,68 @@
package au.com.royalpay.payment.manage.kyc.bean;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
/**
* Created by yishuqian on 8/30/16.
*/
public class KycPartnersQuery {
private String client_moniker;
private String status;
private int page = 1;
private int limit = 10;
private boolean onlyMe = false;
public String getClient_moniker() {
return client_moniker;
}
public void setClient_moniker(String client_moniker) {
this.client_moniker = client_moniker;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public boolean isOnlyMe() {
return onlyMe;
}
public void setOnlyMe(boolean onlyMe) {
this.onlyMe = onlyMe;
}
public JSONObject toJsonParam() {
JSONObject param = new JSONObject();
if (StringUtils.isNotBlank(client_moniker)) {
param.put("client_moniker", getClient_moniker());
}
if (StringUtils.isNotBlank(status)) {
param.put("status", getStatus());
}
return param;
}
}

@ -0,0 +1,30 @@
package au.com.royalpay.payment.manage.kyc.core;
import au.com.royalpay.payment.manage.kyc.bean.KycPartnersQuery;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
public interface KycService {
JSONObject listProgressClients(JSONObject manager, KycPartnersQuery query);
JSONObject listCompletedClients(JSONObject manager, KycPartnersQuery query);
JSONObject getKycDashboard(JSONObject manager);
List<JSONObject> listNeedHelpClients(JSONObject manager, KycPartnersQuery query);
void sendNotify(JSONObject complianceInfo);
void kycNotifyBd(JSONObject account, String source);
JSONObject getKycFilesForBdHelp(JSONObject manager, String clientMoniker);
void commitAuthKycFilesToCompliance(String clientMoniker, JSONObject account, String source);
void uploadKycFiles(JSONObject manager, String clientMoniker, ClientKycFilesInfo kycFilesInfo);
void deleteAuthFiles(String fileId, JSONObject manager);
}

@ -0,0 +1,323 @@
package au.com.royalpay.payment.manage.kyc.core.impls;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.manage.kyc.bean.KycPartnersQuery;
import au.com.royalpay.payment.manage.kyc.core.KycService;
import au.com.royalpay.payment.manage.kyc.enums.FilesAuthEnum;
import au.com.royalpay.payment.manage.mappers.financial.FinancialBDConfigMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientBDMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientComplianceCompanyMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientFilesMapper;
import au.com.royalpay.payment.manage.mappers.system.ClientMapper;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
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.core.SignInAccountService;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApi;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApiProvider;
import au.com.royalpay.payment.tools.connections.mpsupport.beans.TemplateMessage;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.threadpool.RoyalThreadPoolExecutor;
import au.com.royalpay.payment.tools.utils.PageListUtils;
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.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class KycServiceImpl implements KycService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private MailService mailService;
@Resource
private ClientMapper clientMapper;
@Resource
private ClientManager clientManager;
@Resource
private ClientBDMapper clientBDMapper;
@Resource
private FinancialBDConfigMapper financialBDConfigMapper;
@Resource
private ClientComplianceCompanyMapper clientComplianceCompanyMapper;
@Resource
private SpringTemplateEngine thymeleaf;
@Resource
private RoyalThreadPoolExecutor royalThreadPoolExecutor;
@Resource
private MpWechatApiProvider mpWechatApiProvider;
@Resource
private ClientFilesMapper clientFilesMapper;
@Resource
private SignInAccountService signInAccountService;
@Override
public JSONObject listProgressClients(JSONObject manager, KycPartnersQuery query) {
JSONObject params = query.toJsonParam();
checkManagerPermission(manager, params, query);
PageList<JSONObject> progressClients = clientComplianceCompanyMapper.listKycProgressClients(params, new PageBounds(query.getPage(), query.getLimit(), Order.formString("create_time.desc")));
return PageListUtils.buildPageListResult(progressClients);
}
@Override
public JSONObject listCompletedClients(JSONObject manager, KycPartnersQuery query) {
JSONObject params = query.toJsonParam();
checkManagerPermission(manager, params, query);
PageList<JSONObject> completedClients = clientMapper.listCompletedContractKycClients(params, new PageBounds(query.getPage(), query.getLimit(), Order.formString("create_time.desc")));
return PageListUtils.buildPageListResult(completedClients);
}
@Override
public JSONObject getKycDashboard(JSONObject manager) {
JSONObject params = new JSONObject();
JSONObject result = new JSONObject();
checkManagerPermission(manager,params,null);
List<JSONObject> needHelps = clientComplianceCompanyMapper.listNeedHelpClients(params);
result.put("total_need_help", needHelps != null ? needHelps.size() : 0);
result.put("total_partner", clientMapper.countKycClients(params));
result.put("total_progressing", clientComplianceCompanyMapper.countKycProgressClients(params));
params.put("status", 1);
result.put("total_pass_partner", clientComplianceCompanyMapper.countKycProgressClients(params));
params.put("status", 2);
result.put("total_refuse_partner", clientComplianceCompanyMapper.countKycProgressClients(params));
return result;
}
@Override
public List<JSONObject> listNeedHelpClients(JSONObject manager, KycPartnersQuery query) {
JSONObject params = query.toJsonParam();
checkManagerPermission(manager, params, query);
return clientComplianceCompanyMapper.listNeedHelpClients(params);
}
@Override
public void sendNotify(JSONObject complianceInfo) {
JSONObject client = clientMapper.findClient(complianceInfo.getIntValue("client_id"));
List<JSONObject> bds = clientBDMapper.listClientBDInfoAvailable(complianceInfo.getIntValue("client_id"), new Date());
List<String> emails = new ArrayList<>();
List<String> openIds = new ArrayList<>();
String bdNames = "";
for (JSONObject bd : bds) {
String email = bd.getString("email");
if (StringUtils.isNotEmpty(email)) {
emails.add(email);
bdNames += bd.getString("display_name");
}
if (StringUtils.isNotEmpty(bd.getString("wechat_openid"))) {
openIds.add(bd.getString("wechat_openid"));
}
}
Context ctx = new Context();
ctx.setVariable("img_url", PlatformEnvironment.getEnv().concatUrl("/static/images/royalpay_logo.png"));
ctx.setVariable("name", bdNames);
ctx.setVariable("client_moniker", client.getString("client_moniker"));
ctx.setVariable("contact_person", client.getString("contact_person"));
ctx.setVariable("contact_phone", client.getString("contact_phone"));
ctx.setVariable("contact_email", client.getString("contact_email"));
ctx.setVariable("submit_time", DateFormatUtils.format(complianceInfo.getDate("submit_time"),"yyyy-MM-dd HH:mm:ss"));
final String content = thymeleaf.process("mail/kyc_email_notice", ctx);
if (emails.size() > 0) {
royalThreadPoolExecutor.execute(() -> {
try {
mailService.sendEmail("[RoyalPay]商户需要您协助补充KYC材料,请尽快查看", StringUtils.join(emails, ","), "", content);
} catch (Exception e) {
logger.error("邮件发送失败", e);
}
});
}
if (openIds.size() > 0) {
for (String openId : openIds) {
try {
MpWechatApi mpWechatApi = mpWechatApiProvider.getApiFromOpenId(openId);
if (mpWechatApi == null) {
return;
}
String templateId = mpWechatApi.getTemplateId("commission");
if (templateId == null) {
return;
}
TemplateMessage message = new TemplateMessage(openId, templateId, null);
message.put("first", "有新商户需要您协助补充KYC材料,请尽快查看", "#ff0000");
message.put("keyword1", "KYC认证", "#0000ff");
message.put("keyword2", client.getString("company_name")+"("+client.getString("client_moniker")+")", "#000000");
message.put("keyword3", DateFormatUtils.format(complianceInfo.getDate("submit_time"),"yyyy-MM-dd HH:mm:ss"), "#000000");
message.put("keyword4", "联系人:" + client.getString("contact_person") + " 电话:" + client.getString("contact_phone"), "#000000");
message.put("remark", "您可以在后台帮助商户提交材料或填写无法提供材料文件的原因", "#ff0000");
mpWechatApi.sendTemplateMessage(message);
} catch (Exception e) {
logger.error("notify bdhelp message failed:", e);
}
}
}
}
@Override
public void kycNotifyBd(JSONObject account, String source) {
JSONObject client = clientManager.getClientInfo(account.getIntValue("client_id"));
if (client == null) {
throw new InvalidShortIdException();
}
int sourceEnum = 2;
if ("app".equals(source.toLowerCase())) {
sourceEnum = 1;
}
JSONObject fileComp = clientComplianceCompanyMapper.findKycFileByClientId(client.getIntValue("client_id"));
if (fileComp == null) {
fileComp = new JSONObject();
fileComp.put("client_id", client.getIntValue("client_id"));
fileComp.put("submit_time", new Date());
fileComp.put("status", 9);
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.getString("account_id"));
fileComp.put("type", 2);
fileComp.put("is_valid", 1);
clientComplianceCompanyMapper.save(fileComp);
} else if (fileComp.getIntValue("status") == 2) {
fileComp.put("status", 9);
fileComp.put("submit_time", new Date());
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.getString("account_id"));
clientComplianceCompanyMapper.update(fileComp);
} else {
throw new BadRequestException("please do not repeat submission");
}
sendNotify(fileComp);
}
@Override
public JSONObject getKycFilesForBdHelp(JSONObject manager, String clientMoniker) {
JSONObject client = clientManager.getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkClientBelongBd(client.getIntValue("client_id"), manager);
JSONObject kycInfo = clientComplianceCompanyMapper.findKycFileByClientId(client.getIntValue("client_id"));
if (kycInfo == null || kycInfo.getIntValue("status") != 9) {
throw new BadRequestException("This Partner is not application submitted");
}
return clientManager.getKycFilesForBD(client, manager, "client");
}
@Override
public void commitAuthKycFilesToCompliance(String clientMoniker, JSONObject account, String source) {
JSONObject client = clientManager.getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
if (account.containsKey("manager_id")) {
checkClientBelongBd(client.getIntValue("client_id"), account);
}
int sourceEnum = 2;
List<JSONObject> clientAllAuthFiles = clientFilesMapper.findAllClientFile(client.getIntValue("client_id"));
if (clientAllAuthFiles == null || clientAllAuthFiles.size() == 0) {
throw new BadRequestException("Please check the information is uploaded completely");
}
String[] fileKeys = {"client_bank_file", "client_id_file"};
String[] fileNames = {"ASIC File", "ID"};
if(StringUtils.equalsIgnoreCase("passport",account.getString("id_type")) ){
String[] fileKeysPassport = {"client_bank_file", "kyc_utility_bill_file", "client_id_file"};
String[] fileNamesPassport = {"ASIC File", "Utility Bill Files", "ID"};
fileKeys = fileKeysPassport;
fileNames = fileNamesPassport;
}
if( !(account.getString("bd_handle") !=null && account.getString("bd_handle").length() > 0) ){
for (int i = 0; i < fileKeys.length; i++) {
String fileKey = fileKeys[i];
if (clientAllAuthFiles.stream().noneMatch(fileJson -> fileKey.equals(fileJson.getString("file_name")))) {
throw new BadRequestException("Please check the " + fileNames[i] + " is uploaded completely");
}
}
}
if ("app".equals(source.toLowerCase())) {
sourceEnum = 1;
}
JSONObject fileComp = clientComplianceCompanyMapper.findKycFileByClientId(client.getIntValue("client_id"));
if (fileComp == null) {
fileComp = new JSONObject();
fileComp.put("client_id", client.getIntValue("client_id"));
fileComp.put("submit_time", new Date());
fileComp.put("status", 0);
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.containsKey("account_id") ? account.getString("account_id") : account.getString("manager_id"));
fileComp.put("type", 2);
fileComp.put("id_type", account.getString("id_type"));
clientComplianceCompanyMapper.save(fileComp);
} else if (fileComp.getIntValue("status") == 2 || fileComp.getIntValue("status") == 9) {
fileComp.put("status", 0);
fileComp.put("submit_time", new Date());
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.containsKey("account_id") ? account.getString("account_id") : account.getString("manager_id"));
fileComp.put("id_type", account.getString("id_type"));
fileComp.put("bd_handle", account.getString("bd_handle"));
clientComplianceCompanyMapper.update(fileComp);
} else {
throw new BadRequestException("please do not repeat submission");
}
clientFilesMapper.updateFilesAuthStatus(client.getIntValue("client_id"),
FilesAuthEnum.COMMIT_OPR.getAfterStatus(),
FilesAuthEnum.COMMIT_OPR.getBeforeStatus(),
FilesAuthEnum.COMMIT_OPR.getAuthType("kyc"));
if (account.containsKey("account_id")) {
signInAccountService.clearAccountCache(account.getString("account_id"));
}
}
@Override
public void uploadKycFiles(JSONObject manager, String clientMoniker, ClientKycFilesInfo kycFilesInfo) {
JSONObject client = clientManager.getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
checkClientBelongBd(client.getIntValue("client_id"), manager);
clientManager.uploadKycFilesForWaitCompliance(manager, clientMoniker, kycFilesInfo);
}
@Override
public void deleteAuthFiles(String fileId, JSONObject manager) {
JSONObject file = clientFilesMapper.findFileById(fileId);
if (file.getIntValue("status") == 1 || file.getIntValue("status") == 2) {
throw new BadRequestException("The file has passed and cannot be deleted");
}
JSONObject client = clientManager.getClientInfo(file.getIntValue("client_id"));
if (client == null) {
throw new InvalidShortIdException();
}
checkClientBelongBd(file.getIntValue("client_id"), manager);
clientFilesMapper.deleteByClientAndFileId(fileId);
}
private void checkManagerPermission(JSONObject manager, JSONObject params, KycPartnersQuery query) {
if (ManagerRole.BD_USER.hasRole(manager.getIntValue("role"))) {
params.put("bd_user", manager.getString("manager_id"));
}
if (ManagerRole.OPERATOR.hasRole(manager.getIntValue("role"))) {
params.put("bd_user", "186");
}
}
private void checkClientBelongBd(int clientId, JSONObject manager) {
if (ManagerRole.OPERATOR.hasRole(manager.getIntValue("role"))) {
manager.put("manager_id","186");
}
int permissionInt = clientBDMapper.checkBDPermission(clientId, manager.getString("manager_id"));
if (permissionInt < 1) {
throw new BadRequestException("This Partner is not belongs to you");
}
}
}

@ -0,0 +1,41 @@
package au.com.royalpay.payment.manage.kyc.enums;
/**
* @Author: liuxinxin
* @Date: 2019-12-13
*/
public enum FilesAuthEnum {
PASS_OPR(new int[]{2},1),
COMMIT_OPR(new int[]{0,3},2),
REFUSE_OPR(new int[]{2},3);
private final int[] beforeStatus;
private final int afterStatus;
public int[] getBeforeStatus() {
return beforeStatus;
}
public int getAfterStatus() {
return afterStatus;
}
FilesAuthEnum(int[] beforeStatus, int afterStatus) {
this.beforeStatus = beforeStatus;
this.afterStatus = afterStatus;
}
public String[] getAuthType(String type) {
switch (type) {
case "kyc":
return new String[]{"client_bank_file","client_id_file","kyc_utility_bill_file"};
case "compliance":
return new String[]{"client_bank_file","client_id_file","client_agree_file","client_company_file"};
default:
return null;
}
}
}

@ -0,0 +1,40 @@
package au.com.royalpay.payment.manage.kyc.web;
import au.com.royalpay.payment.manage.kyc.core.KycService;
import au.com.royalpay.payment.manage.mappers.system.ClientComplianceCompanyMapper;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.permission.manager.PartnerMapping;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/sys/kyc/partner")
public class KycController {
@Resource
private KycService kycService;
@Resource
private ClientManager clientManager;
@Resource
private ClientComplianceCompanyMapper clientComplianceCompanyMapper;
@PartnerMapping(value = "/notifyBd", method = RequestMethod.PUT)
@ResponseBody
public void clientKycBdIntervention(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account) {
kycService.kycNotifyBd(account, "web");
}
@PartnerMapping(value = "/update/wait_kyc_file", method = RequestMethod.PUT)
@ResponseBody
public void updateWaitKycFile(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestBody ClientKycFilesInfo filesInfo) {
JSONObject kycFilesAuth = clientComplianceCompanyMapper.findKycFileComplete(account.getIntValue("client_id"));
if (kycFilesAuth != null) {
throw new BadRequestException("已通过审核,暂不能提交和修改");
}
clientManager.uploadKycFilesForWaitCompliance(account, account.getString("client_moniker"), filesInfo);
}
}

@ -0,0 +1,62 @@
package au.com.royalpay.payment.manage.kyc.web;
import au.com.royalpay.payment.manage.kyc.bean.KycPartnersQuery;
import au.com.royalpay.payment.manage.kyc.core.KycService;
import au.com.royalpay.payment.manage.merchants.beans.ClientKycFilesInfo;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.tools.CommonConsts;
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.util.List;
@RestController
@RequestMapping("/sys/kyc/manage")
public class KycManageController {
@Resource
private KycService kycService;
@ManagerMapping(value = "/partner/progressing", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public JSONObject listProgressClients(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, KycPartnersQuery query) {
return kycService.listProgressClients(manager, query);
}
@ManagerMapping(value = "/partner/completed", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public JSONObject listCompletedClients(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, KycPartnersQuery query) {
return kycService.listCompletedClients(manager, query);
}
@ManagerMapping(value = "/partner/need_help", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public List<JSONObject> listNeedHelpClients(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, KycPartnersQuery query) {
return kycService.listNeedHelpClients(manager, query);
}
@ManagerMapping(value = "/partner/dashboard", method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public JSONObject getKycDashboard(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return kycService.getKycDashboard(manager);
}
@ManagerMapping(value = "/{clientMoniker}/bd_help",method = RequestMethod.GET, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public JSONObject getKycFilesForBdHelp(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @PathVariable String clientMoniker) {
return kycService.getKycFilesForBdHelp(manager,clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/kycCommit", method = RequestMethod.POST, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void clientKycFilesViewCommit(@PathVariable String clientMoniker ,@RequestBody JSONObject params,@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
manager.put("id_type", params.getString("id_type"));
manager.put("bd_handle", params.getString("bd_handle"));
kycService.commitAuthKycFilesToCompliance(clientMoniker, manager, "Web");
}
@ManagerMapping(value = "/{clientMoniker}/update", role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void updateKycFile(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, @RequestBody ClientKycFilesInfo filesInfo) {
kycService.uploadKycFiles(manager, clientMoniker, filesInfo);
}
@ManagerMapping(value = "/auth_file/{fileId}/delete", method = RequestMethod.PUT, role = {ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void deleteAuthFiles(@PathVariable String fileId, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
kycService.deleteAuthFiles(fileId, manager);
}
}

@ -23,8 +23,23 @@ public interface ClientComplianceCompanyMapper {
void update(JSONObject partner);
@AutoSql(type = SqlType.SELECT)
JSONObject findFileByClientId(@Param("client_id") int client_id);
@AdvanceSelect(addonWhereClause = "type = 1")
JSONObject findFileByClientId(@Param("client_id") int clientId);
@AutoSql(type = SqlType.SELECT)
@AdvanceSelect(addonWhereClause = "type = 2")
JSONObject findKycFileByClientId(@Param("client_id") int clientId);
@AutoSql(type = SqlType.SELECT)
@AdvanceSelect(addonWhereClause = "type = 2 and status in (0,1,9)")
JSONObject findKycFileComplete(@Param("client_id") int clientId);
PageList<JSONObject> listClientCompliances(JSONObject params, PageBounds pageBounds);
List<JSONObject> listNeedHelpClients(JSONObject params);
PageList<JSONObject> listKycProgressClients(JSONObject params, PageBounds pageBounds);
int countKycProgressClients(JSONObject params);
}

@ -6,7 +6,6 @@ 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 org.springframework.core.annotation.Order;
import java.util.List;
@ -25,6 +24,9 @@ public interface ClientFilesMapper {
@AdvanceSelect(addonWhereClause = "is_valid = 1 and status = 1")
List<JSONObject> findClientFile(@Param("client_id") int clientId);
@AutoSql(type = SqlType.SELECT)
JSONObject findFileByIdAndvalue(@Param("client_id") int clientId,@Param("file_name") String fileType);
@AutoSql(type = SqlType.SELECT)
@AdvanceSelect(addonWhereClause = "is_valid = 1 and (status = 1 or status = 2) and file_name='client_agree_file'")
List<JSONObject> findClientPassAggreeFile(@Param("client_id") int clientId);
@ -35,6 +37,12 @@ public interface ClientFilesMapper {
List<JSONObject> findAllClientFile(@Param("client_id") int clientId);
List<JSONObject> findKycClientFileByClient(@Param("client_id") int clientId);
List<JSONObject> findKycClientFileByAudit(@Param("client_id") int clientId);
List<JSONObject> findRepetitiveFiles(@Param("client_id") int clientId,@Param("file_name") String fileType);
@AutoSql(type = SqlType.SELECT)
JSONObject findFileById(@Param("file_id") String file_id);
@ -48,9 +56,7 @@ public interface ClientFilesMapper {
void confirmAgreeFile(@Param("client_id") int client_id);
void updateBeforeCompliance(@Param("client_id") int client_id);
void refuseCompliance(@Param("client_id") int client_id);
void updateFilesAuthStatus(@Param("client_id") int client_id,@Param("status") int status,@Param("original_status_type") int[] original_status_type,@Param("file_names") String[] file_names);
void passCompliance(@Param("client_id") int client_id);
void updateRepeatFilesAfterCommit(@Param("client_id") int client_id, @Param("file_name") String fileName);
}

@ -4,7 +4,6 @@ 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.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
@ -141,4 +140,7 @@ public interface ClientMapper {
List<Integer> listUseAlipayMerchant(@Param("start") int start, @Param("end") int end);
PageList<JSONObject> listCompletedContractKycClients(JSONObject params, PageBounds pageBounds);
int countKycClients(JSONObject params);
}

@ -0,0 +1,54 @@
package au.com.royalpay.payment.manage.merchants.beans;
import com.alibaba.fastjson.JSONObject;
/**
* Created by liuxinxin on 09/12/2019.
*/
public class ClientKycFilesInfo {
private String file_bank_info;
private String file_id_info;
private String utility_bill_info;
private int authStatus=0;
public JSONObject toJson(){
return (JSONObject)JSONObject.toJSON(this);
}
public String getFile_bank_info() {
return file_bank_info;
}
public void setFile_bank_info(String file_bank_info) {
this.file_bank_info = file_bank_info;
}
public String getFile_id_info() {
return file_id_info;
}
public void setFile_id_info(String file_id_info) {
this.file_id_info = file_id_info;
}
public String getUtility_bill_info() {
return utility_bill_info;
}
public void setUtility_bill_info(String utility_bill_info) {
this.utility_bill_info = utility_bill_info;
}
public int getAuthStatus() {
return authStatus;
}
public void setAuthStatus(int authStatus) {
this.authStatus = authStatus;
}
}

@ -252,6 +252,8 @@ public interface ClientManager {
JSONObject getAllAuthFiles(JSONObject manager, String clientMoniker);
JSONObject getAllKycFiles(JSONObject manager, String clientMoniker);
JSONObject getSourceAgreeFiles(JSONObject manage, String clientMoniker);
void deleteAuthFiles(String fileId);
@ -260,6 +262,10 @@ public interface ClientManager {
void uploadAuthFiles(JSONObject manager, String clientMoniker, ClientAuthFilesInfo filesInfo);
void uploadKycFiles(JSONObject manager, String clientMoniker, ClientKycFilesInfo filesInfo);
List<JSONObject> uploadKycFilesForWaitCompliance(JSONObject manager, String clientMoniker, ClientKycFilesInfo filesInfo);
List<JSONObject> uploadAuthFilesForWaitCompliance(JSONObject manager, String clientMoniker, ClientAuthFilesInfo filesInfo);
void commitAuthFilesToCompliance(String clientMoniker, JSONObject account, String source);
@ -493,9 +499,13 @@ public interface ClientManager {
JSONObject getComplianceFiles(JSONObject account);
JSONObject getKycFiles(JSONObject account);
JSONObject getClientInfoByAggree(JSONObject account);
JSONObject getComplianceFilesForBD(JSONObject account);
JSONObject getComplianceFilesForClient(JSONObject account);
JSONObject getKycFilesForBD(JSONObject client, JSONObject manager, String sourceType);
/**
*
@ -505,6 +515,8 @@ public interface ClientManager {
*/
JSONObject partnerIncrementalService(String clientMoniker);
boolean isPartnerKycfilesComplete(String clientMoniker);
/**
* /
*

@ -17,16 +17,16 @@ import au.com.royalpay.payment.core.PaymentChannelApi;
import au.com.royalpay.payment.core.exceptions.EmailException;
import au.com.royalpay.payment.core.exceptions.InvalidShortIdException;
import au.com.royalpay.payment.core.mappers.SysClientMapper;
import au.com.royalpay.payment.manage.appclient.beans.RSvcMchBean;
import au.com.royalpay.payment.tools.defines.IncrementalChannel;
import au.com.royalpay.payment.core.utils.OrderExpiryRuleResolver;
import au.com.royalpay.payment.manage.analysis.mappers.TransactionAnalysisMapper;
import au.com.royalpay.payment.manage.appclient.beans.AppClientBean;
import au.com.royalpay.payment.manage.appclient.beans.AppMerchantBean;
import au.com.royalpay.payment.manage.appclient.beans.RSvcMchBean;
import au.com.royalpay.payment.manage.application.core.SimpleClientApplyService;
import au.com.royalpay.payment.manage.complianceAudit.core.ClientComplianceApply;
import au.com.royalpay.payment.manage.dev.bean.TestMerchantAccountInfo;
import au.com.royalpay.payment.manage.device.core.DeviceManager;
import au.com.royalpay.payment.manage.kyc.enums.FilesAuthEnum;
import au.com.royalpay.payment.manage.management.sysconfig.core.impls.PermissionPartnerManagerImpl;
import au.com.royalpay.payment.manage.mappers.financial.FinancialBDConfigMapper;
import au.com.royalpay.payment.manage.mappers.log.*;
@ -54,6 +54,7 @@ import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApi;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApiProvider;
import au.com.royalpay.payment.tools.connections.mpsupport.beans.TemplateMessage;
import au.com.royalpay.payment.tools.connections.mpsupport.exceptions.WechatException;
import au.com.royalpay.payment.tools.defines.IncrementalChannel;
import au.com.royalpay.payment.tools.env.PlatformEnvironment;
import au.com.royalpay.payment.tools.env.SysConfigManager;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
@ -92,9 +93,8 @@ import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -134,8 +134,8 @@ import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
@ -317,6 +317,8 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
private static final String CLIENT_APPLY_FILE = "client_apply_file";
private static final List<String> tags = new ArrayList<>();
private static final String KYC_UTILITY_BILL_FILE = "kyc_utility_bill_file";
@Value("${app.agreetemplate.classic.path}")
private String agreetemplatePdfPath;
@Value("${app.agreetemplate.aggregate.path}")
@ -2174,6 +2176,18 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return file;
}
@Override
public JSONObject getKycFiles(JSONObject account) {
JSONObject client = getClientInfo(account.getIntValue("client_id"));
if (client == null) {
throw new InvalidShortIdException();
}
JSONObject file = signInAccountService.checkKycFileStatus(client, account, "client");
JSONObject compliance = clientComplianceCompanyMapper.findKycFileByClientId(account.getIntValue("client_id"));
file.put("file_company", compliance);
return file;
}
@Override
public JSONObject getClientInfoByAggree(JSONObject account) {
JSONObject client = getClientInfo(account.getIntValue("client_id"));
@ -2262,7 +2276,7 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}
@Override
public JSONObject getComplianceFilesForBD(JSONObject account) {
public JSONObject getComplianceFilesForClient(JSONObject account) {
JSONObject client = getClientInfo(account.getIntValue("client_id"));
if (client == null) {
throw new InvalidShortIdException();
@ -2274,6 +2288,15 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return file;
}
@Override
public JSONObject getKycFilesForBD(JSONObject client, JSONObject manager, String sourceType) {
JSONObject file = new JSONObject();
file.put("file", signInAccountService.checkKycFileStatus(client, manager, sourceType));
file.put("file_company", clientComplianceCompanyMapper.findKycFileByClientId(client.getIntValue("client_id")));
file.put("client", client);
return file;
}
@Override
@Transactional
public void updateClientBDUsers(JSONObject manager, String clientMoniker, JSONObject data) throws Exception {
@ -3391,7 +3414,9 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
throw new InvalidShortIdException();
}
JSONObject sourceFile = clientFilesMapper.getSourceAgreeFilesByClientId(client.getIntValue("client_id"));
if (sourceFile != null) {
sourceFile.put(sourceFile.getString("file_name"), sourceFile.getString("file_value"));
}
return sourceFile;
}
@ -3424,6 +3449,38 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return fileJson;
}
@Override
public JSONObject getAllKycFiles(JSONObject manager, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
String[] fileKeys = {"client_bank_file", "kyc_utility_bill_file", "client_id_file"};
if (client == null) {
throw new InvalidShortIdException();
}
List<JSONObject> clientFiles = clientFilesMapper.findClientFile(client.getIntValue("client_id"));
JSONObject fileJson = new JSONObject();
JSONObject companyFile = clientComplianceCompanyMapper.findKycFileByClientId(client.getIntValue("client_id"));
fileJson.put("companyFile",companyFile);
if (clientFiles != null && clientFiles.size() > 0) {
for (String fileKey : fileKeys) {
List<JSONObject> clientFileUrl = clientFiles.stream()
.filter(json -> (fileKey.equals(json.getString("file_name"))))
.sorted((log1, log2) -> log2.getDate("last_update_date").compareTo(log1.getDate("last_update_date")))
.map(json -> {
JSONObject params = new JSONObject();
params.put("file_id", json.getString("file_id"));
params.put("file_value", json.getString("file_value"));
return params;
})
.collect(Collectors.toList());
if (clientFileUrl != null && clientFileUrl.size() > 0) {
fileJson.put(fileKey, clientFileUrl);
}
}
}
return fileJson;
}
@Override
public JSONObject getClientViewAuthFiles(JSONObject manager, String clientMoniker) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
@ -3497,6 +3554,23 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
// }
}
@Override
@Transactional
public void uploadKycFiles(JSONObject manager, String clientMoniker, ClientKycFilesInfo filesInfo) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
int clientId = client.getIntValue("client_id");
try {
updateSysClientFiles(manager, clientId, CLIENT_BANK_FILE, filesInfo.getFile_bank_info());
updateSysClientFiles(manager, clientId, CLIENT_ID_FILE, filesInfo.getFile_id_info());
updateSysClientFiles(manager, clientId, KYC_UTILITY_BILL_FILE, filesInfo.getUtility_bill_info());
} catch (Exception e) {
logger.error("上传合规文件失败", e);
}
}
@Override
@Transactional
public List<JSONObject> uploadAuthFilesForWaitCompliance(JSONObject manager, String clientMoniker, ClientAuthFilesInfo filesInfo) {
@ -3519,11 +3593,31 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
return fileResult;
}
@Override
@Transactional
public List<JSONObject> uploadKycFilesForWaitCompliance(JSONObject manager, String clientMoniker, ClientKycFilesInfo filesInfo) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
List<JSONObject> fileResult = new ArrayList<>();
if (client == null) {
throw new InvalidShortIdException();
}
int clientId = client.getIntValue("client_id");
try {
updateFilesForWaitAuditWithoutRepeat(manager, clientId, CLIENT_BANK_FILE, filesInfo.getFile_bank_info(),fileResult);
updateFilesForWaitAuditWithoutRepeat(manager, clientId, CLIENT_ID_FILE, filesInfo.getFile_id_info(),fileResult);
updateSysClientFilesForWaitCompliance(manager, clientId, KYC_UTILITY_BILL_FILE, filesInfo.getUtility_bill_info(),fileResult);
} catch (Exception e) {
logger.error("上传KYC文件失败", e);
throw new BadRequestException("上传KYC文件失败" + e.getMessage());
}
return fileResult;
}
@Override
@Transactional
public void commitAuthFilesToCompliance(String clientMoniker, JSONObject account, String source) {
JSONObject client = getClientInfoByMoniker(clientMoniker);
String clientPayType = "";
String companyPhoto = "";
String storePhoto = "";
String webSite = "";
@ -3563,13 +3657,13 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
fileComp.put("client_id", client.getIntValue("client_id"));
fileComp.put("submit_time", new Date());
fileComp.put("status", 0);
fileComp.put("type", 1);
fileComp.put("company_photo", companyPhoto);
fileComp.put("store_photo", storePhoto);
fileComp.put("company_website", webSite);
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.getString("account_id"));
clientComplianceCompanyMapper.save(fileComp);
clientFilesMapper.updateBeforeCompliance(client.getIntValue("client_id"));
} else if (fileComp.getIntValue("status") == 2) {
fileComp.put("status", 0);
fileComp.put("submit_time", new Date());
@ -3579,10 +3673,13 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
fileComp.put("source", sourceEnum);
fileComp.put("commit_by_id", account.getString("account_id"));
clientComplianceCompanyMapper.update(fileComp);
clientFilesMapper.updateBeforeCompliance(client.getIntValue("client_id"));
} else {
throw new BadRequestException("please do not repeat submission");
}
clientFilesMapper.updateFilesAuthStatus(client.getIntValue("client_id"),
FilesAuthEnum.COMMIT_OPR.getAfterStatus(),
FilesAuthEnum.COMMIT_OPR.getBeforeStatus(),
FilesAuthEnum.COMMIT_OPR.getAuthType("compliance"));
signInAccountService.clearAccountCache(account.getString("account_id"));
}
@ -3893,6 +3990,36 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}
}
public void updateFilesForWaitAuditWithoutRepeat(JSONObject manager, int clientId, String fileType, String fileValue, List<JSONObject> fileResult) {
if (fileValue != null) {
String[] values = fileValue.split(",");
List<JSONObject> repetitiveFiles = clientFilesMapper.findRepetitiveFiles(clientId,fileType);
for (String value : values) {
JSONObject fileJson = new JSONObject();
fileJson.put("client_id", clientId);
fileJson.put("last_update_date", new Date());
fileJson.put("last_update_by", manager.getString("display_name"));
fileJson.put("file_name", fileType);
fileJson.put("file_value", value);
fileJson.put("status", 0);
fileJson.put("is_valid", 1);
clientFilesMapper.save(fileJson);
logger.info(clientId + "的fileType文件上传成功" + fileJson.getString("file_id"));
JSONObject file = new JSONObject();
file.put("file_id", fileJson.getString("file_id"));
file.put("file_value", fileJson.getString("file_value"));
fileResult.add(file);
}
if(repetitiveFiles != null){
for(JSONObject repetitiveFile : repetitiveFiles){
clientFilesMapper.deleteByClientAndFileId(repetitiveFile.getString("file_id"));
}
}
}
}
public void updateAggregateFilesForWaitCompliance(JSONObject manager, int clientId, String fileType, String fileValue, List<JSONObject> fileResult) {
if (fileValue != null) {
List<JSONObject> passAggregateFiles = clientFilesMapper.findClientPassAggreeFile(clientId);
@ -6098,6 +6225,20 @@ public class ClientManagerImpl implements ClientManager, ManagerTodoNoticeProvid
}};
}
@Override
public boolean isPartnerKycfilesComplete(String clientMoniker) {
boolean lessKycFiles = true;
JSONObject client = clientMapper.findClientByMoniker(clientMoniker);
if (client == null) {
throw new InvalidShortIdException();
}
JSONObject KycFilesAuth = clientComplianceCompanyMapper.findKycFileComplete(client.getIntValue("client_id"));
if(KycFilesAuth != null){
lessKycFiles = false;
}
return lessKycFiles;
}
@Override
public JSONObject partnerIncrementalServiceInfo(String clientMoniker,String channel){
JSONObject client = clientMapper.findClientByMoniker(clientMoniker);

@ -537,6 +537,11 @@ public class PartnerManageController {
return clientManager.getAllAuthFiles(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/kycFile", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.BD_USER, ManagerRole.SERVANT})
public JSONObject getKycFiles(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.getAllKycFiles(manager, clientMoniker);
}
@ManagerMapping(value = "/{clientMoniker}/file/source_agree_file", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.BD_USER, ManagerRole.SERVANT})
public JSONObject getSourceAgreeAuthFiles(@PathVariable String clientMoniker, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.getSourceAgreeFiles(manager, clientMoniker);
@ -553,6 +558,12 @@ public class PartnerManageController {
clientManager.uploadAuthFiles(manager, clientMoniker, filesInfo);
}
@ManagerMapping(value = "/{clientMoniker}/kycFile", method = RequestMethod.PUT, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.BD_USER})
public void uploadKycFiles(@PathVariable String clientMoniker, @RequestBody ClientKycFilesInfo filesInfo,
@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
clientManager.uploadKycFiles(manager, clientMoniker, filesInfo);
}
@ManagerMapping(value = "/analysis", method = RequestMethod.GET, role = {ManagerRole.ADMIN, ManagerRole.OPERATOR, ManagerRole.BD_USER})
public JSONObject getClientsAnalysis(@ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager) {
return clientManager.getClientsAnalysis(manager);

@ -1,14 +1,13 @@
package au.com.royalpay.payment.manage.merchants.web;
import au.com.royalpay.payment.core.exceptions.ParamInvalidException;
import au.com.royalpay.payment.manage.application.core.SimpleClientApplyService;
import au.com.royalpay.payment.manage.kyc.core.KycService;
import au.com.royalpay.payment.manage.mappers.system.ClientComplianceCompanyMapper;
import au.com.royalpay.payment.manage.merchants.beans.ClientAuthFilesInfo;
import au.com.royalpay.payment.manage.merchants.beans.ClientRegisterInfo;
import au.com.royalpay.payment.manage.merchants.beans.NewAccountBean;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.merchants.core.ClientSignEventSupport;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.permission.manager.PartnerMapping;
import au.com.royalpay.payment.manage.permission.manager.RequirePartner;
import au.com.royalpay.payment.manage.pos.datasource.ReadOnlyConnection;
@ -25,14 +24,11 @@ import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.http.HttpUtils;
import au.com.royalpay.payment.tools.merchants.beans.QRCodeConfig;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.permission.enums.PartnerRole;
import au.com.royalpay.payment.tools.permission.wechat.WechatMapping;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
@ -44,8 +40,6 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
@ -64,12 +58,11 @@ public class PartnerViewController {
@Resource
private ClientContractService clientContractService;
@Resource
private ClientComplianceCompanyMapper clientComplianceCompanyMapper;
@Resource
private SignInAccountService signInAccountService;
@Resource
private SimpleClientApplyService simpleClientApplyService;
private ClientComplianceCompanyMapper clientComplianceCompanyMapper;
@Resource
private KycService kycService;
@RequestMapping(method = RequestMethod.GET)
@RequirePartner
@ -524,6 +517,7 @@ public class PartnerViewController {
return clientManager.getAuthFiles(null,account.getString("client_moniker"));
}
@PartnerMapping(value = "/compliance/complianceInfo", method = RequestMethod.GET)
@ResponseBody
public JSONObject complianceInfo(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account) {
@ -536,6 +530,12 @@ public class PartnerViewController {
return clientManager.getComplianceFiles(account);
}
@PartnerMapping(value = "/kyc/clientViewFiles", method = RequestMethod.GET)
@ResponseBody
public JSONObject kycFiles(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account) {
return clientManager.getKycFiles(account);
}
@PartnerMapping(value = "/aggregateFile/client_info", method = RequestMethod.GET)
@ResponseBody
@ -594,7 +594,6 @@ public class PartnerViewController {
}
}
@PartnerMapping(value = "/clientCompliance/{clientMoniker}/viewCommit", method = RequestMethod.POST)
@ResponseBody
public void clientComplianceViewCommit(@PathVariable String clientMoniker ,@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestBody JSONObject photoInfo) {
@ -602,6 +601,13 @@ public class PartnerViewController {
clientManager.commitAuthFilesToCompliance(clientMoniker, account, "Web");
}
@PartnerMapping(value = "/clientCompliance/{clientMoniker}/kycFilesViewCommit/{idType}", method = RequestMethod.POST)
@ResponseBody
public void clientKycFilesViewCommit(@PathVariable String clientMoniker ,@PathVariable String idType,@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account) {
account.put("id_type", idType);
kycService.commitAuthKycFilesToCompliance(clientMoniker, account, "Web");
}
@PartnerMapping(value = "/clientCompliance/{clientMoniker}/commit_aggregate_file", method = RequestMethod.POST)
@ResponseBody
public JSONObject getClientArregateFile(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject account, @RequestParam MultipartFile file, @RequestHeader("User-Agent") String userAgent, HttpServletRequest request) throws IOException {

@ -3,7 +3,6 @@ package au.com.royalpay.payment.manage.signin.core;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.beans.LoginInfo;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.servlet.ModelAndView;
/**
* Created by yixian on 2016-06-29.
@ -69,4 +68,8 @@ public interface SignInAccountService {
JSONObject checkAuthFileStatus(JSONObject client);
JSONObject checkKycFileStatus(JSONObject client,JSONObject account, String sourceType);
JSONObject checkKycFileStatusForApp(JSONObject client,JSONObject account);
}

@ -44,7 +44,10 @@ import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -98,6 +101,10 @@ public class SignInAccountServiceImpl implements SignInAccountService, Applicati
private final String[] FILE_KEYS = {"client_bank_file", "client_company_file", "client_id_file", "client_agree_file"};
private final String[] PUT_KEYS = {"file_bank_info", "file_company_info", "file_id_info", "file_agreement_info"};
private final String[] FILE_NAMES = {"* bank statement", "* Certificate of Registration", "* ID", "* Agreement"};
private final String[] KYC_FILE_KEYS = {"client_bank_file", "kyc_utility_bill_file", "client_id_file"};
private final String[] KYC_PUT_KEYS = {"file_bank_info", "utility_bill_info", "file_id_info"};
private final String[] KYC_FILE_NAMES = {"* ASIC File", "Utility Bill Files", "* ID"};
private final int RESET_PASSWORD_TEMPLID = 126978;
private ApplicationEventPublisher publisher;
private static final List<String> tags = new ArrayList<>();
@ -739,6 +746,80 @@ public class SignInAccountServiceImpl implements SignInAccountService, Applicati
return result;
}
@Override
public JSONObject checkKycFileStatus(JSONObject client, JSONObject account, String sourceType) {
JSONObject result = new JSONObject();
boolean lessKycFiles = true;
JSONObject kycFilesAuth = clientComplianceCompanyMapper.findKycFileComplete(client.getIntValue("client_id"));
if(kycFilesAuth != null
|| !("PINE".equals(client.getString("client_moniker"))
|| "LEOH".equals(client.getString("client_moniker")))){
lessKycFiles = false;
}
result.put("client_less_file", lessKycFiles);
if (lessKycFiles || account.containsKey("manager_id")) {
List<JSONObject> kycFiles = new ArrayList<>();
if ("client".equals(sourceType.toLowerCase())) {
kycFiles = clientFilesMapper.findKycClientFileByClient(client.getIntValue("client_id"));
}else {
kycFiles = clientFilesMapper.findKycClientFileByAudit(client.getIntValue("client_id"));
}
for (JSONObject file : kycFiles) {
result.put(file.getString("file_name"), file.getString("file_value"));
}
List<JSONObject> clientFileUrl = kycFiles.stream()
.filter(json -> ("kyc_utility_bill_file".equals(json.getString("file_name"))))
.sorted((log1, log2) -> log2.getDate("last_update_date").compareTo(log1.getDate("last_update_date")))
.map(json -> {
JSONObject params = new JSONObject();
params.put("file_id", json.getString("file_id"));
params.put("status", json.getString("status"));
params.put("file_value", json.getString("file_value"));
return params;
})
.collect(Collectors.toList());
if (clientFileUrl.size() > 0) {
result.put("kyc_utility_bill_file", clientFileUrl);
}
}
return result;
}
@Override
public JSONObject checkKycFileStatusForApp(JSONObject client, JSONObject account) {
JSONObject result = new JSONObject();
boolean lessKycFiles = true;
JSONObject kycFilesAuth = clientComplianceCompanyMapper.findKycFileComplete(client.getIntValue("client_id"));
if(kycFilesAuth != null){
lessKycFiles = false;
}
result.put("client_less_file", lessKycFiles);
if (lessKycFiles || account.containsKey("manager_id")) {
List<JSONObject> kycFiles = new ArrayList<>();
kycFiles = clientFilesMapper.findKycClientFileByClient(client.getIntValue("client_id"));
for (JSONObject file : kycFiles) {
result.put(file.getString("file_name"), file.getString("file_value"));
}
List<JSONObject> clientFileUrl = kycFiles.stream()
.filter(json -> ("kyc_utility_bill_file".equals(json.getString("file_name"))))
.sorted((log1, log2) -> log2.getDate("last_update_date").compareTo(log1.getDate("last_update_date")))
.map(json -> {
JSONObject params = new JSONObject();
params.put("file_id", json.getString("file_id"));
params.put("status", json.getString("status"));
params.put("file_value", json.getString("file_value"));
return params;
})
.collect(Collectors.toList());
if (clientFileUrl.size() > 0) {
result.put("kyc_utility_bill_file", clientFileUrl);
}
}
return result;
}
private void whenClientLessFile(JSONObject client,JSONObject result) {
JSONObject authFileCompliance = clientComplianceCompanyMapper.findFileByClientId(client.getIntValue("client_id"));
if (authFileCompliance != null && StringUtils.isNotBlank(authFileCompliance.getString("description"))) {

@ -1,44 +1,39 @@
package au.com.royalpay.payment.manage.signin.web;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.signin.core.*;
import au.com.royalpay.payment.tools.permission.consumer.ConsumersAction;
import com.google.code.kaptcha.Producer;
import au.com.royalpay.payment.manage.customers.core.CustomerPaymentInfoService;
import au.com.royalpay.payment.manage.merchants.core.ClientManager;
import au.com.royalpay.payment.manage.permission.manager.ManagerMapping;
import au.com.royalpay.payment.manage.permission.manager.PartnerMapping;
import au.com.royalpay.payment.manage.signin.beans.ChangePwdBean;
import au.com.royalpay.payment.manage.signin.beans.FindPwdBean;
import au.com.royalpay.payment.manage.signin.beans.LoginInfo;
import au.com.royalpay.payment.manage.signin.beans.TodoNotice;
import au.com.royalpay.payment.manage.signin.core.*;
import au.com.royalpay.payment.tools.CommonConsts;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApi;
import au.com.royalpay.payment.tools.connections.mpsupport.MpWechatApiProvider;
import au.com.royalpay.payment.tools.connections.mpsupport.beans.WxOauthType;
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
import au.com.royalpay.payment.tools.exceptions.ForbiddenException;
import au.com.royalpay.payment.tools.http.HttpUtils;
import au.com.royalpay.payment.tools.permission.consumer.ConsumersAction;
import au.com.royalpay.payment.tools.permission.enums.ManagerRole;
import au.com.royalpay.payment.tools.permission.wechat.WechatMapping;
import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.Producer;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yixian on 2016-06-29.
@ -191,6 +186,9 @@ public class SignInController {
@PartnerMapping(value = "/current_partner", method = RequestMethod.GET)
public JSONObject partnerLoginStatus(@ModelAttribute(CommonConsts.PARTNER_STATUS) JSONObject partner) {
partner.put("has_incremental_setvice",clientManager.partnerIncrementalService(partner.getString("client_moniker")).getJSONArray("all_service").size()>0);
boolean lessKycFiles = ("PINE".equals(partner.getString("client_moniker")) || "LEOH".equals(partner.getString("client_moniker"))) && clientManager.isPartnerKycfilesComplete(partner.getString("client_moniker"));
partner.put("lessKycFiles", lessKycFiles);
partner.put("lessComplianceFiles",signInAccountService.checkAuthFileStatus(partner.getJSONObject("client")).getBoolean("client_less_file") );
return partner;
}

@ -2,15 +2,92 @@
<!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.ClientComplianceCompanyMapper">
<select id="listClientCompliances" resultType="com.alibaba.fastjson.JSONObject">
SELECT c.client_moniker,c.short_name,c.create_time,c.bd_user_name,c.approve_result,c.approve_time,c.open_status,
c.source as client_source,c.refuse_remark,a.* FROM client_authfile_compliance a INNER JOIN sys_clients c on c.client_id = a.client_id
<where>
<if test="client_moniker!=null">
and c.client_moniker = #{client_moniker}
</if>
<if test="status!=null">
and a.status = #{status}
</if>
<if test="type!=null">
and a.type = #{type}
</if>
and a.status != 9
</where>
</select>
<select id="listNeedHelpClients" resultType="com.alibaba.fastjson.JSONObject">
SELECT c.client_moniker,c.short_name,c.create_time,c.bd_user_name,c.approve_result,c.approve_time,c.open_status,
c.source as client_source,c.refuse_remark,a.* FROM client_authfile_compliance a INNER JOIN sys_clients c on c.client_id = a.client_id
<if test="bd_user!=null">
INNER JOIN sys_client_bd d ON a.client_id = d.client_id AND d.bd_id = #{bd_user} and
date(d.start_date)&lt;= date(now()) and (d.end_date is null or date(d.end_date)&gt;= date(now())) and
d.is_valid=1
</if>
<where>
<if test="bd_group!=null">and a.client_id in
(SELECT b.client_id FROM sys_client_bd b
INNER JOIN financial_bd_config fb ON fb.manager_id=b.bd_id
where b.is_valid=1 and b.start_date&lt;=now() and (b.end_date is null or b.end_date &gt;= now())
AND (fb.bd_group=#{bd_group} or fb.manager_id=#{bd_group})
)
</if>
and a.type = 2
and a.status = 9
</where>
order by a.submit_time desc
</select>
<select id="listKycProgressClients" resultType="com.alibaba.fastjson.JSONObject">
SELECT c.client_moniker,c.short_name,c.create_time,c.bd_user_name,c.approve_result,c.approve_time,c.open_status,
c.source as client_source,a.* FROM client_authfile_compliance a INNER JOIN sys_clients c on c.client_id = a.client_id
<if test="bd_user!=null">
INNER JOIN sys_client_bd d ON a.client_id = d.client_id AND d.bd_id = #{bd_user} and
date(d.start_date)&lt;= date(now()) and (d.end_date is null or date(d.end_date)&gt;= date(now())) and
d.is_valid=1
</if>
<where>
<if test="bd_group!=null">and a.client_id in
(SELECT b.client_id FROM sys_client_bd b
INNER JOIN financial_bd_config fb ON fb.manager_id=b.bd_id
where b.is_valid=1 and b.start_date&lt;=now() and (b.end_date is null or b.end_date &gt;= now())
AND (fb.bd_group=#{bd_group} or fb.manager_id=#{bd_group})
)
</if>
<if test="client_moniker!=null">
and c.client_moniker = #{client_moniker}
</if>
<if test="status!=null">
and a.status = #{status}
</if>
and a.type = 2
and a.status != 9
and a.status != 2
</where>
</select>
<select id="countKycProgressClients" resultType="int">
SELECT count(1) FROM client_authfile_compliance a INNER JOIN sys_clients c on c.client_id = a.client_id
<if test="bd_user!=null">
INNER JOIN sys_client_bd d ON a.client_id = d.client_id AND d.bd_id = #{bd_user} and
date(d.start_date)&lt;= date(now()) and (d.end_date is null or date(d.end_date)&gt;= date(now())) and
d.is_valid=1
</if>
<where>
<if test="bd_group!=null">and a.client_id in
(SELECT b.client_id FROM sys_client_bd b
INNER JOIN financial_bd_config fb ON fb.manager_id=b.bd_id
where b.is_valid=1 and b.start_date&lt;=now() and (b.end_date is null or b.end_date &gt;= now())
AND (fb.bd_group=#{bd_group} or fb.manager_id=#{bd_group})
)
</if>
and a.type = 2
and a.status != 9
<if test="status!=null">
and a.status = #{status}
</if>
</where>
</select>
</mapper>

@ -25,11 +25,36 @@
and file_name='client_agree_file'
and status != 1
</select>
<select id="findRepetitiveFiles" resultType="com.alibaba.fastjson.JSONObject">
SELECT
*
FROM
sys_files
WHERE
client_id = #{client_id}
AND STATUS IN ( 0, 3 )
AND file_name = #{file_name}
AND is_valid = 1
</select>
<select id="findAllClientFile" resultType="com.alibaba.fastjson.JSONObject">
select * from sys_files where is_valid = 1
and client_id = #{client_id}
order by last_update_date asc
</select>
<select id="findKycClientFileByClient" resultType="com.alibaba.fastjson.JSONObject">
select * from sys_files where is_valid = 1
and client_id = #{client_id}
and (status = 0 or status = 1 or status = 3) and file_name in ('client_bank_file','client_id_file','kyc_utility_bill_file')
order by last_update_date asc
</select>
<select id="findKycClientFileByAudit" resultType="com.alibaba.fastjson.JSONObject">
select * from sys_files where is_valid = 1
and client_id = #{client_id}
and (status = 1 or status = 2 or status = 3) and file_name in ('client_bank_file','client_id_file','kyc_utility_bill_file')
order by last_update_date asc
</select>
<update id="confirmAgreeFile">
update sys_files
set state = 2
@ -37,20 +62,52 @@
and client_id = #{client_id}
</update>
<update id="updateBeforeCompliance">
<update id="updateFilesAuthStatus">
update sys_files
set status = 2
set status = #{status}
where client_id = #{client_id}
and is_valid = 1
and (status = 0 or status = 3)
<if test="original_status_type !=null ">
AND status IN
<foreach collection="original_status_type" open="(" close=")" separator="," item="status_type">
#{status_type}
</foreach>
</if>
<if test="file_names!=null">
AND file_name IN
<foreach collection="file_names" open="(" close=")" separator="," item="file_name">
#{file_name}
</foreach>
</if>
</update>
<update id="refuseCompliance">
update sys_files set `status` = 3 where client_id = #{client_id} and is_valid = 1 and status = 2
<update id="updateRepeatFilesAfterCommit">
UPDATE sys_files
SET is_valid = 0
WHERE
client_id = #{client_id}
AND file_name = #{file_name}
AND file_id NOT IN (
SELECT
a.file_id
FROM
(
SELECT
file_id
FROM
sys_files a
WHERE
client_id = #{client_id}
AND a.is_valid = 1
AND `status` = 1
AND a.file_name = #{file_name}
ORDER BY
last_update_date DESC
LIMIT 1
) a
)
</update>
<update id="passCompliance">
update sys_files set `status` = 1 where client_id = #{client_id} and is_valid = 1 and status = 2
</update>
</mapper>

@ -770,5 +770,51 @@
and client_id &lt; #{end}
</select>
<select id="listCompletedContractKycClients" resultType="com.alibaba.fastjson.JSONObject">
SELECT c.client_moniker,c.short_name,c.create_time,c.bd_user_name,c.approve_result,c.approve_time,c.open_status,
c.source AS client_source,c.refuse_remark,a.* FROM sys_clients c LEFT JOIN client_authfile_compliance a ON c.client_id = a.client_id AND a.type=2
<if test="bd_user!=null">
INNER JOIN sys_client_bd d ON c.client_id = d.client_id AND d.bd_id = #{bd_user} and
date(d.start_date)&lt;= date(now()) and (d.end_date is null or date(d.end_date)&gt;= date(now())) and
d.is_valid=1
</if>
<where>
and c.is_valid=1 and (a.is_valid is null or a.status = 2)
<if test="client_moniker!=null">
and c.client_moniker = #{client_moniker}
</if>
<if test="status==3">
and a.is_valid is null
</if>
<if test="status==2">
and a.status = 2
</if>
<if test="bd_group!=null">and a.client_id in
(SELECT b.client_id FROM sys_client_bd b
INNER JOIN financial_bd_config fb ON fb.manager_id=b.bd_id
where b.is_valid=1 and b.start_date&lt;=now() and (b.end_date is null or b.end_date &gt;= now())
AND (fb.bd_group=#{bd_group} or fb.manager_id=#{bd_group})
)
</if>
</where>
</select>
<select id="countKycClients" resultType="int">
SELECT count(1) FROM sys_clients c
<if test="bd_user!=null">
INNER JOIN sys_client_bd d ON c.client_id = d.client_id AND d.bd_id = #{bd_user} and
date(d.start_date)&lt;= date(now()) and (d.end_date is null or date(d.end_date)&gt;= date(now())) and
d.is_valid=1
</if>
<where>
and c.is_valid=1
<if test="bd_group!=null">and c.client_id in
(SELECT b.client_id FROM sys_client_bd b
INNER JOIN financial_bd_config fb ON fb.manager_id=b.bd_id
where b.is_valid=1 and b.start_date&lt;=now() and (b.end_date is null or b.end_date &gt;= now())
AND (fb.bd_group=#{bd_group} or fb.manager_id=#{bd_group})
)
</if>
</where>
</select>
</mapper>

@ -116,4 +116,7 @@ contract.old.waring=Dear Valued Merchants to ensure we comply with the ATO, w
sys.mondelay.cancel.waring=Are you sure to quit this activity?
client.auth.file.title=RoyalPay is committed to providing a secure and safe platform for Chinese payments. As a part of this we regularly participate in communication with Austrac and China's Foreign Exchange Regulator. To ensure your business is fully compliant, we require certain documents from you by the 31st of October. If you believe you may not be able to submit these documents on time please get in touch with us as soon as possible.
client.auth.file.aggregate.title=Notice Of Supplementary Files
client.auth.file.compliance.type=Compliance Files
client.auth.file.kyc.type=KYC Files
client.auth.file.aggregate.deadline=Deadline 2020-1-20

@ -109,3 +109,7 @@ contract.old.waring=尊敬的商户RoyalPay于近期正式收到澳洲监管
sys.mondelay.cancel.waring=是否确认退出活动
client.auth.file.title=应澳洲政府反洗钱监管机构Austrac和中国外汇监管相关要求需要您配合补充完善基本资料以完成合规流程截止时间2019年10月31日前超期未提交将可能会影响您的正常交易谢谢您的配合。
client.auth.file.aggregate.title=补充材料通知
client.auth.file.compliance.type=合规材料
client.auth.file.kyc.type=KYC材料
client.auth.file.aggregate.deadline=截止时间 2020-1-20

@ -0,0 +1,28 @@
<html xmlns:th="http://www.thymeleaf.org" lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<div style="width: 91%;border: 1px #F2F2F2 solid;margin: 0 auto; ">
<div style="height: 3%;background-color: #F2F2F2;"></div>
<div style="text-align: center;margin-top: 2.5%;">
<img th:src="${img_url}"/>
</div>
<div style="width: 80.3%;margin: 0 auto;">
<p>您好,<span th:text="${name}"></span></p>
<p>商户:<span th:text="${client_moniker}"></span>需要您协助上传KYC材料。(申请时间:<span th:text="${submit_time}"></span>)</p>
<p>请尽快联系商户,您可以帮助商户提交材料或填写无法提供材料文件的原因。</p>
<p>商户联系人:<span th:text="${contact_person}"></span></p>
<p>联系电话:<span th:text="${contact_phone}"></span></p>
<p>邮箱:<span th:text="${contact_email}"></span></p>
<span>此致</span><br />
<span>RoyalPay</span>
</div>
<div style="height: 3%;background-color: #F2F2F2;margin-top: 6.5%;"></div>
</div>
</body>
</html>

@ -327,6 +327,13 @@ margin-bottom: 10%;"/>
<i class="fa fa-envelope-o"></i> <span>自主申请|Partner Applies</span>
</a>
</li>-->
<li ui-sref-active="active" ng-if="roleNow=='bduser' && (currentUser.org_id==null || currentUser.org_id==1)">
<a ui-sref="partnerKYCProgress" ui-sref-opts="{reload:true}">
<i class="fa fa-area-chart"></i> <span>商户KYC认证进度</span>
</a>
</li>
</ul>
</li>

@ -79,7 +79,8 @@ var modules = [
{path: 'static/integralmall/coupon_cancellation', module: 'couponCancellation', roles: [1,2]},
{path: 'static/invoice/invoice_assistant', module: 'partnerInvoice', roles: [1]},
{path: 'static/payment/billqrcode/bill-qrcode-manage', module: 'billQrCodeManagement', roles: [1,2,3]},
{path: 'static/incrementalService/partner-incremental-service', module: 'partnerIncrementalService', roles: [1,2,3]}
{path: 'static/incrementalService/partner-incremental-service', module: 'partnerIncrementalService', roles: [1,2,3]},
{path: 'static/payment/kyc/kyc', module: 'kycApp', roles: [1,2,3]}
];
require(['angular', 'jquery'], function (angular, $) {

@ -52,14 +52,17 @@ define(['angular', 'angularSanitize', 'angularAnimate', 'angularMessages', 'uiRo
resolve: {
file: ['$http', function ($http) {
return $http.get('/client/partner_info/compliance/clientViewFiles');
}],
kycFile: ['$http', function ($http) {
return $http.get('/client/partner_info/kyc/clientViewFiles');
}]
}
})
};
if($scope.currentUser.client.client_less_file && complianceNoticeCount==0 && $scope.currentUser.role!=3)
{
//todo 这边需要调整 或者关系 不能做两个if,字段放到client里位置要一致有bug当补充合规材料提交后不提示弹窗弹窗样式要修改
if(($scope.currentUser.lessComplianceFiles ||$scope.currentUser.lessKycFiles) && complianceNoticeCount==0 && $scope.currentUser.role!=3) {
$scope.ComplianceToperfect();
complianceNoticeCount++;
}
@ -477,8 +480,20 @@ define(['angular', 'angularSanitize', 'angularAnimate', 'angularMessages', 'uiRo
})
}
}]);
app.controller('partnerFilesCtrl', ['$scope', '$http', '$sce', 'file', function ($scope, $http, $sce, file) {
$scope.file = angular.copy(file);
app.controller('partnerFilesCtrl', ['$scope', '$http', '$sce', 'file', 'kycFile', function ($scope, $http, $sce, file , kycFile) {
$scope.file = angular.copy(file.data);
$scope.kycFile = angular.copy(kycFile.data);
var lang = navigator.language || navigator.userLanguage; //常规浏览器语言和IE浏览器
lang = lang.substr(0, 2);
if (lang == 'zh') {
$scope.adviceLanguage = 'zh'
} else {
$scope.adviceLanguage = 'en';
}
$scope.changeLanguage = function (language) {
$scope.adviceLanguage = language;
}
}]);
app.factory('myLoginLogView', ['$uibModal', function ($uibModal) {
return {

File diff suppressed because one or more lines are too long

@ -31,7 +31,8 @@
</div>
</div>
</div>
--> <a role="button" style="float: right;line-height: 46px" ui-sref="home" ng-click="headerCopyDisplay()"><i class="fa fa-reply"></i> 返回</a>
-->
<a role="button" style="float: right;line-height: 46px" ui-sref="home" ng-click="headerCopyDisplay()"><i class="fa fa-reply"></i> 返回</a>
<div class="list-group" ng-if="role!=null && role!='administrator' && role!='developer' && 'partners'|withModule">
<div class="row">
<div class="col-sm-2 col-lg-2 col-xs-6" id="partners">
@ -61,6 +62,16 @@
</div>
</a>
</div>
<div ng-if="'100'|withRole" class="col-sm-2 col-xs-6">
<a ui-sref="partnerKYCProgress" ui-sref-opts="{reload:true}">
<div class="description-block">
<img src="/static/images/main_menu/merchant_info.png"/>
<div class="description-text">
<span class="description-text">商户KYC认证进度</span>
</div>
</div>
</a>
</div>
<!--<div ng-if="'log'|withModule" class="col-sm-2 col-xs-6">-->
<!--<a ui-sref="logview.config_operation" ui-sref-opts="{reload:true}">-->
<!--<div class="description-block">-->

@ -0,0 +1,315 @@
define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootSwitch', 'ngFileUpload', 'uiSelect'], function (angular) {
'use strict';
var app = angular.module('kycManageApp', ['ui.bootstrap', 'ui.router', 'frapontillo.bootstrap-switch', 'ngFileUpload', 'ui.select']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('partnerKYCProgress', {
url: '/partners/partnerKYCProgress',
templateUrl: 'static/payment/kyc/templates/bd_client_progress.html',
controller: 'partnerKYCProgressCtrl'
}).state('partnerKYCProgress.bdHelpKycProgress', {
url: '/{clientMoniker}/bdHelpKycProgress',
templateUrl: 'static/payment/kyc/templates/bd_help_client_progress.html',
controller: 'bdHelpKYCProgressCtrl',
resolve: {
file: ['$http','$stateParams',function ($http, $stateParams) {
return $http.get('/sys/kyc/manage/' + $stateParams.clientMoniker + '/bd_help');
}]
}
}).state('partnerKYCProgress.partner_detail', {
url: '/{clientMoniker}/partner_detail',
templateUrl: '/static/payment/kyc/templates/bd_help_client_detail.html',
controller: 'partnerDetailForBDHelpCtrl',
resolve: {
partner: ['$http', '$stateParams', function ($http, $stateParams) {
return $http.get('/sys/partners/' + $stateParams.clientMoniker);
}]
}
})
}]);
app.controller('partnerKYCProgressCtrl', ['$scope', '$sce', '$http','$uibModal', 'commonDialog',
function ($scope, $sce, $http, $uibModal, commonDialog) {
$scope.ctrl = {
plusShow1: false,
plusShow2: false,
plusShow3: false
};
$scope.progressPagination = {};
$scope.completedPagination = {};
$scope.params = {};
$scope.loadClientProgressing = function (page,status) {
var params = angular.copy($scope.params);
params.status = status;
params.client_moniker = params.progress_client_moniker;
params.page = page || $scope.progressPagination.page || 1;
$http.get('/sys/kyc/manage/partner/progressing', {params: params}).then(function (resp) {
$scope.approving = resp.data.data;
$scope.progressPagination = resp.data.pagination;
});
};
$scope.loadClientCompleted = function (page) {
var params = angular.copy($scope.params);
params.client_moniker = params.completed_client_moniker;
params.page = page || $scope.completedPagination.page || 1;
$http.get('/sys/kyc/manage/partner/completed', {params: params}).then(function (resp) {
$scope.completed_contract = resp.data.data;
$scope.completedPagination = resp.data.pagination;
});
};
$scope.loadClientNeedHelp = function () {
var params = angular.copy($scope.params);
$http.get('/sys/kyc/manage/partner/need_help', {params: params}).then(function (resp) {
$scope.need_help = resp.data;
});
};
$scope.loadClientNeedHelp();
$scope.loadClientCompleted();
$scope.loadClientProgressing();
$scope.statusSelected = function (arr) {
return $scope.params.status != null && $scope.params.status.filter(function (status) {
return arr.indexOf(status) >= 0
}).length > 0 || $scope.params.progress_status != null && $scope.params.progress_status.filter(function (status) {
return arr.indexOf(status) >= 0
}).length > 0
};
$scope.addHandleLog = function (info) {
$uibModal.open({
templateUrl: '/static/payment/partner/templates/add_handle_log.html',
controller: 'addHandleDetailCtrl',
resolve:{
compliance_id:function () {
return info.compliance_id;
}}
}).result.then(function () {
commonDialog.alert({title: 'Success', type: 'success'});
})
};
$scope.loadKYCDashboardInfo = function () {
$http.get('/sys/kyc/manage/partner/dashboard').then(function (resp) {
$scope.total_need_help = resp.data.total_need_help;
$scope.total_partner = resp.data.total_partner;
$scope.total_progressing = resp.data.total_progressing;
$scope.total_pass_partner = resp.data.total_pass_partner;
$scope.total_refuse_partner = resp.data.total_refuse_partner;
$(".circleChart1").circleChart({
value: ($scope.total_need_help/$scope.total_partner)*100,
redraw: false,
startAngle: 75,
color: "#68cf7c",
size: 130,
text: 0 + '%',
onDraw: function(el, circle){
$(".circleChart_text", el).html(Math.round(circle.value) + '%');
}
});
$(".circleChart2").circleChart({
value: ($scope.total_progressing/$scope.total_partner)*100,
redraw: false,
startAngle: 75,
color: "#68cf7c",
size: 130,
text: 0 + '%',
onDraw: function(el, circle){
$(".circleChart_text", el).html(Math.round(circle.value) + '%');
}
});
$(".circleChart3").circleChart({
value: ($scope.total_pass_partner/$scope.total_partner)*100,
redraw: false,
startAngle: 75,
color: "#96cf9a",
size: 130,
text: 0 + '%',
onDraw: function(el, circle){
$(".circleChart_text", el).html(Math.round(circle.value) + '%');
}
});
$(".circleChart4").circleChart({
value: ($scope.total_refuse_partner/$scope.total_progressing)*100,
redraw: false,
startAngle: 75,
color: "#96cf9a",
size: 130,
text: 0 + '%',
onDraw: function(el, circle){
$(".circleChart_text", el).html(Math.round(circle.value) + '%');
}
});
});
};
$scope.loadKYCDashboardInfo();
}]);
app.controller('bdHelpKYCProgressCtrl', [ '$scope', '$http', '$state', 'file', 'commonDialog', '$location', '$anchorScroll','Upload',function ($scope, $http, $state, file, commonDialog, $location, $anchorScroll, Upload) {
$scope.file = angular.copy(file.data) || {};
if(!$scope.file.file_company.id_type){
$scope.file.file_company.id_type = sessionStorage.getItem($scope.file.client.client_moniker+'_idType');
}
$scope.setSession = function(idType){
sessionStorage.setItem($scope.file.client.client_moniker+'_idType',idType);
}
$scope.uploadBankFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.bankFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.bankFileProgress;
$scope.file.file_bank_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_bank_info.endsWith('pdf')) {
$scope.bankIsImage = false;
} else {
$scope.bankIsImage = true;
}
}, function (resp) {
delete $scope.bankFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.bankFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
$scope.uploadIDFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.idFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.idFileProgress;
$scope.file.file_id_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_id_info.endsWith('pdf')) {
$scope.idIsImage = false;
} else {
$scope.idIsImage = true;
}
}, function (resp) {
delete $scope.idFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.idFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
$scope.uploadCompanyFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.billFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.billFileProgress;
$scope.file.utility_bill_info = resp.data.url;
$scope.updateFile();
if ($scope.file.utility_bill_info.endsWith('pdf')) {
$scope.billIsImage = false;
} else {
$scope.billIsImage = true;
}
}, function (resp) {
delete $scope.billFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.billFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
$scope.updateFile = function () {
$http.put('/sys/kyc/manage/'+ $scope.file.client.client_moniker + '/update', $scope.file).then(function () {
commonDialog.alert({
title: 'Success',
content: 'Upload Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
};
$scope.deleteComplianceFiles = function (file_id) {
$scope.file_id = file_id;
commonDialog.confirm({
title: 'Warning',
content: 'This operation will delete the file, Are you sure?'
}).then(function () {
$http.put('/sys/kyc/manage/auth_file/' + $scope.file_id + '/delete').then(function (resp) {
commonDialog.alert({
title: 'Success',
content: 'Delete Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.clientComplianceViewCommit = function () {
if (!$scope.file.file.client_bank_file && !$scope.file.file_company.bd_handle) {
commonDialog.alert({title: 'Error', content: '请提交* ASIC File', type: 'error'});
return;
}
if (!$scope.file.file.client_id_file && !$scope.file.file_company.bd_handle) {
commonDialog.alert({title: 'Error', content: '请提交ID护照或驾照信息', type: 'error'});
return;
}
if (($scope.file.file_company.id_type == "" || $scope.file.file_company.id_type == undefined || $scope.file.file_company.id_type == null) && !$scope.file.file_company.bd_handle) {
commonDialog.alert({title: 'Error', content: '请选择ID文件的类型', type: 'error'});
return;
}
if ($scope.file.id_type == "passport" && !$scope.file.file_company.bd_handle) {
if (!$scope.file.file.kyc_utility_bill_file) {
commonDialog.alert({title: 'Error', content: '请提交Utility Bill FIles(水电煤账单)信息', type: 'error'});
return;
}
}
var params = {};
params.bd_handle = $scope.file.file_company.bd_handle;
params.id_type = $scope.file.file_company.id_type;
commonDialog.confirm({
title: 'Warning',
content: 'Are you sure to submit files?'
}).then(function () {
$http.post('/sys/kyc/manage/' + $scope.file.client.client_moniker + '/kycCommit', params).then(function () {
commonDialog.alert({
title: 'Success',
content: 'Commit Successful',
type: 'success'
});
$state.go('partnerKYCProgress',{},{reload: true});
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
});
};
$scope.hrefBdHandle = function () {
$location.hash("bd-handle");
$anchorScroll();
$('#bd-handle').focus()
}
}]);
app.controller('partnerDetailForBDHelpCtrl', [ '$scope', '$http', '$state', 'partner', 'commonDialog',function ($scope, $http, $state, partner, commonDialog) {
$scope.partner = angular.copy(partner.data);
}]);
return app;
});

@ -0,0 +1,220 @@
define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootSwitch', 'ngFileUpload', 'uiSelect'], function (angular) {
'use strict';
var app = angular.module('kycApp', ['ui.bootstrap', 'ui.router', 'frapontillo.bootstrap-switch', 'ngFileUpload', 'ui.select']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('kyc_files_perfect', {
url: '/kyc_files_perfect',
templateUrl: '/static/payment/kyc/templates/client_kyc_files_progress.html',
controller: 'clientCommitToKycFilesCtrl',
resolve: {
file: ['$http', function ($http) {
return $http.get('/client/partner_info/kyc/clientViewFiles');
}],
partner: ['$http', function ($http) {
return $http.get('/client/partner_info');
}]
}
});
}]);
app.controller('clientCommitToKycFilesCtrl', ['$scope', '$http', '$rootScope', 'commonDialog', '$state', 'Upload', 'file', 'partner', function ($scope, $http, $rootScope, commonDialog, $state, Upload, file, partner) {
$scope.file = file.data || {};
$scope.partner = partner.data || {};
if($scope.file.file_company){
$scope.file.id_type = $scope.file.file_company.id_type||"";
}else{
$scope.file.id_type = sessionStorage.getItem($scope.partner.client_moniker+'_idType');
}
$scope.file.need_bd = true;
$scope.setSession = function(idType){
sessionStorage.setItem($scope.partner.client_moniker+'_idType',idType);
}
//audit files
$scope.uploadBankFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.bankFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.bankFileProgress;
$scope.file.file_bank_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_bank_info.endsWith('pdf')) {
$scope.bankIsImage = false;
} else {
$scope.bankIsImage = true;
}
}, function (resp) {
delete $scope.bankFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.bankFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
//上传ID信息
$scope.uploadIDFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.idFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.idFileProgress;
$scope.file.file_id_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_id_info.endsWith('pdf')) {
$scope.idIsImage = false;
} else {
$scope.idIsImage = true;
}
}, function (resp) {
delete $scope.idFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.idFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
//上传账单流水
$scope.uploadCompanyFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.billFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.billFileProgress;
$scope.file.utility_bill_info = resp.data.url;
$scope.updateFile();
if ($scope.file.utility_bill_info.endsWith('pdf')) {
$scope.billIsImage = false;
} else {
$scope.billIsImage = true;
}
}, function (resp) {
delete $scope.billFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.billFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
$scope.bankIsImage = true;
if ($scope.file.file_bank_info && $scope.file.file_bank_info.endsWith('pdf')) {
$scope.bankIsImage = false;
}
$scope.idIsImage = true;
if ($scope.file.file_id_info && $scope.file.file_id_info.endsWith('pdf')) {
$scope.idIsImage = false;
}
$scope.billIsImage = true;
if ($scope.file.file_company_info && $scope.file.file_company_info.endsWith('pdf')) {
$scope.billIsImage = false;
}
$scope.updateFile = function () {
$http.put('/sys/kyc/partner/update/wait_kyc_file', $scope.file).then(function () {
commonDialog.alert({
title: 'Success',
content: 'Upload Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
};
$scope.needBDIntervention = function () {
commonDialog.confirm({
title: 'Warning',
content: 'Are you sure to need notify BD ?'
}).then(function () {
$http.put('/sys/kyc/partner/notifyBd').then(function () {
commonDialog.alert({
title: 'Success',
content: 'Notify Successful,Please wait for bd to contact you',
type: 'success'
});
$state.go('partner_dashboard');
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.clientComplianceViewCommit = function () {
if (!$scope.file.client_bank_file) {
commonDialog.alert({title: 'Error', content: '请提交* ASIC File', type: 'error'});
return;
}
if (!$scope.file.client_id_file) {
commonDialog.alert({title: 'Error', content: '请提交ID护照或驾照信息', type: 'error'});
return;
}
if ($scope.file.id_type == "" || $scope.file.id_type == undefined || $scope.file.id_type == null) {
commonDialog.alert({title: 'Error', content: '请选择ID文件的类型', type: 'error'});
return;
}
if ($scope.file.id_type == "passport") {
if (!$scope.file.kyc_utility_bill_file) {
commonDialog.alert({title: 'Error', content: '请提交Utility Bill FIles(水电煤账单)信息', type: 'error'});
return;
}
}
commonDialog.confirm({
title: 'Warning',
content: 'Are you sure to submit files?'
}).then(function () {
$http.post('/client/partner_info/clientCompliance/' + $scope.partner.client_moniker + '/kycFilesViewCommit/' + $scope.file.id_type).then(function () {
commonDialog.alert({
title: 'Success',
content: 'Commit Successful',
type: 'success'
});
$state.go('partner_dashboard');
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
});
};
$scope.deleteComplianceFiles = function (file_id) {
$scope.file_id = file_id;
commonDialog.confirm({
title: 'Warning',
content: 'This operation will delete the file, Are you sure?'
}).then(function () {
$http.put('/client/partner_info/auth_file/' + $scope.file_id + '/delete').then(function (resp) {
commonDialog.alert({
title: 'Success',
content: 'Delete Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
}]);
return app;
});

@ -0,0 +1,380 @@
<script src="static/commons/services/circleChart.min.js"></script>
<style>
.btn-box-tool {
color: #97a0b3
}
.bg-info4 {
color: white;
background-color: #00c0ef;
margin: 0 10px 20px 10px;
}
.bg-info1 {
color: white;
background-color: #dd4b39;
margin: 0 10px 20px 10px;
}
.bg-info2 {
color: white;
background-color: #00a65a;
margin: 0 10px 20px 10px;
}
.bg-info3 {
color: white;
background-color: #f39c12;
margin: 0 10px 20px 10px;
}
.circleChart_canvas {
display: none;
}
</style>
<section class="content-header">
<h1>商户KYC认证进度</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-sitemap"></i> Partner Manage
</li>
<li class="active">商户KYC认证进度</li>
</ol>
</section>
<div ui-view>
<div class="row" style="padding: 0 30px;margin-top: 30px;">
<div class="col-lg-3 col-6">
<!-- small card -->
<div class="small-box bg-info4">
<div class="inner" style="height: 130px;">
<h2 class="bg-title">{{total_need_help}}</h2>
<p class="bg-title1">{{total_need_help}}/{{total_partner}}</p>
<p class="bg-title2">需要帮助的商户/总商户数</p>
</div>
<div class="icon" style="position: absolute;top: 2px;right: 10px;">
<div class="circleChart1" style="color: white"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-6">
<!-- small card -->
<div class="small-box bg-info3">
<div class="inner" style="height: 130px;">
<h2 class="bg-title">{{total_progressing}}</h2>
<p class="bg-title1">{{total_progressing}}/{{total_partner}}</p>
<p class="bg-title2">已提交材料/总商户数</p>
</div>
<div class="icon" style="position: absolute;top: 2px;right: 10px;">
<div class="circleChart2" style="color: white"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-6">
<!-- small card -->
<div class="small-box bg-info2">
<div class="inner" style="height: 130px;">
<h2 class="bg-title">{{total_pass_partner}}</h2>
<p class="bg-title1">{{total_pass_partner}}/{{total_partner}}</p>
<p class="bg-title2">已通过/总商户数</p>
</div>
<div class="icon" style="position: absolute;top: 2px;right: 10px;">
<div class="circleChart3" style="color: white"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-6">
<!-- small card -->
<div class="small-box bg-info1">
<div class="inner" style="height: 130px;">
<h2 class="bg-title">{{total_refuse_partner}}</h2>
<p class="bg-title1">{{total_refuse_partner}}/{{total_progressing}}</p>
<p class="bg-title2">材料打回/提交审核商户数</p>
</div>
<div class="icon" style="position: absolute;top: 2px;right: 10px;">
<div class="circleChart4" style="color: white"></div>
</div>
</div>
</div>
</div>
<div class="box box-warning">
<div class="box-header">待处理需要帮助的商户({{need_help.length}}家):
<div class="box-tools pull-right">
<button type="button" ng-if="!ctrl.plusShow1" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#need-help" ng-click="ctrl.plusShow1=true">
<i class="fa fa-minus"></i>
</button>
<button type="button" ng-if="ctrl.plusShow1" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#need-help" ng-click="ctrl.plusShow1=false">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body table-responsive collapse in" id="need-help">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>Submit Time</th>
<th>Source</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in need_help">
<td>
{{client.client_moniker}}
</td>
<td ng-bind="client.short_name"></td>
<td ng-class="{'bg-green':(client.approve_result==2 && (client.client_source==1 || client.client_source==2)),'bg-red':((client.open_status==1||client.open_status==2||client.open_status==4) && client.approve_result!=3)||(client.approve_result==3 && (!client.open_status || client.open_status==1 || client.open_status == 4))||(client.approve_result==4 && !client.open_status)||(client.open_status==10)}">
<span ng-if="client.approve_result==1 && client.approve_time">通过({{client.approve_time}})</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source!=4">资料完善中</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!client.open_status && client.approve_result==2 && client.approve_time">自助开通试用中({{client.approve_time}}~{{client.expiry_time}})</span>
<span ng-if="client.approve_result==0 && client.approve_time">不通过({{client.approve_time}})</span>
<span ng-if="client.approve_result==5 && client.approve_time && client.refuse_remark">申请打回({{client.refuse_remark|limitTo:15}})</span>
<span ng-if="(client.open_status==1||client.open_status==4) && client.approve_result!=3"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="client.approve_result==3 && (!client.open_status || client.open_status==4)">自助开通(等待合规)</span>
<span ng-if="client.open_status==2">合同制作完成</span>
<span ng-if="client.open_status==3 && client.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="client.open_status==10">绿色通道申请中</span>
<span ng-if="client.approve_result==4 && !client.open_status"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="client.create_time|date:'dd/MMM/yyyy'"></td>
<td ng-bind="client.submit_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="client.source==1">App</span>
<span ng-if="client.source==2">Web</span>
</td>
<td>
<a class="text-primary" role="button" title="Detail"
ui-sref="partners.detail({clientMoniker:client.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>|
<a class="text-primary" role="button" title="Detail" ui-sref="partnerKYCProgress.bdHelpKycProgress({clientMoniker:client.client_moniker})">Handle
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="box box-info" style="margin-top: 30px;">
<div class="box-header">已提交审核({{progressPagination.totalCount}}家):
<div class="box-tools pull-right">
<button type="button" ng-if="!ctrl.plusShow2" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#approving" ng-click="ctrl.plusShow2=true">
<i class="fa fa-minus"></i>
</button>
<button type="button" ng-if="ctrl.plusShow2" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#approving" ng-click="ctrl.plusShow2=false">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body table-responsive collapse in" id="approving">
<div class="row">
<div class="col-sm-12">
<div class="form-horizontal">
<div class="form-group col-xs-12">
<label class="col-xs-4 col-sm-2 control-label">Partner Code</label>
<div class="col-sm-5 col-xs-8">
<input class="form-control" placeholder="" ng-click="loadClientProgressing(1)"
ng-model="params.progress_client_moniker">
</div>
</div>
<div class="form-group col-xs-12">
<label class="control-label col-xs-4 col-sm-2">审核状态:</label>
<div class="col-sm-10 col-xs-8">
<p class="form-control-static">
<a role="button" ng-class="{'bg-primary':params.progress_status==null}"
ng-click="params.progress_status=null;loadClientProgressing(1,params.progress_status)">All</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([0])}"
ng-click="params.progress_status=[0];loadClientProgressing(1,params.progress_status)">待审核</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([1])}"
ng-click="params.progress_status=[1];loadClientProgressing(1,params.progress_status)">通过</a>
</p>
</div>
</div>
<button class="btn btn-success" type="button" ng-click="loadClientProgressing()">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>AuthFile Status</th>
<th>Submit Time</th>
<th>Source</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in approving">
<td ng-bind="client.client_moniker"></td>
<td ng-bind="client.short_name"></td>
<td ng-class="{'bg-green':(client.approve_result==2 && (client.client_source==1 || client.client_source==2)),'bg-red':((client.open_status==1||client.open_status==2||client.open_status==4) && client.approve_result!=3)||(client.approve_result==3 && (!client.open_status || client.open_status==1 || client.open_status == 4))||(client.approve_result==4 && !client.open_status)||(client.open_status==10)}">
<span ng-if="client.approve_result==1 && client.approve_time">通过({{client.approve_time}})</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source!=4">资料完善中</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!client.open_status && client.approve_result==2 && client.approve_time">自助开通试用中({{client.approve_time}}~{{client.expiry_time}})</span>
<span ng-if="client.approve_result==0 && client.approve_time">不通过({{client.approve_time}})</span>
<span ng-if="client.approve_result==5 && client.approve_time && client.refuse_remark">申请打回({{client.refuse_remark|limitTo:15}})</span>
<span ng-if="(client.open_status==1||client.open_status==4) && client.approve_result!=3"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="client.approve_result==3 && (!client.open_status || client.open_status==4)">自助开通(等待合规)</span>
<span ng-if="client.open_status==2">合同制作完成</span>
<span ng-if="client.open_status==3 && client.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="client.open_status==10">绿色通道申请中</span>
<span ng-if="client.approve_result==4 && !client.open_status"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="client.create_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="client.status==0">待审核</span>
<span ng-if="client.status==1">通过</span>
<span ng-if="client.status==2">打回</span>
</td>
<td ng-bind="client.submit_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="client.source==1">App</span>
<span ng-if="client.source==2">Web</span>
</td>
<td><a class="text-primary" role="button" title="Detail"
ui-sref="partners.detail({clientMoniker:client.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>
</td>
<!--({client_id:client.client_id})-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="progressPagination"
class="pagination"
total-items="progressPagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadClientProgressing()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="col-xs-12">Total Records:{{progressPagination.totalCount}};Total Pages:{{progressPagination.totalPages}}</div>
</div>
</div>
</div>
<div class="box box-danger" style="margin-top: 30px;">
<div class="box-header">未提交审核({{completedPagination.totalCount}}家):
<div class="box-tools pull-right">
<button type="button" ng-if="!ctrl.plusShow3" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#completed_contract" ng-click="ctrl.plusShow3=true">
<i class="fa fa-minus"></i>
</button>
<button type="button" ng-if="ctrl.plusShow3" class="btn btn-tool btn-box-tool" data-toggle="collapse" data-target="#completed_contract" ng-click="ctrl.plusShow3=false">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body table-responsive collapse in" id="completed_contract">
<div class="row">
<div class="col-sm-12">
<div class="form-horizontal">
<div class="form-group col-xs-12">
<label class="col-xs-4 col-sm-2 control-label">Partner Code</label>
<div class="col-sm-5 col-xs-8">
<input class="form-control" placeholder="" ng-click="loadClientCompleted(1)"
ng-model="params.completed_client_moniker">
</div>
</div>
<div class="form-group col-xs-12">
<label class="control-label col-xs-4 col-sm-2">审核状态:</label>
<div class="col-sm-10 col-xs-8">
<p class="form-control-static">
<a role="button" ng-class="{'bg-primary':params.status==null}"
ng-click="params.status=null;loadClientCompleted(1)">All</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([3])}"
ng-click="params.status=[3];loadClientCompleted(1)">未提交</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([2])}"
ng-click="params.status=[2];loadClientCompleted(1)">打回</a>
</p>
</div>
</div>
<button class="btn btn-success" type="button" ng-click="loadClientCompleted()">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
</div>
<div class="box-body table-responsive">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in completed_contract">
<td ng-bind="client.client_moniker"></td>
<td ng-bind="client.short_name"></td>
<td ng-class="{'bg-green':(client.approve_result==2 && (client.client_source==1 || client.client_source==2)),'bg-red':((client.open_status==1||client.open_status==2||client.open_status==4) && client.approve_result!=3)||(client.approve_result==3 && (!client.open_status || client.open_status==1 || client.open_status == 4))||(client.approve_result==4 && !client.open_status)||(client.open_status==10)}">
<span ng-if="client.approve_result==1 && client.approve_time">通过({{client.approve_time}})</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source!=4">资料完善中</span>
<span ng-if="!client.open_status && !client.approve_result && client.approve_result!=5 && client.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!client.open_status && client.approve_result==2 && client.approve_time">自助开通试用中({{client.approve_time}}~{{client.expiry_time}})</span>
<span ng-if="client.approve_result==0 && client.approve_time">不通过({{client.approve_time}})</span>
<span ng-if="client.approve_result==5 && client.approve_time && client.refuse_remark">申请打回({{client.refuse_remark|limitTo:15}})</span>
<span ng-if="(client.open_status==1||client.open_status==4) && client.approve_result!=3"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="client.approve_result==3 && (!client.open_status || client.open_status==4)">自助开通(等待合规)</span>
<span ng-if="client.open_status==2">合同制作完成</span>
<span ng-if="client.open_status==3 && client.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="client.open_status==10">绿色通道申请中</span>
<span ng-if="client.approve_result==4 && !client.open_status"><i
ng-if="client.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="client.create_time|date:'dd/MMM/yyyy'"></td>
<td><a class="text-primary" role="button" title="Detail"
ui-sref="partners.detail({clientMoniker:client.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>
</td>
<!--({client_id:client.client_id})-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="completed_contract.length"
class="pagination"
total-items="completedPagination.totalCount"
boundary-links="true"
ng-model="completedPagination.page"
items-per-page="completedPagination.limit"
max-size="10"
ng-change="loadClientCompleted()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="col-xs-12">Total Records:{{completedPagination.totalCount}};Total Pages:{{completedPagination.totalPages}}</div>
</div>
</div>
</div>
</div>

@ -47,11 +47,11 @@
<div class="col-sm-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref="partner_detail({client_moniker:partner.client_moniker})">Partner Detail</a>
<li class="active">
<a>Partner Detail</a>
</li>
<li ui-sref-active="active">
<a ui-sref="compliance_detail({client_moniker:partner.client_moniker})">Compliance Audit</a>
<li>
<a ui-sref="partnerKYCProgress.bdHelpKycProgress({clientMoniker:partner.client_moniker})">KYC Files Audit</a>
</li>
</ul>
<div class="tab-content" ui-view>

@ -0,0 +1,204 @@
<style type="text/css">
img {
width: 100%;
}
</style>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li>
<a ui-sref="partnerKYCProgress.partner_detail({clientMoniker:file.client.client_moniker})">Partner Detail</a>
</li>
<li class="active">
<a>KYC Files Audit</a>
</li>
</ul>
<div class="tab-content" ui-view>
<div class="panel panel-default">
<div class="panel-body">
<div class="form-group">
<label class="control-label col-sm-2">商户状态:</label>
<div class="col-sm-10">
<p class="form-control-static">
<span ng-if="file.file_company.status==0">待审核</span>
<span ng-if="file.file_company.status==1">通过</span>
<span ng-if="file.file_company.status==9">需要帮助<p class="small text-danger" ng-if="file.file_company.description && file.file_company.description!=' '"> 打回原因:({{file.file_company.description}}</p></span>
<span ng-if="file.file_company.status==2">打回<p class="small text-danger" ng-if="file.file_company.description && file.file_company.description!=' '"> 打回原因:({{file.file_company.description}}</p></span>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Partner Code</label>
<div class="col-sm-10">
<p class="form-control-static">
<a class="text-primary" role="button" title="Detail"
ui-sref="partners.detail({clientMoniker:file.client.client_moniker})">
<span id="parent_code">{{file.client.client_moniker}}</span>
</a>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Company Name</label>
<div class="col-sm-10">
<p class="form-control-static">
<span ng-bind="file.client.company_name"></span>
</p>
</div>
</div>
</div>
<div class="panel-heading">Audit Files &nbsp;&nbsp;&nbsp;
<button class="btn btn-warning" type="button" ng-click="hrefBdHandle()">如无法提供KYC文件在下方"无法提供材料原因"填写原因后提交
</button>
</a>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-3">* ASIC File</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadBankFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="bankFileProgress.value" ng-if="bankFileProgress"></uib-progressbar>
<a target="_blank" ng-href="{{file.file.client_bank_file}}">
<img class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.file.client_bank_file}}"
class="col-sm-8"
onerror="this.src='/static/images/file_close.png'"></a>
</div>
<div class="col-sm-3">
<div class="form-control-static">
<p>Example请保证图片信息清晰可见,如示例
<img class="col-sm-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/03/07/1488859920633_5ruVtDa30yY2ytBSDAAqxg0Ob2nreh.jpeg">
</p>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Choose ID Type </label>
<div class="col-sm-5">
<div class="form-control-static">
<select class="form-control" ng-model="file.file_company.id_type" style="width: 250px" ng-change="setSession(file.file_company.id_type)">
<option value="">Please Choose</option>
<option value="passport" >Passport</option>
<option value="driver_license">Driver's license</option>
</select>
<p class="text-info">
<i class="fa fa-info"></i> Please select the file type for uploading the ID.<br>
<i class="fa fa-info"></i> Uploading your passport file requires you to upload your utility bill file. <br>
<i class="fa fa-info"></i> You can upload your driver's license and leave the utility bill file blank. <br>
<i class="fa fa-info"></i> 请选择上传ID的文件类型.<br>
<i class="fa fa-info"></i> 上传护照文件需要您上传水电煤账单文件.<br>
<i class="fa fa-info"></i> 上传驾照,水电煤账单文件可以不填.
</p>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* ID </label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadIDFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="idFileProgress.value" ng-if="idFileProgress"></uib-progressbar>
<a target="_blank" ng-href="{{file.file.client_id_file}}">
<img class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.file.client_id_file}}"
class="col-sm-8"
onerror="this.src='/static/images/file_close.png'"></a>
</div>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<p>Example请保证图片(护照或驾照)信息清晰可见,如示例
<img class="col-xs-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725651779_OPiqOP1dGnTpaxPsCR3P9lVrp4384b.jpg">
<img class="col-sm-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725678615_Bv2tzUtihY5U6YK9ScveXzKkVWOnrF.jpg">
</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3"> Utility Bill Files</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadCompanyFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="billFileProgress.value" ng-if="billFileProgress"></uib-progressbar>
<table>
<tbody>
<tr ng-repeat="file_src in file.file.kyc_utility_bill_file track by $index">
<td ng-bind="$index+1+'.'" class="btn">1</td>
<td><a target="_blank" ng-href="{{file_src.file_value}}">
<img ng-src="{{file_src.file_value}}" class="col-sm-8"
onerror="this.src='/static/images/file_close.png'">
</a>
<button class="btn btn-danger" type="button"
ng-click="deleteComplianceFiles(file_src.file_id)">
X
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-5">
<div class="form-control-static">
<div class="col-sm-12">
<p class="col-sm-6">Example公司请提供以下文件图片,如示例
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491226098_Ho29fpS08rNP9AvPTZQfyoIrNa9bcB.png" title="" alt="水费.png"/>
<br/><img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491263193_hqD9DkQOZvqx8Qaw1ABIkqL21aSNrd.jpg" title="" alt="电费.jpg"/>
</p>
<p class="col-sm-6">
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491285195_C8oXVU4QIJ3ADDEMghaNXTt3cXUhtd.png" title="" alt="煤气.png"/>
</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3"> 无法提供材料原因:</label>
<div class="col-sm-4">
<div class="form-control-static">
<textarea class="form-control" ng-model="file.file_company.bd_handle" style="height: 150px" id="bd-handle"></textarea>
</div>
</div>
</div>
<div class="row" style="text-align: center">
<button style="width: 30%;height: 50px;font-size: 20px;margin-top: 40px;margin-bottom: 20px;" class="btn-group btn btn-success" type="button"
ng-click="clientComplianceViewCommit()">Submit Files
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,162 @@
<style type="text/css">
img {
width: 100%;
}
.btn btn-default:active{
position: relative;
top: 1px;
box-shadow: inset 0 3px 5px 0 rgba(0,0,0, 0.2);
outline: 0;
}
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
color: #333;
background-color: #f7bf90;
border-color: #adadad;
}
</style>
<section class="content-header">
<h1>商户KYC文件补充
<span class="small text-danger" style="margin: 20px 20px;font-size: 20px;" ng-if="file.file_company.description">
({{file.file_company.description}})</span>
</h1>
<br/>
<p ng-if="currentUser.lessComplianceFiles && currentUser.lessKycFiles">前去补充合规文件:<a ui-sref="compliance_to_perfect">点击前往</a></p>
</section>
<div class="panel-body box box-warning ng-scope" style="margin-top: 20px;">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-3">* ASIC File</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadBankFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="bankFileProgress.value" ng-if="bankFileProgress"></uib-progressbar>
<a ng-if="bankIsImage" target="_blank" ng-href="{{file.client_bank_file}}">
<img ng-if="file.client_bank_file"
class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.client_bank_file}}"
class="col-sm-8"
onerror="this.src='/static/images/file_close.png'"></a>
</div>
<div class="col-sm-3">
<div class="form-control-static">
<p>Example请保证图片信息清晰可见,如示例
<img class="col-sm-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/03/07/1488859920633_5ruVtDa30yY2ytBSDAAqxg0Ob2nreh.jpeg">
</p>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* Choose ID Type </label>
<div class="col-sm-5">
<div class="form-control-static">
<select class="form-control" ng-model="file.id_type" style="width: 250px" ng-change="setSession(file.id_type)">
<option value="">Please Choose</option>
<option value="passport" >Passport</option>
<option value="driver_license">Driver's license</option>
</select>
<p class="text-info">
<i class="fa fa-info"></i> Please select the file type for uploading the ID.<br>
<i class="fa fa-info"></i> Uploading your passport file requires you to upload your utility bill file. <br>
<i class="fa fa-info"></i> You can upload your driver's license and leave the utility bill file blank. <br>
<i class="fa fa-info"></i> 请选择上传ID的文件类型.<br>
<i class="fa fa-info"></i> 上传护照文件需要您上传水电煤账单文件.<br>
<i class="fa fa-info"></i> 上传驾照,水电煤账单文件可以不填.
</p>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3">* ID </label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadIDFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="idFileProgress.value" ng-if="idFileProgress"></uib-progressbar>
<a ng-if="bankIsImage" target="_blank" ng-href="{{file.client_id_file}}">
<img ng-if="file.client_id_file"
class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.client_id_file}}"
class="col-sm-8"
onerror="this.src='/static/images/file_close.png'"></a>
</div>
<div class="col-sm-3">
<div class="form-control-static">
<div class="col-sm-12">
<p>Example请保证图片(护照或驾照)信息清晰可见,如示例
<img class="col-xs-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725651779_OPiqOP1dGnTpaxPsCR3P9lVrp4384b.jpg">
<img class="col-sm-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725678615_Bv2tzUtihY5U6YK9ScveXzKkVWOnrF.jpg">
</p>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-3"> Utility Bill Files</label>
<div class="col-sm-3">
<div class="form-control-static">
<button class="btn btn-primary" type="button"
ngf-select="uploadCompanyFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="billFileProgress.value" ng-if="billFileProgress"></uib-progressbar>
<table>
<tbody>
<tr ng-repeat="file_src in file.kyc_utility_bill_file track by $index">
<td ng-bind="$index+1+'.'" class="btn">1</td>
<td><a ng-if="billIsImage" target="_blank" ng-href="{{file_src.file_value}}">
<img ng-src="{{file_src.file_value}}" class="col-sm-8"
onerror="this.src='/static/images/file_close.png'">
</a>
<button class="btn btn-danger" type="button"
ng-click="deleteComplianceFiles(file_src.file_id)">
X
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-5">
<div class="form-control-static">
<div class="col-sm-12">
<p class="col-sm-6">Example公司请提供以下文件图片,如示例
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491226098_Ho29fpS08rNP9AvPTZQfyoIrNa9bcB.png" title="" alt="水费.png"/>
<br/><img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491263193_hqD9DkQOZvqx8Qaw1ABIkqL21aSNrd.jpg" title="" alt="电费.jpg"/>
</p>
<p class="col-sm-6">
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491285195_C8oXVU4QIJ3ADDEMghaNXTt3cXUhtd.png" title="" alt="煤气.png"/>
</p>
</div>
</div>
</div>
</div>
<div class="row" style="text-align: center">
<button style="width: 30%;height: 50px;font-size: 20px;margin-top: 40px;margin-bottom: 20px;" class="btn-group btn btn-success" type="button"
ng-click="clientComplianceViewCommit()">Submit Files
</button>
<button style="width: 10%;height: 50px;font-size: 15px;margin-top: 40px;margin-bottom: 20px;" class="btn-group btn btn-warning" type="button"
ng-click="needBDIntervention()">Notify BD Help
</button>
</div>
</div>
</div>
</div>

@ -0,0 +1,37 @@
<section class="content-header">
<h1>商户合规文件审核</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-sitemap"></i> Compliance Management
</li>
<li class="active">商户合规文件审核</li>
</ol>
</section>
<div class="content">
<div class="row">
<div class="col-sm-12 analysis-nav">
<ul class="nav nav-pills">
<li ui-sref-active-eq="active">
<a ui-sref="partner_compliance_auth.partner_authfile"><span>合规文件审核</span></a>
</li>
<li ui-sref-active="active">
<a ui-sref="partner_compliance_auth.partner_kyc_files_auth"> <span>KYC文件审核</span></a>
</li>
<li ui-sref-active="active">
<a ui-sref="partnerKYCProgress"> <span>CustomerService商户KYC认证进度</span></a>
</li>
</ul>
</div>
</div>
<div class="content">
<div class="row">
<div class="nav-tabs-custom" ui-view>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,119 @@
<div class="tab-content">
<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-group col-xs-12">
<label class="col-xs-4 col-sm-2 control-label">Partner Code</label>
<div class="col-sm-5 col-xs-8">
<input class="form-control" placeholder="" ng-click="loadClientCompliance(1)"
ng-model="params.client_moniker">
</div>
</div>
<div class="form-group col-xs-12">
<label class="control-label col-xs-4 col-sm-2">审核状态:</label>
<div class="col-sm-10 col-xs-8">
<p class="form-control-static">
<a role="button" ng-class="{'bg-primary':params.status==null}"
ng-click="params.status=null;loadClientCompliance(1)">All</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([0])}"
ng-click="params.status=[0];loadClientCompliance(1)">待审核</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([1])}"
ng-click="params.status=[1];loadClientCompliance(1)">通过</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([2])}"
ng-click="params.status=[2];loadClientCompliance(1)">打回</a>
</p>
</div>
</div>
<button class="btn btn-success" type="button" ng-click="loadClientCompliance()">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
<div class="box">
<div class="box-header">
</div>
<div class="box-body">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>BD</th>
<th>AuthFile Status</th>
<th>Submit Time</th>
<th>Source</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="compliance_company in compliances">
<td ng-bind="compliance_company.client_moniker"></td>
<td ng-bind="compliance_company.short_name"></td>
<td ng-class="{'bg-green':(compliance_company.approve_result==2 && (compliance_company.client_source==1 || compliance_company.client_source==2)),'bg-red':((compliance_company.open_status==1||compliance_company.open_status==2||compliance_company.open_status==4) && compliance_company.approve_result!=3)||(compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==1 || compliance_company.open_status == 4))||(compliance_company.approve_result==4 && !compliance_company.open_status)||(compliance_company.open_status==10)}">
<span ng-if="compliance_company.approve_result==1 && compliance_company.approve_time">通过({{compliance_company.approve_time}})</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source!=4">资料完善中</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!compliance_company.open_status && compliance_company.approve_result==2 && compliance_company.approve_time">自助开通试用中({{compliance_company.approve_time}}~{{compliance_company.expiry_time}})</span>
<span ng-if="compliance_company.approve_result==0 && compliance_company.approve_time">不通过({{compliance_company.approve_time}})</span>
<span ng-if="compliance_company.approve_result==5 && compliance_company.approve_time && compliance_company.refuse_remark">申请打回({{compliance_company.refuse_remark|limitTo:15}})</span>
<span ng-if="(compliance_company.open_status==1||compliance_company.open_status==4) && compliance_company.approve_result!=3"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==4)">自助开通(等待合规)</span>
<span ng-if="compliance_company.open_status==2">合同制作完成</span>
<span ng-if="compliance_company.open_status==3 && compliance_company.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="compliance_company.open_status==10">绿色通道申请中</span>
<span ng-if="compliance_company.approve_result==4 && !compliance_company.open_status"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="compliance_company.create_time|date:'dd/MMM/yyyy'"></td>
<td ng-bind="compliance_company.bd_user_name"></td>
<td>
<span ng-if="compliance_company.status==0">待审核</span>
<span ng-if="compliance_company.status==1">通过</span>
<span ng-if="compliance_company.status==2">打回</span>
</td>
<td ng-bind="compliance_company.submit_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="compliance_company.source==1">App</span>
<span ng-if="compliance_company.source==2">Web</span>
</td>
<td><a class="text-primary" role="button" title="Detail"
ui-sref="partner_compliance_auth.complianceDetail({client_moniker:compliance_company.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>
</td>
<!--({client_id:compliance_company.client_id})-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="compliances.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadClientCompliance()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="col-xs-12">Total Records:{{pagination.totalCount}};Total Pages:{{pagination.totalPages}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,228 @@
<div class="panel panel-default">
<div class="panel-heading">
Partner Basic Information
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">Partner Code</label>
<div class="col-sm-10">
<p class="form-control-static">
<span id="parent_code">{{partner.client_moniker}}</span>
<span ng-if="partner.parent_client_id!=null">(Sub Partner of
<a ui-sref="partners.detail({clientMoniker:partner.parent_client.client_moniker})"
ng-bind="partner.parent_client.client_moniker"></a>)
</span>
<span ng-if="partner.is_valid==0"
ng-class="{pass_timeout:partner.is_valid==0}">(已禁用)</span>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Company Name</label>
<div class="col-sm-10">
<p class="form-control-static">
<span ng-bind="partner.company_name"></span>
<span
ng-if="isComplianceOfCompanyName && partner.open_status"
style="margin-left: 10px;font-weight: 700;color: red;">
注意:(微信渠道可能不合规)
</span>
<span class="description-text text-red" ng-if="('10000000010' | withRole)" ng-bind="partner.same_company_name"></span>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Short Name</label>
<div class="col-sm-10">
<p class="form-control-static pull-left" ng-bind="partner.short_name"></p>
<p class="form-control-static pull-left"
ng-if="isComplianceOfShortName && partner.open_status"
style="margin-left: 10px;font-weight: 700;color: red;">
注意:(微信渠道可能不合规)
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Business Name</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.business_name"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Store Name</label>
<div class="col-sm-10">
<p class="form-control-static pull-left" ng-bind="partner.store_name"></p>
<p class="form-control-static pull-left"
ng-if="isComplianceOfShortName && partner.open_status"
style="margin-left: 10px;font-weight: 700;color: red;">
注意:(微信渠道可能不合规)
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Business Structure</label>
<div class="col-sm-10">
<p class="form-control-static pull-left"
ng-bind="partner.business_structure|business_structure"></p>
<p class="form-control-static pull-left"
ng-if="isComplianceOfBusinessStructure && partner.open_status"
style="margin-left: 10px;font-weight: 700;color: red;">
注意:(微信渠道可能不合规)
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Logo</label>
<div class="col-sm-10">
<img ng-src="{{partner.logo_url}}" style="max-height: 100px;">
</div>
</div>
<div class="form-group" ng-if="partner.abn">
<label class="control-label col-sm-2">ABN</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.abn"></p>
</div>
</div>
<div class="form-group" ng-if="partner.acn">
<label class="control-label col-sm-2">ACN</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.acn"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Industry</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.industry|partner_industry"></p>
</div>
</div>
<div hidden class="form-group">
<label class="control-label col-sm-2">Sector</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.sector"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Service Phone</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.company_phone||'-'"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Major Products/Service</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.description"></p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Remark</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.remark"></p>
</div>
</div>
<div class="form-group" ng-if="partner.referrer_id">
<label class="control-label col-sm-2">Referrer</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.referrer_name"></p>
</div>
</div>
</div>
</div>
</div>
<!--end 商户基本资料-->
<div class="panel panel-default">
<div class="panel-heading">Partner Contact Information</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">Contact Person Name</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.contact_person"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">Phone</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.contact_phone"></p>
<p class="description-text text-red" ng-if="('10000000010' | withRole)" ng-bind="partner.same_phone"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">E-mail</label>
<div class="col-sm-8">
<p class="form-control-static">
<span ng-bind="partner.contact_email"></span>
</span>
</p>
<p class="description-text text-red" ng-if="('10000000010' | withRole)" ng-bind="partner.same_email"></p>
</div>
</div>
</div>
</div>
</div>
<!--end 商户联系资料-->
<div class="panel panel-default">
<div class="panel-heading">Address Information</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">Address</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.address"></p>
<p class="description-text text-red" ng-if="('10000000010' | withRole)" ng-bind="partner.same_address"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">Suburb</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.suburb"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">PostCode</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.postcode"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">State</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.state"></p>
</div>
</div>
<div class="form-group col-sm-6">
<label class="control-label col-sm-4">Country</label>
<div class="col-sm-8">
<p class="form-control-static" ng-bind="partner.country"></p>
</div>
</div>
<div class="form-group ">
<label class="control-label col-sm-2">Timezone</label>
<div class="col-sm-10">
<p class="form-control-static" ng-bind="partner.timezone|timezoneLabel"></p>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,18 @@
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref=".partner_detail({client_moniker:clientMoniker})">Partner Detail</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".compliance_detail({client_moniker:clientMoniker})">Compliance Files Audit</a>
</li>
</ul>
<div class="tab-content" ui-view>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,119 @@
<div class="tab-content">
<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-group col-xs-12">
<label class="col-xs-4 col-sm-2 control-label">Partner Code</label>
<div class="col-sm-5 col-xs-8">
<input class="form-control" placeholder="" ng-click="loadClientCompliance(1)"
ng-model="params.client_moniker">
</div>
</div>
<div class="form-group col-xs-12">
<label class="control-label col-xs-4 col-sm-2">审核状态:</label>
<div class="col-sm-10 col-xs-8">
<p class="form-control-static">
<a role="button" ng-class="{'bg-primary':params.status==null}"
ng-click="params.status=null;loadClientCompliance(1)">All</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([0])}"
ng-click="params.status=[0];loadClientCompliance(1)">待审核</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([1])}"
ng-click="params.status=[1];loadClientCompliance(1)">通过</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([2])}"
ng-click="params.status=[2];loadClientCompliance(1)">打回</a>
</p>
</div>
</div>
<button class="btn btn-success" type="button" ng-click="loadClientCompliance()">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
<div class="box">
<div class="box-header">
</div>
<div class="box-body">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>BD</th>
<th>AuthFile Status</th>
<th>Submit Time</th>
<th>Source</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="compliance_company in compliances">
<td ng-bind="compliance_company.client_moniker"></td>
<td ng-bind="compliance_company.short_name"></td>
<td ng-class="{'bg-green':(compliance_company.approve_result==2 && (compliance_company.client_source==1 || compliance_company.client_source==2)),'bg-red':((compliance_company.open_status==1||compliance_company.open_status==2||compliance_company.open_status==4) && compliance_company.approve_result!=3)||(compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==1 || compliance_company.open_status == 4))||(compliance_company.approve_result==4 && !compliance_company.open_status)||(compliance_company.open_status==10)}">
<span ng-if="compliance_company.approve_result==1 && compliance_company.approve_time">通过({{compliance_company.approve_time}})</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source!=4">资料完善中</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!compliance_company.open_status && compliance_company.approve_result==2 && compliance_company.approve_time">自助开通试用中({{compliance_company.approve_time}}~{{compliance_company.expiry_time}})</span>
<span ng-if="compliance_company.approve_result==0 && compliance_company.approve_time">不通过({{compliance_company.approve_time}})</span>
<span ng-if="compliance_company.approve_result==5 && compliance_company.approve_time && compliance_company.refuse_remark">申请打回({{compliance_company.refuse_remark|limitTo:15}})</span>
<span ng-if="(compliance_company.open_status==1||compliance_company.open_status==4) && compliance_company.approve_result!=3"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==4)">自助开通(等待合规)</span>
<span ng-if="compliance_company.open_status==2">合同制作完成</span>
<span ng-if="compliance_company.open_status==3 && compliance_company.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="compliance_company.open_status==10">绿色通道申请中</span>
<span ng-if="compliance_company.approve_result==4 && !compliance_company.open_status"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="compliance_company.create_time|date:'dd/MMM/yyyy'"></td>
<td ng-bind="compliance_company.bd_user_name"></td>
<td>
<span ng-if="compliance_company.status==0">待审核</span>
<span ng-if="compliance_company.status==1">通过</span>
<span ng-if="compliance_company.status==2">打回</span>
</td>
<td ng-bind="compliance_company.submit_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="compliance_company.source==1">App</span>
<span ng-if="compliance_company.source==2">Web</span>
</td>
<td><a class="text-primary" role="button" title="Detail"
ui-sref="partner_compliance_auth.kycDetail({client_moniker:compliance_company.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>
</td>
<!--({client_id:compliance_company.client_id})-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="compliances.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadClientCompliance()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="col-xs-12">Total Records:{{pagination.totalCount}};Total Pages:{{pagination.totalPages}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,18 @@
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref=".partner_detail({client_moniker:clientMoniker})">Partner Detail</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".kyc_files_detail({client_moniker:clientMoniker})">KYC Files Audit</a>
</li>
</ul>
<div class="tab-content" ui-view>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,174 @@
<style type="text/css">
img {
width: 100%;
}
</style>
<div class="panel panel-default">
<div class="panel-heading">KYC Files &nbsp;&nbsp;&nbsp;
<span ng-if="!file.companyFile">(未提交)</span>
<span ng-if="file.companyFile">
<b><span ng-if="file.companyFile.status == 9" style="color: red">(BD帮助)</span></b>
<b> <span ng-if="file.companyFile.status == 0" style="color: orange">(待审核)</span></b>
<b> <span ng-if="file.companyFile.status == 1" style="color: green">(已通过)</span></b>
<b> <span ng-if="file.companyFile.status == 2" style="color: red;">(已打回)</span></b>
</span>
<!--<a class="btn-group btn btn-success" ng-if="file" ng-href="{{downloadAsZip()}}" target="_blank">
<i class="fa fa-cloud-download">一键下载</i>
</a>-->
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">* ASIC File</label>
<div class="col-sm-4">
<div class="form-control-static" ng-if="role =='compliance'">
<button class="btn btn-primary" type="button"
ngf-select="uploadBankFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
<i class="fa fa-check-square-o check-i" aria-hidden="true" style="float: none" ng-if="$root.complianceCheck.authFile"></i>
</div>
<uib-progressbar value="bankFileProgress.value" ng-if="bankFileProgress"></uib-progressbar>
<!-- <a ng-if="bankIsImage" target="_blank" ng-repeat="src in file.client_bank_file" ng-href="{{src}}">
<img ng-src="{{src}}" class="col-sm-8">
</a>-->
<table>
<tbody>
<tr ng-repeat="file_src in file.client_bank_file track by $index">
<td ng-bind="$index+1+'.'" ALIGN="left" VALIGN="top" class="btn">1</td>
<td><a ng-if="bankIsImage" target="_blank" ng-href="{{file_src.file_value}}">
<img ng-src="{{file_src.file_value}}"class="col-sm-6" style="border: 1px solid #ddd" onerror="this.src='/static/images/file_close.png'">
</a>
<button class="btn btn-danger" type="button" ng-click="deleteComplianceFiles(file_src.file_id)">X</button>
<a role="button" download="" target="_blank" class="btn-group btn btn-warning" type="button" href="{{file_src.file_value}}" ><i class="fa fa-download"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-6">
<div class="form-control-static">
<p>Example请保证图片信息清晰可见,如下图</p>
<img class="col-sm-6" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/03/07/1488859920633_5ruVtDa30yY2ytBSDAAqxg0Ob2nreh.jpeg">
</div>
</div>
</div>
<div class="form-group" ng-if="file.companyFile">
<label class="control-label col-sm-2">* ID Type </label>
<div class="col-sm-4">
<div class="form-control-static">
<p ng-if="file.companyFile.id_type == 'passport'" >Passport</p>
<p ng-if="file.companyFile.id_type == 'driver_license' ">Driver's license</p>
</select>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">* ID </label>
<div class="col-sm-4">
<div class="form-control-static" ng-if="role =='compliance'">
<button class="btn btn-primary" type="button"
ngf-select="uploadIDFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
<i class="fa fa-check-square-o check-i" aria-hidden="true" style="float: none" ng-if="$root.complianceCheck.authFile"></i>
</div>
<uib-progressbar value="idFileProgress.value" ng-if="idFileProgress"></uib-progressbar>
<!--<a ng-if="idIsImage" ng-repeat="src in file.client_id_file" ng-href="{{src}}" target="_blank">
<img ng-src="{{src}}" class="col-sm-8"></a>-->
<table>
<tbody>
<tr ng-repeat="file_src in file.client_id_file track by $index">
<td ng-bind="$index+1+'.'" class="btn">1</td>
<td><a ng-if="bankIsImage" target="_blank" ng-href="{{file_src.file_value}}">
<img ng-src="{{file_src.file_value}}" class="col-sm-6" style="border: 1px solid #ddd" onerror="this.src='/static/images/file_close.png'">
</a>
<button class="btn btn-danger" type="button" ng-click="deleteComplianceFiles(file_src.file_id)">X</button>
<a role="button" class="btn-group btn btn-warning" type="button" ng-href="{{file_src.file_value}}" download="" target="_blank"><i class="fa fa-download"></i></a>
</td>
</tr>
</tbody></table>
</div>
<div class="col-sm-6">
<div class="form-control-static">
<div class="col-sm-6">
<p>Example请保证图片(护照或驾照)信息清晰可见,如下图</p>
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725651779_OPiqOP1dGnTpaxPsCR3P9lVrp4384b.jpg">
</div>
<div class="col-sm-6">
<br/>
<br/>
<img class="col-sm-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2017/06/29/1498725678615_Bv2tzUtihY5U6YK9ScveXzKkVWOnrF.jpg">
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2"> Utility Bill Files</label>
<div class="col-sm-4">
<div class="form-control-static" ng-if="role =='compliance'">
<button class="btn btn-primary" type="button"
ngf-select="uploadCompanyFile($file)">
<i class="fa fa-upload"></i> Upload
</button>
</div>
<uib-progressbar value="billFileProgress.value" ng-if="billFileProgress"></uib-progressbar>
<table>
<tbody>
<tr ng-repeat="file_src in file.kyc_utility_bill_file track by $index">
<td ng-bind="$index+1+'.'" class="btn">1</td>
<td><a ng-if="billIsImage" target="_blank" ng-href="{{file_src.file_value}}">
<img ng-src="{{file_src.file_value}}" class="col-sm-8"
onerror="this.src='/static/images/file_close.png'">
</a>
<button class="btn btn-danger" type="button"
ng-click="deleteComplianceFiles(file_src.file_id)">
X
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-6">
<div class="form-control-static">
<div class="col-sm-12">
<p class="col-sm-6">Example公司请提供以下文件图片,如示例
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491226098_Ho29fpS08rNP9AvPTZQfyoIrNa9bcB.png" title="" alt="水费.png"/>
<br/><img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491263193_hqD9DkQOZvqx8Qaw1ABIkqL21aSNrd.jpg" title="" alt="电费.jpg"/>
</p>
<p class="col-sm-6">
<img class="col-xs-12" style="border: 1px solid #ddd"
src="https://file.royalpay.com.au/open/2019/12/16/1576491285195_C8oXVU4QIJ3ADDEMghaNXTt3cXUhtd.png" title="" alt="煤气.png"/>
</p>
</div>
</div>
</div>
</div>
<div class="form-group" ng-if="file.companyFile && file.companyFile.bd_handle">
<label class="control-label col-sm-2"> 无法提供材料原因:</label>
<div class="col-sm-4">
<div class="form-control-static">
<textarea class="form-control" ng-model="file.companyFile.bd_handle" style="height: 150px" id="bd-handle" readonly></textarea>
</div>
</div>
</div>
</div>
</div>
<div style="text-align: center">
<a role="button" style="margin-bottom: 25px;" class="btn btn-success btn-sm ng-scope" ng-if="('10'|withRole)" ng-click="complianceCheck()">check</a>
</div>
</div>

@ -167,6 +167,15 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
return $http.get('/sys/partners/' + $stateParams.clientMoniker + '/file');
}]
}
}).state('partners.detail.kyc_files', {
url: '/kyc_files',
templateUrl: '/static/payment/kyc/templates/partner_kyc_files.html',
controller: 'partnerKycFileCtrl',
resolve: {
file: ['$http', '$stateParams', function ($http, $stateParams) {
return $http.get('/sys/partners/' + $stateParams.clientMoniker + '/kycFile');
}]
}
}).state('partners.detail.settlement', {
url: '/settlement',
templateUrl: '/static/payment/partner/templates/partner_settlement.html',
@ -4044,6 +4053,171 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
$scope.complianceChangeCheck();
}]);
app.controller('partnerKycFileCtrl', ['$scope', '$http', '$rootScope', 'commonDialog', '$state', 'Upload', 'file', function ($scope, $http, $rootScope, commonDialog, $state, Upload, file) {
$scope.file = file.data || {};
//kyc files
$scope.uploadBankFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.bankFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.bankFileProgress;
$scope.file.file_bank_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_bank_info.endsWith('pdf')) {
$scope.bankIsImage = false;
} else {
$scope.bankIsImage = true;
}
}, function (resp) {
delete $scope.bankFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.bankFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
$scope.bankIsImage = true;
if ($scope.file.file_bank_info && $scope.file.file_bank_info.endsWith('pdf')) {
$scope.bankIsImage = false;
}
$scope.idIsImage = true;
if ($scope.file.file_id_info && $scope.file.file_id_info.endsWith('pdf')) {
$scope.idIsImage = false;
}
$scope.billIsImage = true;
if ($scope.file.file_company_info && $scope.file.file_company_info.endsWith('pdf')) {
$scope.billIsImage = false;
}
//上传ID信息
$scope.uploadIDFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.idFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.idFileProgress;
$scope.file.file_id_info = resp.data.url;
$scope.updateFile();
if ($scope.file.file_id_info.endsWith('pdf')) {
$scope.idIsImage = false;
} else {
$scope.idIsImage = true;
}
}, function (resp) {
delete $scope.idFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.idFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
//上传账单流水
$scope.uploadCompanyFile = function (file) {
if (file != null) {
if (file.size > 3 * 1024 * 1024) {
commonDialog.alert({title: 'Error', content: '文件大小不能超过3MB请压缩后重试', type: 'error'})
} else {
$scope.billFileProgress = {value: 0};
Upload.upload({
url: '/attachment/files',
data: {file: file}
}).then(function (resp) {
delete $scope.billFileProgress;
$scope.file.utility_bill_info = resp.data.url;
$scope.updateFile();
if ($scope.file.utility_bill_info.endsWith('pdf')) {
$scope.billIsImage = false;
} else {
$scope.billIsImage = true;
}
}, function (resp) {
delete $scope.billFileProgress;
commonDialog.alert({title: 'Upload Failed', content: resp.data.message, type: 'error'})
}, function (evt) {
$scope.billFileProgress.value = parseInt(100 * evt.loaded / evt.total);
})
}
}
};
/* $scope.downloadAsZip = function () {
var url = '/sys/partners/' + $scope.partner.client_moniker + '/download/complianceAsZIP';
return url;
};*/
$scope.deleteComplianceFiles = function (file_id) {
commonDialog.confirm({
title: 'Warning',
content: 'This operation will delete the file, Are you sure?'
}).then(function () {
$http.put('/sys/partners/auth_file/' + file_id + '/delete').then(function (resp) {
commonDialog.alert({
title: 'Success',
content: 'Delete Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.updateFile = function () {
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/kycFile', $scope.file).then(function () {
commonDialog.alert({
title: 'Success',
content: 'Upload Successful',
type: 'success'
});
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
}
function commitError() {
commonDialog.alert({
title: 'Error',
content: 'Missing file',
type: 'error'
});
};
$scope.complianceCheck = function () {
if (!$rootScope.complianceCheck) {
$rootScope.complianceCheck = {};
}
$rootScope.complianceCheck.client_id = $scope.partner.client_id;
$rootScope.complianceCheck.authFile = true;
};
$scope.complianceChangeCheck = function () {
if ($rootScope.complianceCheck) {
if ($scope.partner.client_id != $rootScope.complianceCheck.client_id) {
delete $rootScope.complianceCheck;
}
}
};
$scope.complianceChangeCheck();
}]);
app.controller('partnerSettlementCtrl', ['$scope', '$uibModal', '$http', 'clientMoniker', '$filter', function ($scope, $uibModal, $http, clientMoniker, $filter) {
$scope.params = {};
$scope.pagination = {};

@ -856,6 +856,7 @@ define(['angular', 'decimal', 'uiRouter', 'ngBootSwitch', 'ngFileUpload', 'uiBoo
}
};
}]);
app.controller('clientCommitToComplianceFilesCtrl', ['$scope', '$http', '$rootScope', 'commonDialog', '$state', 'Upload', 'file','partner', function ($scope, $http, $rootScope, commonDialog, $state, Upload, file, partner) {
$scope.file = file.data || {};
$scope.partner = partner.data || {};
@ -1148,23 +1149,6 @@ define(['angular', 'decimal', 'uiRouter', 'ngBootSwitch', 'ngFileUpload', 'uiBoo
})
})
};
$scope.commitPartner = function () {
if ($scope.file) {
if ($scope.file.file_bank_info != null && $scope.file.file_company_info != null && $scope.file.file_id_info != null && $scope.file_apply_info != null) {
$http.put('/client/partner_info/compliance_audit').then(function (resp) {
});
} else {
commitError();
}
} else {
commitError();
}
};
}]);
app.controller('aggregateFileCtrl', ['$scope', '$http', '$rootScope', 'commonDialog', '$state', '$uibModal', 'Upload', function ($scope, $http, $rootScope, commonDialog, $state, $uibModal, Upload) {

@ -4,9 +4,13 @@ define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootS
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('partner_compliance_auth', {
url: '/partners/complianceForClient',
templateUrl: 'static/sys/templates/partner_compliance_for_client.html',
templateUrl: 'static/payment/kyc/templates/compliance_audit.html',
controller: 'compliancePartnerForClientCtrl'
}).state('compliance_detail', {
}).state('partner_compliance_auth.complianceDetail', {
url: '/{client_moniker}/complianceAuth',
templateUrl: 'static/payment/kyc/templates/compliance_audit_compliance_detail.html',
controller: 'complianceDetailCtrl'
}).state('partner_compliance_auth.complianceDetail.compliance_detail', {
url: '/{client_moniker}/compliance_detail',
templateUrl: '/static/payment/partner/templates/client_compliance_to_auth.html',
controller: 'partnerComplianceCompanyDetail',
@ -15,24 +19,78 @@ define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootS
return $http.get('/compliance/audit/compliance/clientViewFiles/'+ $stateParams.client_moniker);
}]
}
}).state('partner_detail', {
url: '/{client_moniker}/partner_detail',
templateUrl: '/static/payment/partner/templates/partner_detail_for_compliance.html',
controller: 'partnerComplianceCompanyDetail',
}).state('partner_compliance_auth.complianceDetail.partner_detail', {
url: '/partner_detail',
templateUrl: '/static/payment/kyc/templates/compliance_audit_client_detail.html',
controller: 'compliancePartnerDetailCtrl',
resolve: {
partner: ['$http', '$stateParams', function ($http, $stateParams) {
return $http.get('/sys/partners/' + $stateParams.client_moniker);
}]
}
}).state('partner_compliance_auth.kycDetail.partner_detail', {
url: '/partner_detail',
templateUrl: '/static/payment/kyc/templates/compliance_audit_client_detail.html',
controller: 'compliancePartnerDetailCtrl',
resolve: {
partner: ['$http', '$stateParams', function ($http, $stateParams) {
return $http.get('/sys/partners/' + $stateParams.client_moniker);
}]
}
}).state('partner_compliance_auth.partner_kyc_files_auth', {
url: '/partners/KycFiles',
templateUrl: 'static/payment/kyc/templates/compliance_audit_kyc.html',
controller: 'kycFilesAuthForClientCtrl'
}).state('partner_compliance_auth.kycDetail', {
url: '/{client_moniker}',
templateUrl: 'static/payment/kyc/templates/compliance_audit_kyc_detail.html',
controller: 'kycDetailCtrl'
}).state('partner_compliance_auth.partner_authfile', {
url: '/partners/authfile',
templateUrl: 'static/payment/kyc/templates/compliance_audit_authfile.html',
controller: 'authFileForClientCtrl'
}).state('partner_compliance_auth.kycDetail.kyc_files_detail', {
url: '/kyc_files_audit',
templateUrl: '/static/payment/partner/templates/client_kyc_files_to_auth.html',
controller: 'partnerKycFilesDetail',
resolve: {
file: ['$http','$stateParams',function ($http, $stateParams) {
return $http.get('/compliance/audit/compliance/clientViewFiles/'+ $stateParams.client_moniker);
return $http.get('/compliance/audit/kyc/clientViewFiles/'+ $stateParams.client_moniker);
}]
}
}).state('compliance_for_audit_detail', {
url: '/partner/complianceForAudit',
templateUrl: '/static/payment/partner/templates/compliance_auth.html',
controller: 'partnerComplianceAuditCtrl'
})
}]);
app.controller('compliancePartnerForClientCtrl', ['$scope', '$sce', '$http', '$filter', '$uibModal', 'businessStructuresMap', 'industryMap', 'stateMap', 'sectorMap', 'countryMap',
app.controller('compliancePartnerForClientCtrl', ['$rootScope','$state', '$stateParams', function ($rootScope,$state,$stateParams) {
if ($state.is('partner_compliance_auth')){
$state.go('.partner_authfile');
}
}]);
app.controller('kycFilesAuthForClientCtrl', ['$scope', '$sce', '$http', '$filter', '$uibModal', 'businessStructuresMap', 'industryMap', 'stateMap', 'sectorMap', 'countryMap',
function ($scope, $sce, $http, $filter, $uibModal, businessStructuresMap, industryMap, stateMap, sectorMap, countryMap) {
$scope.pagination = {};
$scope.industries = industryMap.configs();
$scope.states = stateMap.configs();
$scope.countries = countryMap.configs();
$scope.params = {type:'2'};
$scope.loadClientCompliance = function (page) {
var params = angular.copy($scope.params);
params.page = page || $scope.pagination.page || 1;
$http.get('/compliance/audit/listClientCompliances', {params: params}).then(function (resp) {
$scope.compliances = resp.data.data;
$scope.pagination = resp.data.pagination;
});
};
$scope.loadClientCompliance(1);
$scope.statusSelected = function (arr) {
return $scope.params.status != null && $scope.params.status.filter(function (status) {
return arr.indexOf(status) >= 0
}).length > 0
};
}]);
app.controller('authFileForClientCtrl', ['$scope', '$sce', '$http', '$filter', '$uibModal', 'businessStructuresMap', 'industryMap', 'stateMap', 'sectorMap', 'countryMap',
function ($scope, $sce, $http, $filter, $uibModal, businessStructuresMap, industryMap, stateMap, sectorMap, countryMap) {
$scope.pagination = {};
$scope.industries = industryMap.configs();
@ -70,28 +128,74 @@ define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootS
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.refusePartnerComplianceFiles = function (obj) {
var partner = angular.copy(obj);
$uibModal.open({
templateUrl: '/static/payment/partner/templates/refuse_reason.html',
controller: 'refusePartnerComplianceFilesCtrl',
resolve: {
partner: partner
}
})
};
}]);
app.controller('kycDetailCtrl', ['$scope', '$rootScope','$state', '$stateParams', function ($scope,$rootScope,$state, $stateParams) {
$scope.clientMoniker = $stateParams.client_moniker;
if ($state.is('partner_compliance_auth.kycDetail')){
$state.go('.kyc_files_detail', {client_moniker: $stateParams.client_moniker});
}
}]);
app.controller('complianceDetailCtrl', ['$scope', '$rootScope','$state', '$stateParams', function ($scope,$rootScope,$state, $stateParams) {
$scope.clientMoniker = $stateParams.client_moniker;
if ($state.is('partner_compliance_auth.complianceDetail')){
$state.go('.compliance_detail', {client_moniker: $stateParams.client_moniker});
}
}]);
app.controller('compliancePartnerDetailCtrl', ['$scope', 'partner','$rootScope', '$stateParams', function ($scope, partner,$rootScope, $stateParams) {
$scope.partner = angular.copy(partner.data);
$scope.clientMoniker = $stateParams.client_moniker;
}]);
app.controller('partnerKycFilesDetail', ['$rootScope', '$scope', '$http', '$state', '$uibModal', 'commonDialog', 'file', '$stateParams', function ($rootScope, $scope, $http, $state, $uibModal, commonDialog, file, $stateParams) {
$scope.clientMoniker = $stateParams.client_moniker;
$scope.file = file.data || {};
$scope.partner = $scope.file.client;
$scope.passPartnerComplianceFiles = function () {
commonDialog.confirm({
title: 'Confirm!',
content: '确认是否通过商户合规文件?'
}).then(function () {
$http.put('/compliance/audit/' + $scope.file.client.client_id + '/pass/kycFile', {}).then(function (resp) {
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
})
};
$scope.refusePartnerComplianceFiles = function (obj) {
var partner = angular.copy(obj);
$uibModal.open({
templateUrl: '/static/payment/partner/templates/refuse_reason.html',
controller: 'refusePartnerComplianceFilesCtrl',
controller: 'refusePartnerKycFilesCtrl',
resolve: {
partner: partner
}
})
};
}]);
app.controller('refusePartnerComplianceFilesCtrl', ['$scope', '$http', '$state', 'partner', function ($scope, $http, $state, partner) {
app.controller('refusePartnerKycFilesCtrl', ['$scope', '$http', '$state', 'partner', function ($scope, $http, $state, partner) {
$scope.partner = angular.copy(partner);
$scope.partner.description = "";
$scope.refusePartnerComplianceFiles = function () {
var a = $scope.partner.description;
$http.put('/compliance/audit/'+$scope.partner.client_id+'/refuse/complianceFile',{description:$scope.partner.description}).then(function (resp) {
$http.put('/compliance/audit/'+$scope.partner.client_id+'/refuse/kycFile',{description:$scope.partner.description}).then(function (resp) {
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
@ -99,14 +203,19 @@ define(['angular', 'static/commons/commons', 'uiBootstrap', 'uiRouter', 'ngBootS
}
}]);
app.controller('refusePartnerComplianceFilesCtrl', ['$scope', '$http', '$state', 'partner', function ($scope, $http, $state, partner) {
$scope.partner = angular.copy(partner);
$scope.partner.description = "";
app.controller('partnerComplianceAuditCtrl', ['$rootScope','$state','$stateParams', function ($rootScope,$state,$stateParams) {
if ($state.is('compliance_for_audit_detail')){
$state.go('partner_detail');
$scope.refusePartnerComplianceFiles = function () {
var a = $scope.partner.description;
$http.put('/compliance/audit/'+$scope.partner.client_id+'/refuse/complianceFile',{description:$scope.partner.description}).then(function (resp) {
$state.reload();
}, function (resp) {
commonDialog.alert({title: 'Error', content: resp.data.message, type: 'error'});
})
}
}]);
return app;
});

@ -4,19 +4,6 @@
}
</style>
<div class="content">
<div class="row">
<div class="col-sm-12">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li ui-sref-active-eq="active">
<a ui-sref="partner_detail({client_moniker:partner.client_moniker})">Partner Detail</a>
</li>
<li ui-sref-active="active">
<a ui-sref="compliance_detail({client_moniker:partner.client_moniker})">Compliance Audit</a>
</li>
</ul>
<div class="tab-content" ui-view>
<div class="panel panel-default">
<div class="panel-body">
<div class="form-group">
@ -195,11 +182,7 @@
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -21,6 +21,8 @@
<span class="small text-danger" style="margin: 20px 20px;font-size: 20px;" ng-if="file.client_refuse_reason">
({{file.client_refuse_reason}})</span>
</h1>
<br/>
<p ng-if="currentUser.lessComplianceFiles && currentUser.lessKycFiles">前去补充KYC文件<a ui-sref="kyc_files_perfect">点击前往</a></p>
</section>
<div class="panel-body box box-warning ng-scope" style="margin-top: 20px;">
<div class="form-horizontal">

@ -0,0 +1,122 @@
<style type="text/css">
img {
width: 100%;
}
</style>
<div class="panel panel-default">
<div class="panel-body">
<div class="form-group">
<label class="control-label col-sm-2">商户KYC文件审核详情</label>
<div class="col-sm-10">
<p class="form-control-static">
<span ng-if="file.file_company.status==0">待审核</span>
<span ng-if="file.file_company.status==1">通过</span>
<span ng-if="file.file_company.status==2">打回<p class="small text-danger" ng-if="file.file_company.description && file.file_company.description!=' '"> 打回原因:({{file.file_company.description}}</p></span>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Partner Code</label>
<div class="col-sm-10">
<p class="form-control-static">
<a class="text-primary" role="button" title="Detail"
ui-sref="partners.detail({clientMoniker:partner.client_moniker})">
<span id="parent_code">{{partner.client_moniker}}</span>
</a>
</p>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Company Name</label>
<div class="col-sm-10">
<p class="form-control-static">
<span ng-bind="partner.company_name"></span>
<span
ng-if="isComplianceOfCompanyName && partner.open_status"
style="margin-left: 10px;font-weight: 700;color: red;">
注意:(微信渠道可能不合规)
</span>
<span class="description-text text-red" ng-if="('10000000010' | withRole)" ng-bind="partner.same_company_name"></span>
</p>
</div>
</div>
</div>
<div class="panel-heading" ng-if="'10'|withRole">KYC Files &nbsp;&nbsp;&nbsp;
<button class="btn-group btn btn-warning" type="button"
ng-click="passPartnerComplianceFiles()" ng-if="file.file_company.status !=1 && file.file_company.status !=2" >PASS
</button>
<button class="btn btn-danger" type="button"
ng-click="refusePartnerComplianceFiles(file.client)" ng-if="file.file_company.status !=1 && file.file_company.status !=2">REFUSE
</button>
<button class="btn-group btn btn-warning" type="button" ng-if="file.file_company.status == 1" >Already Passed
</button>
<button class="btn btn-danger" type="button" ng-if=" file.file_company.status == 2">Already Refused
</button>
</div>
<div class="panel-body">
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-4" style="text-align: center;">bank statement
<span ng-if="file.file_company.status==0" class="small text-danger">(待审核)</span>
<span ng-if="file.file_company.status==1" class="small text-success">(已通过)</span>
<span ng-if="file.file_company.status==2" class="small text-danger">(已驳回)</span>
</label>
<div class="col-sm-6">
<a target="_blank" ng-href="{{file.file.client_bank_file}}">
<img class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.file.client_bank_file}}" class="col-sm-8" onerror="this.src='/static/images/file_close.png'">
</a>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" style="text-align: center;">ID
<span ng-if="file.file_company.status==0" class="small text-danger">(待审核)</span>
<span ng-if="file.file_company.status==1" class="small text-success">(已通过)</span>
<span ng-if="file.file_company.status==2" class="small text-danger">(已驳回)</span>
</label>
<div class="col-sm-6">
<a target="_blank" ng-href="{{file.file.client_id_file}}">
<img class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file.file.client_id_file}}" class="col-sm-8" onerror="this.src='/static/images/file_close.png'">
</a>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" style="text-align: center;">Utility Bill Files
<span ng-if="file.file_company.status==0" class="small text-danger">(待审核)</span>
<span ng-if="file.file_company.status==1" class="small text-success">(已通过)</span>
<span ng-if="file.file_company.status==2" class="small text-danger">(已驳回)</span>
</label>
<div class="col-sm-6">
<table>
<tbody>
<tr ng-repeat="file_src in file.file.kyc_utility_bill_file track by $index">
<td ng-bind="$index+1+'.'" class="btn">1</td>
<td><a target="_blank" ng-href="{{file_src.file_value}}">
<img class="col-sm-6" style="border: 1px solid #ddd" ng-src="{{file_src.file_value}}" class="col-sm-8" onerror="this.src='/static/images/file_close.png'">
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="form-group" ng-if="file.file_company.bd_handle">
<label class="control-label col-sm-4" style="text-align: center;">无法提供材料原因
<span ng-if="file.file_company.status==0" class="small text-danger">(待审核)</span>
<span ng-if="file.file_company.status==1" class="small text-success">(已通过)</span>
<span ng-if="file.file_company.status==2" class="small text-danger">(已驳回)</span>
</label>
<div class="col-sm-6">
{{file.file_company.bd_handle}}
</div>
</div>
</div>
</div>
</div>

@ -52,7 +52,6 @@
<li ui-sref-active="active" ng-show="partner.source==4">
<a ui-sref=".compliance_files">Compliance files</a>
</li>
</ul>
<div class="tab-content" ui-view>
<div ng-show="(partner.source == 4 && (partner.approve_result ==3 || partner.approve_result == 1) ) || partner.source != 4">

@ -1,7 +1,15 @@
<style>
.selectedLanguage{
color:#f06101;
}
</style>
<div class="modal-header bg-green">
<h4 style="text-align: center">合规文件补充通知<span ng-if="file.data.client_refuse_reason" style="color:#b55252">({{file.data.client_refuse_reason}})</span></h4>
<h4 ng-if="adviceLanguage == 'en'" style="text-align: center">Merchant Supplement Compliance File Notification</h4>
<h4 ng-if="adviceLanguage == 'zh'" style="text-align: center">商户资料文件补充通知</h4>
</div>
<div class="modal-body" style="padding: 30px">
<div class="modal-body" style="padding: 20px">
<div class="row">
<div class="col-xs-12">
<div class="form-horizontal">
@ -16,14 +24,15 @@
<div class="form-group">
<!--<label class="control-label col-xs-3">Content</label>-->
<div class="col-xs-12">
<a><h5 style="text-align: right"><span ng-click="changeLanguage('en')" ng-class="{'selectedLanguage':adviceLanguage == 'en'}"style="cursor: pointer;">EN</span> | <span ng-click="changeLanguage('zh')" ng-class="{'selectedLanguage':adviceLanguage == 'zh'}" style="cursor: pointer;">中文</span></h5></a>
<div ng-if="adviceLanguage == 'en'">
<p style="text-align: center;"><span
style="text-align: center; font-family: DengXian; font-size: 14px;">RoyalPay</span>Merchant Supplement
Compliance File Notification<span style="text-align: center; font-family: DengXian; font-size: 14px;"></span>
</p>
<p><span style="font-family: DengXian; font-size: 14px;">Dear RoyalPay Merchants:</span></p>
<p class="p1">RoyalPay is committed to providing a secure and safe platform for Chinese payments. As a part of this
we regularly participate in communication with Austrac and China&#39;s Foreign Exchange Regulator. To ensure
your business is fully compliant, we require certain documents from you by the 31st of October. If you believe
we regularly participate in communication with Austrac and China&#39;s Foreign Exchange Regulator. If you believe
you may not be able to submit these documents on time please get in touch with us as soon as possible.</p>
<p><br/><span style="font-family: DengXian; font-size: 14px;"></span></p>
<p><span
@ -38,18 +47,19 @@
style="font-family: DengXian; font-size: 14px;">.</span></p>
<p><span style="font-family: DengXian; font-size: 14px;">Best Regards,</span></p>
<p><span style="font-family: DengXian; font-size: 14px;">RoyalPay Customer Service Team</span></p>
<hr/>
<p style="text-align: center;"><span style="font-family: DengXian; font-size: 14px;">RoyalPay皇家支付商户合规文件补充通知</span>
</div>
<div ng-if="adviceLanguage == 'zh'">
<p style="text-align: center;"><span style="font-family: DengXian; font-size: 14px;">RoyalPay皇家支付商户文件补充通知</span>
</p>
<p><span style="font-family: DengXian; font-size: 14px;">尊敬的RoyalPay商户</span></p>
<p class="p1">应澳洲政府反洗钱监管机构Austrac和中国外汇监管相关要求需要您配合补充完善基本资料以完成合规流程截止时间2019年10月31日前超期未提交将可能会影响您的正常交易,谢谢您的配合。</p>
<p class="p1">应澳洲政府反洗钱监管机构Austrac和中国外汇监管相关要求需要您配合补充完善基本资料以完成合规流程超期未提交将可能会影响您的正常交易谢谢您的配合。</p>
<p class="p1"><br/><span style="font-family: DengXian; font-size: 14px;"></span></p>
<p><span style="font-family: DengXian; font-size: 14px;">RoyalPay客服与技术支持在此期间将竭诚为您服务如有疑问或需帮助请拨打我们的客服电话1300 107 750或添加RoyalPay官方客服号royalpay_</span><span
style="font-family: DengXian; font-size: 14px;">1</span><span
style="font-family: DengXian; font-size: 14px;">详询。</span></p>
<p><span style="font-family: DengXian; font-size: 14px;">顺颂商祺</span></p>
<p><span style="font-family: DengXian; font-size: 14px;">RoyalPay Customer Service Team</span></p>
</p>
</div>
</div>
</div>
@ -57,9 +67,100 @@
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success" ui-sref="compliance_to_perfect" ng-click="$dismiss()" type="button">Submit Documents
</button>
<div class="box-body table-responsive" ng-if="adviceLanguage == 'en'">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr><th colspan="4" style="text-align: center">List Of Information To Be Supplemented</th></tr>
<tr>
<th>Supplement Type</th>
<th>Deadline</th>
<th>Status</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-if="file.client_less_file">
<td>Supplement Compliance File</td>
<td>2020-01-31</td>
<td>
<p ng-if="file.file_company" style="color: red">
<span ng-if="file.file_company.status == 2">Refused</span>
<span ng-if="file.file_company.description">({{file.file_company.description}})</span>
</p>
<p ng-if=" !file.file_company">
<span>Not Submitted</span>
</p>
</td>
<td><p><a ui-sref="compliance_to_perfect" ng-click="$dismiss()">Go to replenish>></a></p></td>
</tr>
<tr ng-if="kycFile.client_less_file">
<td>KYC Certification Information Supplement</td>
<td>2020-01-31</td>
<td>
<p ng-if="kycFile.file_company" style="color: red">
<span ng-if="kycFile.file_company.status == 2">Refused</span>
<span ng-if="kycFile.file_company.description">({{kycFile.file_company.description}})</span>
</p>
<p ng-if=" !kycFile.file_company">
<span>Not Submitted</span>
</p>
</td>
<td><p><a ui-sref="kyc_files_perfect" ng-click="$dismiss()">Go to replenish>></a></p></td>
</tr>
</tbody>
</table>
</div>
<div class="box-body table-responsive" ng-if="adviceLanguage == 'zh'">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr><th colspan="4" style="text-align: center">待补充资料列表</th></tr>
<tr>
<th>资料类型</th>
<th>截止时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr ng-if="file.client_less_file">
<td>合规资料补充</td>
<td>2020-01-31</td>
<td>
<p ng-if="file.file_company" style="color: red">
<span ng-if="file.file_company.status == 2">打回</span>
<span ng-if="file.file_company.description">({{file.file_company.description}})</span>
</p>
<p ng-if=" !file.file_company">
<span>未提交</span>
</p>
</td>
<td><p><a ui-sref="compliance_to_perfect" ng-click="$dismiss()">前往补充>></a></p></td>
</tr>
<tr ng-if="kycFile.client_less_file">
<td>KYC认证资料补充</td>
<td>2020-01-31</td>
<td>
<p ng-if="kycFile.file_company" style="color: red">
<span ng-if="kycFile.file_company.status == 2">打回</span>
<span ng-if="kycFile.file_company.description">({{kycFile.file_company.description}})</span>
</p>
<p ng-if=" !kycFile.file_company">
<span>未提交</span>
</p>
</td>
<td><p><a ui-sref="kyc_files_perfect" ng-click="$dismiss()">前往补充>></a></p></td>
</tr>
</tbody>
</table>
</div>
<br/>
<br/>
</div>
<div class="modal-footer">
<button class="btn btn-danger" ng-click="$dismiss()" type="button">Cancel</button>
</div>

@ -277,6 +277,9 @@
<li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1">
<a ui-sref=".files">Compliance Files</a>
</li>
<li ui-sref-active="active" ng-if="partner.show_all_permission && partner.is_valid==1">
<a ui-sref=".kyc_files">KYC Files</a>
</li>
<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>
</li>

@ -1,128 +0,0 @@
<section class="content-header">
<h1>商户合规文件审核</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-sitemap"></i> Compliance Management
</li>
<li class="active">商户合规文件审核</li>
</ol>
</section>
<div class="box box-warning" style="margin-top: 30px;">
<div class="box-header">
<div class="row">
<div class="col-sm-12">
<div class="form-horizontal">
<div class="form-group col-xs-12">
<label class="col-xs-4 col-sm-2 control-label">Partner Code</label>
<div class="col-sm-5 col-xs-8">
<input class="form-control" placeholder="" ng-click="loadClientCompliance(1)"
ng-model="params.client_moniker">
</div>
</div>
<div class="form-group col-xs-12">
<label class="control-label col-xs-4 col-sm-2">审核状态:</label>
<div class="col-sm-10 col-xs-8">
<p class="form-control-static">
<a role="button" ng-class="{'bg-primary':params.status==null}"
ng-click="params.status=null;loadClientCompliance(1)">All</a> |
<a role="button" ng-class="{'bg-primary':statusSelected([0])}"
ng-click="params.status=[0];loadClientCompliance(1)">待审核</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([1])}"
ng-click="params.status=[1];loadClientCompliance(1)">通过</a>|
<a role="button" ng-class="{'bg-primary':statusSelected([2])}"
ng-click="params.status=[2];loadClientCompliance(1)">打回</a>
</p>
</div>
</div>
<button class="btn btn-success" type="button" ng-click="loadClientCompliance()">
<i class="fa fa-search"></i> Search
</button>
</div>
</div>
</div>
</div>
</div>
<div class="box box-danger">
<div class="modal-body">
<div class="box-body table-responsive">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Client Moniker</th>
<th>Short Name</th>
<th>Compliance Status</th>
<th>Register Time</th>
<th>BD</th>
<th>AuthFile Status</th>
<th>Submit Time</th>
<th>Source</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="compliance_company in compliances">
<td ng-bind="compliance_company.client_moniker"></td>
<td ng-bind="compliance_company.short_name"></td>
<td ng-class="{'bg-green':(compliance_company.approve_result==2 && (compliance_company.client_source==1 || compliance_company.client_source==2)),'bg-red':((compliance_company.open_status==1||compliance_company.open_status==2||compliance_company.open_status==4) && compliance_company.approve_result!=3)||(compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==1 || compliance_company.open_status == 4))||(compliance_company.approve_result==4 && !compliance_company.open_status)||(compliance_company.open_status==10)}">
<span ng-if="compliance_company.approve_result==1 && compliance_company.approve_time">通过({{compliance_company.approve_time}})</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source!=4">资料完善中</span>
<span ng-if="!compliance_company.open_status && !compliance_company.approve_result && compliance_company.approve_result!=5 && compliance_company.client_source==4">(自助开通)资料完善中</span>
<span ng-if="!compliance_company.open_status && compliance_company.approve_result==2 && compliance_company.approve_time">自助开通试用中({{compliance_company.approve_time}}~{{compliance_company.expiry_time}})</span>
<span ng-if="compliance_company.approve_result==0 && compliance_company.approve_time">不通过({{compliance_company.approve_time}})</span>
<span ng-if="compliance_company.approve_result==5 && compliance_company.approve_time && compliance_company.refuse_remark">申请打回({{compliance_company.refuse_remark|limitTo:15}})</span>
<span ng-if="(compliance_company.open_status==1||compliance_company.open_status==4) && compliance_company.approve_result!=3"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
<span ng-if="compliance_company.approve_result==3 && (!compliance_company.open_status || compliance_company.open_status==4)">自助开通(等待合规)</span>
<span ng-if="compliance_company.open_status==2">合同制作完成</span>
<span ng-if="compliance_company.open_status==3 && compliance_company.approve_result!=5">等待BD上传材料审核</span>
<span ng-if="compliance_company.open_status==10">绿色通道申请中</span>
<span ng-if="compliance_company.approve_result==4 && !compliance_company.open_status"><i
ng-if="compliance_company.refuse_remark.length>0" class="fa fa-reply" aria-hidden="true"
title="被打回重新提交"></i>等待合规</span>
</td>
<td ng-bind="compliance_company.create_time|date:'dd/MMM/yyyy'"></td>
<td ng-bind="compliance_company.bd_user_name"></td>
<td>
<span ng-if="compliance_company.status==0">待审核</span>
<span ng-if="compliance_company.status==1">通过</span>
<span ng-if="compliance_company.status==2">打回</span>
</td>
<td ng-bind="compliance_company.submit_time|date:'dd/MMM/yyyy'"></td>
<td>
<span ng-if="compliance_company.source==1">App</span>
<span ng-if="compliance_company.source==2">Web</span>
</td>
<td><a class="text-primary" role="button" title="Detail"
ui-sref="compliance_detail({client_moniker:compliance_company.client_moniker})">
<i class="fa fa-search"></i> Detail
</a>
</td>
<!--({client_id:compliance_company.client_id})-->
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<uib-pagination ng-if="compliances.length"
class="pagination"
total-items="pagination.totalCount"
boundary-links="true"
ng-model="pagination.page"
items-per-page="pagination.limit"
max-size="10"
ng-change="loadClientCompliance()"
previous-text="&lsaquo;"
next-text="&rsaquo;"
first-text="&laquo;"
last-text="&raquo;"></uib-pagination>
<div class="col-xs-12">Total Records:{{pagination.totalCount}};Total Pages:{{pagination.totalPages}}</div>
</div>
</div>
</div>
Loading…
Cancel
Save