diff --git a/src/functions/blocked/blocked.schema.ts b/src/functions/blocked/blocked.schema.ts index c8c16653..96404597 100644 --- a/src/functions/blocked/blocked.schema.ts +++ b/src/functions/blocked/blocked.schema.ts @@ -10,22 +10,19 @@ export interface IBlockedModel extends Model {} export const BlockedMongooseSchema = new mongoose.Schema< IBlockedDocument, IBlockedModel ->( - { - customerId: { - type: Number, - index: true, - }, - start: { - index: true, - required: true, - type: Date, - }, - end: { - index: true, - required: true, - type: Date, - }, +>({ + customerId: { + type: Number, + index: true, }, - { timestamps: true } -); + start: { + index: true, + required: true, + type: Date, + }, + end: { + index: true, + required: true, + type: Date, + }, +}); diff --git a/src/functions/customer/services/blocked/create.spec.ts b/src/functions/customer/services/blocked/create.spec.ts new file mode 100644 index 00000000..85b87bb4 --- /dev/null +++ b/src/functions/customer/services/blocked/create.spec.ts @@ -0,0 +1,22 @@ +import { createUser } from "~/library/jest/helpers"; +import { CustomerBlockedServiceCreate } from "./create"; +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerBlockedServiceCreate", () => { + it("should create blocked document", async () => { + const customer = await createUser({ customerId: 7106990342471 }); + + const start = new Date("2023-11-26T00:00:00+03:00"); + const end = new Date("2024-01-07T00:00:00+03:00"); + + const blockedDocuments = await CustomerBlockedServiceCreate({ + customerId: 7106990342471, + start, + end, + }); + + expect(blockedDocuments.customerId).toEqual(7106990342471); + expect(blockedDocuments.start).toEqual(start); + expect(blockedDocuments.end).toEqual(end); + }); +}); diff --git a/src/functions/customer/services/blocked/create.ts b/src/functions/customer/services/blocked/create.ts new file mode 100644 index 00000000..1b8c14b4 --- /dev/null +++ b/src/functions/customer/services/blocked/create.ts @@ -0,0 +1,7 @@ +import { BlockedModel } from "~/functions/blocked/blocked.model"; +import { Blocked } from "~/functions/blocked/blocked.types"; + +export const CustomerBlockedServiceCreate = (props: Blocked) => { + const created = new BlockedModel(props); + return created.save(); +}; diff --git a/src/functions/customer/services/blocked/destroy.spec.ts b/src/functions/customer/services/blocked/destroy.spec.ts new file mode 100644 index 00000000..42fbfeab --- /dev/null +++ b/src/functions/customer/services/blocked/destroy.spec.ts @@ -0,0 +1,26 @@ +import { createUser } from "~/library/jest/helpers"; +import { createBlocked } from "~/library/jest/helpers/blocked"; +import { CustomerBlockedServiceDestroy } from "./destroy"; +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerBlockedServiceDestroy", () => { + it("should destroy blocked document", async () => { + const customer = await createUser({ customerId: 7106990342471 }); + + const start = new Date("2023-11-26T00:00:00+03:00"); + const end = new Date("2024-01-07T00:00:00+03:00"); + + const blocked = await createBlocked({ + customerId: 7106990342471, + start, + end, + }); + + const blockedDocuments = await CustomerBlockedServiceDestroy({ + blockedId: blocked._id, + customerId: customer.customerId, + }); + + expect(blockedDocuments.deletedCount).toBe(1); + }); +}); diff --git a/src/functions/customer/services/blocked/destroy.ts b/src/functions/customer/services/blocked/destroy.ts new file mode 100644 index 00000000..925e978b --- /dev/null +++ b/src/functions/customer/services/blocked/destroy.ts @@ -0,0 +1,17 @@ +import { BlockedModel } from "~/functions/blocked/blocked.model"; +import { StringOrObjectId } from "~/library/zod"; + +export type CustomerBlockedServiceDestroyProps = { + blockedId: StringOrObjectId; + customerId: number; +}; + +export const CustomerBlockedServiceDestroy = ({ + blockedId, + customerId, +}: CustomerBlockedServiceDestroyProps) => { + return BlockedModel.deleteOne({ + _id: blockedId, + customerId, + }); +}; diff --git a/src/functions/customer/services/blocked/range.spec.ts b/src/functions/customer/services/blocked/range.spec.ts new file mode 100644 index 00000000..1f1300cb --- /dev/null +++ b/src/functions/customer/services/blocked/range.spec.ts @@ -0,0 +1,49 @@ +import { isWithinInterval } from "date-fns"; +import { createUser } from "~/library/jest/helpers"; +import { createBlocked } from "~/library/jest/helpers/blocked"; +import { CustomerBlockedServiceRange } from "./range"; +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerBlockedServiceRange", () => { + beforeAll(async () => { + await createBlocked({ + customerId: 7106990342471, + start: new Date("2023-11-25"), + end: new Date("2023-11-27"), + }); + await createBlocked({ + customerId: 7106990342471, + start: new Date("2023-12-15"), + end: new Date("2023-12-20"), + }); + // outside range + await createBlocked({ + customerId: 7106990342471, + start: new Date("2024-01-08"), + end: new Date("2024-01-10"), + }); + }); + + it("should return blockeds for customer", async () => { + const customer = await createUser({ customerId: 7106990342471 }); + + const start = new Date("2023-11-26T00:00:00+03:00"); + const end = new Date("2024-01-07T00:00:00+03:00"); + const blockedDocuments = await CustomerBlockedServiceRange({ + customerId: customer.customerId, + start, + end, + }); + + const range = { start, end }; + const allInOrIntersectRange = blockedDocuments.every( + (doc) => + isWithinInterval(new Date(doc.start), range) || + isWithinInterval(new Date(doc.end), range) || + (new Date(doc.start) < start && new Date(doc.end) > end) + ); + + expect(blockedDocuments.length).toBe(2); + expect(allInOrIntersectRange).toBe(true); + }); +}); diff --git a/src/functions/customer/services/blocked/range.ts b/src/functions/customer/services/blocked/range.ts new file mode 100644 index 00000000..ca481dba --- /dev/null +++ b/src/functions/customer/services/blocked/range.ts @@ -0,0 +1,50 @@ +import { BlockedModel } from "~/functions/blocked/blocked.model"; + +export type CustomerBlockedServiceRangeProps = { + customerId: number; + start: string | Date; + end: string | Date; +}; + +export type CustomerBlockedServiceRangeAggregate = { + start: Date; + end: Date; + title: string; +}; + +export const CustomerBlockedServiceRange = async ({ + customerId, + start: startDate, + end: endDate, +}: CustomerBlockedServiceRangeProps) => { + const start = new Date(startDate); + const end = new Date(endDate); + + return BlockedModel.aggregate([ + { + $match: { + $and: [ + { + customerId, + }, + { + $or: [ + { + start: { + $gte: start, + $lte: end, + }, + }, + { + end: { + $gte: start, + $lte: end, + }, + }, + ], + }, + ], + }, + }, + ]); +}; diff --git a/src/functions/customer/services/booking/range.ts b/src/functions/customer/services/booking/range.ts index ecfe0c00..b7af9b8d 100644 --- a/src/functions/customer/services/booking/range.ts +++ b/src/functions/customer/services/booking/range.ts @@ -50,11 +50,7 @@ export const CustomerBookingServiceRange = async ({ $match: { $and: [ { - $or: [ - { - "line_items.properties.customerId": customerId, - }, - ], + "line_items.properties.customerId": customerId, }, { $or: [ @@ -80,11 +76,7 @@ export const CustomerBookingServiceRange = async ({ $match: { $and: [ { - $or: [ - { - "line_items.properties.customerId": customerId, - }, - ], + "line_items.properties.customerId": customerId, }, { $or: [ diff --git a/src/library/jest/helpers/blocked.ts b/src/library/jest/helpers/blocked.ts new file mode 100644 index 00000000..831d9654 --- /dev/null +++ b/src/library/jest/helpers/blocked.ts @@ -0,0 +1,17 @@ +import { faker } from "@faker-js/faker"; +import { BlockedModel } from "~/functions/blocked/blocked.model"; +import { Blocked } from "~/functions/blocked/blocked.types"; + +export const getBlockedObject = ( + props: Partial = {} +): Omit => ({ + start: faker.date.past(), + end: faker.date.future(), + customerId: 1, + ...props, +}); + +export const createBlocked = (props: Blocked) => { + const blocked = new BlockedModel(getBlockedObject({ ...props })); + return blocked.save(); +};