@saltcorn/reservable 0.3.0 → 0.3.2
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/common.js +32 -2
- package/package.json +1 -1
- package/table-provider.js +50 -26
package/common.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const Table = require("@saltcorn/data/models/table");
|
|
2
|
+
|
|
1
3
|
const gcd = function (a, b) {
|
|
2
4
|
if (!b) {
|
|
3
5
|
return a;
|
|
@@ -27,6 +29,7 @@ const get_available_slots = async ({
|
|
|
27
29
|
services,
|
|
28
30
|
start_field,
|
|
29
31
|
duration_field,
|
|
32
|
+
expand_entities,
|
|
30
33
|
}) => {
|
|
31
34
|
const from = new Date(date);
|
|
32
35
|
from.setHours(0, 0, 0, 0);
|
|
@@ -38,6 +41,19 @@ const get_available_slots = async ({
|
|
|
38
41
|
q[reservable_entity_key] = entity_wanted;
|
|
39
42
|
//console.log(JSON.stringify({ date, q }, null, 2));
|
|
40
43
|
const taken_slots = await table.getRows(q);
|
|
44
|
+
let ents = [];
|
|
45
|
+
let entTable;
|
|
46
|
+
let entityTablePK;
|
|
47
|
+
const available_entity_slots = {};
|
|
48
|
+
if (reservable_entity_key && !entity_wanted && expand_entities) {
|
|
49
|
+
const entKey = table.getField(reservable_entity_key);
|
|
50
|
+
entTable = Table.findOne(entKey.reftable_name);
|
|
51
|
+
ents = await entTable.getRows();
|
|
52
|
+
entityTablePK = entTable.pk_name;
|
|
53
|
+
ents.forEach((e) => {
|
|
54
|
+
available_entity_slots[e[entityTablePK]] = [];
|
|
55
|
+
});
|
|
56
|
+
}
|
|
41
57
|
|
|
42
58
|
// figure out regular availability for this day
|
|
43
59
|
const dayOfWeek = [
|
|
@@ -56,10 +72,13 @@ const get_available_slots = async ({
|
|
|
56
72
|
);
|
|
57
73
|
|
|
58
74
|
const available_slots = [];
|
|
59
|
-
const durGCD = gcdArr(services.map((s) => s.duration));
|
|
75
|
+
const durGCD = gcdArr([60, ...services.map((s) => s.duration)]);
|
|
60
76
|
relevant_availabilities.forEach(({ from, to }) => {
|
|
61
77
|
for (let i = (from * 60) / durGCD; i < (to * 60) / durGCD; i++) {
|
|
62
78
|
available_slots[i] = true;
|
|
79
|
+
ents.forEach((e) => {
|
|
80
|
+
available_entity_slots[e[entityTablePK]][i] = true;
|
|
81
|
+
});
|
|
63
82
|
}
|
|
64
83
|
});
|
|
65
84
|
//console.log({ taken_slots });
|
|
@@ -75,9 +94,20 @@ const get_available_slots = async ({
|
|
|
75
94
|
const to = from + slot[duration_field];
|
|
76
95
|
for (let i = from / durGCD; i < to / durGCD; i++) {
|
|
77
96
|
available_slots[i] = false;
|
|
97
|
+
ents.forEach((e) => {
|
|
98
|
+
available_entity_slots[e[entityTablePK]][i] = false;
|
|
99
|
+
});
|
|
78
100
|
}
|
|
79
101
|
});
|
|
80
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
available_slots,
|
|
104
|
+
available_entity_slots,
|
|
105
|
+
from,
|
|
106
|
+
durGCD,
|
|
107
|
+
taken_slots,
|
|
108
|
+
entities: ents,
|
|
109
|
+
entityTablePK,
|
|
110
|
+
};
|
|
81
111
|
};
|
|
82
112
|
|
|
83
113
|
module.exports = { get_available_slots, range };
|
package/package.json
CHANGED
package/table-provider.js
CHANGED
|
@@ -164,7 +164,7 @@ module.exports = {
|
|
|
164
164
|
}
|
|
165
165
|
return [
|
|
166
166
|
{
|
|
167
|
-
name: "
|
|
167
|
+
name: "id",
|
|
168
168
|
type: "String",
|
|
169
169
|
primary_key: true,
|
|
170
170
|
is_unique: true,
|
|
@@ -196,7 +196,7 @@ module.exports = {
|
|
|
196
196
|
name: "service",
|
|
197
197
|
label: "Service",
|
|
198
198
|
type: "String",
|
|
199
|
-
attributes: { options: cfg.services.map((s) => s.title) },
|
|
199
|
+
attributes: { options: cfg.services.map((s) => s.title).join(",") },
|
|
200
200
|
},
|
|
201
201
|
{
|
|
202
202
|
name: "service_duration",
|
|
@@ -220,28 +220,42 @@ module.exports = {
|
|
|
220
220
|
get_table: (cfg) => {
|
|
221
221
|
return {
|
|
222
222
|
disableFiltering: true,
|
|
223
|
-
getRows: async (
|
|
223
|
+
getRows: async (where0, opts) => {
|
|
224
|
+
const where = { ...where0 };
|
|
224
225
|
const table = Table.findOne({ name: cfg.table_name });
|
|
225
|
-
|
|
226
|
+
let date = !where?.start_day
|
|
226
227
|
? new Date()
|
|
227
228
|
: where?.start_day.constructor.name === "PlainDate"
|
|
228
229
|
? where.start_day.toDate()
|
|
229
230
|
: new Date(where?.start_day);
|
|
230
|
-
|
|
231
|
+
if (typeof where?.id === "string") {
|
|
232
|
+
const service = where?.id.split("//")[1];
|
|
233
|
+
if (service) where.service = service;
|
|
234
|
+
date = new Date(where?.id.split("//")[0]);
|
|
235
|
+
}
|
|
231
236
|
const services = where?.service
|
|
232
237
|
? cfg.services.filter((s) => s.title === where.service)
|
|
233
238
|
: cfg.services;
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
239
|
+
const expand_entities = !where?.entity && cfg.reservable_entity_key;
|
|
240
|
+
const {
|
|
241
|
+
available_slots,
|
|
242
|
+
from,
|
|
243
|
+
durGCD,
|
|
244
|
+
taken_slots,
|
|
245
|
+
available_entity_slots,
|
|
246
|
+
entities,
|
|
247
|
+
entityTablePK,
|
|
248
|
+
} = await get_available_slots({
|
|
249
|
+
table,
|
|
250
|
+
date,
|
|
251
|
+
availability: cfg.availability,
|
|
252
|
+
entity_wanted: where?.entity || undefined,
|
|
253
|
+
reservable_entity_key: cfg.reservable_entity_key,
|
|
254
|
+
start_field: cfg.start_field,
|
|
255
|
+
duration_field: cfg.duration_field,
|
|
256
|
+
services,
|
|
257
|
+
expand_entities,
|
|
258
|
+
});
|
|
245
259
|
const minSlot = Math.min(...Object.keys(available_slots));
|
|
246
260
|
const maxSlot = Math.max(...Object.keys(available_slots));
|
|
247
261
|
const service_availabilities = services.map((service, serviceIx) => {
|
|
@@ -258,17 +272,21 @@ module.exports = {
|
|
|
258
272
|
date1.setSeconds(0);
|
|
259
273
|
date1.setMilliseconds(0);
|
|
260
274
|
if (date1 > new Date())
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
275
|
+
if (expand_entities)
|
|
276
|
+
entities.forEach((e) => {
|
|
277
|
+
availabilities.push({
|
|
278
|
+
date: date1,
|
|
279
|
+
available: range(nslots, i).every(
|
|
280
|
+
(j) => available_entity_slots[e[entityTablePK]][j]
|
|
281
|
+
),
|
|
282
|
+
entity: e[entityTablePK],
|
|
283
|
+
});
|
|
265
284
|
});
|
|
266
|
-
|
|
285
|
+
else
|
|
267
286
|
availabilities.push({
|
|
268
287
|
date: date1,
|
|
269
|
-
available:
|
|
288
|
+
available: range(nslots, i).every((j) => available_slots[j]),
|
|
270
289
|
});
|
|
271
|
-
}
|
|
272
290
|
}
|
|
273
291
|
//console.log({ availabilities, service });
|
|
274
292
|
return { availabilities, service, serviceIx };
|
|
@@ -278,20 +296,26 @@ module.exports = {
|
|
|
278
296
|
.map(({ availabilities, service, serviceIx }) =>
|
|
279
297
|
availabilities
|
|
280
298
|
.filter((a) => a.available)
|
|
281
|
-
.map(({ date }) => {
|
|
299
|
+
.map(({ date, entity }) => {
|
|
282
300
|
return {
|
|
283
|
-
|
|
301
|
+
id: `${date.toISOString()}//${service.title}`,
|
|
284
302
|
service: service.title,
|
|
285
303
|
service_duration: service.duration,
|
|
286
304
|
start_day: new PlainDate(date),
|
|
287
305
|
start_date: date,
|
|
288
306
|
start_hour: date.getHours(),
|
|
289
307
|
start_minute: date.getMinutes(),
|
|
308
|
+
...(where?.entity
|
|
309
|
+
? { entity: where.entity }
|
|
310
|
+
: entity
|
|
311
|
+
? { entity }
|
|
312
|
+
: {}),
|
|
290
313
|
};
|
|
291
314
|
})
|
|
292
315
|
)
|
|
293
316
|
.flat();
|
|
294
|
-
return rows;
|
|
317
|
+
if (where?.id) return rows.filter((r) => r.id === where.id);
|
|
318
|
+
else return rows;
|
|
295
319
|
},
|
|
296
320
|
};
|
|
297
321
|
},
|