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

master
yixian 6 years ago
commit 707085458e

@ -48,4 +48,10 @@ public interface BDPrizeService {
void exportCommissionDetail(String month, String managerId, HttpServletResponse response);
List<JSONObject> findCommissionList(JSONObject manager);
List<JSONObject> getBDTeamKpiCompletionDegree(String month);
List<JSONObject> getBDProportionByTeamType(String month, String teamType);
JSONObject getBDKpiByManagerId(String month, String manager_id);
}

@ -46,6 +46,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@ -690,6 +691,45 @@ public class BDPrizeServiceImpl implements BDPrizeService {
return null;
}
@Override
public List<JSONObject> getBDTeamKpiCompletionDegree(String month) {
List<JSONObject> prizeAmountAndBdTypeList = financialBDPrizeLogMapper.findBdPrizeAmountAndBdType(getReportByMonth(month));
for (JSONObject prize : prizeAmountAndBdTypeList) {
BigDecimal kpi = financialBDCommissionConfigMapper.findCurrentCommissionMaxAmount(month, prize.getIntValue("bd_type"));
prize.put("kpi", kpi);
prize.put("completionDegree", prize.getBigDecimal("total_amount").divide(kpi,2));
}
List<JSONObject> prizeSort = prizeAmountAndBdTypeList.stream()
.sorted((prize1, prize2) -> prize2.getBigDecimal("completionDegree").compareTo(prize1.getBigDecimal("completionDegree")))
.collect(Collectors.toList());
return prizeSort;
}
@Override
public List<JSONObject> getBDProportionByTeamType(String month, String teamType) {
return financialBDConfigMapper.findManagerByTeamType(teamType, getReportByMonth(month));
}
@Override
public JSONObject getBDKpiByManagerId(String month, String manager_id) {
return financialBDPrizeLogMapper.findByReportAndBDTotal(getReportByMonth(month), manager_id);
}
public String getReportByMonth(String month) {
try {
Date mon = DateUtils.parseDate(month, new String[]{"yyyy-MM"});
month = DateFormatUtils.format(mon, "yyyy-MM");
} catch (ParseException e) {
throw new BadRequestException("Invalid Month");
}
JSONObject report = financialBDPrizeRecordMapper.findByMonth(month);
if (report == null) {
throw new BadRequestException("Report not created");
}
return report.getString("record_id");
}
private String financialBdLevel (int level) {
switch (level) {
case 0:

@ -119,4 +119,28 @@ public class BDPrizeController {
public void exportCommissionBdUserDetail(@PathVariable String month, @ModelAttribute(CommonConsts.MANAGER_STATUS) JSONObject manager, HttpServletResponse response) {
bdPrizeService.exportCommissionDetail(month, manager.getString("manager_id"), response);
}
/**
* BDKPI
*/
@ManagerMapping(value = "/commission/{month}/completion_degree", method = RequestMethod.GET, role = {ManagerRole.DIRECTOR, ManagerRole.ADMIN})
public List<JSONObject> getBDTeamKpiCompletionDegree(@PathVariable String month) {
return bdPrizeService.getBDTeamKpiCompletionDegree(month);
}
/**
* BD
*/
@ManagerMapping(value = "/commission/{month}/bd_proportion/{teamType}", method = RequestMethod.GET, role = {ManagerRole.DIRECTOR, ManagerRole.ADMIN})
public List<JSONObject> getBDProportionByTeamType(@PathVariable String month, @PathVariable String teamType) {
return bdPrizeService.getBDProportionByTeamType(month, teamType);
}
/**
* BD KPI
*/
@ManagerMapping(value = "/commission/{month}/bd_user_kpi/{manager_id}", method = RequestMethod.GET, role = {ManagerRole.DIRECTOR, ManagerRole.ADMIN})
public JSONObject getBDKpiByManagerId(@PathVariable String month, @PathVariable String manager_id) {
return bdPrizeService.getBDKpiByManagerId(month, manager_id);
}
}

@ -6,6 +6,7 @@ import cn.yixblog.support.mybatis.autosql.annotations.SqlType;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
/**
@ -31,4 +32,6 @@ public interface FinancialBDCommissionConfigMapper {
void deleteConfig(@Param("bc_config_id") String configInfo);
JSONObject findCurrentCommissionRate(@Param("month") String month, @Param("amount") String amount, @Param("bd_type") int bd_type);
BigDecimal findCurrentCommissionMaxAmount(@Param("month") String month, @Param("bd_type") int bd_type);
}

@ -37,4 +37,6 @@ public interface FinancialBDConfigMapper {
List<JSONObject> listBDCity();
JSONObject listCityCommission(@Param("city") String city, @Param("record_id") String record_id);
List<JSONObject> findManagerByTeamType(@Param("bd_type") String bdType, @Param("record_id") String record_id);
}

@ -32,7 +32,7 @@ public interface FinancialBDPrizeLogMapper {
@AdvanceSelect(addonWhereClause = "prize_type=0")
List<JSONObject> findByReportAndBD(@Param("record_id") String recordId, @Param("manager_id") String managerId);
@Select("SELECT prize_log_id,record_id,manager_id,bd_name,bd_level,SUM(total_amount) total_amount, " +
@Select("SELECT prize_log_id,record_id,kpi_amount,manager_id,bd_name,bd_level,SUM(total_amount) total_amount, " +
"SUM(total_prize) total_prize,SUM(total_donation) total_donation, SUM(send_prize) send_prize, " +
"SUM(hold_prize) hold_prize,last_punish,prize_type FROM financial_bd_prize_log fbpl " +
"where fbpl.prize_type = 0 and fbpl.record_id = #{record_id} and fbpl.manager_id = #{manager_id} " +
@ -60,4 +60,11 @@ public interface FinancialBDPrizeLogMapper {
@AutoSql(type = SqlType.SELECT)
List<JSONObject> findReportByOne(@Param("record_id") String recordId, @Param("manager_id") String managerId);
@Select("SELECT c.manager_id, SUM(total_amount) total_amount, c.bd_type\n" +
"FROM financial_bd_prize_log l\n" +
"INNER JOIN financial_bd_config c ON l.manager_id = c.manager_id\n" +
"WHERE prize_type = 1 AND record_id = #{record_id}\n" +
"GROUP BY l.manager_id")
List<JSONObject> findBdPrizeAmountAndBdType(@Param("record_id") String recordId);
}

@ -75,17 +75,14 @@ public class RefundServiceImpl implements RefundService, ApplicationEventPublish
@Override
public JSONObject checkOrderRefundAmount(String orderId, JSONObject account) {
JSONObject order = orderMapper.getOrderDetail(orderId);
if (account != null) {
if (account != null && (account.getIntValue("client_id") != order.getIntValue("client_id"))) {
JSONObject client = clientMapper.findClient(account.getIntValue("client_id"));
////父商户全局管理子商户时候,跳过
if (account.getIntValue("client_id") != order.getIntValue("client_id")) {
JSONObject clientOrder = clientMapper.findClient(order.getIntValue("client_id"));
if(!(client.getBoolean("sub_manage") &&
clientOrder.containsKey("parent_client_id")?clientOrder.getIntValue("parent_client_id")==client.getIntValue("client_id"):false)){
throw new ForbiddenException("Order is not belong to your shop/merchant");
}
JSONObject orderTargetClient = clientMapper.findClient(order.getIntValue("client_id"));
if (orderTargetClient.getIntValue("parent_client_id") != account.getIntValue("client_id")) {
throw new ForbiddenException("Order is not belong to your shop/merchant");
} else if (!client.getBooleanValue("sub_manage")) {
throw new ForbiddenException("Order is not belong to your shop/merchant");
}
}
Assert.notNull(order, "Order Not Exists");

@ -23,4 +23,11 @@
AND #{amount} >= COMMISSION_START_AMOUNT
AND #{bd_type} = BD_TYPE
</select>
<select id="findCurrentCommissionMaxAmount" resultType="java.math.BigDecimal">
SELECT ifnull(MAX(commission_start_amount), 1) max_amount
FROM financial_bd_commission_config
WHERE #{month} >= DATE_FORMAT(START_DATE, '%Y-%m')
AND DATE_FORMAT(END_DATE, '%Y-%m') >= #{month}
AND #{bd_type} = BD_TYPE
</select>
</mapper>

@ -82,4 +82,47 @@
AND fbpl.prize_type <> 1
]]>
</select>
<select id="findManagerByTeamType" resultType="com.alibaba.fastjson.JSONObject">
SELECT
config.manager_id,config.bd_name,ifnull(total_amount, 0) total_amount,log.kpi_amount
FROM
(
SELECT
*
FROM
financial_bd_config
WHERE
(
manager_id IN (
SELECT
manager_id
FROM
financial_bd_config c
WHERE
bd_type = #{bd_type}
)
OR bd_group IN (
SELECT
manager_id
FROM
financial_bd_config c
WHERE
bd_type = #{bd_type}
)
)
AND get_prize = 1
) config
LEFT JOIN (
SELECT
manager_id,
SUM(total_amount) total_amount,
kpi_amount
FROM
financial_bd_prize_log l
WHERE
record_id = #{record_id} AND prize_type = 0
group by manager_id
) log ON log.manager_id = config.manager_id
</select>
</mapper>

@ -776,6 +776,11 @@ margin-bottom: 10%;"/>
<i class="fa fa-usd"></i> <span>BD提成|BD Commissions</span>
</a>
</li>
<li ui-sref-active="active" ng-if="('bdprize'|withModule)&&(currentUser.org_id==null||currentUser.org_id==1)">
<a ui-sref="analysis_bd.bd_data_analysis" ui-sref-opts="{reload:true}">
<i class="fa fa-usd"></i> <span>BD数据分析|BD Data Analysis</span>
</a>
</li>
<li ui-sref-active="active" ng-if="'10000000001000'|withRole">
<a ng-click="editRateConfig()" style="cursor: pointer">
<i class="fa fa-cog"></i> <span>BD绩效设置</span>

@ -0,0 +1,364 @@
define(['angular', 'uiBootstrap', 'uiRouter'], function (angular) {
'use strict';
var app = angular.module('bdPrizeDataAnalysis', ['ui.bootstrap', 'ui.router']);
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('analysis_bd.bd_data_analysis', {
url: '/bd_data_analysis',
templateUrl: '/static/config/bdprize/templates/bd_data_analysis.html',
controller: 'bdPrizeDataAnalysisCtrl'
})
}]);
app.controller('bdPrizeDataAnalysisCtrl', ['$scope', '$filter', '$http', function ($scope, $filter, $http) {
$scope.bdprize = {};
$scope.getBDTeamKpi = function (month) {
$http.get('/sys/bd_prize/commission/'+ month +'/completion_degree').then(function (resp) {
$scope.BDTeamKpi = $scope.getBDTeamKpiEcharts(resp.data);
if (resp.data) {
$scope.getBdProportion(resp.data[0].bd_type);
}
});
};
$scope.getBdProportion = function (teamType) {
$http.get('/sys/bd_prize/commission/'+ $scope.month +'/bd_proportion/' + teamType).then(function (resp) {
$scope.bdProportion = $scope.getBdAmountProportion(resp.data, teamType);
$scope.bdProportionData = resp.data;
if (resp.data) {
$scope.getBdKpiCompletionDegree(resp.data[0].manager_id);
}
})
};
$scope.getBdKpiCompletionDegree = function(manager_id) {
$http.get('/sys/bd_prize/commission/'+ $scope.month +'/bd_user_kpi/' + manager_id).then(function (resp) {
$scope.bdKpi = $scope.getBdKpi(resp.data);
$scope.bdKpiData = resp.data;
})
};
$scope.bdTeamKpiEcharts = function (chart) {
chart.on('click', function (params) {
$scope.getBdProportion($scope.BDTeamKpiData[params.seriesIndex].bd_type);
})
};
$scope.bdProportionEcharts = function(chart) {
chart.on('click', function (params) {
var managerId = $scope.bdProportionData[params.dataIndex].manager_id;
$scope.getBdKpiCompletionDegree(managerId);
})
};
$scope.selectBdPrizeAnalysis = function () {
var month = $filter('date')(new Date(), 'yyyy-MM');
if ($scope.bdprize.month) {
month = $filter('date')($scope.bdprize.month, 'yyyy-MM');
}
$scope.month = month;
$scope.getBDTeamKpi(month);
};
$scope.selectBdPrizeAnalysis();
$scope.getBDTeamKpiEcharts = function(data){
var BDTeamKpi = {
tooltip : {
formatter: "{a} <br/>{c} {b}"
},
toolbox: {
show : true,
feature : {
mark : {show: true},
restore : {show: true},
saveAsImage : {show: true}
}
},
series : [
{
name:'KPI',
type:'gauge',
z: 3,
min:0,
max:100,
splitNumber:10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
width: 10
}
},
axisTick: { // 坐标轴小标记
length :15, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
}
},
splitLine: { // 分隔线
length :20, // 属性length控制线长
lineStyle: { // 属性lineStyle详见lineStyle控制线条样式
color: 'auto'
}
},
title : {
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
fontWeight: 'bolder',
fontSize: 20,
fontStyle: 'italic'
}
},
detail : {
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
fontWeight: 'bolder'
}
},
data:[{value: 0, name: '完成度'}]
},
{
name:'KPI',
type:'gauge',
center : ['25%', '55%'], // 默认全局居中
radius : '50%',
min:0,
max:100,
endAngle:45,
splitNumber:10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
width: 8
}
},
axisTick: { // 坐标轴小标记
length :12, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
}
},
splitLine: { // 分隔线
length :20, // 属性length控制线长
lineStyle: { // 属性lineStyle详见lineStyle控制线条样式
color: 'auto'
}
},
pointer: {
width:5
},
title : {
offsetCenter: [0, '-30%'], // x, y单位px
},
detail : {
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
fontWeight: 'bolder'
}
},
data:[{value: 0, name: ''}]
},
{
name:'KPI',
type:'gauge',
center : ['75%', '55%'], // 默认全局居中
radius : '50%',
min:0,
max:100,
startAngle:135,
endAngle:-45,
splitNumber:10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
width: 8
}
},
axisTick: { // 坐标轴小标记
length :12, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
}
},
splitLine: { // 分隔线
length :20, // 属性length控制线长
lineStyle: { // 属性lineStyle详见lineStyle控制线条样式
color: 'auto'
}
},
pointer: {
width:5
},
title : {
offsetCenter: [0, '-30%'], // x, y单位px
},
detail : {
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
fontWeight: 'bolder'
}
},
data:[{value: 0, name: ''}]
}
]
};
angular.forEach(data, function(data, index){
data["team_name"] = $scope.filterBdType(data.bd_type);
BDTeamKpi.series[index].data[0] = {"value":(data.completionDegree*100).toFixed(2),
"name":$scope.filterBdType(data.bd_type)}
});
$scope.BDTeamKpiData = data;
return BDTeamKpi;
};
$scope.getBdAmountProportion = function(data, teamType) {
var bdProportion = {
title : {
text: 'BD总金额分布',
x:'center'
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient : 'vertical',
x : 'left',
data:[]
},
toolbox: {
show : true,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {
show: true,
type: ['pie', 'funnel'],
option: {
funnel: {
x: '25%',
width: '50%',
funnelAlign: 'left',
max: 1548
}
}
},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
series : [
{
type:'pie',
radius : '55%',
center: ['50%', '60%'],
data:[
]
}
]
};
angular.forEach(data, function(data, index){
bdProportion.legend.data.push(data.bd_name);
bdProportion.series[0].data.push({"value": data.total_amount, "name": data.bd_name})
});
bdProportion.title.text = $scope.filterBdType(teamType) + " BD总金额分布";
return bdProportion;
};
$scope.getBdKpi = function(data) {
var bdKpi = {
tooltip : {
formatter: "{a} <br/>{b} : {c}%"
},
toolbox: {
show : true,
feature : {
mark : {show: true},
restore : {show: true},
saveAsImage : {show: true}
}
},
series : [
{
name:'业务指标',
type:'gauge',
startAngle: 180,
endAngle: 0,
center : ['50%', '90%'], // 默认全局居中
radius : 320,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
width: 200
}
},
axisTick: { // 坐标轴小标记
splitNumber: 10, // 每份split细分多少段
length :12, // 属性length控制线长
},
axisLabel: { // 坐标轴文本标签详见axis.axisLabel
formatter: function(v){
switch (v+''){
case '10': return '低';
case '50': return '中';
case '90': return '高';
default: return '';
}
},
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
color: '#fff',
fontSize: 15,
fontWeight: 'bolder'
}
},
pointer: {
width:10,
length: '80%',
color: 'rgba(0, 0, 0, 0.8)'
},
title : {
show : true,
offsetCenter: [0, '-60%'], // x, y单位px
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
color: '#fff',
fontSize: 30
}
},
detail : {
show : true,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 0,
borderColor: '#ccc',
width: 100,
height: 40,
offsetCenter: [0, -40], // x, y单位px
formatter:'{value}%',
textStyle: { // 其余属性默认使用全局文本样式详见TEXTSTYLE
fontSize : 50
}
},
data:[{value: 0, name: '完成率'}]
}
]
};
bdKpi.series[0].data[0] = {"value":(data.total_amount/data.kpi_amount*100).toFixed(2),"name":data.bd_name + "完成度"};
return bdKpi;
}
$scope.filterBdType = function (type) {
switch (type) {
case 1:
return 'Sydney';
case 2:
return 'KA Manager';
case 6:
return 'Melbourne';
case 7:
return 'KA Manager';
}
}
}]);
app.filter('financialBdLevel', function () {
return function (level) {
switch (level) {
case 0:
return 'Leader';
case 1:
return 'Junior';
case 2:
return 'Intermediate';
case 3:
return 'Senior';
default:
return 'Unknown';
}
}
});
return app;
});

@ -0,0 +1,78 @@
<div ui-view>
<section class="content-header">
<h1>BD Data Analysis</h1>
<ol class="breadcrumb">
<li><i class="fa fa-usd"></i> Performance</li>
<li class="active">BD Data Analysis</li>
</ol>
</section>
<section class="content">
<div class="box box-danger" ng-if="('10000000000000'|withRole)">
<div class="box-body">
<div class="form-inline">
<div class="form-group">
<input type="text" class="form-control" uib-datepicker-popup="yyyy-MM" ng-model="bdprize.month"
is-open="ctrl.bdprize" datepicker-options="{minMode: 'month'}"
ng-click="ctrl.bdprize=true" placeholder="Select Month"/>
</div>
<button class="btn btn-primary" ng-click="selectBdPrizeAnalysis()" ng-disabled="!bdprize.month">
查询
</button>
</div>
</div>
</div>
<div class="box box-default" ng-if="('1000'|withRole) || ('1000000'|withRole) || ('10000000000000'|withRole)">
<div class="box-header">
团队总KPI完成度
</div>
<div class="box-body">
<div class="chart" style="height: 400px" id="BDTeamKpi" echarts="BDTeamKpi"
chart-setter="bdTeamKpiEcharts($chart)"
ng-class="{nodata:!BDTeamKpiData}"></div>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<td>teamName</td>
<td>kpiAmount</td>
<td>totalAmount</td>
</tr>
</thead>
<tr ng-repeat="data in BDTeamKpiData">
<td ng-bind="data.team_name"></td>
<td ng-bind="data.kpi"></td>
<td ng-bind="data.total_amount"></td>
</tr>
</table>
</div>
</div>
<div class="box box-info">
<div class="box-header">BD占比</div>
<div class="box-body">
<div class="chart" style="height: 400px" id="bdProportion" echarts="bdProportion"
chart-setter="bdProportionEcharts($chart)"
ng-class="{nodata:!bdProportionData}"></div>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<td>bdName</td>
<td>kpiAmount</td>
<td>totalAmount</td>
</tr>
</thead>
<tr ng-repeat="data in bdProportionData">
<td ng-bind="data.bd_name"></td>
<td ng-bind="data.kpi_amount"></td>
<td ng-bind="data.total_amount"></td>
</tr>
</table>
</div>
</div>
<div class="box box-info">
<div class="box-header">BD KPI完成度</div>
<div class="box-body">
<div class="chart" style="height: 400px" id="bdKpi" echarts="bdKpi"
ng-class="{nodata:!bdKpiData}"></div>
</div>
</div>
</section>
</div>

File diff suppressed because one or more lines are too long

@ -2115,6 +2115,34 @@ define(['angular', 'decimal', 'static/commons/commons', 'uiBootstrap', 'uiRouter
};
$scope.loadSubClients();
$scope.loadPartnerPaymentInfo = function () {
$http.get('/sys/partners/' + $scope.partner.client_moniker).then(function (resp) {
$scope.paymentInfo = resp.data;
})
};
$scope.loadPartnerPaymentInfo();
$scope.switchSubManage = function () {
if (!$scope.paymentInfo) {
return;
}
if (!$scope.init.sub_manage) {
$scope.init.sub_manage = true;
return;
}
$http.put('/sys/partners/' + $scope.partner.client_moniker + '/sub_manage', {allow: $scope.paymentInfo.sub_manage}).then(function () {
//$scope.loadPartnerPaymentInfo();
}, function (resp) {
commonDialog.alert({
title: 'Failed to change Sub Partners Manage status',
content: resp.data.message,
type: 'error'
})
})
};
}]);
app.controller('partnerRatesCtrl', ['$scope', '$rootScope', '$http', '$uibModal', 'commonDialog','$sce', function ($scope, $rootScope, $http, $uibModal, commonDialog,$sce) {
$scope.bankCtrl = {edit: true, rate_name: 'Wechat'};

@ -184,12 +184,12 @@
</div>
</div>
</div>
<div class="form-group" ng-if="('10'|withRole) && partner.parent_client_id==null">
<label class="col-sm-3 control-label">Sub Partners Manage</label>
<div class="col-xs-9">
<input type="checkbox" ng-model="paymentInfo.sub_manage" bs-switch switch-change="switchSubManage()">
</div>
</div>
<!--<div class="form-group" ng-if="('10'|withRole) && partner.parent_client_id==null">-->
<!--<label class="col-sm-3 control-label">Sub Partners Manage</label>-->
<!--<div class="col-xs-9" title="开启后,父商户具有帮子商户新建账户、退款等管理权限">-->
<!--<input type="checkbox" ng-model="paymentInfo.sub_manage" bs-switch switch-change="switchSubManage()">-->
<!--</div>-->
<!--</div>-->
</div>
</div>
</div>

@ -1,9 +1,17 @@
<div class="panel panel-default" ng-if="'111'|withRole">
<div class="panel-body" ng-if="('10'|withRole) && partner.parent_client_id==null">
<div class="panel-body" title="开启后,父商户具有帮子商户新建账户、退款等管理权限">
Sub Partners Manage <input type="checkbox" ng-model="paymentInfo.sub_manage" bs-switch switch-change="switchSubManage()">
</div>
</div>
<div class="panel-body">
<button class="btn btn-primary" type="button" ng-click="newSubClient()">
<i class="fa fa-plus"></i> New Sub Partner
</button>
</div>
</div>
<div class="row">
<div class="col-sm-12 table-responsive">

Loading…
Cancel
Save