|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
|
|
const moment = require('moment');
|
|
|
|
//业绩报表相关
|
|
|
|
async function getReceivedDetail(ctx) {
|
|
|
|
try {
|
|
|
|
const { models } = ctx.fs.dc;
|
|
|
|
const { keywordTarget, keyword, limit, page, toExport } = ctx.query
|
|
|
|
let where = {}
|
|
|
|
if (keywordTarget == 'contract' && keyword) {
|
|
|
|
where.contractNo = { $like: `%${keyword}%` }
|
|
|
|
}
|
|
|
|
let findOption = {
|
|
|
|
where: where,
|
|
|
|
order: [['id', 'DESC']]
|
|
|
|
}
|
|
|
|
if (!toExport) {//非导出时考虑分页
|
|
|
|
if (limit) {
|
|
|
|
findOption.limit = Number(limit)
|
|
|
|
}
|
|
|
|
if (page && limit) {
|
|
|
|
findOption.offset = Number(page) * Number(limit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let res = await models.ReceivableDetail.findAndCountAll(findOption);
|
|
|
|
if (toExport) {//数据导出相关
|
|
|
|
await exportReceivedDetail(ctx, res.rows);
|
|
|
|
} else {
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = {
|
|
|
|
count: res.count,
|
|
|
|
rows: res.rows
|
|
|
|
};
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = { name: 'FindAllError', message: '获取失败' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function exportReceivedDetail(ctx, dataList) {
|
|
|
|
try {
|
|
|
|
let header = [{
|
|
|
|
title: '年度',
|
|
|
|
key: 'year',
|
|
|
|
}, {
|
|
|
|
title: '序号',
|
|
|
|
key: 'serialNo',
|
|
|
|
}, {
|
|
|
|
title: '编号',
|
|
|
|
key: 'number',
|
|
|
|
}, {
|
|
|
|
title: '部门',
|
|
|
|
key: 'department',
|
|
|
|
}, {
|
|
|
|
title: '销售人员',
|
|
|
|
key: 'sale',
|
|
|
|
}, {
|
|
|
|
title: '合同编号',
|
|
|
|
key: 'contractNo',
|
|
|
|
}, {
|
|
|
|
title: '客户名称',
|
|
|
|
key: 'customer',
|
|
|
|
}, {
|
|
|
|
title: '项目名称',
|
|
|
|
key: 'item',
|
|
|
|
}, {
|
|
|
|
title: '合同金额',
|
|
|
|
key: 'amount',
|
|
|
|
}, {
|
|
|
|
title: '变更后合同金额',
|
|
|
|
key: 'changeAmount',
|
|
|
|
}, {
|
|
|
|
title: '回款年份',
|
|
|
|
key: 'receivableYear',
|
|
|
|
}, {
|
|
|
|
title: '回款日期',
|
|
|
|
key: 'receivableDate',
|
|
|
|
}, {
|
|
|
|
title: '回款金额',
|
|
|
|
key: 'receivableAmount',
|
|
|
|
}, {
|
|
|
|
title: '开票-回款',
|
|
|
|
key: 'invoicedBack',
|
|
|
|
}, {
|
|
|
|
title: '剩余合同金额',
|
|
|
|
key: 'remainConAmount',
|
|
|
|
}, {
|
|
|
|
title: '收入确认时间',
|
|
|
|
key: 'incomeConfirmdate',
|
|
|
|
}, {
|
|
|
|
title: '第三方付款单位',
|
|
|
|
key: 'thirdPayment',
|
|
|
|
}, {
|
|
|
|
title: '备注',
|
|
|
|
key: 'remark',
|
|
|
|
}]
|
|
|
|
const { utils: { simpleExcelDown } } = ctx.app.fs;
|
|
|
|
let exportData = []
|
|
|
|
for (let { dataValues: item } of dataList) {
|
|
|
|
exportData.push(item)
|
|
|
|
}
|
|
|
|
const fileName = `回款明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'
|
|
|
|
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName })
|
|
|
|
const fileData = fs.readFileSync(filePath);
|
|
|
|
ctx.status = 200;
|
|
|
|
ctx.set('Content-Type', 'application/x-xls');
|
|
|
|
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
|
|
|
|
ctx.body = fileData;
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = {
|
|
|
|
message: typeof error == 'string' ? error : undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async function getAchievementDetail(ctx) {
|
|
|
|
try {
|
|
|
|
const { models } = ctx.fs.dc;
|
|
|
|
const { keywordTarget, keyword, limit, page, toExport } = ctx.query
|
|
|
|
let where = {}
|
|
|
|
if (keywordTarget == 'saler' && keyword) {
|
|
|
|
where.sale = { $like: `%${keyword}%` }
|
|
|
|
}
|
|
|
|
if (keywordTarget == 'line' && keyword) {
|
|
|
|
where.serviceLine = { $like: `%${keyword}%` }
|
|
|
|
}
|
|
|
|
if (keywordTarget == 'dep' && keyword) {
|
|
|
|
where.department = { $like: `%${keyword}%` }
|
|
|
|
}
|
|
|
|
let findOption = {
|
|
|
|
where: where,
|
|
|
|
order: [['id', 'DESC']]
|
|
|
|
}
|
|
|
|
if (!toExport) {//非导出时考虑分页
|
|
|
|
if (limit) {
|
|
|
|
findOption.limit = Number(limit)
|
|
|
|
}
|
|
|
|
if (page && limit) {
|
|
|
|
findOption.offset = Number(page) * Number(limit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let res = await models.PerformanceDetail.findAndCountAll(findOption);
|
|
|
|
if (toExport) {//数据导出相关
|
|
|
|
await exportAchievementDetail(ctx, res.rows);
|
|
|
|
} else {
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = {
|
|
|
|
count: res.count,
|
|
|
|
rows: res.rows
|
|
|
|
};
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = { name: 'FindAllError', message: '获取失败' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function exportAchievementDetail(ctx, dataList) {
|
|
|
|
try {
|
|
|
|
let header = [{
|
|
|
|
title: '收到合同日期',
|
|
|
|
key: 'recConDate',
|
|
|
|
}, {
|
|
|
|
title: '月份',
|
|
|
|
key: 'month',
|
|
|
|
}, {
|
|
|
|
title: '部门',
|
|
|
|
key: 'department',
|
|
|
|
}, {
|
|
|
|
title: '销售人员',
|
|
|
|
key: 'sale',
|
|
|
|
}, {
|
|
|
|
title: '客户名称',
|
|
|
|
key: 'customer',
|
|
|
|
}, {
|
|
|
|
title: '项目名称',
|
|
|
|
key: 'item',
|
|
|
|
}, {
|
|
|
|
title: '合同金额',
|
|
|
|
key: 'amount',
|
|
|
|
}, {
|
|
|
|
title: '实际业绩',
|
|
|
|
key: 'realPerformance',
|
|
|
|
}, {
|
|
|
|
title: '考核业绩',
|
|
|
|
key: 'assessmentPerformance',
|
|
|
|
}, {
|
|
|
|
title: '价格是否特批',
|
|
|
|
key: 'isApproval',
|
|
|
|
}, {
|
|
|
|
title: '特批折算比例',
|
|
|
|
key: 'approvalProp',
|
|
|
|
}, {
|
|
|
|
title: '预支提成及委外费用',
|
|
|
|
key: 'cost',
|
|
|
|
}, {
|
|
|
|
title: '业务线',
|
|
|
|
key: 'serviceLine',
|
|
|
|
}, {
|
|
|
|
title: '客户类型',
|
|
|
|
key: 'cusType',
|
|
|
|
}, {
|
|
|
|
title: '行业',
|
|
|
|
key: 'industry',
|
|
|
|
}, {
|
|
|
|
title: '信息来源',
|
|
|
|
key: 'source',
|
|
|
|
}, {
|
|
|
|
title: '项目类型',
|
|
|
|
key: 'itemType',
|
|
|
|
}, {
|
|
|
|
title: '客户省份',
|
|
|
|
key: 'cusProvince',
|
|
|
|
}, {
|
|
|
|
title: '客户属性',
|
|
|
|
key: 'cusAttribute',
|
|
|
|
}, {
|
|
|
|
title: '复购次数',
|
|
|
|
key: 'repurchaseCount',
|
|
|
|
}, {
|
|
|
|
title: '是否可复制的业务路径',
|
|
|
|
key: 'reproducible',
|
|
|
|
}, {
|
|
|
|
title: '省外业务1.1',
|
|
|
|
key: 'outProvince',
|
|
|
|
}, {
|
|
|
|
title: '复购业务1.05',
|
|
|
|
key: 'repurchase',
|
|
|
|
}, {
|
|
|
|
title: '可复制的业务路径1.1',
|
|
|
|
key: 'isreproduce',
|
|
|
|
}]
|
|
|
|
const { utils: { simpleExcelDown } } = ctx.app.fs;
|
|
|
|
let exportData = []
|
|
|
|
for (let { dataValues: item } of dataList) {
|
|
|
|
item.isApproval = item.isApproval ? '是' : '否';
|
|
|
|
item.reproducible = item.reproducible ? '是' : '否';
|
|
|
|
exportData.push(item)
|
|
|
|
}
|
|
|
|
const fileName = `业绩明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'
|
|
|
|
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName })
|
|
|
|
const fileData = fs.readFileSync(filePath);
|
|
|
|
ctx.status = 200;
|
|
|
|
ctx.set('Content-Type', 'application/x-xls');
|
|
|
|
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
|
|
|
|
ctx.body = fileData;
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = {
|
|
|
|
message: typeof error == 'string' ? error : undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 查询合同明细表数据
|
|
|
|
* @param {*} ctx ctx ctx.query:{keywordTarget-关键字项、keyword-关键字内容、limit-页宽, page-页码}
|
|
|
|
*/
|
|
|
|
async function getContractDetail(ctx) {
|
|
|
|
try {
|
|
|
|
const { models } = ctx.fs.dc;
|
|
|
|
const { keywordTarget, keyword, limit, page } = ctx.query;
|
|
|
|
const where = {};
|
|
|
|
if (keywordTarget && keyword) {
|
|
|
|
where[keywordTarget] = { $iLike: `%${keyword}%` };
|
|
|
|
}
|
|
|
|
let contractDetail = await models.ContractDetail.findAndCountAll({
|
|
|
|
where: where,
|
|
|
|
offset: Number(page) * Number(limit),
|
|
|
|
limit: Number(limit),
|
|
|
|
order: [['id', 'DESC']]
|
|
|
|
});
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = contractDetail;
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = { name: 'FindError', message: '查询合同明细表数据失败' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 查询开票明细表数据
|
|
|
|
* @param {*} ctx ctx ctx.query:{keywordTarget-关键字项、keyword-关键字内容、limit-页宽, page-页码}
|
|
|
|
*/
|
|
|
|
async function getInvoicingDetail(ctx) {
|
|
|
|
try {
|
|
|
|
const { models } = ctx.fs.dc;
|
|
|
|
const { keywordTarget, keyword, limit, page } = ctx.query;
|
|
|
|
const where = {};
|
|
|
|
if (keywordTarget && keyword) {
|
|
|
|
where[keywordTarget] = { $iLike: `%${keyword}%` };
|
|
|
|
}
|
|
|
|
let invoiceDetail = await models.InvoiceDetail.findAndCountAll({
|
|
|
|
where: where,
|
|
|
|
offset: Number(page) * Number(limit),
|
|
|
|
limit: Number(limit),
|
|
|
|
order: [['id', 'DESC']]
|
|
|
|
});
|
|
|
|
ctx.status = 200
|
|
|
|
ctx.body = invoiceDetail;
|
|
|
|
} catch (error) {
|
|
|
|
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
|
|
|
|
ctx.status = 400;
|
|
|
|
ctx.body = { name: 'FindError', message: '查询开票明细表数据失败' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = {
|
|
|
|
getReceivedDetail,//回款
|
|
|
|
getAchievementDetail,//业绩
|
|
|
|
getContractDetail,
|
|
|
|
getInvoicingDetail
|
|
|
|
}
|