项企-报表中心
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
15 KiB

'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', 'ASC']]
}
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, needIndexCell: false })
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', 'ASC']]
}
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: '省外业务',
key: 'outProvince',
}, {
title: '复购业务',
key: 'repurchase',
}, {
title: '可复制的业务路径',
key: 'isreproduce',
}]
const { utils: { simpleExcelDown } } = ctx.app.fs;
let exportData = []
for (let { dataValues: item } of dataList) {
item.isApproval = JSON.stringify(item.isApproval) === 'null' ? '-' : item.isApproval ? '是' : '否';
item.reproducible = JSON.stringify(item.reproducible) === 'null' ? '-' : 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:{tableModel表模型名}
*/
async function getReceivedNumbers(ctx) {
let errorMsg = { name: 'FindError', message: '查询失败' };
try {
const { tableModel } = ctx.query;
const models = ctx.fs.dc.models;
let modelName = tableModel || 'ReceivableDetail'
let list = await models[modelName].findAll({//查编号
attributes: ['number']
});
ctx.status = 200
ctx.body = list;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errorMsg;
}
}
/**
* 导入明细表数据回款合同开票通用
* @param {*} ctx ctx ctx.query:{tableModel表模型名}
*/
async function importBackDetails(ctx) {
let errorMsg = { message: '导入失败' };
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
const { tableModel } = ctx.query;
let modelName = tableModel || 'ReceivableDetail'
let addArr = [];
let dataList = await models[modelName].findAll({//查编号
attributes: ['number']
});
data.map(d => {
let exist = dataList.find(m => m.dataValues.number == d.number);
if (!exist) {
addArr.push(d);
}
})
//只处理新增的
if (addArr.length) {
await models[modelName].bulkCreate(addArr, { transaction });
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errorMsg;
}
}
async function importAchieveDetails(ctx) {
let errorMsg = { message: '导入业绩明细失败' };
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
//业绩明细 没有唯一标识,前端校验后,导啥存啥
if (data.length) {
await models.PerformanceDetail.bulkCreate(data);
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errorMsg;
}
}
/**
* 查询合同明细表数据
* @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({
attributes: { exclude: ['iscopy', 'hiredate', 'regularDate'] },
where: where,
offset: Number(page) * Number(limit),
limit: Number(limit),
order: [['id', 'ASC']]
});
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', 'ASC']]
});
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: '查询开票明细表数据失败' }
}
}
/**
* 导出合同明细表数据
*/
async function exportContractDetail(ctx) {
try {
const { models } = ctx.fs.dc;
let exportData = await models.ContractDetail.findAll({
attributes: { exclude: ['iscopy', 'hiredate', 'regularDate'] },
order: [['id', 'ASC']]
});
const { utils: { simpleExcelDown, contractDetailsColumnKeys } } = ctx.app.fs;
let header = [];
Object.keys(contractDetailsColumnKeys).map(key => {
header.push({ title: contractDetailsColumnKeys[key], key: key });
})
const fileName = `合同明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName, needIndexCell: false })
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 = { name: 'ExportAllError', message: '导出合同明细表数据失败' }
}
}
/**
* 导出开票明细表数据
*/
async function exportInvoicingDetail(ctx) {
try {
const { models } = ctx.fs.dc;
let exportData = await models.InvoiceDetail.findAll({
order: [['id', 'ASC']]
});
const { utils: { simpleExcelDown, invoicingDetailsColumnKeys } } = ctx.app.fs;
let header = [];
Object.keys(invoicingDetailsColumnKeys).map(key => {
header.push({ title: invoicingDetailsColumnKeys[key], key: key });
})
const fileName = `开票明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName, needIndexCell: false })
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 = { name: 'ExportAllError', message: '导出开票明细表数据失败' }
}
}
module.exports = {
getReceivedDetail,//回款
getAchievementDetail,//业绩
getReceivedNumbers,//查询回款、合同、开票明细表 已有的所有编号
importBackDetails,//导入回款、合同、开票明细
importAchieveDetails,//导入业绩明细
getContractDetail,
getInvoicingDetail,
exportContractDetail,
exportInvoicingDetail
}