@delicity/client-cart 1.2.11 → 1.2.12

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.
Files changed (54) hide show
  1. package/README.md +1 -0
  2. package/coverage/clover.xml +71 -0
  3. package/coverage/coverage-final.json +3 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/classes/Cart.ts.html +340 -0
  7. package/coverage/lcov-report/classes/index.html +116 -0
  8. package/coverage/lcov-report/favicon.png +0 -0
  9. package/coverage/lcov-report/index.html +131 -0
  10. package/coverage/lcov-report/prettify.css +1 -0
  11. package/coverage/lcov-report/prettify.js +2 -0
  12. package/coverage/lcov-report/service/CartService.ts.html +238 -0
  13. package/coverage/lcov-report/service/index.html +116 -0
  14. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  15. package/coverage/lcov-report/sorter.js +196 -0
  16. package/coverage/lcov.info +129 -0
  17. package/jest.config.js +8 -0
  18. package/package.json +1 -1
  19. package/src/classes/Cart.ts +563 -0
  20. package/src/index.ts +3 -0
  21. package/src/service/CartService.ts +139 -0
  22. package/src/service/CategoryAvailabilityService.ts +121 -0
  23. package/src/service/DeliveryService.ts +17 -0
  24. package/src/service/HelperService.ts +9 -0
  25. package/src/test/availability.test.ts +346 -0
  26. package/src/test/class.test.ts +497 -0
  27. package/src/test/data/CartData.json +244 -0
  28. package/src/test/data/menu.json +5875 -0
  29. package/src/test/data/merchant.json +186 -0
  30. package/tsconfig.json +24 -0
  31. package/classes/Cart.d.ts +0 -129
  32. package/classes/Cart.d.ts.map +0 -1
  33. package/classes/Cart.js +0 -482
  34. package/classes/Cart.js.map +0 -1
  35. package/index.d.ts +0 -4
  36. package/index.d.ts.map +0 -1
  37. package/index.js +0 -20
  38. package/index.js.map +0 -1
  39. package/service/CartService.d.ts +0 -14
  40. package/service/CartService.d.ts.map +0 -1
  41. package/service/CartService.js +0 -130
  42. package/service/CartService.js.map +0 -1
  43. package/service/CategoryAvailabilityService.d.ts +0 -23
  44. package/service/CategoryAvailabilityService.d.ts.map +0 -1
  45. package/service/CategoryAvailabilityService.js +0 -103
  46. package/service/CategoryAvailabilityService.js.map +0 -1
  47. package/service/DeliveryService.d.ts +0 -4
  48. package/service/DeliveryService.d.ts.map +0 -1
  49. package/service/DeliveryService.js +0 -30
  50. package/service/DeliveryService.js.map +0 -1
  51. package/service/HelperService.d.ts +0 -2
  52. package/service/HelperService.d.ts.map +0 -1
  53. package/service/HelperService.js +0 -14
  54. package/service/HelperService.js.map +0 -1
