Skip to content

Commit 4215e4b

Browse files
Added Sales Reports by book for admins and merge
2 parents b15abbe + 32babe9 commit 4215e4b

File tree

14 files changed

+483
-18
lines changed

14 files changed

+483
-18
lines changed

back/src/controllers/admin.controller.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ export const getFeedback = (request, response) => {
7373
});
7474
};
7575

76+
const phaseDateUtil = (datesPerPhase, newPhase, oldPhase) =>{
77+
if(oldPhase < newPhase){
78+
for(let i=oldPhase+1; i<=newPhase; i++){
79+
datesPerPhase[i] = new Date();
80+
}
81+
}
82+
else{
83+
for(let i=oldPhase; i>newPhase; i--){
84+
datesPerPhase[i] = null;
85+
}
86+
}
87+
return datesPerPhase;
88+
}
7689
//Funcion que avanza la fase del texto del cual recibe su ID
7790
export const movePhase = (request, response) => {
7891
send(response, async () => {
@@ -82,7 +95,7 @@ export const movePhase = (request, response) => {
8295
const newPhase = request.body.phase;
8396
const phase = await TextModel.updateOne(
8497
{ _id: id },
85-
{ $set: { phase: newPhase } },
98+
{ $set: { phase: newPhase, datesPerPhase: phaseDateUtil(text.datesPerPhase, newPhase, text.phase)}},
8699
function (err, res) {
87100
if (err) throw err;
88101
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { send } from "@/utils/errors";
2+
import { TextModel } from "@/models/text.model";
3+
import { UserModel } from "@/models/user.model";
4+
5+
6+
7+
// Response with all texts with their genres.
8+
export const getTimeBenchmarks = (request, response) => {
9+
send(response, async () => {
10+
const texts = await TextModel.find().populate("genres").populate("writer");
11+
let phases = {
12+
1: {
13+
max: Number.MIN_VALUE,
14+
min: Number.MAX_VALUE,
15+
total: 0
16+
},
17+
2: {
18+
max: Number.MIN_VALUE,
19+
min: Number.MAX_VALUE,
20+
total: 0
21+
},
22+
3: {
23+
max: Number.MIN_VALUE,
24+
min: Number.MAX_VALUE,
25+
total: 0
26+
},
27+
4: {
28+
max: Number.MIN_VALUE,
29+
min: Number.MAX_VALUE,
30+
total: 0
31+
},
32+
5: {
33+
max: Number.MIN_VALUE,
34+
min: Number.MAX_VALUE,
35+
total: 0
36+
},
37+
6: {
38+
max: Number.MIN_VALUE,
39+
min: Number.MAX_VALUE,
40+
total: 0
41+
},
42+
7: {
43+
max: Number.MIN_VALUE,
44+
min: Number.MAX_VALUE,
45+
total: 0
46+
},
47+
8: {
48+
max: Number.MIN_VALUE,
49+
min: Number.MAX_VALUE,
50+
total: 0
51+
},
52+
9: {
53+
max: Number.MIN_VALUE,
54+
min: Number.MAX_VALUE,
55+
total: 0
56+
},
57+
overall:{
58+
max: Number.MIN_VALUE,
59+
min: Number.MAX_VALUE,
60+
total: 0
61+
}
62+
}
63+
texts.forEach((text) => {
64+
let thisDate = new Date(text.createdAt)
65+
for(let i=1; i<9; i++){
66+
const nextDate = text.datesPerPhase[i+1] !== null ? new Date(text.datesPerPhase[i+1]) : null
67+
const timeInPhase = getHours(thisDate, nextDate)
68+
phases[i] ={
69+
min: phases[i].min > timeInPhase ? ((timeInPhase !== -1) ? timeInPhase : phases[i].min) : phases[i].min,
70+
max: phases[i].max < timeInPhase ? ((timeInPhase !== -1) ? timeInPhase : phases[i].max) : phases[i].max,
71+
total: (timeInPhase !== -1) ? timeInPhase + phases[i].total : phases[i].total
72+
}
73+
thisDate = nextDate
74+
}
75+
const startDate = new Date(text.createdAt)
76+
const endDate = text.datesPerPhase[9] !== null ? new Date(text.datesPerPhase[i+1]) : null
77+
const totalTime = getHours(startDate, endDate)
78+
phases['overall'] = {
79+
min: phases['overall'].min > totalTime ? ((totalTime !== -1) ? totalTime : phases['overall'].min) : phases['overall'].min,
80+
max: phases['overall'].max < totalTime ? ((totalTime !== -1) ? totalTime : phases['overall'].max) : phases['overall'].max,
81+
total: (totalTime !== -1) ? totalTime + phases['overall'].total : phases['overall'].total
82+
}
83+
})
84+
for(let i=1; i<9; i++){
85+
phases[i] ={
86+
...phases[i],
87+
avg: phases[i].total/getLengthOfNotNull(texts,i+1)
88+
}
89+
}
90+
phases['overall'] = {
91+
...phases['overall'],
92+
avg: phases['overall'].total/getLengthOfNotNull(texts,9)
93+
}
94+
95+
console.log(phases)
96+
return phases;
97+
});
98+
};
99+
100+
// Response with a particular text based on its id.
101+
export const getText = (request, response) => {
102+
send(response, async () => {
103+
const { id } = request.params;
104+
const reader = await TextModel.find({_id:id}).populate("genres");
105+
return reader;
106+
});
107+
};
108+
109+
const getHours = (date1, date2) =>{
110+
if(date1 !== null && date2 !== null){
111+
const milliseconds = Math.abs(date2 - date1);
112+
return milliseconds / 36e5;
113+
}
114+
return -1
115+
}
116+
117+
const getLengthOfNotNull = (texts, phase) => {
118+
let length = 0
119+
texts.forEach((text) =>{
120+
if(text.datesPerPhase[phase] !== null) length++
121+
})
122+
return length
123+
}

back/src/models/text.model.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,24 @@ export const TextSchema = new Schema({
5858
isRejected: {
5959
type: Boolean,
6060
default: false
61+
},
62+
63+
datesPerPhase: {
64+
type: Object,
65+
default:{
66+
1: null,
67+
2: null,
68+
3: null,
69+
4: null,
70+
5: null,
71+
6: null,
72+
7: null,
73+
8: null,
74+
9: null
75+
}
6176
}
62-
});
77+
78+
}, {timestamps: true});
6379
TextSchema.plugin(beautifyUnique);
6480

6581
export const TextModel = model("Text", TextSchema);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {
2+
getTimeBenchmarks,
3+
getEventById,
4+
createEvent,
5+
updateEvent,
6+
deleteEvent
7+
} from "@/controllers/benchmarks.controller";
8+
import { verifyToken } from "@/utils/jwt";
9+
10+
export const addBenchmarkRoutes = (router) => {
11+
router.get("/timeBenchmarks", verifyToken(["admin"]), getTimeBenchmarks);
12+
};
13+

back/src/routes/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { addGenreRoutes } from "./genre.route";
1111
import { addPointOfSaleRoutes } from "./pointOfsale.route";
1212
import { addEventRoutes } from "./event.route";
1313
import { addSaleRoutes } from "./sale.route";
14+
import { addBenchmarkRoutes } from "./benchamarks.route";
1415
import {
1516
authUser,
1617
getAllGenres,
@@ -41,5 +42,6 @@ export const createRoutes = () => {
4142
addSaleRoutes(router);
4243
addInventoryRoutes(router);
4344
addProductRoutes(router);
45+
addBenchmarkRoutes(router)
4446
return router;
4547
};

front/package-lock.json

Lines changed: 43 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
},
1010
"dependencies": {
1111
"axios": "^0.19.2",
12+
"chart.js": "2",
1213
"commonmark": "^0.29.1",
1314
"core-js": "^3.6.4",
1415
"date-fns": "^2.11.1",
1516
"moment": "^2.26.0",
16-
"vue": "^2.6.11",
17+
"vue": "2.6.11",
1718
"vue-async-computed": "^3.8.2",
19+
"vue-chartjs": "^3.5.1",
1820
"vue-cookies": "^1.7.0",
1921
"vue-router": "^3.1.5",
2022
"vuetify": "^2.2.19"

front/src/components/PieChart.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Pie, mixins } from 'vue-chartjs'
2+
const { reactiveProp } = mixins
3+
4+
export default {
5+
extends: Pie,
6+
mixins: [reactiveProp],
7+
props: ['options'],
8+
mounted () {
9+
// this.chartData is created in the mixin.
10+
// If you want to pass options please create a local options object
11+
this.renderChart(this.chartData, this.options)
12+
}
13+
}

front/src/components/dashboardAdmin.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ export default {
218218
route: "/salesReports",
219219
hasPermission: hasPermission.bind(this)("saleRead")
220220
},
221+
{
222+
title: "Tiempos en Fase",
223+
route: "/tiempos",
224+
hasPermission: hasPermission.bind(this)("reportsRead")
225+
},
221226
{
222227
title: "Eventos",
223228
route: "/event",
@@ -253,6 +258,7 @@ export default {
253258
});
254259
book.genres = genreNames;
255260
});
261+
console.log(data)
256262
this.dataTexts = data;
257263
},
258264
seeSuggestions(item) {

front/src/components/reportsTable.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<tr v-for="item in props.items" :key="item._id">
1414
<td v-for="header in displayedHeaders" :key="header.value">
1515
<div v-if="header.text == 'Fase'">
16-
{{ faseOptions[item.phase].label }}
16+
{{item.phase !== 9 ? faseOptions[item.phase].label : "Total" }}
1717
</div>
1818
<div v-if="header.text == 'Acciones'">
1919
<div style="margin: 2.5px 2.5px" v-if="item.go">
@@ -30,7 +30,7 @@
3030
</div>
3131

3232
</td>
33-
<td class="text-xs-center">
33+
<td class="text-xs-center" v-if="item.go">
3434
<slot name="actions">
3535
<div style="margin: 2.5px 2.5px" v-if="item.go">
3636
<v-tooltip bottom>

0 commit comments

Comments
 (0)