31 changed files with 3842 additions and 206 deletions
@ -0,0 +1,290 @@ |
|||||
|
'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: '查询合同明细表数据失败' } |
||||
|
} |
||||
|
} |
||||
|
module.exports = { |
||||
|
getReceivedDetail,//回款
|
||||
|
getAchievementDetail,//业绩
|
||||
|
getContractDetail, |
||||
|
} |
@ -0,0 +1,430 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const ContractDetail = sequelize.define("contractDetail", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true |
||||
|
}, |
||||
|
year: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "年度", |
||||
|
primaryKey: false, |
||||
|
field: "year ", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
serialNo: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "序号", |
||||
|
primaryKey: false, |
||||
|
field: "serial_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
number: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "编号", |
||||
|
primaryKey: false, |
||||
|
field: "number", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
introduction: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "简介", |
||||
|
primaryKey: false, |
||||
|
field: "introduction", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
contractNo: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "合同编号", |
||||
|
primaryKey: false, |
||||
|
field: "contract_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
applyDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "申请日期", |
||||
|
primaryKey: false, |
||||
|
field: "apply_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
recConDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "收到合同日期", |
||||
|
primaryKey: false, |
||||
|
field: "rec_con_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
contractPaper: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "合同纸质版情况", |
||||
|
primaryKey: false, |
||||
|
field: "contract_paper", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
contractElec: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "合同电子版情况", |
||||
|
primaryKey: false, |
||||
|
field: "contract_elec", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
department: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "部门", |
||||
|
primaryKey: false, |
||||
|
field: "department", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
business: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "业务线", |
||||
|
primaryKey: false, |
||||
|
field: "business", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
sale: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "销售人员", |
||||
|
primaryKey: false, |
||||
|
field: "sale", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
customer: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "客户名称", |
||||
|
primaryKey: false, |
||||
|
field: "customer", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
item: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "项目名称", |
||||
|
primaryKey: false, |
||||
|
field: "item", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
itemType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "项目类型", |
||||
|
primaryKey: false, |
||||
|
field: "item_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
amount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
changeAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "变更后合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "change_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cInvoicedAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "累计开票金额", |
||||
|
primaryKey: false, |
||||
|
field: "c_invoiced_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cBackAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "累计回款金额", |
||||
|
primaryKey: false, |
||||
|
field: "c_back_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoicedBack: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "开票-回款", |
||||
|
primaryKey: false, |
||||
|
field: "invoiced_back", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
unInvoicedAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "未开票金额", |
||||
|
primaryKey: false, |
||||
|
field: "un_invoiced_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
remainConAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "剩余合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "remain_con_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
backPercent: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "回款率", |
||||
|
primaryKey: false, |
||||
|
field: "back_percent", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
retentionMoney: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "质保金", |
||||
|
primaryKey: false, |
||||
|
field: "retention_money", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
retentionPercent: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "质保金比例", |
||||
|
primaryKey: false, |
||||
|
field: "retention_percent", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
retentionTerm: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "质保期", |
||||
|
primaryKey: false, |
||||
|
field: "retention_term", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceTax1: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "发票税率金额", |
||||
|
primaryKey: false, |
||||
|
field: "invoice_tax1", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceTax2: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "invoice_tax2", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceTax3: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "invoice_tax3", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
payType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "合同付款方式", |
||||
|
primaryKey: false, |
||||
|
field: "pay_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cost: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "预支提成及委外费用", |
||||
|
primaryKey: false, |
||||
|
field: "cost", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
performanceRatio: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "业绩折算比例", |
||||
|
primaryKey: false, |
||||
|
field: "performance_ratio", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
realPerformance: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "实际业绩", |
||||
|
primaryKey: false, |
||||
|
field: "real_performance", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
assessmentPerformance: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "考核业绩", |
||||
|
primaryKey: false, |
||||
|
field: "assessment_performance", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
acceptanceDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "验收日期", |
||||
|
primaryKey: false, |
||||
|
field: "acceptance_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
backConfirmDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "收入确认时间", |
||||
|
primaryKey: false, |
||||
|
field: "back_confirm_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
recYear: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "接单年份", |
||||
|
primaryKey: false, |
||||
|
field: "rec_year", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
recMonth: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "接单月份", |
||||
|
primaryKey: false, |
||||
|
field: "rec_month", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusAttribute: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "客户属性", |
||||
|
primaryKey: false, |
||||
|
field: "cus_attribute", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "客户类型", |
||||
|
primaryKey: false, |
||||
|
field: "cus_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
industry: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "行业", |
||||
|
primaryKey: false, |
||||
|
field: "industry", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
source: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "信息来源", |
||||
|
primaryKey: false, |
||||
|
field: "source", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusProvince: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "客户省份", |
||||
|
primaryKey: false, |
||||
|
field: "cus_province", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusArea: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "项目所在地", |
||||
|
primaryKey: false, |
||||
|
field: "cus_area", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
text: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "text", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "contract_detail", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.ContractDetail = ContractDetail; |
||||
|
return ContractDetail; |
||||
|
}; |
@ -0,0 +1,196 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const InvoiceDetail = sequelize.define("invoiceDetail", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
year: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "年度:【申请日期】-年份", |
||||
|
primaryKey: false, |
||||
|
field: "year", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
serialNo: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "序号:自动生成\n(自动升序),每一年自动从1开始", |
||||
|
primaryKey: false, |
||||
|
field: "serial_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
number: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "编号:年份+序号 如2022年1", |
||||
|
primaryKey: false, |
||||
|
field: "number", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
department: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "部门:申请部门", |
||||
|
primaryKey: false, |
||||
|
field: "department", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
sale: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "销售人员:申请人", |
||||
|
primaryKey: false, |
||||
|
field: "sale", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
contractNo: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同编号", |
||||
|
primaryKey: false, |
||||
|
field: "contract_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
customer: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户名称:【甲方名称】", |
||||
|
primaryKey: false, |
||||
|
field: "customer", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
item: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "项目名称", |
||||
|
primaryKey: false, |
||||
|
field: "item", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
amount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同金额:【合同金额\n(元)】", |
||||
|
primaryKey: false, |
||||
|
field: "amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
changeAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "变更后合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "change_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceNo: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "发票号码:《发票申请单》【发票号】一个发票号码一个行数据", |
||||
|
primaryKey: false, |
||||
|
field: "invoice_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "开票类型:《发票申请单》\n【发票类型】", |
||||
|
primaryKey: false, |
||||
|
field: "invoice_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "开票日期:《发票申请单》\n【开票日期】", |
||||
|
primaryKey: false, |
||||
|
field: "invoice_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoiceAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "开票金额:《发票申请单》【发票金额】取财务填写数据", |
||||
|
primaryKey: false, |
||||
|
field: "invoice_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
outputTax: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "销项税额:《发票申请单》-销项税额", |
||||
|
primaryKey: false, |
||||
|
field: "output_tax", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
total: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合计:自动算出\n(开票金额+销项税额)", |
||||
|
primaryKey: false, |
||||
|
field: "total", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
taxRate13: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "税率13%:《发票申请单》", |
||||
|
primaryKey: false, |
||||
|
field: "tax_rate13", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
taxRate9: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "税率9%:《发票申请单》", |
||||
|
primaryKey: false, |
||||
|
field: "tax_rate9", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
taxRate6: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "税率6%:《发票申请单》", |
||||
|
primaryKey: false, |
||||
|
field: "tax_rate6", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "invoice_detail", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.InvoiceDetail = InvoiceDetail; |
||||
|
return InvoiceDetail; |
||||
|
}; |
@ -0,0 +1,241 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const PerformanceDetail = sequelize.define("performanceDetail", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
recConDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "收到合同日期", |
||||
|
primaryKey: false, |
||||
|
field: "rec_con_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
month: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "月份", |
||||
|
primaryKey: false, |
||||
|
field: "month", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
department: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "部门:申请部门", |
||||
|
primaryKey: false, |
||||
|
field: "department", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
sale: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "销售人员", |
||||
|
primaryKey: false, |
||||
|
field: "sale", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
customer: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户名称:【甲方名称】", |
||||
|
primaryKey: false, |
||||
|
field: "customer", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
item: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "项目名称", |
||||
|
primaryKey: false, |
||||
|
field: "item", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
amount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同金额:【合同金额\n(元)】", |
||||
|
primaryKey: false, |
||||
|
field: "amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
realPerformance: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "实际业绩;(合同金额-预\n支提成及委外费用)*特批折算比例\n(G-L)*K", |
||||
|
primaryKey: false, |
||||
|
field: "real_performance", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
assessmentPerformance: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同金额*省外业务(1.1)*复购业务\n(1.05)*可复制的业务路径(1.1)", |
||||
|
primaryKey: false, |
||||
|
field: "assessment_performance", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
isApproval: { |
||||
|
type: DataTypes.BOOLEAN, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "价格是否特批:根据折算比例-《合同明细表》推\n算(100%——“是”;其他为否)", |
||||
|
primaryKey: false, |
||||
|
field: "isApproval", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
approvalProp: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "特批折算比例:【业绩折\n算比例】", |
||||
|
primaryKey: false, |
||||
|
field: "approval_prop", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cost: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "预支提成及委外费用", |
||||
|
primaryKey: false, |
||||
|
field: "cost", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
serviceLine: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "业务线", |
||||
|
primaryKey: false, |
||||
|
field: "service_line", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户类型", |
||||
|
primaryKey: false, |
||||
|
field: "cus_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
industry: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "行业", |
||||
|
primaryKey: false, |
||||
|
field: "industry", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
source: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "信息来源", |
||||
|
primaryKey: false, |
||||
|
field: "source", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
itemType: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "项目类型", |
||||
|
primaryKey: false, |
||||
|
field: "item_type", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusProvince: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户省份", |
||||
|
primaryKey: false, |
||||
|
field: "cus_province", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
cusAttribute: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户属性:G:政府、事业单位\nB:央企、国企、平台商\nC:资源方", |
||||
|
primaryKey: false, |
||||
|
field: "cus_attribute", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
repurchaseCount: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "复购次数:同一客户储备成单-成单项目数量\n(PM)", |
||||
|
primaryKey: false, |
||||
|
field: "repurchase_count", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
reproducible: { |
||||
|
type: DataTypes.BOOLEAN, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "是否可复制的业务路径:《合同评审》表单获取", |
||||
|
primaryKey: false, |
||||
|
field: "reproducible", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
outProvince: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "省外业务1.1:当【客户省份】=“江西”时,省外业务=1;当【客户省份】<>“江西”时,省外业务=1.1", |
||||
|
primaryKey: false, |
||||
|
field: "out_province", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
repurchase: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "复购业务1.05:当【复购次数】\n<2时,复购业务=1;当【复购次数】\n>=2时,复购业务=1.05;", |
||||
|
primaryKey: false, |
||||
|
field: "repurchase", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
isreproduce: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "可复制的业务路径1.1:当【是否可复\n制的业务路径】=“是”,可复制的业务路径=1.1;当【是否可复制的业务路径】=“否”,可复制的业务路径=1;", |
||||
|
primaryKey: false, |
||||
|
field: "isreproduce", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "performance_detail", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.PerformanceDetail = PerformanceDetail; |
||||
|
return PerformanceDetail; |
||||
|
}; |
@ -0,0 +1,187 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const ReceivableDetail = sequelize.define("receivableDetail", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
year: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "年度:【申请日期】-年份", |
||||
|
primaryKey: false, |
||||
|
field: "year", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
serialNo: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "序号:自动生成\n(自动升序),每一年自动从1开始", |
||||
|
primaryKey: false, |
||||
|
field: "serial_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
number: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "编号:年份+序号 如2022年1", |
||||
|
primaryKey: false, |
||||
|
field: "number", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
department: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "部门:申请部门", |
||||
|
primaryKey: false, |
||||
|
field: "department", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
sale: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "销售人员:申请人", |
||||
|
primaryKey: false, |
||||
|
field: "sale", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
contractNo: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同编号", |
||||
|
primaryKey: false, |
||||
|
field: "contract_no", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
customer: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "客户名称:【甲方名称】", |
||||
|
primaryKey: false, |
||||
|
field: "customer", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
item: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "项目名称", |
||||
|
primaryKey: false, |
||||
|
field: "item", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
amount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "合同金额:【合同金额\n(元)】", |
||||
|
primaryKey: false, |
||||
|
field: "amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
changeAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "变更后合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "change_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
receivableYear: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "回款年份", |
||||
|
primaryKey: false, |
||||
|
field: "receivable_year", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
receivableDate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "回款日期", |
||||
|
primaryKey: false, |
||||
|
field: "receivable_date", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
receivableAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "回款金额", |
||||
|
primaryKey: false, |
||||
|
field: "receivable_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
invoicedBack: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "开票-回款", |
||||
|
primaryKey: false, |
||||
|
field: "invoiced_back ", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
remainConAmount: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "剩余合同金额", |
||||
|
primaryKey: false, |
||||
|
field: "remain_con_amount", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
incomeConfirmdate: { |
||||
|
type: DataTypes.DATEONLY, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: "收入确认时间", |
||||
|
primaryKey: false, |
||||
|
field: "income_confirmdate", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
thirdPayment: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "第三方付款单位", |
||||
|
primaryKey: false, |
||||
|
field: "third_payment", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
remark: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "备注:回款流程》-备注", |
||||
|
primaryKey: false, |
||||
|
field: "remark", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "receivable_detail", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.ReceivableDetail = ReceivableDetail; |
||||
|
return ReceivableDetail; |
||||
|
}; |
@ -1,8 +1,21 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
const report = require('../../controllers/report'); |
const report = require('../../controllers/report'); |
||||
|
const achieve = require('../../controllers/report/achievement'); |
||||
|
|
||||
module.exports = function (app, router, opts) { |
module.exports = function (app, router, opts) { |
||||
app.fs.api.logAttr['GET/reserveItem/report/:type'] = { content: '查询储备项目统计表', visible: false }; |
app.fs.api.logAttr['GET/reserveItem/report/:type'] = { content: '查询储备项目统计表', visible: false }; |
||||
router.get('/reserveItem/report/:type', report.getReserveItemReport); |
router.get('/reserveItem/report/:type', report.getReserveItemReport); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/sales/member/list'] = { content: '查询销售人员分布明细表', visible: false }; |
||||
|
router.get('/sales/member/list', report.getSalersReport); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/detail/received/back'] = { content: '查询回款明细表', visible: false }; |
||||
|
router.get('/detail/received/back', achieve.getReceivedDetail); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/detail/achievement'] = { content: '查询业绩明细表', visible: false }; |
||||
|
router.get('/detail/achievement', achieve.getAchievementDetail); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/contract/detail'] = { content: '查询合同明细表', visible: false }; |
||||
|
router.get('/contract/detail', achieve.getContractDetail); |
||||
}; |
}; |
@ -0,0 +1,415 @@ |
|||||
|
'use strict'; |
||||
|
const moment = require('moment') |
||||
|
const request = require('superagent'); |
||||
|
|
||||
|
module.exports = function (app, opts) { |
||||
|
|
||||
|
async function memberList({ |
||||
|
keywordTarget, keyword, limit, page, state, |
||||
|
hiredateStart, hiredateEnd, marital, native, workPlace, |
||||
|
orderBy, orderDirection, |
||||
|
nowAttendanceTime, |
||||
|
overtimeDayStatisticStartDate, overtimeDayStatisticendDate, |
||||
|
overtimeCountStatistic, overtimeCountStatisticStartDate, overtimeCountStatisticendDate, |
||||
|
vacateDayStatisticStartDate, vacateDayStatisticendDate, |
||||
|
vacateDurationStatistic, vacateCountStatistic, vacateCountStatisticStartDate, vacateCountStatisticendDate |
||||
|
}) { |
||||
|
//const { judgeHoliday } = app.fs.utils
|
||||
|
const { clickHouse } = app.fs |
||||
|
const { database: pepEmis } = clickHouse.pepEmis.opts.config |
||||
|
|
||||
|
const curDay = moment().format('YYYY-MM-DD') |
||||
|
const nowTime = moment() |
||||
|
let whereOption = [] |
||||
|
let whereFromSelectOption = [] |
||||
|
let returnEmpty = false |
||||
|
if (state == 'inOffice') { |
||||
|
// 在岗
|
||||
|
//const holidayJudge = await judgeHoliday(curDay)
|
||||
|
// if (holidayJudge) {
|
||||
|
// if (
|
||||
|
// holidayJudge.workday
|
||||
|
// && nowTime.isAfter(moment(curDay + ' 08:30'))
|
||||
|
// && nowTime.isBefore(moment(curDay + ' 17:30'))
|
||||
|
// ) {
|
||||
|
// // 在工作日的工作时间范围 无请假记录
|
||||
|
// whereFromSelectOption.push(`vacateStartTime = '1970-01-01 00:00:00.000000'`)
|
||||
|
// } else {
|
||||
|
// returnEmpty = true
|
||||
|
// }
|
||||
|
// } else {
|
||||
|
// returnEmpty = true
|
||||
|
// }
|
||||
|
} |
||||
|
if (state == 'dayoff') { |
||||
|
// 放假
|
||||
|
// const holidayJudge = await judgeHoliday(curDay)
|
||||
|
// if (holidayJudge) {
|
||||
|
// if (
|
||||
|
// holidayJudge.dayoff || holidayJudge.festivals
|
||||
|
// ) {
|
||||
|
// // 在休息日范围内且无加班申请
|
||||
|
// whereFromSelectOption.push(`overtimeStartTime = '1970-01-01 00:00:00.000000'`)
|
||||
|
// } else {
|
||||
|
// returnEmpty = true
|
||||
|
// }
|
||||
|
// } else {
|
||||
|
// returnEmpty = true
|
||||
|
// }
|
||||
|
} |
||||
|
if (returnEmpty) { |
||||
|
return { |
||||
|
count: 0, |
||||
|
rows: [] |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let overtimeDayStatisticWhere = [] |
||||
|
// if (overtimeDayStatisticStartDate) {
|
||||
|
// overtimeDayStatisticWhere.push(`overtime_day.day >= '${moment(overtimeDayStatisticStartDate).format('YYYY-MM-DD')}'`)
|
||||
|
// }
|
||||
|
// if (overtimeDayStatisticendDate) {
|
||||
|
// overtimeDayStatisticWhere.push(`overtime_day.day <= '${moment(overtimeDayStatisticendDate).format('YYYY-MM-DD')}'`)
|
||||
|
// }
|
||||
|
|
||||
|
let overtimeCountStatisticWhere = [] |
||||
|
// if (overtimeCountStatisticStartDate) {
|
||||
|
// overtimeCountStatisticWhere.push(`overtime.start_time >= '${moment(overtimeCountStatisticStartDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`)
|
||||
|
// }
|
||||
|
// if (overtimeCountStatisticendDate) {
|
||||
|
// overtimeCountStatisticWhere.push(`overtime.end_time <= '${moment(overtimeCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`)
|
||||
|
// }
|
||||
|
|
||||
|
let vacateDayStatisticWhere = [] |
||||
|
// if (vacateDayStatisticStartDate) {
|
||||
|
// vacateDayStatisticWhere.push(`vacate_day.day >= '${moment(vacateDayStatisticStartDate).format('YYYY-MM-DD')}'`)
|
||||
|
// }
|
||||
|
// if (vacateDayStatisticendDate) {
|
||||
|
// vacateDayStatisticWhere.push(`vacate_day.day <= '${moment(vacateDayStatisticendDate).format('YYYY-MM-DD')}'`)
|
||||
|
// }
|
||||
|
|
||||
|
let vacateCountStatisticWhere = [] |
||||
|
// if (vacateCountStatisticStartDate) {
|
||||
|
// vacateCountStatisticWhere.push(`vacate.start_time >= '${moment(vacateCountStatisticStartDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`)
|
||||
|
// }
|
||||
|
// if (vacateCountStatisticendDate) {
|
||||
|
// vacateCountStatisticWhere.push(`vacate.end_time <= '${moment(vacateCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`)
|
||||
|
// }
|
||||
|
// CRAZY
|
||||
|
const innerSelectQuery = ` |
||||
|
FROM member |
||||
|
INNER JOIN ${pepEmis}.user AS user |
||||
|
ON member.pep_user_id = user.id |
||||
|
${keywordTarget == 'number' && keyword ? ` |
||||
|
AND user.people_code LIKE '%${keyword}%' |
||||
|
`: ''}
|
||||
|
${keywordTarget == 'name' && keyword ? ` |
||||
|
AND user.name LIKE '%${keyword}%' |
||||
|
`: ''}
|
||||
|
|
||||
|
${nowAttendanceTime ? ` |
||||
|
${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( |
||||
|
SELECT |
||||
|
pep_user_id, |
||||
|
any(start_time) AS vacateStartTime, |
||||
|
any(end_time) AS vacateEndTime |
||||
|
FROM vacate |
||||
|
WHERE |
||||
|
start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
GROUP BY pep_user_id |
||||
|
) AS hrVacate |
||||
|
ON hrVacate.pep_user_id = member.pep_user_id |
||||
|
`: ''}
|
||||
|
${nowAttendanceTime ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
pep_user_id, |
||||
|
any(start_time) AS overtimeStartTime, |
||||
|
any(end_time) AS overtimeEndTime |
||||
|
FROM overtime |
||||
|
WHERE |
||||
|
start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' |
||||
|
GROUP BY pep_user_id |
||||
|
) AS hrOvertime |
||||
|
ON hrOvertime.pep_user_id = member.pep_user_id |
||||
|
`: ''}
|
||||
|
|
||||
|
${orderBy == 'overtimeTakeRestSum' || |
||||
|
orderBy == 'overtimePaySum' || |
||||
|
orderBy == 'overtimeSum' ? |
||||
|
`LEFT JOIN (
|
||||
|
SELECT |
||||
|
overtime.pep_user_id AS pepUserId, |
||||
|
sum(overtime_day.duration) AS duration |
||||
|
FROM overtime_day |
||||
|
INNER JOIN overtime |
||||
|
ON overtime.id = overtime_day.overtime_id |
||||
|
${orderBy == 'overtimeTakeRestSum' ? `AND overtime.compensate = '调休'` : ''} |
||||
|
${orderBy == 'overtimePaySum' ? `AND overtime.compensate = '发放加班补偿'` : ''} |
||||
|
${overtimeDayStatisticWhere.length ? ` |
||||
|
WHERE ${overtimeDayStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY overtime.pep_user_id |
||||
|
) AS overtimeDayStatistic |
||||
|
ON overtimeDayStatistic.pepUserId = member.pep_user_id`: ''}
|
||||
|
|
||||
|
${overtimeCountStatistic ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
overtime.pep_user_id AS pepUserId, |
||||
|
count(pep_process_story_id) AS count |
||||
|
FROM overtime |
||||
|
${overtimeCountStatisticWhere.length ? ` |
||||
|
WHERE ${overtimeCountStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY overtime.pep_user_id |
||||
|
) AS overtimeCountStatistic |
||||
|
ON overtimeCountStatistic.pepUserId = member.pep_user_id |
||||
|
`: ''}
|
||||
|
|
||||
|
${vacateDurationStatistic || |
||||
|
orderBy == 'vacateSum' ? |
||||
|
`LEFT JOIN (
|
||||
|
SELECT |
||||
|
vacate.pep_user_id AS pepUserId, |
||||
|
sum(vacate_day.duration) AS duration |
||||
|
FROM vacate_day |
||||
|
INNER JOIN vacate |
||||
|
ON vacate.id = vacate_day.vacate_id |
||||
|
${vacateDayStatisticWhere.length ? ` |
||||
|
WHERE ${vacateDayStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY vacate.pep_user_id |
||||
|
) AS vacateDayStatistic |
||||
|
ON vacateDayStatistic.pepUserId = member.pep_user_id`: ''}
|
||||
|
|
||||
|
${vacateCountStatistic ? ` |
||||
|
LEFT JOIN ( |
||||
|
SELECT |
||||
|
vacate.pep_user_id AS pepUserId, |
||||
|
count(pep_process_story_id) AS count |
||||
|
FROM vacate |
||||
|
${vacateCountStatisticWhere.length ? ` |
||||
|
WHERE ${vacateCountStatisticWhere.join(' AND ')} |
||||
|
`: ''}
|
||||
|
GROUP BY vacate.pep_user_id |
||||
|
) AS vacateCountStatistic |
||||
|
ON vacateCountStatistic.pepUserId = member.pep_user_id |
||||
|
`: ''}
|
||||
|
WHERE |
||||
|
member.del = '0' |
||||
|
${keywordTarget == 'post' && keyword ? ` |
||||
|
AND user.post IN ( |
||||
|
SELECT basicDataPost.id |
||||
|
FROM ${pepEmis}.basicdata_post AS basicDataPost |
||||
|
where basicDataPost.name LIKE '%${keyword}%' |
||||
|
) |
||||
|
` : ''}
|
||||
|
${keywordTarget == 'dep' && keyword ? ` |
||||
|
AND user.id IN ( |
||||
|
SELECT department_user.user |
||||
|
FROM ${pepEmis}.department_user AS department_user |
||||
|
INNER JOIN ${pepEmis}.department AS department |
||||
|
ON department.id = department_user.department |
||||
|
AND department.name LIKE '%${keyword}%' |
||||
|
) |
||||
|
` : ''}
|
||||
|
${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''} |
||||
|
${state == 'onJob' ? `AND member.dimission_date IS null` : ''} |
||||
|
${whereFromSelectOption.length && nowAttendanceTime ? `AND ${whereFromSelectOption.join('AND')}` : ''} |
||||
|
${hiredateStart ? ` |
||||
|
AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}' |
||||
|
`: ''}
|
||||
|
${hiredateEnd ? `
|
||||
|
AND member.hiredate <= '${moment(hiredateEnd).format('YYYY-MM-DD')}' |
||||
|
` : ''}
|
||||
|
${marital ? ` |
||||
|
AND member.marital = '${marital}' |
||||
|
`: ''}
|
||||
|
${native ? ` |
||||
|
AND member.native_place = '${native}' |
||||
|
`: ''}
|
||||
|
${workPlace ? ` |
||||
|
AND member.work_place = '${workPlace}' |
||||
|
`: ''}
|
||||
|
` |
||||
|
|
||||
|
const userRes = await clickHouse.hr.query(` |
||||
|
SELECT |
||||
|
hrMember."member.pep_user_id" AS pepUserId, |
||||
|
hrMember.*, |
||||
|
user.name AS userName, |
||||
|
user.people_code AS userCode, |
||||
|
basicDataPost.name AS userPost, |
||||
|
role.name AS roleName, |
||||
|
role.id AS roleId, |
||||
|
department.name AS depName, |
||||
|
department.id AS depId, |
||||
|
user.job AS userJob, |
||||
|
user.active_status AS userActiveStatus, |
||||
|
user.organization AS userOrganization |
||||
|
FROM ( |
||||
|
SELECT |
||||
|
${orderBy == 'overtimeTakeRestSum' |
||||
|
|| orderBy == 'overtimePaySum' |
||||
|
|| orderBy == 'overtimeSum' ? ` |
||||
|
overtimeDayStatistic.duration AS overtimeDayStatisticDuration, |
||||
|
`: ''}
|
||||
|
|
||||
|
${overtimeCountStatistic ? ` |
||||
|
overtimeCountStatistic.count AS overtimeCount, |
||||
|
`: ''}
|
||||
|
|
||||
|
${orderBy == 'vacateSum' || vacateDurationStatistic ? ` |
||||
|
vacateDayStatistic.duration AS vacateDayStatisticDuration, |
||||
|
`: ''}
|
||||
|
|
||||
|
${vacateCountStatistic ? ` |
||||
|
vacateCountStatistic.count AS vacateCount, |
||||
|
`: ''}
|
||||
|
|
||||
|
${nowAttendanceTime ? ` |
||||
|
hrVacate.vacateStartTime AS vacateStartTime, |
||||
|
hrVacate.vacateEndTime AS vacateEndTime, |
||||
|
hrOvertime.overtimeStartTime AS overtimeStartTime, |
||||
|
hrOvertime.overtimeEndTime AS overtimeEndTime, |
||||
|
`: ''}
|
||||
|
|
||||
|
member.* |
||||
|
${innerSelectQuery} |
||||
|
${limit ? `LIMIT ${limit}` : ''} |
||||
|
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} |
||||
|
) AS hrMember |
||||
|
|
||||
|
LEFT JOIN ${pepEmis}.user AS user |
||||
|
ON pepUserId = user.id |
||||
|
LEFT JOIN ${pepEmis}.user_role AS user_role |
||||
|
ON ${pepEmis}.user_role.user = user.id |
||||
|
LEFT JOIN ${pepEmis}.role AS role |
||||
|
ON ${pepEmis}.role.id = user_role.role |
||||
|
LEFT JOIN ${pepEmis}.basicdata_post AS basicDataPost |
||||
|
ON ${pepEmis}.basicdata_post.id = user.post |
||||
|
LEFT JOIN ${pepEmis}.department_user AS department_user |
||||
|
ON department_user.user = user.id |
||||
|
LEFT JOIN ${pepEmis}.department AS department |
||||
|
ON department.id = department_user.department |
||||
|
${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''} |
||||
|
ORDER BY ${orderBy == 'code' ? |
||||
|
'user.people_code' |
||||
|
: orderBy == 'hiredate' |
||||
|
? 'hrMember."member.hiredate"' |
||||
|
: orderBy == 'age' |
||||
|
? 'hrMember."member.birthday"' |
||||
|
: orderBy == 'overtimeTakeRestSum' |
||||
|
|| orderBy == 'overtimePaySum' |
||||
|
|| orderBy == 'overtimeSum' ? |
||||
|
'hrMember.overtimeDayStatisticDuration' |
||||
|
: orderBy == 'overtimeCount' ? |
||||
|
'hrMember.overtimeCount' |
||||
|
: orderBy == 'vacateSum' ? |
||||
|
'hrMember.vacateDayStatisticDuration' |
||||
|
: orderBy == 'vacateCount' ? |
||||
|
'hrMember.vacateCount' |
||||
|
: 'user.people_code'} |
||||
|
${orderDirection || 'ASC'} |
||||
|
`).toPromise()
|
||||
|
|
||||
|
const countRes = await clickHouse.hr.query(` |
||||
|
SELECT |
||||
|
count(member.pep_user_id) AS count |
||||
|
${innerSelectQuery} |
||||
|
`).toPromise()
|
||||
|
|
||||
|
return { |
||||
|
count: countRes[0].count, |
||||
|
rows: userRes |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function packageUserData(userRes, option = {}) { |
||||
|
|
||||
|
//const { judgeHoliday, } = app.fs.utils
|
||||
|
let workTime = false |
||||
|
let dayoffTime = false |
||||
|
if (option.state) { |
||||
|
const curDay = moment().format('YYYY-MM-DD') |
||||
|
const nowTime = moment() |
||||
|
//const holidayJudge = await judgeHoliday(curDay)
|
||||
|
// if (holidayJudge) {
|
||||
|
// if (
|
||||
|
// holidayJudge.workday
|
||||
|
// && nowTime.isAfter(moment(curDay + ' 08:30'))
|
||||
|
// && nowTime.isBefore(moment(curDay + ' 17:30'))
|
||||
|
// ) {
|
||||
|
// workTime = true
|
||||
|
// } else if (holidayJudge.dayoff || holidayJudge.festivals) {
|
||||
|
// dayoffTime = true
|
||||
|
// }
|
||||
|
// }
|
||||
|
} |
||||
|
|
||||
|
let returnD = [] |
||||
|
let pepUserIds = [-1] |
||||
|
userRes.rows.forEach(u => { |
||||
|
let existUser = returnD.find(r => r.pepUserId == u.pepUserId) |
||||
|
if (existUser) { |
||||
|
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) { |
||||
|
existUser.departmrnt.push({ |
||||
|
id: u.depId, |
||||
|
name: u.depName |
||||
|
}) |
||||
|
} |
||||
|
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) { |
||||
|
existUser.role.push({ |
||||
|
id: u.roleId, |
||||
|
name: u.roleName |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
let obj = {} |
||||
|
for (let k in u) { |
||||
|
let nextKey = k.replace('hrMember.', '') |
||||
|
.replace('member.', '') |
||||
|
if (nextKey.includes('_')) { |
||||
|
nextKey = nextKey.toLowerCase() |
||||
|
.replace( |
||||
|
/(_)[a-z]/g, |
||||
|
(L) => L.toUpperCase() |
||||
|
) |
||||
|
.replace(/_/g, '') |
||||
|
} |
||||
|
obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' || u[k] == '1970-01-01 08:00:00.000000' ? null : u[k] |
||||
|
} |
||||
|
pepUserIds.push(u.pepUserId) |
||||
|
console.log("查询到的用户信息:", obj); |
||||
|
returnD.push({ |
||||
|
...obj, |
||||
|
departmrnt: u.depId ? [{ |
||||
|
id: u.depId, |
||||
|
name: u.depName |
||||
|
}] : [], |
||||
|
role: u.roleId ? [{ |
||||
|
id: u.roleId, |
||||
|
name: u.roleName |
||||
|
}] : [], |
||||
|
state: option.state ? |
||||
|
obj['dimissionDate'] ? 'dimission' : |
||||
|
obj['vacateStartTime'] ? 'vacate' : |
||||
|
workTime ? 'inOffice' : |
||||
|
dayoffTime ? 'dayoff' : 'rest' |
||||
|
: undefined, |
||||
|
del: undefined, |
||||
|
pepuserid: undefined |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
return { packageUser: returnD, pepUserIds } |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
memberList, |
||||
|
packageUserData |
||||
|
} |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import { ApiTable, basicAction } from '$utils' |
||||
|
|
||||
|
//回款明细表
|
||||
|
export function getReceivedDetail(query) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: "get", |
||||
|
dispatch: dispatch, |
||||
|
actionType: "GET_RECEIVED_DETAIL", |
||||
|
query: query, |
||||
|
url: `${ApiTable.getReceivedDetail}`, |
||||
|
msg: { option: "查询回款明细表" }, |
||||
|
reducer: { name: "ReceivedDetail", params: { noClear: true } }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
//业绩明细表
|
||||
|
export function getAchievementDetail(query) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: "get", |
||||
|
dispatch: dispatch, |
||||
|
actionType: "GET_ACHIEVEMENT_DETAIL", |
||||
|
query: query, |
||||
|
url: `${ApiTable.getAchievementDetail}`, |
||||
|
msg: { option: "查询业绩明细表" }, |
||||
|
reducer: { name: "AchievementDetail", params: { noClear: true } }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
//查询合同明细表
|
||||
|
export function getContractDetail(query) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: "get", |
||||
|
dispatch: dispatch, |
||||
|
actionType: "GET_CONTRACT_DETAIL", |
||||
|
query: query, |
||||
|
url: `${ApiTable.getContractDetail}`, |
||||
|
msg: { option: "查询合同明细表" }, |
||||
|
reducer: { name: "ContractDetail", params: { noClear: true } }, |
||||
|
}); |
||||
|
} |
@ -1,6 +1,9 @@ |
|||||
'use strict'; |
'use strict'; |
||||
import * as reserveItem from './reserve-item'; |
import * as reserveItem from './reserve-item'; |
||||
|
import * as salersReport from './salers-report'; |
||||
|
import * as achievementReport from './achievement-report'; |
||||
export default { |
export default { |
||||
...reserveItem |
...reserveItem, |
||||
|
...salersReport, |
||||
|
...achievementReport |
||||
} |
} |
@ -0,0 +1,17 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import { ApiTable, basicAction } from '$utils' |
||||
|
|
||||
|
export function getSalesList(query) {//查询
|
||||
|
return (dispatch) => basicAction({ |
||||
|
type: "get", |
||||
|
dispatch: dispatch, |
||||
|
actionType: "GET_SALES_MENBER_LIST", |
||||
|
query: query, |
||||
|
url: `${ApiTable.getSalesList}`, |
||||
|
msg: { option: "查询销售人员列表" }, |
||||
|
reducer: { name: "SalesMemberList", params: { noClear: true } }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,175 @@ |
|||||
|
'use strict'; |
||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; |
||||
|
import { IconUpload } from '@douyinfe/semi-icons'; |
||||
|
import XLSX from 'xlsx'; |
||||
|
import { contractDetailsColumnKeys } from '../../constants/index'; |
||||
|
//下载模板和上传文件读取
|
||||
|
const ImportContractDetailsModal = props => { |
||||
|
const { dispatch, actions, onCancel } = props; |
||||
|
const { humanAffairs } = actions; |
||||
|
const [msg, setMsg] = useState(''); |
||||
|
const [loading, setLoading] = useState(''); |
||||
|
const [postData, setPostData] = useState([]); |
||||
|
//初始化
|
||||
|
useEffect(() => { |
||||
|
}, []); |
||||
|
|
||||
|
const confirm = () => { |
||||
|
if (postData.length) { |
||||
|
setLoading(true) |
||||
|
// dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => {
|
||||
|
// if (res.success) {
|
||||
|
// onCancel()
|
||||
|
// }
|
||||
|
// setLoading(false)
|
||||
|
// })
|
||||
|
} else { |
||||
|
Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const dldCsvMb = () => { |
||||
|
//表头
|
||||
|
let head = []; |
||||
|
Object.keys(contractDetailsColumnKeys).map(key => { |
||||
|
head.push(contractDetailsColumnKeys[key]); |
||||
|
}) |
||||
|
head = head.join(',') + "\n"; |
||||
|
//数据
|
||||
|
//let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
|
||||
|
let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head; |
||||
|
//创建一个a标签
|
||||
|
let link = document.createElement("a"); |
||||
|
//为a标签设置属性
|
||||
|
link.setAttribute("href", templateCsv); |
||||
|
link.setAttribute("download", "合同明细表导入模板.csv"); |
||||
|
//点击a标签
|
||||
|
link.click(); |
||||
|
} |
||||
|
const download = () => { |
||||
|
dldCsvMb(); |
||||
|
} |
||||
|
|
||||
|
const fileLimit = '.csv'; |
||||
|
|
||||
|
const getFileBlob = (url) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
let request = new XMLHttpRequest() |
||||
|
request.open("GET", url, true) |
||||
|
request.responseType = "blob" |
||||
|
request.onreadystatechange = e => { |
||||
|
if (request.readyState == 4) { |
||||
|
if (request.status == 200) { |
||||
|
if (window.FileReader) { |
||||
|
let reader = new FileReader(); |
||||
|
reader.readAsBinaryString(request.response); |
||||
|
reader.onload = event => { |
||||
|
try { |
||||
|
const { result } = event.target; |
||||
|
// 以二进制流方式读取得到整份excel表格对象
|
||||
|
const workbook = XLSX.read(result, { |
||||
|
type: "binary", |
||||
|
cellDates: true,//设为true,将天数的时间戳转为时间格式
|
||||
|
codepage: 936//解决了乱码问题
|
||||
|
}); |
||||
|
let data = []; // 存储获取到的数据
|
||||
|
// 遍历每张工作表进行读取(这里默认只读取第一张表)
|
||||
|
for (const sheet in workbook.Sheets) { |
||||
|
if (workbook.Sheets.hasOwnProperty(sheet)) { |
||||
|
data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); |
||||
|
} |
||||
|
} |
||||
|
resolve(data);//导出数据
|
||||
|
} catch (e) { |
||||
|
reject("失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
request.send(); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const judgeNull = (value) => { |
||||
|
return value ? String(value).trim().replace(/\s*/g, "") : null; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
title="导入" visible={true} |
||||
|
onOk={confirm} width={620} |
||||
|
confirmLoading={loading} |
||||
|
onCancel={() => { |
||||
|
setMsg('') |
||||
|
setLoading(false) |
||||
|
setPostData([]) |
||||
|
onCancel() |
||||
|
}} |
||||
|
> |
||||
|
<div style={{ borderBottom: '1px solid #DCDEE0', margin: '0px -24px' }}></div> |
||||
|
<Form> |
||||
|
<Form.Upload |
||||
|
label={'合同明细表'} labelPosition='left' |
||||
|
action={'/'} accept={fileLimit} |
||||
|
maxSize={200} limit={1} |
||||
|
onRemove={(currentFile, fileList, fileItem) => { |
||||
|
setMsg(''); |
||||
|
setPostData([]); |
||||
|
}} |
||||
|
customRequest={(data) => { |
||||
|
const { file, onSuccess, onError } = data |
||||
|
getFileBlob(file.url).then(res => { |
||||
|
const error = (msg) => { |
||||
|
setMsg(msg) |
||||
|
onError({ message: msg }) |
||||
|
} |
||||
|
if (res.length > 1000) { |
||||
|
error('一次性上传数据行数应小于1000行,请分批上传') |
||||
|
return |
||||
|
} |
||||
|
if (!res.length) { |
||||
|
error('请填写至少一行数据') |
||||
|
return |
||||
|
} |
||||
|
let postData = []; |
||||
|
for (let i = 0; i < res.length; i++) { |
||||
|
let d = res[i]; |
||||
|
let obj = {}; |
||||
|
Object.keys(contractDetailsColumnKeys).map(key => { |
||||
|
obj[key] = d[contractDetailsColumnKeys[key]] || ''; |
||||
|
}) |
||||
|
postData.push(obj); |
||||
|
} |
||||
|
setPostData(postData) |
||||
|
let msg = '文件解析完成,点击确定按钮上传保存!' |
||||
|
setMsg(msg) |
||||
|
onSuccess({ message: msg }) |
||||
|
}) |
||||
|
}}> |
||||
|
<Button icon={<IconUpload />} theme="light"> |
||||
|
请选择文件 |
||||
|
</Button> |
||||
|
</Form.Upload> |
||||
|
<span>{msg}</span> |
||||
|
<div style={{ color: '#ccc' }}>最大不超过200M,导入文件需与 |
||||
|
<span onClick={() => download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板</span> |
||||
|
一致</div> |
||||
|
</Form> |
||||
|
</Modal > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { auth, global } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(ImportContractDetailsModal); |
@ -0,0 +1,175 @@ |
|||||
|
'use strict'; |
||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; |
||||
|
import { IconUpload } from '@douyinfe/semi-icons'; |
||||
|
import XLSX from 'xlsx'; |
||||
|
import { invoicingDetailsColumnKeys } from '../../constants/index'; |
||||
|
//下载模板和上传文件读取
|
||||
|
const ImportInvoicingDetailsModal = props => { |
||||
|
const { dispatch, actions, onCancel } = props; |
||||
|
const { humanAffairs } = actions; |
||||
|
const [msg, setMsg] = useState(''); |
||||
|
const [loading, setLoading] = useState(''); |
||||
|
const [postData, setPostData] = useState([]); |
||||
|
//初始化
|
||||
|
useEffect(() => { |
||||
|
}, []); |
||||
|
|
||||
|
const confirm = () => { |
||||
|
if (postData.length) { |
||||
|
setLoading(true) |
||||
|
dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => { |
||||
|
if (res.success) { |
||||
|
onCancel() |
||||
|
} |
||||
|
setLoading(false) |
||||
|
}) |
||||
|
} else { |
||||
|
Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const dldCsvMb = () => { |
||||
|
//表头
|
||||
|
let head = []; |
||||
|
Object.keys(invoicingDetailsColumnKeys).map(key => { |
||||
|
head.push(invoicingDetailsColumnKeys[key]); |
||||
|
}) |
||||
|
head = head.join(',') + "\n"; |
||||
|
//数据
|
||||
|
//let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
|
||||
|
let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head; |
||||
|
//创建一个a标签
|
||||
|
let link = document.createElement("a"); |
||||
|
//为a标签设置属性
|
||||
|
link.setAttribute("href", templateCsv); |
||||
|
link.setAttribute("download", "开票明细表导入模板.csv"); |
||||
|
//点击a标签
|
||||
|
link.click(); |
||||
|
} |
||||
|
const download = () => { |
||||
|
dldCsvMb(); |
||||
|
} |
||||
|
|
||||
|
const fileLimit = '.csv'; |
||||
|
|
||||
|
const getFileBlob = (url) => { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
let request = new XMLHttpRequest() |
||||
|
request.open("GET", url, true) |
||||
|
request.responseType = "blob" |
||||
|
request.onreadystatechange = e => { |
||||
|
if (request.readyState == 4) { |
||||
|
if (request.status == 200) { |
||||
|
if (window.FileReader) { |
||||
|
let reader = new FileReader(); |
||||
|
reader.readAsBinaryString(request.response); |
||||
|
reader.onload = event => { |
||||
|
try { |
||||
|
const { result } = event.target; |
||||
|
// 以二进制流方式读取得到整份excel表格对象
|
||||
|
const workbook = XLSX.read(result, { |
||||
|
type: "binary", |
||||
|
cellDates: true,//设为true,将天数的时间戳转为时间格式
|
||||
|
codepage: 936//解决了乱码问题
|
||||
|
}); |
||||
|
let data = []; // 存储获取到的数据
|
||||
|
// 遍历每张工作表进行读取(这里默认只读取第一张表)
|
||||
|
for (const sheet in workbook.Sheets) { |
||||
|
if (workbook.Sheets.hasOwnProperty(sheet)) { |
||||
|
data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); |
||||
|
} |
||||
|
} |
||||
|
resolve(data);//导出数据
|
||||
|
} catch (e) { |
||||
|
reject("失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
request.send(); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const judgeNull = (value) => { |
||||
|
return value ? String(value).trim().replace(/\s*/g, "") : null; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
title="导入" visible={true} |
||||
|
onOk={confirm} width={620} |
||||
|
confirmLoading={loading} |
||||
|
onCancel={() => { |
||||
|
setMsg('') |
||||
|
setLoading(false) |
||||
|
setPostData([]) |
||||
|
onCancel() |
||||
|
}} |
||||
|
> |
||||
|
<div style={{ borderBottom: '1px solid #DCDEE0', margin: '0px -24px' }}></div> |
||||
|
<Form> |
||||
|
<Form.Upload |
||||
|
label={'开票明细表'} labelPosition='left' |
||||
|
action={'/'} accept={fileLimit} |
||||
|
maxSize={200} limit={1} |
||||
|
onRemove={(currentFile, fileList, fileItem) => { |
||||
|
setMsg(''); |
||||
|
setPostData([]); |
||||
|
}} |
||||
|
customRequest={(data) => { |
||||
|
const { file, onSuccess, onError } = data |
||||
|
getFileBlob(file.url).then(res => { |
||||
|
const error = (msg) => { |
||||
|
setMsg(msg) |
||||
|
onError({ message: msg }) |
||||
|
} |
||||
|
if (res.length > 1000) { |
||||
|
error('一次性上传数据行数应小于1000行,请分批上传') |
||||
|
return |
||||
|
} |
||||
|
if (!res.length) { |
||||
|
error('请填写至少一行数据') |
||||
|
return |
||||
|
} |
||||
|
let postData = []; |
||||
|
for (let i = 0; i < res.length; i++) { |
||||
|
let d = res[i]; |
||||
|
let obj = {}; |
||||
|
Object.keys(invoicingDetailsColumnKeys).map(key => { |
||||
|
obj[key] = d[invoicingDetailsColumnKeys[key]] || ''; |
||||
|
}) |
||||
|
postData.push(obj); |
||||
|
} |
||||
|
setPostData(postData) |
||||
|
let msg = '文件解析完成,点击确定按钮上传保存!' |
||||
|
setMsg(msg) |
||||
|
onSuccess({ message: msg }) |
||||
|
}) |
||||
|
}}> |
||||
|
<Button icon={<IconUpload />} theme="light"> |
||||
|
请选择文件 |
||||
|
</Button> |
||||
|
</Form.Upload> |
||||
|
<span>{msg}</span> |
||||
|
<div style={{ color: '#ccc' }}>最大不超过200M,导入文件需与 |
||||
|
<span onClick={() => download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板</span> |
||||
|
一致</div> |
||||
|
</Form> |
||||
|
</Modal > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { auth, global } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(ImportInvoicingDetailsModal); |
Loading…
Reference in new issue