@@ -0,0 +1,139 @@
1
+ import {
2
+ ICart,
3
+ ICartItem,
4
+ ICartModifierGroup,
5
+ IClientConfig,
6
+ Menu,
7
+ MenuItem,
8
+ OrderModesEnum
9
+ } from "@delicity/client-types";
10
+ import axios from "axios";
11
+
12
+ export function getProductPriceSum(cart:ICart): number{
13
+ return cart.items.reduce((acc, item) => acc + item.totalPrice, 0);
14
+ }
15
+ export function getProductCount(cart:ICart): number{
16
+ return cart.items.reduce((acc, item) => acc + item.quantity, 0);
17
+ }
18
+
19
+ export function getItemModifierValue(item:ICartItem): string {
20
+ return getItemModifierValueArray(item).join(', ');
21
+ }
22
+ export function getItemModifierValueArray(item:ICartItem): string[] {
23
+ return item.modifierGroups
24
+ .filter(mg => mg.modifiers.length > 0)
25
+ .map(mg => {
26
+ return mg.item.name + ': ' + mg.modifiers.map(m => m.item.name).join(', ');
27
+ })
28
+ }
29
+
30
+ export function mandatoryModifierCheck(item: MenuItem, cartModifier: ICartModifierGroup[], menu: Menu): boolean{
31
+ if(!item.children) return true;
32
+
33
+ // get all mandatory modifiers in this item.
34
+ const modifierGroups = menu.modifierGroups.filter((m:any) => item.children?.includes(m.uid) && m.min>0 && m.min);
35
+
36
+ for(let modifier of modifierGroups){
37
+ const m = cartModifier.find((m:any) => m.item.uid === modifier.uid);
38
+ if(!m) return false;
39
+ if(modifier.min === null) continue;
40
+
41
+ const selectedOption = m.modifiers.reduce((acc:any, m:any) => acc + m.quantity, 0);
42
+ if(selectedOption < modifier.min) return false;
43
+ }
44
+
45
+ return true;
46
+ }
47
+
48
+ export function isItemAvailable(item: MenuItem, menu: Menu){
49
+ const menuItem = menu.items.find((i:any) => i.uid === item.uid);
50
+ if(!menuItem) return false;
51
+ return !menuItem.unavailable;
52
+ }
53
+
54
+
55
+ export function getProductPrice(item:MenuItem, mode:OrderModesEnum): number{
56
+ if(!item.price){
57
+ throw new Error('price_not_set');
58
+ }
59
+ if(typeof item.price === 'number'){
60
+ return item.price;
61
+ }
62
+ if(mode === 'delivery'){
63
+ return item.price.delivery;
64
+ }
65
+ else if(mode === 'pickup'){
66
+ return item.price.pickup;
67
+ }
68
+ else if(mode === 'on_site_counter'){
69
+ return item.price.onsite;
70
+ }
71
+ return item.price.delivery;
72
+ }
73
+
74
+ export function getTotalModifiersUnitPrice(modifierGroup:ICartModifierGroup[]): number{
75
+ return modifierGroup.reduce((acc, mg) => acc + mg.modifiers.reduce((bcc, m) => bcc + m.price, 0), 0);
76
+ }
77
+
78
+ export function isItemAlreadyInCart(item:MenuItem, modifierGroups:ICartModifierGroup[], cart:ICart, comment?:string): number{
79
+ // Check if item is already in cart
80
+ const sameCartProducts = cart.items
81
+ .filter((i) => i.item.uid === item.uid)
82
+ .filter((i) => i.comment === (comment||null))
83
+ .filter((c) => {
84
+ if(c.modifierGroups.length !== modifierGroups.length) return false;
85
+ const newItemModifierGroupsKey = modifierGroups.flatMap((m) => {
86
+ return m.modifiers.map((o) => {return {id: o.item.id, quantity: o.quantity}});
87
+ }).sort((a, b) => a.id - b.id).map((m) => m.id + ':' + m.quantity).join('|');
88
+ const CartItemModifierGroupsKey = c.modifierGroups.flatMap((m) => {
89
+ return m.modifiers.map((o) => {return {id: o.item.id, quantity: o.quantity}});
90
+ }).sort((a, b) => a.id - b.id).map((m) => m.id + ':' + m.quantity).join('|');
91
+ return newItemModifierGroupsKey === CartItemModifierGroupsKey;
92
+ })
93
+
94
+ // If not existing in cart, return -1
95
+ if(sameCartProducts.length === 0) return -1;
96
+
97
+ return cart.items.findIndex((c) => c.uuid === sameCartProducts[0].uuid);
98
+ }
99
+
100
+
101
+ export function synchronizeCart(config:IClientConfig, cart: ICart){
102
+ return new Promise(((resolve, reject) => {
103
+ config.axiosClient.post(config.apiUrl+'/v1/client/cart/'+cart.uuid, cart)
104
+ .then((response) => {
105
+ resolve(response.data);
106
+ })
107
+ .catch((error) => {
108
+ reject(error);
109
+ })
110
+ }));
111
+ }
112
+
113
+
114
+ export function addDiscountCode(config:IClientConfig, cart: ICart, code: string){
115
+ return new Promise(((resolve, reject) => {
116
+ config.axiosClient.put(config.apiUrl+'/v1/client/cart/'+cart.uuid+"/coupon", {code})
117
+ .then((response) => {
118
+ resolve(response.data);
119
+ })
120
+ .catch((error) => {
121
+ reject(error);
122
+ })
123
+ }));
124
+ }
125
+
126
+
127
+ export function removeDiscountCode(config:IClientConfig, cart: ICart, discountId: number){
128
+ return new Promise(((resolve, reject) => {
129
+ config.axiosClient.delete(config.apiUrl+'/v1/client/cart/'+cart.uuid+'/coupon/'+discountId)
130
+ .then((response) => {
131
+ resolve(response.data);
132
+ })
133
+ .catch((error) => {
134
+ reject(error);
135
+ })
136
+ }));
137
+ }
138
+
139
+
@@ -0,0 +1,121 @@
1
+ import {DateTime, Interval} from "luxon";
2
+ //@ts-ignore
3
+ import ScheduleManagement from "@delicity/backend-schedule-management";
4
+ import ScheduleMerger from "@delicity/backend-schedule-management/ScheduleMerger";
5
+
6
+ export interface CategoryAvailabilitySlot {
7
+ id: number;
8
+ day: number;
9
+ start: string;
10
+ end: string;
11
+ }
12
+
13
+ export interface CategoryAvailability {
14
+ type: 'some_days' | 'some_shifts' | 'timetable' | 'one_date' | 'between_two_date';
15
+ slots: CategoryAvailabilitySlot[];
16
+ startDate: string;
17
+ endDate: string;
18
+ weekNumber: number;
19
+ weekYear: number;
20
+ }
21
+
22
+ export interface CategoryAvailableResponse {
23
+ isAvailable: boolean;
24
+ willBeAvailableInTheFuture: boolean;
25
+ }
26
+
27
+ export function categoryAvailable(availability: CategoryAvailability, atDate: DateTime, merchantSchedule: ScheduleManagement): CategoryAvailableResponse{
28
+ const category = new ScheduleManagement(availability.slots)
29
+ const categorySchedule = ScheduleMerger(category, merchantSchedule);
30
+
31
+ // If merchant is open
32
+ if(availability.type === 'some_days'){
33
+ if(categorySchedule.isOpenAt(atDate)){
34
+ return {
35
+ isAvailable: true,
36
+ willBeAvailableInTheFuture: true
37
+ };
38
+ }
39
+ }
40
+ else if(availability.type === 'some_shifts'){
41
+ if(categorySchedule.isOpenAt(atDate)){
42
+ return {
43
+ isAvailable: true,
44
+ willBeAvailableInTheFuture: true
45
+ };
46
+ }
47
+ }
48
+ else if(availability.type === 'timetable'){
49
+ if(categorySchedule.isOpenAt(atDate)){
50
+ return {
51
+ isAvailable: true,
52
+ willBeAvailableInTheFuture: true
53
+ };
54
+ }
55
+ }
56
+ // if category is open only at one date
57
+ else if(availability.type === 'one_date'){
58
+ // only this day ?
59
+ if(DateTime.fromFormat(availability.startDate, 'yyyy-LL-dd').hasSame(atDate, 'day')){
60
+ if(categorySchedule.isOpenAt(atDate)){
61
+ return {
62
+ isAvailable: true,
63
+ willBeAvailableInTheFuture: false
64
+ };
65
+ }
66
+ }
67
+ }
68
+ else if(availability.type === 'between_two_date'){
69
+ const start = DateTime.fromFormat(availability.startDate, 'yyyy-LL-dd');
70
+ const end = DateTime.fromFormat(availability.endDate, 'yyyy-LL-dd').endOf('day');
71
+ if(start.toSeconds() < atDate.toSeconds() && end.toSeconds() >= atDate.toSeconds()){
72
+ if(categorySchedule.isOpenAt(atDate)){
73
+ return {
74
+ isAvailable: true,
75
+ willBeAvailableInTheFuture: false
76
+ };
77
+ }
78
+ }
79
+ }
80
+
81
+ let willBeAvailableInTheFuture = true;
82
+ if(availability.type === 'between_two_date' || availability.type === 'one_date'){
83
+ willBeAvailableInTheFuture = DateTime.fromFormat(availability.startDate, 'yyyy-LL-dd').toSeconds() > atDate.toSeconds();
84
+ }
85
+
86
+ return {
87
+ isAvailable: false,
88
+ willBeAvailableInTheFuture
89
+ };
90
+ }
91
+
92
+
93
+ export function getAvailabilityNextInterval(availability: CategoryAvailability, merchantSchedule: ScheduleManagement, atDate: DateTime): Interval | null{
94
+ const category = new ScheduleManagement(availability.slots)
95
+ const categorySchedule = ScheduleMerger(category, merchantSchedule);
96
+
97
+ if(availability.type === 'some_days' || availability.type === 'some_shifts' || availability.type === 'timetable'){
98
+ const nextOpen = categorySchedule.getNextOpen(atDate);
99
+ if(nextOpen){
100
+ const dateIntervals = categorySchedule.getNextOpeningHoursInterval(Interval.fromDateTimes(nextOpen.startOf('day'), nextOpen.endOf('day')));
101
+ if(dateIntervals.length === 0) return null;
102
+ return dateIntervals[0];
103
+ }
104
+ }
105
+ else if(availability.type === 'one_date'){
106
+ const date = DateTime.fromFormat(availability.startDate, 'yyyy-LL-dd');
107
+ const dateIntervals = categorySchedule.getNextOpeningHoursInterval(Interval.fromDateTimes(date.startOf('day'), date.endOf('day')));
108
+ if(dateIntervals.length === 0) return null;
109
+ return dateIntervals[0];
110
+ }
111
+ else if(availability.type === 'between_two_date'){
112
+ const start = DateTime.fromFormat(availability.startDate, 'yyyy-LL-dd');
113
+ const end = DateTime.fromFormat(availability.endDate, 'yyyy-LL-dd');
114
+ const dateIntervals = categorySchedule.getNextOpeningHoursInterval(Interval.fromDateTimes(start.startOf('day'), end.endOf('day')))
115
+ if(dateIntervals.length === 0) return null;
116
+ return dateIntervals[0];
117
+ }
118
+ return null;
119
+ }
120
+
121
+
@@ -0,0 +1,17 @@
1
+ import {Point} from "geojson";
2
+ import {ICartDelivery, IClientConfig} from "@delicity/client-types";
3
+
4
+ export async function getDeliveryDetails(config:IClientConfig, merchantId: number, position: Point):Promise<ICartDelivery>{
5
+ return new Promise(((resolve, reject) => {
6
+ config.axiosClient.post(config.apiUrl + '/v1/client/cart/delivery/infos', {
7
+ merchantId,
8
+ position
9
+ })
10
+ .then((response) => {
11
+ resolve(response.data);
12
+ })
13
+ .catch((error) => {
14
+ reject(error);
15
+ })
16
+ }));
17
+ }
@@ -0,0 +1,9 @@
1
+ export function formatPrice(price:number|string|null) {
2
+ if(typeof price == 'string'){
3
+ price = parseFloat(price);
4
+ }
5
+ if(!price && typeof price !== 'number'){
6
+ return '--,-- €'
7
+ }
8
+ return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(price/100)
9
+ }
@@ -0,0 +1,346 @@
1
+ // @ts-nocheck
2
+
3
+ import { describe, expect, test } from '@jest/globals'
4
+ import ScheduleManagement from "@delicity/backend-schedule-management";
5
+ import {
6
+ categoryAvailable,
7
+ getAvailabilityNextInterval,
8
+ } from "../service/CategoryAvailabilityService";
9
+
10
+ import {DateTime} from "luxon";
11
+
12
+ describe('Category availability check', () => {
13
+
14
+
15
+ test('one_date', () => {
16
+ const categoryAvailability = {
17
+ type: "one_date",
18
+ slots: [{id: 0, day: 3, start: "00:00", end: "23:59"}],
19
+ startDate: "2024-02-14",
20
+ endDate: "2024-02-14"
21
+ };
22
+ const slots = [
23
+ {id: 0, day: 1, start: "12:00", end: "14:00"},
24
+ {id: 0, day: 1, start: "18:00", end: "23:00"},
25
+ {id: 0, day: 2, start: "18:00", end: "23:00"},
26
+ {id: 0, day: 3, start: "18:00", end: "23:00"}
27
+ ];
28
+ const merchantSchedule = new ScheduleManagement(slots, [], {timezone: 'Europe/Paris'});
29
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
30
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-17 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
31
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-14 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
32
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-14 19:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
33
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-14 20:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
34
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-14 20:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(true);
35
+ // Good day
36
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-14 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
37
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-14 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true); // good date
38
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-14 19:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true); // good date
39
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-14 19:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(false); // good date
40
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-14 23:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
41
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-15 10:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
42
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-13 19:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
43
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-15 19:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(false);
44
+ });
45
+
46
+
47
+ test('between_two_date', () => {
48
+ const categoryAvailability = {
49
+ type: "between_two_date",
50
+ slots: [
51
+ {id: 0, day: 1, start: "00:00", end: "23:59"},
52
+ {id: 1, day: 2, start: "00:00", end: "23:59"},
53
+ {id: 2, day: 3, start: "00:00", end: "23:59"},
54
+ {id: 3, day: 4, start: "00:00", end: "23:59"},
55
+ {id: 4, day: 5, start: "00:00", end: "23:59"},
56
+ {id: 5, day: 6, start: "00:00", end: "23:59"}
57
+ ],
58
+ startDate: "2024-02-12",
59
+ endDate: "2024-02-18"
60
+ };
61
+ const slots = [
62
+ {id: 0, day: 1, start: "12:00", end: "14:00"},
63
+ {id: 0, day: 1, start: "18:00", end: "23:00"},
64
+ {id: 0, day: 2, start: "18:00", end: "23:00"},
65
+ {id: 0, day: 3, start: "18:00", end: "23:00"}
66
+ ];
67
+ const merchantSchedule = new ScheduleManagement(slots, [], {timezone: 'Europe/Paris'});
68
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
69
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(true);
70
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-11 13:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
71
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-19 11:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
72
+ // Between two dates
73
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-12 11:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
74
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-12 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
75
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-12 13:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
76
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-12 14:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
77
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-13 14:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
78
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-13 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
79
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-15 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(false);
80
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-02-18 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
81
+
82
+ });
83
+
84
+
85
+ test('timetable', () => {
86
+ const categoryAvailability = {
87
+ type: "timetable",
88
+ slots: [
89
+ {id: 0, day: 2, start: "11:00", end: "16:00"},
90
+ {id: 1, day: 3, start: "17:00", end: "21:00"},
91
+ {id: 2, day: 7, start: "17:00", end: "20:30"}
92
+ ]
93
+ };
94
+ const slots = [
95
+ {id: 3151, day: 1, start: "01:00", end: "23:59"},
96
+ {id: 3152, day: 2, start: "01:00", end: "23:59"},
97
+ {id: 3153, day: 3, start: "01:00", end: "23:59"},
98
+ {id: 3154, day: 4, start: "01:00", end: "23:59"},
99
+ {id: 3155, day: 5, start: "01:00", end: "23:59"},
100
+ {id: 3156, day: 6, start: "01:00", end: "23:59"},
101
+ {id: 3157, day: 7, start: "01:00", end: "23:59"}
102
+ ];
103
+
104
+ const merchantSchedule = new ScheduleManagement(slots, [], {timezone: 'Europe/Paris'});
105
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
106
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-02 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
107
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-03 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
108
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-03 17:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
109
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-03 20:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
110
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-03 23:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
111
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-07 15:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
112
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-07 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
113
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-08 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
114
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-08 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(true);
115
+ });
116
+
117
+ test('some_shifts', () => {
118
+ const categoryAvailability = {
119
+ type: "some_shifts",
120
+ slots: [
121
+ {id: 0, day: 1, start: "13:30", end: "18:00"},
122
+ {id: 1, day: 2, start: "13:30", end: "18:00"},
123
+ {id: 2, day: 3, start: "13:30", end: "18:00"},
124
+ {id: 3, day: 4, start: "13:30", end: "18:00"},
125
+ {id: 4, day: 5, start: "13:30", end: "18:00"},
126
+ {id: 5, day: 6, start: "13:30", end: "18:00"},
127
+ {id: 6, day: 7, start: "13:30", end: "18:00"}
128
+ ],
129
+ startDate: "2024-02-12",
130
+ endDate: "2024-02-18",
131
+ weekNumber: 7,
132
+ weekYear: 2024
133
+ };
134
+ const slots = [
135
+ {id: 3151, day: 1, start: "01:00", end: "23:59"},
136
+ {id: 3152, day: 2, start: "01:00", end: "23:59"},
137
+ {id: 3153, day: 3, start: "01:00", end: "23:59"},
138
+ {id: 3154, day: 4, start: "01:00", end: "23:59"},
139
+ {id: 3155, day: 5, start: "01:00", end: "23:59"},
140
+ {id: 3156, day: 6, start: "01:00", end: "23:59"},
141
+ {id: 3157, day: 7, start: "01:00", end: "23:59"}
142
+ ];
143
+
144
+ const merchantSchedule = new ScheduleManagement(slots, [], {timezone: 'Europe/Paris'});
145
+ for(let i=1; i<=7; i++){
146
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-0'+i+' 12:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
147
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-0'+i+' 13:30', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
148
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-0'+i+' 17:30', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
149
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-0'+i+' 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
150
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-0'+i+' 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(true);
151
+ }
152
+ });
153
+
154
+
155
+ test('some_days', () => {
156
+ const categoryAvailability = {
157
+ type: "some_days",
158
+ slots: [
159
+ {id: 0, day: 1, start: "00:00", end: "23:59"},
160
+ {id: 1, day: 2, start: "00:00", end: "23:59"}
161
+ ]
162
+ };
163
+
164
+ const slots = [
165
+ {id: 3151, day: 1, start: "01:00", end: "23:59"},
166
+ {id: 3152, day: 2, start: "01:00", end: "23:59"},
167
+ {id: 3153, day: 3, start: "01:00", end: "23:59"},
168
+ {id: 3154, day: 4, start: "01:00", end: "23:59"},
169
+ {id: 3155, day: 5, start: "01:00", end: "23:59"},
170
+ {id: 3156, day: 6, start: "01:00", end: "23:59"},
171
+ {id: 3157, day: 7, start: "01:00", end: "23:59"}
172
+ ];
173
+
174
+ const merchantSchedule = new ScheduleManagement(slots, [], {timezone: 'Europe/Paris'});
175
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-01 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
176
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-02 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(true);
177
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-03 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
178
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-04 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
179
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-05 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
180
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-06 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
181
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-07 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).isAvailable).toBe(false);
182
+ expect(categoryAvailable(categoryAvailability, DateTime.fromFormat('2024-01-07 18:00', 'yyyy-LL-dd HH:mm'), merchantSchedule).willBeAvailableInTheFuture).toBe(true);
183
+ });
184
+
185
+
186
+ })
187
+
188
+
189
+ const merchantSlots = [
190
+ {id: 3151, day: 1, start: "12:00", end: "22:00"},
191
+ {id: 3152, day: 2, start: "12:00", end: "22:00"},
192
+ {id: 3153, day: 3, start: "12:00", end: "22:00"},
193
+ {id: 3154, day: 4, start: "12:00", end: "22:00"},
194
+ {id: 3155, day: 5, start: "12:00", end: "22:00"},
195
+ {id: 3156, day: 6, start: "12:00", end: "22:00"},
196
+ {id: 3157, day: 7, start: "12:00", end: "22:00"}
197
+ ];
198
+
199
+
200
+
201
+
202
+
203
+ describe('Category availability get next available date', () => {
204
+
205
+ test('one_date', () => {
206
+ const categoryAvailability = {
207
+ type: "one_date",
208
+ slots: [{id: 0, day: 3, start: "00:00", end: "23:59"}],
209
+ startDate: "2024-02-14",
210
+ endDate: "2024-02-14"
211
+ };
212
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
213
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'));
214
+ expect(interval).not.toBe(null);
215
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-02-14 12:00');
216
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-02-14 22:00');
217
+ });
218
+
219
+ test('between_two_date', () => {
220
+ const categoryAvailability = {
221
+ type: "between_two_date",
222
+ slots: [
223
+ {id: 0, day: 1, start: "00:00", end: "23:59"},
224
+ {id: 1, day: 2, start: "00:00", end: "23:59"},
225
+ {id: 2, day: 3, start: "00:00", end: "23:59"},
226
+ {id: 3, day: 4, start: "00:00", end: "23:59"},
227
+ {id: 4, day: 5, start: "00:00", end: "23:59"},
228
+ {id: 5, day: 6, start: "00:00", end: "23:59"}
229
+ ],
230
+ startDate: "2024-02-13",
231
+ endDate: "2024-02-18"
232
+ };
233
+
234
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
235
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'));
236
+ expect(interval).not.toBe(null);
237
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-02-13 12:00');
238
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-02-13 22:00');
239
+ });
240
+
241
+ test('timetable: Open tomorrow', () => {
242
+ const categoryAvailability = {
243
+ type: "timetable",
244
+ slots: [
245
+ {id: 0, day: 2, start: "11:00", end: "16:00"},
246
+ {id: 1, day: 3, start: "17:00", end: "21:00"},
247
+ {id: 2, day: 7, start: "17:00", end: "20:30"}
248
+ ]
249
+ };
250
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
251
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'));
252
+ expect(interval).not.toBe(null);
253
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-02 12:00');
254
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-02 16:00');
255
+ });
256
+
257
+ test('timetable: Is open at this time', () => {
258
+ const categoryAvailability = {
259
+ type: "timetable",
260
+ slots: [
261
+ {id: 0, day: 2, start: "11:00", end: "16:00"},
262
+ {id: 1, day: 3, start: "17:00", end: "21:00"},
263
+ {id: 2, day: 7, start: "17:00", end: "20:30"}
264
+ ]
265
+ };
266
+
267
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
268
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-02 12:00', 'yyyy-LL-dd HH:mm'));
269
+ expect(interval).not.toBe(null);
270
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-03 17:00');
271
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-03 21:00');
272
+ });
273
+
274
+
275
+ test('timetable: Open while week-end', () => {
276
+ const categoryAvailability = {
277
+ type: "timetable",
278
+ slots: [
279
+ {id: 0, day: 6, start: "08:00", end: "13:00"},
280
+ {id: 1, day: 7, start: "08:00", end: "13:00"}
281
+ ]
282
+ };
283
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
284
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-12 16:31', 'yyyy-LL-dd HH:mm'));
285
+ expect(interval).not.toBe(null);
286
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-13 12:00');
287
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-13 13:00');
288
+ });
289
+
290
+
291
+ test('some_shifts', () => {
292
+ const categoryAvailability = {
293
+ type: "some_shifts",
294
+ slots: [
295
+ {id: 0, day: 1, start: "13:30", end: "18:00"},
296
+ {id: 1, day: 2, start: "13:30", end: "18:00"},
297
+ {id: 2, day: 3, start: "13:30", end: "18:00"},
298
+ {id: 3, day: 4, start: "13:30", end: "18:00"},
299
+ {id: 4, day: 5, start: "13:30", end: "18:00"},
300
+ {id: 5, day: 6, start: "13:30", end: "18:00"},
301
+ {id: 6, day: 7, start: "13:30", end: "18:00"}
302
+ ]
303
+ };
304
+
305
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
306
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'));
307
+ expect(interval).not.toBe(null);
308
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-01 13:30');
309
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-01 18:00');
310
+ });
311
+
312
+ test('some_days : not currently open', () => {
313
+ const categoryAvailability = {
314
+ type: "some_days",
315
+ slots: [
316
+ {id: 0, day: 1, start: "00:00", end: "23:59"},
317
+ {id: 1, day: 2, start: "00:00", end: "23:59"},
318
+ {id: 1, day: 3, start: "00:00", end: "23:59"},
319
+ {id: 1, day: 7, start: "00:00", end: "23:59"}
320
+ ]
321
+ };
322
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
323
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 00:00', 'yyyy-LL-dd HH:mm'));
324
+ expect(interval).not.toBe(null);
325
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-01 12:00');
326
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-01 22:00');
327
+ });
328
+ test('some_days : currently open', () => {
329
+ const categoryAvailability = {
330
+ type: "some_days",
331
+ slots: [
332
+ {id: 0, day: 1, start: "00:00", end: "23:59"},
333
+ {id: 1, day: 2, start: "00:00", end: "23:59"},
334
+ {id: 1, day: 3, start: "00:00", end: "23:59"},
335
+ {id: 1, day: 7, start: "00:00", end: "23:59"}
336
+ ]
337
+ };
338
+ const merchantSchedule = new ScheduleManagement(merchantSlots, [], {timezone: 'Europe/Paris'});
339
+ const interval = getAvailabilityNextInterval(categoryAvailability, merchantSchedule, DateTime.fromFormat('2024-01-01 12:00', 'yyyy-LL-dd HH:mm'));
340
+ expect(interval).not.toBe(null);
341
+ expect(interval.start.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-02 12:00');
342
+ expect(interval.end.toFormat('yyyy-LL-dd HH:mm')).toBe('2024-01-02 22:00');
343
+ });
344
+
345
+
346
+ })