@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 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 { available_slots, from, durGCD, taken_slots };
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/reservable",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Reservable resources",
5
5
  "main": "index.js",
6
6
  "dependencies": {
package/table-provider.js CHANGED
@@ -164,7 +164,7 @@ module.exports = {
164
164
  }
165
165
  return [
166
166
  {
167
- name: "reserve_ident",
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 (where, opts) => {
223
+ getRows: async (where0, opts) => {
224
+ const where = { ...where0 };
224
225
  const table = Table.findOne({ name: cfg.table_name });
225
- const date = !where?.start_day
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 { available_slots, from, durGCD, taken_slots } =
235
- await get_available_slots({
236
- table,
237
- date,
238
- availability: cfg.availability,
239
- entity_wanted: where?.entity || undefined,
240
- reservable_entity_key: cfg.reservable_entity_key,
241
- start_field: cfg.start_field,
242
- duration_field: cfg.duration_field,
243
- services,
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 (range(nslots, i).every((j) => available_slots[j])) {
262
- availabilities.push({
263
- date: date1,
264
- available: true,
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
- } else {
285
+ else
267
286
  availabilities.push({
268
287
  date: date1,
269
- available: false,
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
- reserve_ident: `${date.toISOString()}//${service.title}`,
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
  },