fleetmap-reports 2.0.387 → 2.0.389

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "2.0.387",
3
+ "version": "2.0.389",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,7 +1,7 @@
1
1
  const automaticReports = require('./automaticReports')
2
2
  const {
3
3
  convertMS, getDates, getTranslations, weekDaySelected, convertToLocaleString, isClientSide,
4
- getLanguage, executeServerSide
4
+ getLanguage, executeServerSide, getTimetableText
5
5
  } = require('./util/utils')
6
6
  const jsPDF = require('jspdf')
7
7
  require('jspdf-autotable')
@@ -673,15 +673,7 @@ function exportActivityReportToPDFDriverGroupByDay (doc, translations, reportDat
673
673
  doc.text(new Date(reportData.from).toLocaleString() + ' - ' + new Date(reportData.to).toLocaleString(), 20, space + 25)
674
674
 
675
675
  if (!userData.allWeek && userData.weekDays) {
676
- doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '') +
677
- (userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '') +
678
- (userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '') +
679
- (userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '') +
680
- (userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '') +
681
- (userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '') +
682
- (userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '') +
683
- ' das ' +
684
- userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
676
+ doc.text(getTimetableText(userData, translations), 20, space + 30)
685
677
  }
686
678
 
687
679
  const data = []
@@ -3,7 +3,7 @@ const traccarHelper = require('./util/traccar')
3
3
  const odoo = require('./util/odoo')
4
4
  const automaticReports = require('./automaticReports')
5
5
  const { devicesToProcess } = require('./util/device')
6
- const { getTranslations, convertToLocaleString, getLanguage, convertMS, formatNumber, isClientSide, executeServerSide } = require('./util/utils')
6
+ const { getTranslations, convertToLocaleString, getLanguage, convertMS, formatNumber, isClientSide, executeServerSide, getDayHoursByWeekDay } = require('./util/utils')
7
7
  const { getStyle } = require('./reportStyle')
8
8
  const { getUserPartner } = require('fleetmap-partners')
9
9
  const { addTable, headerFromUser } = require('./util/pdfDocument')
