|
@@ -46,7 +46,6 @@ class StatisticsService extends CrudService {
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 教练统计, 授课情况
|
|
|
async coachLesson({ coach_id, school_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -74,7 +73,6 @@ class StatisticsService extends CrudService {
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 学员统计,付费情况
|
|
|
async studentPay({ school_id, student_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -106,7 +104,6 @@ class StatisticsService extends CrudService {
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 学员统计,学员上课时长及签到
|
|
|
async studentLearning({ school_id, student_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -144,7 +141,6 @@ class StatisticsService extends CrudService {
|
|
|
return { minutes, signs };
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 学校统计,教练收入
|
|
|
async schoolCoachIn({ school_id, coach_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -193,10 +189,8 @@ class StatisticsService extends CrudService {
|
|
|
arr.push(obj);
|
|
|
}
|
|
|
return arr;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 学校统计 每月上课次数
|
|
|
async schoolSignCoach({ school_id, coach_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -213,7 +207,7 @@ class StatisticsService extends CrudService {
|
|
|
return [ start, end ];
|
|
|
});
|
|
|
let lcList = await this.lessonCoachModel.find(query, { coach_id: 1, meta: 1 });
|
|
|
- if (lcList.length > 0) lcList = JSON.parse(JSON.stringify((lcList)));
|
|
|
+ if (lcList.length > 0) lcList = JSON.parse(JSON.stringify(lcList));
|
|
|
const arr = [];
|
|
|
for (const months of monthList) {
|
|
|
const s = _.head(months);
|
|
@@ -228,7 +222,6 @@ class StatisticsService extends CrudService {
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 学校统计:学员按岁数区间
|
|
|
async schoolStudentAge({ school_id }) {
|
|
|
assert(school_id, '缺少学校信息');
|
|
@@ -243,7 +236,7 @@ class StatisticsService extends CrudService {
|
|
|
];
|
|
|
const data = [];
|
|
|
let list = await this.rssModel.find({ school_id }).populate('student_id', 'birth');
|
|
|
- if (list.length > 0)list = JSON.parse(JSON.stringify(list));
|
|
|
+ if (list.length > 0) list = JSON.parse(JSON.stringify(list));
|
|
|
for (const a of ageList) {
|
|
|
const start = _.head(a);
|
|
|
const end = _.last(a);
|
|
@@ -265,88 +258,110 @@ class StatisticsService extends CrudService {
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 羽校总收入
|
|
|
- * 统计账单的 收入(类型为-1/-2) - 退款(至余额,2) 且 is_pay 为 1
|
|
|
+ * 统计账单的 收入(类型为-1/-2) 且 is_pay 不为 0
|
|
|
* m:当前这个月; 3m: 往前推3个月; 6m:往前推6个月; 1y:当前年
|
|
|
* @param {Object} query 查询条件
|
|
|
* @property {String} school_id 学校id
|
|
|
- * @property {String} time 时间 m:月;3m:3月;6m:6个月; 1y:1年
|
|
|
+ * @property {String} skip 分页
|
|
|
+ * @property {String} limit 分页
|
|
|
*/
|
|
|
- async schoolTotalIn({ school_id, time }) {
|
|
|
+ async schoolTotalIn({ school_id }) {
|
|
|
assert(school_id, '缺少羽校信息');
|
|
|
- assert(time, '缺少时间范围');
|
|
|
- let query = { is_pay: '1', $or: [{ type: '-1' }, { type: '-2' }, { type: '2' }], school_id };
|
|
|
+ const query = { is_pay: { $ne: '0' }, school_id, type: [ '-1', '-2' ] };
|
|
|
+ const projection = { pay_for: 1, from_id: 1, type: 1, money: 1, time: 1, payer_id: 1 };
|
|
|
+ const qm = this.resetQuery('m');
|
|
|
+ const bm = await this.billModel.find({ ...qm, ...query }, projection);
|
|
|
+ const mm = bm.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ const q3m = this.resetQuery('3m');
|
|
|
+ const b3m = await this.billModel.find({ ...q3m, ...query }, projection);
|
|
|
+ const m3m = b3m.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ const q6m = this.resetQuery('6m');
|
|
|
+ const b6m = await this.billModel.find({ ...q6m, ...query }, projection);
|
|
|
+ const m6m = b6m.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ const qy = this.resetQuery('1y');
|
|
|
+ const by = await this.billModel.find({ ...qy, ...query }, projection);
|
|
|
+ const my = by.reduce((p, n) => this.ctx.plus(p, n.money), 0);
|
|
|
+ return { mm, m3m, m6m, my };
|
|
|
+ }
|
|
|
+
|
|
|
+ async schoolInByLesson({ school_id, time = 'm', skip = 0, limit }) {
|
|
|
+ const tq = this.resetQuery(time, 'time_start');
|
|
|
+ const query = { ...tq, school_id };
|
|
|
+ const pipeline = [{ $match: query }];
|
|
|
+ const baseCol = { time_start: 1, title: 1 };
|
|
|
+ // #region 整理课程数据
|
|
|
+ pipeline.push({
|
|
|
+ $project: {
|
|
|
+ ...baseCol,
|
|
|
+ money: { $toDouble: '$money' },
|
|
|
+ },
|
|
|
+ });
|
|
|
+ baseCol.money = 1;
|
|
|
+ // #endregion
|
|
|
+ // #region 正式学员
|
|
|
+ pipeline.push({ $addFields: { lesson_id: { $toString: '$_id' } } });
|
|
|
+ baseCol.lesson_id = 1;
|
|
|
+ pipeline.push({
|
|
|
+ $lookup: {
|
|
|
+ from: 'lessonStudent',
|
|
|
+ localField: 'lesson_id',
|
|
|
+ foreignField: 'lesson_id',
|
|
|
+ pipeline: [
|
|
|
+ { $group: { _id: '$lesson_id', num: { $sum: 1 } } },
|
|
|
+ ],
|
|
|
+ as: 'zStudent',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ pipeline.push({ $set: { zStudent: { $sum: '$zStudent.num' } } });
|
|
|
+ pipeline.push({ $project: { ...baseCol, zStudent: { $toDouble: '$zStudent' } } });
|
|
|
+ baseCol.zStudent = 1;
|
|
|
+ // #endregion
|
|
|
+ // #region 临时学员
|
|
|
+ pipeline.push({
|
|
|
+ $lookup: {
|
|
|
+ from: 'tempLessonApply',
|
|
|
+ localField: 'lesson_id',
|
|
|
+ foreignField: 'lesson_id',
|
|
|
+ pipeline: [{ $group: { _id: '$lesson_id', num: { $sum: 1 } } }],
|
|
|
+ as: 'lStudent',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ pipeline.push({ $set: { lStudent: { $sum: '$lStudent.num' } } });
|
|
|
+ pipeline.push({ $project: { ...baseCol, lStudent: { $toDouble: '$lStudent' } } });
|
|
|
+ baseCol.lStudent = 1;
|
|
|
+ pipeline.push({ $set: { total: { $multiply: [ '$money', { $add: [ '$zStudent', '$lStudent' ] }] } } });
|
|
|
+ // #endregion
|
|
|
+ if (parseInt(skip)) pipeline.push({ $skip: parseInt(skip) });
|
|
|
+ if (parseInt(limit))pipeline.push({ $limit: parseInt(limit) });
|
|
|
+ const res = await this.lessonModel.aggregate(pipeline);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ resetQuery(time, key = 'time') {
|
|
|
+ let query = {};
|
|
|
const { year, month, lastDate } = this.getPartsOfNow();
|
|
|
- const timeQuery = (start, end) => ({ $and: [{ time: { $gte: start } }, { time: { $lte: end } }] });
|
|
|
- let xList;
|
|
|
- const yList = [];
|
|
|
+ const timeQuery = (start, end) => ({ $and: [{ [key]: { $gte: start } }, { [key]: { $lte: end } }] });
|
|
|
if (time === 'm') {
|
|
|
- // 这个月,按天查
|
|
|
const start = `${year}-${month}-01`;
|
|
|
const end = `${year}-${month}-${lastDate}`;
|
|
|
query = { ...query, ...timeQuery(start, end) };
|
|
|
- xList = this.getEachDay(start, end);
|
|
|
} else if ([ '3m', '6m' ].includes(time)) {
|
|
|
const ms = _.head(time.split('')); // 月份数量 3/6/...
|
|
|
- xList = this.getMonthList(ms);
|
|
|
- const start = _.last(xList);
|
|
|
- const { year, month, lastDate } = this.getPartsOfNow(_.head(xList));
|
|
|
- const end = `${year}-${month}-${lastDate}`;
|
|
|
+ const start = moment().subtract(ms, 'months').format('YYYY-MM-01');
|
|
|
+ const { lastDate } = this.getPartsOfNow();
|
|
|
+ const end = lastDate;
|
|
|
query = { ...query, ...timeQuery(start, end) };
|
|
|
} else if (time === '1y') {
|
|
|
const { year } = this.getPartsOfNow();
|
|
|
const start = `${year}-01-01`;
|
|
|
const end = `${year}-12-31`;
|
|
|
- xList = this.getMonthList(12, end);
|
|
|
query = { ...query, ...timeQuery(start, end) };
|
|
|
}
|
|
|
-
|
|
|
- let billList = await this.billModel.find(query, { pay_for: 1, from_id: 1, type: 1, money: 1, time: 1, payer_id: 1 });
|
|
|
- if (billList.length > 0) billList = JSON.parse(JSON.stringify(billList));
|
|
|
- for (const i of billList) {
|
|
|
- const { time } = i;
|
|
|
- const date = this.getDate(time);
|
|
|
- i.date = date;
|
|
|
- }
|
|
|
- if (time === 'm') {
|
|
|
- for (const x of xList) {
|
|
|
- const date = x;
|
|
|
- const list = billList.filter(f => f.date === date);
|
|
|
- const inList = list.filter(f => f.type !== '2');
|
|
|
- const outList = list.filter(f => f.type === '2');
|
|
|
- const inTotal = inList.reduce((p, n) => p + (n.money || 0), 0);
|
|
|
- const outTotal = outList.reduce((p, n) => p + (n.money || 0), 0);
|
|
|
- const total = inTotal - outTotal;
|
|
|
- yList.push(total);
|
|
|
- }
|
|
|
- xList = xList.map(i => {
|
|
|
- const { date } = this.getPartsOfNow(i);
|
|
|
- return `${date}日`;
|
|
|
- });
|
|
|
- } else if ([ '3m', '6m', '1y' ].includes(time)) {
|
|
|
- for (const x of xList) {
|
|
|
- const start = x;
|
|
|
- const { year, month, lastDate } = this.getPartsOfNow(x);
|
|
|
- const end = `${year}-${month}-${lastDate}`;
|
|
|
- const list = billList.filter(f => moment(f.date).isBetween(start, end, null, '[]'));
|
|
|
- const inList = list.filter(f => f.type !== '2');
|
|
|
- const outList = list.filter(f => f.type === '2');
|
|
|
- const inTotal = inList.reduce((p, n) => p + (n.money || 0), 0);
|
|
|
- const outTotal = outList.reduce((p, n) => p + (n.money || 0), 0);
|
|
|
- const total = inTotal - outTotal;
|
|
|
- yList.unshift(total);
|
|
|
- }
|
|
|
- xList = xList.map(i => {
|
|
|
- const { month } = this.getPartsOfNow(i);
|
|
|
- return `${parseInt(month)}月`;
|
|
|
- });
|
|
|
- xList = _.reverse(xList);
|
|
|
- }
|
|
|
- console.log('line 189 in function:');
|
|
|
- return { x: xList, y: yList };
|
|
|
+ return query;
|
|
|
}
|
|
|
+
|
|
|
// 获取现在时间的各个部分 年月日时分秒 和 当月最后一天是几号
|
|
|
getPartsOfNow(time = new Date()) {
|
|
|
const year = moment(time).year();
|