package com.sobey.cmop.mvc.service.cost;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sobey.cmop.mvc.comm.BaseSevcie;
import com.sobey.cmop.mvc.constant.CPConstant;
import com.sobey.cmop.mvc.constant.ComputeConstant;
import com.sobey.cmop.mvc.constant.CostingConstant;
import com.sobey.cmop.mvc.constant.NetworkConstant;
import com.sobey.cmop.mvc.constant.RedmineConstant;
import com.sobey.cmop.mvc.constant.StorageConstant;
import com.sobey.cmop.mvc.entity.Apply;
import com.sobey.cmop.mvc.entity.ComputeItem;
import com.sobey.cmop.mvc.entity.CpItem;
import com.sobey.cmop.mvc.entity.MdnItem;
import com.sobey.cmop.mvc.entity.NetworkEipItem;
import com.sobey.cmop.mvc.entity.StorageItem;
import com.sobey.cmop.mvc.service.onecmdb.OneCmdbService;
import com.sobey.framework.utils.MathsUtil;
/**
* 成本核算相关的管理类.
*
* @author liukai
*/
@Service
@Transactional(readOnly = true)
public class CostService extends BaseSevcie {
/**
* 资源数量
*/
public static final int RESOURCE_COUNT = 1;
/**
* 汇总所有设备的成本价格
*
* @param apply
* @return
*/
public String costPrice(Apply apply) {
StringBuilder sb = new StringBuilder();
double workTime = this.applyDaysBetween(apply);
double intiCost = this.humanCost(apply, workTime);
double ecsCost = this.computeCost(apply, workTime);
double es3Cost = this.es3Cost(apply, workTime);
double elbCost = this.elbCost(apply, workTime);
double eipCost = this.eipCost(apply, workTime);
double dnsCost = this.dnsCost(apply, workTime);
double mdnCost = this.mdnCost(apply, workTime);
double cpCost = this.cpCost(apply, workTime);
double totalPrice = this.totalCost(intiCost, ecsCost, es3Cost, elbCost, eipCost, dnsCost, mdnCost, cpCost);
if (intiCost != 0) {
sb.append("人工成本 :").append(intiCost).append(" 元").append("<br>");
}
if (ecsCost != 0) {
sb.append("ECS成本 :").append(ecsCost).append(" 元").append("<br>");
}
if (es3Cost != 0) {
sb.append("ES3成本 :").append(es3Cost).append(" 元").append("<br>");
}
if (elbCost != 0) {
sb.append("ELB成本 :").append(elbCost).append(" 元").append("<br>");
}
if (eipCost != 0) {
sb.append("EIP成本 :").append(eipCost).append(" 元").append("<br>");
}
if (dnsCost != 0) {
sb.append("DNS成本 :").append(dnsCost).append(" 元").append("<br>");
}
if (mdnCost != 0) {
sb.append("MDN成本 :").append(mdnCost).append(" 元").append("<br>");
}
if (cpCost != 0) {
sb.append("云生产成本 :").append(cpCost).append(" 元").append("<br>");
}
sb.append("总成本 :<strong class='text-error'>").append(totalPrice).append("</strong> 元").append("<br>");
return sb.toString();
}
public double cpCost(Apply apply, double workTime) {
double price = 0;
if (!apply.getCpItems().isEmpty()) {
double recordServerCosting = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.收录服务器硬件单位成本.toString()).getDescription());
double partitionTime = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.拆条时长.toString()).getDescription());
double transcodingCosting = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.转码服务器硬件单位成本.toString()).getDescription());
double humanCosting = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.拆条人工单位成本.toString()).getDescription());
double platformCostring = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.云平台各项服务成本.toString()).getDescription());
double es3Costing = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.ES3.toString())
.getDescription());
for (CpItem cpItem : apply.getCpItems()) {
double recordBitrate = getRecordBitrateForK(cpItem);
double recordTime = getRecordTimeForHours(cpItem);
// CP核算成本公式:每月服务成本 = 收录时长 × 收录服务器硬件单位成本 + 拆条时长 ×(转码服务器硬件单位成本 +
// 拆条人工单位成本) +
// 收录码率 × 收录时长 × 25200 × 云平台各项服务成本 ÷ 8388608 - ES3
// 收录
double record = MathsUtil.mul(recordTime, recordServerCosting);
// 拆条
double partition = MathsUtil.mul(partitionTime, MathsUtil.add(transcodingCosting, humanCosting));
double other1 = MathsUtil.mul(recordBitrate, recordTime);
other1 = MathsUtil.mul(other1, 25200); // 合并 3600 ×七天
other1 = MathsUtil.mul(other1, platformCostring);
other1 = MathsUtil.div(other1, 8388608); // 合并 1024 ÷ 1024 ÷ 8
price = MathsUtil.add(price, record);
price = MathsUtil.add(price, partition);
price = MathsUtil.add(price, other1);
price = MathsUtil.sub(price, es3Costing);
}
price = MathsUtil.mul(price, workTime);
}
return price;
}
/**
* 获得收录码率 , 码率是硬编码,注意以后维护.
*
* @param cpItem
* @return
*/
public double getRecordBitrateForK(CpItem cpItem) {
double bitrate = 0;
if (cpItem.getRecordBitrate().equals("1")) {
bitrate = 800;
} else if (cpItem.getRecordBitrate().equals("2")) {
bitrate = 1024;
} else if (cpItem.getRecordBitrate().equals("3")) {
bitrate = 2048;
} else if (cpItem.getRecordBitrate().equals("4")) {
bitrate = 4816;
} else {
// 默认 800K
bitrate = 800;
}
return bitrate;
}
/**
* 获得收录时间. 每天默认为收录时间. 每周和每月分别乘以 7 和 198 得到总的收录时间.
*
* @param cpItem
* @return
*/
public double getRecordTimeForHours(CpItem cpItem) {
double time = 0;
if (CPConstant.RecordType.每天.toInteger().equals(cpItem.getRecordType())) {
time = Double.valueOf(cpItem.getRecordDuration());
} else if (CPConstant.RecordType.每周.toInteger().equals(cpItem.getRecordType())) {
time = MathsUtil.mul(7, Double.valueOf(cpItem.getRecordDuration()));
} else {
// 每月
time = MathsUtil.mul(168, Double.valueOf(cpItem.getRecordDuration()));
}
return time;
}
public double mdnCost(Apply apply, double workTime) {
// MDN 核算成本公式: 每月服务成本 = 每M带宽占用 x 带宽
double price = 0;
if (!apply.getMdnItems().isEmpty()) {
double bandwidthPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.每M带宽占用.toString()).getDescription());
for (MdnItem mdnItem : apply.getMdnItems()) {
price = MathsUtil.mul(bandwidthPrice, Double.valueOf(mdnItem.getBandwidth()));
}
price = MathsUtil.mul(price, workTime);
}
return price;
}
private double dnsCost(Apply apply, double workTime) {
double price = 0;
if (!apply.getNetworkDnsItems().isEmpty()) {
// DNS核算成本公式:每月服务成本=云平台各项服务成本 - DNS
double platformPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.云平台各项服务成本.toString()).getDescription());
double dnsPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.DNS.toString())
.getDescription());
price = MathsUtil.mul(apply.getNetworkDnsItems().size(), MathsUtil.sub(platformPrice, dnsPrice));
price = MathsUtil.mul(price, workTime);
}
return price;
}
private double eipCost(Apply apply, double workTime) {
/**
* 中国联通
*/
int unicom = 0;
/**
* 中国电信
*/
int telecom = 0;
for (NetworkEipItem networkEipItem : apply.getNetworkEipItems()) {
if (NetworkConstant.ISPType.中国电信.toInteger().equals(networkEipItem.getIspType())) {
telecom++;
}
if (NetworkConstant.ISPType.中国联通.toInteger().equals(networkEipItem.getIspType())) {
unicom++;
}
}
// EIP核算成本公式:每月服务成本=(接入速率 × 电信带宽单价 + 接入速率 × 联通带宽单价)+(电信IP数量 × 电信带宽单价 + 联通IP数量 × 联通带宽单价)
double unicomPrice = 0;
double telecomPrice = 0;
if (unicom != 0) {
unicomPrice = comm.costService.eipCost(NetworkConstant.ISPType.中国联通, workTime, unicom);
}
if (telecom != 0) {
telecomPrice = comm.costService.eipCost(NetworkConstant.ISPType.中国电信, workTime, telecom);
}
return MathsUtil.add(unicomPrice, telecomPrice);
}
private double elbCost(Apply apply, double workTime) {
double price = 0;
if (!apply.getNetworkElbItems().isEmpty()) {
double platformPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.云平台各项服务成本.toString()).getDescription());
double EFWPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.EFW.toString())
.getDescription());
// ELB核算成本公式:每月服务成本=云平台各项服务成本 - EFW
price = MathsUtil.mul(apply.getNetworkElbItems().size(), MathsUtil.sub(platformPrice, EFWPrice));
price = MathsUtil.mul(price, workTime);
}
return price;
}
private double es3Cost(Apply apply, double workTime) {
double price = 0;
if (!apply.getStorageItems().isEmpty()) {
double netAppPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.业务存储单价.toString()).getDescription());
double fimasPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.数据存储单价.toString()).getDescription());
for (StorageItem storageItem : apply.getStorageItems()) {
// ES3核算成本公式:每月服务成本=业务存储大小 × 业务存储单价
if (StorageConstant.StorageType.Netapp_高IOPS.toInteger().equals(storageItem.getStorageType())) {
price = MathsUtil.add(price, MathsUtil.mul(storageItem.getSpace().doubleValue(), netAppPrice));
} else {
price = MathsUtil.add(price, MathsUtil.mul(storageItem.getSpace().doubleValue(), fimasPrice));
}
}
price = MathsUtil.mul(price, workTime);
}
return price;
}
/**
* 总价
*
* @param intiCost
* @param ecsCost
* @return
*/
public double totalCost(double intiCost, double ecsCost, double es3Cost, double elbCost, double eipCost,
double dnsCost, double mdnCost, double cpCost) {
double totalPrice = 0;
totalPrice = MathsUtil.add(totalPrice, intiCost);
totalPrice = MathsUtil.add(totalPrice, ecsCost);
totalPrice = MathsUtil.add(totalPrice, es3Cost);
totalPrice = MathsUtil.add(totalPrice, elbCost);
totalPrice = MathsUtil.add(totalPrice, eipCost);
totalPrice = MathsUtil.add(totalPrice, dnsCost);
totalPrice = MathsUtil.add(totalPrice, mdnCost);
totalPrice = MathsUtil.add(totalPrice, cpCost);
return totalPrice;
}
/**
* 人力成本
*
* @param workTime
* @return
*/
public Double humanCost(Apply apply, double workTime) {
double price = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.服务人力成本.toString())
.getDescription());
Integer priority = apply.getPriority();
// (“高”和“紧急”分别乘以2和3倍。)
if (RedmineConstant.Priority.高.toInteger().equals(priority)) {
price = MathsUtil.mul(price, 2);
} else if (RedmineConstant.Priority.紧急.toInteger().equals(priority)) {
price = MathsUtil.mul(price, 3);
} else {
// 普通人工不收费,其他收费.
price = 0;
}
return price;
}
/**
* ECS成本
*
* @param apply
* @param cost
* @return
*/
private double computeCost(Apply apply, double workTime) {
double price = 0;
if (!apply.getComputeItems().isEmpty()) {
double smallPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Small服务器单价.toString()).getDescription());
double middlePrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Middle服务器单价.toString()).getDescription());
double largePrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Large服务器单价.toString()).getDescription());
for (ComputeItem computeItem : apply.getComputeItems()) {
// ECS核算成本公式:每月服务成本=Small服务器数量×单价+Middle服务器数量×Middle服务器单价+Large服务器×单价
if (ComputeConstant.ComputeType.ECS.toInteger().equals(computeItem.getComputeType())) {
if (ComputeConstant.ECSServerType.Small_CPUx1_Memoryx1GB_DISKx20GB.toInteger().equals(
computeItem.getServerType())) {
price = MathsUtil.add(price, MathsUtil.mul(RESOURCE_COUNT, smallPrice));
} else if (ComputeConstant.ECSServerType.Middle_CPUx2_Memoryx2GB_DISKx20GB.toInteger().equals(
computeItem.getServerType())) {
price = MathsUtil.add(price, MathsUtil.mul(RESOURCE_COUNT, middlePrice));
} else {
price = MathsUtil.add(price, MathsUtil.mul(RESOURCE_COUNT, largePrice));
}
}
}
price = MathsUtil.mul(price, workTime);
}
return price;
}
/**
* 获得ECS的价格
*
* @param serverType
* 规格
* @param workTime
* 申请时间(月)
* @param number
* 数量
* @return 价格
*/
public Double computeCost(ComputeConstant.ECSServerType serverType, double workTime, int number) {
double price = 0;
if (ComputeConstant.ECSServerType.Small_CPUx1_Memoryx1GB_DISKx20GB.toInteger().equals(serverType.toInteger())) {
price = MathsUtil.mul(number, Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Small服务器单价.toString()).getDescription()));
} else if (ComputeConstant.ECSServerType.Middle_CPUx2_Memoryx2GB_DISKx20GB.toInteger().equals(
serverType.toInteger())) {
price = MathsUtil.mul(number, Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Middle服务器单价.toString()).getDescription()));
} else if (ComputeConstant.ECSServerType.Large_CPUx4_Memoryx4GB_DISKx20GB.toInteger().equals(
serverType.toInteger())) {
price = MathsUtil.mul(number, Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.Large服务器单价.toString()).getDescription()));
}
return MathsUtil.mul(price, workTime);
}
/**
* 获得es3的价格
*
* @param storageType
* 规格
* @param workTime
* 申请时间(月)
* @param number
* 数量
* @return
*/
public Double es3Cost(StorageConstant.StorageType storageType, double workTime, double space) {
double price = 0;
if (StorageConstant.StorageType.Netapp_高IOPS.toInteger().equals(storageType.toInteger())) {
price = MathsUtil.mul(space, Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.业务存储单价.toString()).getDescription()));
} else {
price = MathsUtil.mul(space, Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.数据存储单价.toString()).getDescription()));
}
return MathsUtil.mul(price, workTime);
}
/**
* 获得elb的价格
*
* @param workTime
* 申请时间(月)
* @param number
* 数量
* @return
*/
public Double elbCost(double workTime, int number) {
double price = 0;
// ELB核算成本公式:每月服务成本=云平台各项服务成本 - EFW
double platformPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.云平台各项服务成本.toString()).getDescription());
double EFWPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.EFW.toString())
.getDescription());
price = MathsUtil.mul(number, MathsUtil.sub(platformPrice, EFWPrice));
return MathsUtil.mul(price, workTime);
}
/**
* 获得elb的价格
*
* @param type
* 规格
* @param workTime
* 申请时间(月)
* @param number
* 数量
* @return
*/
public Double eipCost(NetworkConstant.ISPType type, double workTime, int number) {
double price = 0;
/**
* 接入速率
*/
double accessRate = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.CostingParameter.接入速率.toString()).getDescription());
/**
* 双线
*/
double bandwidthRate = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.双线.toString())
.getDescription());
/**
* 单价
*/
double ispPrice = 0;
if (NetworkConstant.ISPType.中国电信.toInteger().equals(type.toInteger())) {
ispPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.电信带宽单价.toString())
.getDescription());
} else if (NetworkConstant.ISPType.中国联通.toInteger().equals(type.toInteger())) {
ispPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.联通带宽单价.toString())
.getDescription());
} else {
// TODO 中国移动
}
// EIP核算成本公式:每月服务成本=(接入速率 × 电信带宽单价 + 接入速率 × 联通带宽单价)+(电信IP数量 × 电信带宽单价 + 联通IP数量 × 联通带宽单价)
// 带宽成本 + IP成本
price = MathsUtil.add(MathsUtil.mul(accessRate, bandwidthRate), MathsUtil.mul(number, ispPrice));
return MathsUtil.mul(price, workTime);
}
/**
* 获得elb的价格
*
* @param type
* 规格
* @param workTime
* 申请时间(月)
* @param number
* 数量
* @return
*/
public Double dnsCost(double workTime, int number) {
double price = 0;
// DNS核算成本公式:每月服务成本=云平台各项服务成本 - DNS
double platformPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(
CostingConstant.Costing.云平台各项服务成本.toString()).getDescription());
double dnsPrice = Double.valueOf(OneCmdbService.findCiBeanByAlias(CostingConstant.Costing.DNS.toString())
.getDescription());
price = MathsUtil.mul(number, MathsUtil.sub(platformPrice, dnsPrice));
return MathsUtil.mul(price, workTime);
}
/**
* 服务申请Apply的日期差
*
* 获得两个日期的 天数差,再除以 30天. 获得可能带小数点的天数.
*
* @return
*/
public double applyDaysBetween(Apply apply) {
/**
* 默认的每月天数
*/
int DEFAULT_DAY_NUMBER = 30;
DateTime startTime = new DateTime(apply.getServiceStart());
DateTime endTime = new DateTime(apply.getServiceEnd());
double costTime = MathsUtil.div(Days.daysBetween(startTime, endTime).getDays(), DEFAULT_DAY_NUMBER, 2);
// 如果是当天,时间差算成1天.
return costTime == 0 ? 0.04 : costTime;
}
}