@@ -80,15 +80,16 @@ async function getReportSummaryByDay (dates, userData, traccar, devices, tz, rep
80
80
  const days = []
81
81
  for (const date of dates) {
82
82
  const { year, month, day } = zonedParts(date, tz)
83
+ const dayHours = getDayHoursByWeekDay(new Date(Date.UTC(year, month, day)).getUTCDay(), userData)
83
84
 
84
- let startDate = zonedToUTC(year, month, day, ...parseHMS(userData.dayHours.startTime), tz)
85
+ let startDate = zonedToUTC(year, month, day, ...parseHMS(dayHours.startTime), tz)
85
86
  if (date.getTime() === firstDate.getTime()) {
86
87
  const p = zonedParts(reportFrom, tz)
87
88
  const clamp = zonedToUTC(year, month, day, p.hour, p.minute, p.second, tz)
88
89
  if (clamp.getTime() > startDate.getTime()) startDate = clamp
89
90
  }
90
91
 
91
- let endDate = zonedToUTC(year, month, day, ...parseHMS(userData.dayHours.endTime), tz)
92
+ let endDate = zonedToUTC(year, month, day, ...parseHMS(dayHours.endTime), tz)
92
93
  if (date.getTime() === lastDate.getTime()) {
93
94
  const p = zonedParts(reportTo, tz)
94
95
  const clamp = zonedToUTC(year, month, day, p.hour, p.minute, p.second, tz)
package/src/kms-report.js CHANGED
@@ -11,16 +11,18 @@ const { getDates, getTranslations, isClientSide, executeServerSide } = require('
11
11
  const driversUtil = require('./util/driver')
12
12
  const {
13
13
  isInsideTimetable, isPartialInsideTimetable, calculateTrip, getDataByDay, getKms,
14
- getTripTotalKms, calculateMultiDayTrips
14
+ getTripTotalKms, calculateMultiDayTrips, getUncompletedTrip
15
15
  } = require('./util/trips')
16
16
  const { devicesToProcess } = require('./util/device')
17
17
  const { getDriverData, reportByDriver } = require('./util/driver')
18
18
  const automaticReports = require('./automaticReports')
19
- const { getSummaryByDay } = require('./util/traccar')
20
19
  const { getStop } = require('./trip-report')
21
20
 
22
21
  const fileName = 'KmsReport'
23
22
 
23
+ // dates from getDates are at noon: 12h back/forward to the day boundary plus a 24h buffer
24
+ const CHUNK_BOUNDARY_BUFFER_MS = 36 * 60 * 60 * 1000
25
+
24
26
  async function createKmsReport (from, to, userData, traccarInstance) {
25
27
  console.log('Create KmsReport', from, to, userData.byDriver ? 'by driver' : (userData.byGroup ? 'by group' : 'by device'))
26
28
  const reportData = []
@@ -47,52 +49,31 @@ async function createKmsReportByDevice (from, to, userData, traccarInstance) {
47
49
  to
48
50
  }
49
51
 
50
- if (isClientSide() && (allDevices.length > 50 || ((new Date(to).getTime() - new Date(from).getTime()) > (1000 * 60 * 60 * 24 * 15))) && userData.groupByDay) {
52
+ if (isClientSide() && allDevices.length > 20) {
51
53
  const sliced = automaticReports.sliceArray(allDevices, 1)
52
54
  await executeServerSide('kms-report', sliced, from, to, userData, allDevices.length, traccarInstance).then(devices => {
53
55
  allData.devices = devices
54
56
  })
55
57
  } else {
56
- if (userData.allWeek && userData.groupByDay) {
57
- const dates = getDates(from, to, userData.user.attributes.timezone || getUserPartner(userData.user).timezone)
58
- const summary = await getSummaryByDay(dates, userData, traccarInstance, allDevices, false, from, to)
59
- for (const device of allDevices) {
60
- const days = []
61
- dates.forEach(date => {
62
- const summaryByDay = summary.find(a => a.date === date).summary
63
- const summaryByDevice = summaryByDay.find(a => a.deviceId === device.id)
64
- if (summaryByDevice) {
65
- days.push({
66
- date,
67
- kms: summaryByDevice.distance,
68
- startOdometer: summaryByDevice.startOdometer,
69
- endOdometer: summaryByDevice.endOdometer
70
- })
71
- }
72
- })
73
- const daysWithOdometer = days.filter(a => a.startOdometer > 0)
74
- allData.devices.push({
75
- device,
76
- startOdometer: daysWithOdometer.length > 0 ? daysWithOdometer[0].startOdometer : 0,
77
- endOdometer: daysWithOdometer.length > 0 ? daysWithOdometer[daysWithOdometer.length - 1].endOdometer : 0,
78
- days
79
- })
80
- }
58
+ if (userData.groupByDay) {
59
+ allData.devices = await createKmsReportByDeviceByDay(from, to, allDevices, userData, traccarInstance)
81
60
  } else {
82
61
  let deviceCount = 0
83
62
  const sliced = automaticReports.sliceArray(allDevices,
84
63
  20)
85
64
  for (const devices of sliced) {
86
- const needRoute = userData.groupByDay || !userData.allWeek
65
+ // without groupByDay the distance is the sum of getTripTotalKms, which needs route and stops
87
66
  const {
88
67
  trips,
89
68
  route,
69
+ stops,
90
70
  summary
91
- } = await traccar.getAllInOne(traccarInstance, from, to, devices, needRoute, true, false, !userData.groupByDay, deviceCount, allDevices.length, 10, 1)
71
+ } = await traccar.getAllInOne(traccarInstance, from, to, devices, true, true, !userData.groupByDay, !userData.groupByDay, deviceCount, allDevices.length, 10, 1)
92
72
 
93
73
  allData.devices = allData.devices.concat(await processDevices(from, to, devices, {
94
74
  trips,
95
75
  route,
76
+ stops,
96
77
  summary
97
78
  }, userData, traccarInstance))
98
79
 
@@ -104,6 +85,63 @@ async function createKmsReportByDevice (from, to, userData, traccarInstance) {
104
85
  return allData
105
86
  }
106
87
 
88
+ // Same distance as the trip report (sum of getTripTotalKms), split by day.
89
+ // The period is fetched in blocks of 7 days and 20 devices so long periods and large fleets
90
+ // aren't loaded all at once (same approach as the fuel consumption report).
91
+ async function createKmsReportByDeviceByDay (from, to, allDevices, userData, traccarInstance) {
92
+ const dates = getDates(from, to, userData.user.attributes.timezone || getUserPartner(userData.user).timezone)
93
+ const dateGroups = automaticReports.sliceArray(dates, 7)
94
+ const slicedDevices = automaticReports.sliceArray(allDevices, 20)
95
+ const totalDevices = allDevices.length * dateGroups.length
96
+ const results = new Map(allDevices.map(d => [d.id, { device: d, startOdometer: 0, endOdometer: 0, days: [], hasTrips: false }]))
97
+
98
+ let deviceCount = 0
99
+ for (const [index, chunkDates] of dateGroups.entries()) {
100
+ // internal boundaries are widened so a trip crossing them is fetched whole and then clipped by getDataByDay
101
+ const chunkFrom = index === 0 ? from : new Date(chunkDates[0].getTime() - CHUNK_BOUNDARY_BUFFER_MS)
102
+ const chunkTo = index === dateGroups.length - 1 ? to : new Date(chunkDates[chunkDates.length - 1].getTime() + CHUNK_BOUNDARY_BUFFER_MS)
103
+
104
+ for (const devices of slicedDevices) {
105
+ const data = await traccar.getAllInOne(traccarInstance, chunkFrom, chunkTo, devices, true, true, true, false, deviceCount, totalDevices, 10, 1)
106
+
107
+ for (const d of devices) {
108
+ const result = results.get(d.id)
109
+ const route = data.route.filter(p => p.deviceId === d.id)
110
+ const stops = data.stops.filter(s => s.deviceId === d.id)
111
+ const deviceTrips = data.trips.filter(t => t.deviceId === d.id)
112
+ const uncompletedTrip = getUncompletedTrip(d, route, deviceTrips)
113
+ if (uncompletedTrip) {
114
+ deviceTrips.push(uncompletedTrip)
115
+ }
116
+ const trips = deviceTrips.filter(t => userData.allWeek || !userData.weekDays || isInsideTimetable(t, userData) || isPartialInsideTimetable(d, t, userData, route))
117
+
118
+ for (const date of chunkDates) {
119
+ const { tripsByDay, stopsByDay } = await getDataByDay(d, date, { trips, stops, route }, userData, traccarInstance)
120
+ if (tripsByDay.length) {
121
+ if (!result.hasTrips) {
122
+ result.startOdometer = tripsByDay[0].startOdometer
123
+ }
124
+ result.endOdometer = tripsByDay[tripsByDay.length - 1].endOdometer
125
+ result.hasTrips = true
126
+ }
127
+ result.days.push({
128
+ date,
129
+ kms: tripsByDay.reduce((a, b) =>
130
+ a + getTripTotalKms(b, getStop(new Date(b.endTime), stopsByDay), route), 0
131
+ ) * 1000
132
+ })
133
+ }
134
+ }
135
+ deviceCount += devices.length
136
+ }
137
+ }
138
+
139
+ // with a timetable, devices without trips were already left out of the report
140
+ return [...results.values()]
141
+ .filter(r => userData.allWeek || r.hasTrips)
142
+ .map(({ hasTrips, ...r }) => r)
143
+ }
144
+
107
145
  async function createKmsReportByDriver (from, to, userData, traccarInstance) {
108
146
  const report = { drivers: [] }
109
147
 
@@ -257,7 +295,17 @@ async function processDevices (from, to, devices, data, userData, traccarInstanc
257
295
  })
258
296
  }
259
297
  } else {
260
- const summary = data.summary.find(s => s.deviceId === d.id)
298
+ let summary = data.summary.find(s => s.deviceId === d.id)
299
+ if (trips.length > 0) {
300
+ // same calculation as the trip report and the kms report by driver, so all of them give the same distance
301
+ const deviceStops = (data.stops || []).filter(s => s.deviceId === d.id)
302
+ summary = {
303
+ ...summary,
304
+ distance: trips.reduce((a, b) =>
305
+ a + getTripTotalKms(b, getStop(new Date(b.endTime), deviceStops), deviceRoute), 0
306
+ ) * 1000
307
+ }
308
+ }
261
309
  devicesResult.push({
262
310
  device: d,
263
311
  summary
@@ -39,6 +39,8 @@ function processDeviceData (allInOne, d, userData) {
39
39
  friday: true,
40
40
  saturday: true
41
41
  }
42
+ // this report splits each day into fixed morning/afternoon windows, so per-day hours don't apply
43
+ userData.dayHoursByDay = undefined
42
44
  userData.dayHours = {
43
45
  startTime: '00:00',
44
46
  endTime: '12:00'
@@ -2,7 +2,7 @@ const automaticReports = require('./automaticReports')
2
2
  const jsPDF = require('jspdf')
3
3
  const {
4
4
  convertMS, convertToLocaleString, convertToLocaleDateString, convertToLocaleTimeString, getTranslations,
5
- isClientSide, formatNumber
5
+ isClientSide, formatNumber, getTimetableText
6
6
  } = require('./util/utils')
7
7
  require('jspdf-autotable')
8
8
  const { getUserPartner } = require('fleetmap-partners')
@@ -373,15 +373,7 @@ async function exportTripReportToPDF (userData, reportData) {
373
373
  doc.text(group ? translations.report.group + ': ' + group.name : '', 200, space + 20)
374
374
  doc.text(convertToLocaleString(d.from, lang, timezone, userData.user) + ' - ' + convertToLocaleString(d.to, lang, timezone, userData.user), 20, space + 25)
375
375
  if (!userData.allWeek && userData.weekDays) {
376
- doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '') +
377
- (userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '') +
378
- (userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '') +
379
- (userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '') +
380
- (userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '') +
381
- (userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '') +
382
- (userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '') +
383
- ' das ' +
384
- userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
376
+ doc.text(getTimetableText(userData, translations), 20, space + 30)
385
377
  doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space + 40)
386
378
  } else {
387
379
  doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space + 35)
@@ -1,7 +1,7 @@
1
1
  require('jspdf-autotable')
2
2
  const { getStyle } = require('../reportStyle')
3
3
  const { getUserPartner } = require('fleetmap-partners')
4
- const { getImgFromUrl } = require('./utils')
4
+ const { getImgFromUrl, getTimetableText } = require('./utils')
5
5
  const { version } = require('../../package.json')
6
6
 
7
7
  function addVersionFooter (doc) {
@@ -128,14 +128,6 @@ exports.pdfPageByDay = (userData, page, index, doc, translations, reportData) =>
128
128
  doc.text(new Date(reportData.from).toLocaleString() + ' - ' + new Date(reportData.to).toLocaleString(), 20, space + 25)
129
129
 
130
130
  if (!userData.allWeek && userData.weekDays) {
131
- doc.text((userData.weekDays.monday ? ' ' + translations.report.monday + ',' : '') +
132
- (userData.weekDays.tuesday ? ' ' + translations.report.tuesday + ',' : '') +
133
- (userData.weekDays.wednesday ? ' ' + translations.report.wednesday + ',' : '') +
134
- (userData.weekDays.thursday ? ' ' + translations.report.thursday + ',' : '') +
135
- (userData.weekDays.friday ? ' ' + translations.report.friday + ',' : '') +
136
- (userData.weekDays.saturday ? ' ' + translations.report.saturday + ',' : '') +
137
- (userData.weekDays.sunday ? ' ' + translations.report.sunday + ',' : '') +
138
- ' das ' +
139
- userData.dayHours.startTime + ' - ' + userData.dayHours.endTime, 20, space + 30)
131
+ doc.text(getTimetableText(userData, translations), 20, space + 30)
140
132
  }
141
133
  }
@@ -1,12 +1,13 @@
1
- const { weekDaySelected, convertFromUTC, isClientSide, convertFromLocal } = require('./utils')
1
+ const { weekDaySelected, convertFromUTC, isClientSide, convertFromLocal, getDayHours } = require('./utils')
2
2
 
3
3
  function isInside (_tripStart, _tripEnd, userData) {
4
4
  const tripStart = new Date(_tripStart)
5
5
  const tripEnd = new Date(_tripEnd)
6
6
 
7
7
  if (weekDaySelected(tripStart, userData.weekDays)) {
8
- const timeWindowStartLocal = new Date(convertFromUTC(_tripStart, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
9
- const timeWindowEndLocal = new Date(convertFromUTC(_tripEnd, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
8
+ const dayHours = getDayHours(_tripStart, userData)
9
+ const timeWindowStartLocal = new Date(convertFromUTC(_tripStart, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.startTime)
10
+ const timeWindowEndLocal = new Date(convertFromUTC(_tripEnd, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.endTime)
10
11
 
11
12
  const timeWindowStartUTC = isClientSide() ? timeWindowStartLocal : convertFromLocal(timeWindowStartLocal, userData.user.attributes.timezone)
12
13
  const timeWindowEndUTC = isClientSide() ? timeWindowEndLocal : convertFromLocal(timeWindowEndLocal, userData.user.attributes.timezone)
@@ -1,5 +1,5 @@
1
1
  const automaticReports = require('../automaticReports')
2
- const { convertFromUTC, isClientSide, convertFromLocal } = require('./utils')
2
+ const { convertFromUTC, isClientSide, convertFromLocal, getDayHours } = require('./utils')
3
3
  const path = require('path')
4
4
  const { cleanPositions, filterPosition } = require('./route')
5
5
  const Piscina = require('piscina')
@@ -174,13 +174,14 @@ async function getSummaryByDay (dates, userData, traccarInstance, allDevices, ig
174
174
  const days = []
175
175
  let counter = 0
176
176
  for (const [index, date] of dates.entries()) {
177
- let startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
177
+ const dayHours = getDayHours(date, userData)
178
+ let startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.startTime)
178
179
  if (index === 0) {
179
180
  const _startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + (isClientSide() ? from.toTimeString().slice(0, 8) : convertFromUTC(from, userData.user.attributes.timezone).toTimeString().slice(0, 8)))
180
181
  startDateLocal = startDateLocal.getTime() > _startDateLocal.getTime() ? startDateLocal : _startDateLocal
181
182
  }
182
183
 
183
- let endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
184
+ let endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.endTime)
184
185
  if (index === dates.length - 1) {
185
186
  const _endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + (isClientSide() ? to.toTimeString().slice(0, 8) : convertFromUTC(to, userData.user.attributes.timezone).toTimeString().slice(0, 8)))
186
187
  endDateLocal = endDateLocal.getTime() < _endDateLocal.getTime() ? endDateLocal : _endDateLocal
package/src/util/trips.js CHANGED
@@ -1,4 +1,4 @@
1
- const { coordsDistance, convertFromUTC, weekDaySelected, convertFromLocal, isClientSide, calculateDistance } = require('./utils')
1
+ const { coordsDistance, convertFromUTC, weekDaySelected, convertFromLocal, isClientSide, calculateDistance, getDayHours } = require('./utils')
2
2
  const { isInside } = require('./timetable')
3
3
  const traccarHelper = require('./traccar')
4
4
 
@@ -69,8 +69,9 @@ async function calculatePartialTrip (device, startDate, endDate, route, t, tracc
69
69
 
70
70
  function isPartialInsideTimetable (device, t, userData, route) {
71
71
  if (weekDaySelected(new Date(t.startTime), userData.weekDays)) {
72
- const startDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
73
- const endDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
72
+ const dayHours = getDayHours(t.startTime, userData)
73
+ const startDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.startTime)
74
+ const endDateLocal = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.endTime)
74
75
 
75
76
  const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
76
77
  const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
package/src/util/utils.js CHANGED
@@ -270,6 +270,40 @@ function weekDaySelected (date, weekDays) {
270
270
  (date.getDay() === 6 && weekDays.saturday))
271
271
  }
272
272
 
273
+ const weekDayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
274
+
275
+ // Time window ({ startTime, endTime }) for a weekday (0 = sunday ... 6 = saturday).
276
+ // When the report uses per-day hours (userData.dayHoursByDay, keyed by weekday name),
277
+ // returns that day's window; otherwise the single userData.dayHours used for every day.
278
+ function getDayHoursByWeekDay (weekDay, userData) {
279
+ return (userData.dayHoursByDay && userData.dayHoursByDay[weekDayNames[weekDay]]) || userData.dayHours
280
+ }
281
+
282
+ // Time window for the calendar day of `date`, taken in the same local day the callers
283
+ // use to build the window (convertFromUTC(date, timezone).toISOString().split('T')[0]).
284
+ function getDayHours (date, userData) {
285
+ if (!userData.dayHoursByDay) {
286
+ return userData.dayHours
287
+ }
288
+ const localDay = convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0]
289
+ return getDayHoursByWeekDay(new Date(localDay + 'T00:00:00Z').getUTCDay(), userData)
290
+ }
291
+
292
+ // Header text for the selected days and hours, e.g. " Monday, Tuesday, das 08:00 - 18:00"
293
+ // or, with per-day hours, " Monday 08:00 - 18:00, Wednesday 08:00 - 13:00".
294
+ function getTimetableText (userData, translations) {
295
+ const order = [1, 2, 3, 4, 5, 6, 0]
296
+ const selected = order.filter(i => userData.weekDays[weekDayNames[i]])
297
+ if (userData.dayHoursByDay) {
298
+ return selected.map(i => {
299
+ const hours = getDayHoursByWeekDay(i, userData)
300
+ return ' ' + translations.report[weekDayNames[i]] + ' ' + hours.startTime + ' - ' + hours.endTime
301
+ }).join(',')
302
+ }
303
+ return selected.map(i => ' ' + translations.report[weekDayNames[i]] + ',').join('') +
304
+ ' das ' + userData.dayHours.startTime + ' - ' + userData.dayHours.endTime
305
+ }
306
+
273
307
  async function executeServerSide (type, sliced, from, to, userData, totalItems, traccar, maxRequests = 10, getExtraUserData) {
274
308
  let itemsCount = 0
275
309
  console.log('PROGRESS_PERC:1')
@@ -344,6 +378,9 @@ exports.isClientSide = isClientSide
344
378
  exports.getTimezoneOffset = getTimezoneOffset
345
379
  exports.convertFromUTC = convertFromUTC
346
380
  exports.weekDaySelected = weekDaySelected
381
+ exports.getDayHours = getDayHours
382
+ exports.getDayHoursByWeekDay = getDayHoursByWeekDay
383
+ exports.getTimetableText = getTimetableText
347
384
  exports.getLogo = (user) => {
348
385
  const host = window ? window.location.hostname : getUserPartner(user).host
349
386
  return getImage(getLogoUrl(host))
@@ -4,7 +4,7 @@ const {
4
4
  calculateDistance,
5
5
  sortPositions, getDates, convertToLocaleDateString, convertToLocaleTimeString,
6
6
  isClientSide,
7
- getLanguage, convertFromUTC, convertFromLocal
7
+ getLanguage, convertFromUTC, convertFromLocal, getDayHours
8
8
  } = require('./util/utils')
9
9
  const jsPDF = require('jspdf')
10
10
  require('jspdf-autotable')
@@ -165,8 +165,9 @@ async function processDevices (from, to, devices, userData, data) {
165
165
 
166
166
  const dataByDay = []
167
167
  for (const date of dates) {
168
- const startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
169
- const endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
168
+ const dayHours = getDayHours(date, userData)
169
+ const startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.startTime)
170
+ const endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.endTime)
170
171
  const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
171
172
  const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
172
173
 
@@ -200,8 +201,9 @@ async function processDevices (from, to, devices, userData, data) {
200
201
  if (userData.zonesByColumn) {
201
202
  const groupByDay = []
202
203
  for (const date of dates) {
203
- const startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
204
- const endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
204
+ const dayHours = getDayHours(date, userData)
205
+ const startDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.startTime)
206
+ const endDateLocal = new Date(convertFromUTC(date, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + dayHours.endTime)
205
207
  const startDate = isClientSide() ? startDateLocal : convertFromLocal(startDateLocal, userData.user.attributes.timezone)
206
208
  const endDate = isClientSide() ? endDateLocal : convertFromLocal(endDateLocal, userData.user.attributes.timezone)
207
209