diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index dddea5b6..0203b4fb 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -188,8 +188,6 @@ components: $ref: paths/customer/location/_types/location.yaml CustomerLocationIsDefault: $ref: paths/customer/location/_types/location-is-default.yaml - CustomerLocationGetAllOriginsRepsonse: - $ref: paths/customer/location/get-all-origins/response.yaml CustomerLocationCreateBody: $ref: paths/customer/location/create/body.yaml CustomerLocationCreateResponse: @@ -202,8 +200,6 @@ components: $ref: paths/customer/location/update/body.yaml CustomerLocationUpdateResponse: $ref: paths/customer/location/update/response.yaml - CustomerLocationAddResponse: - $ref: paths/customer/location/add/response.yaml CustomerLocationRemoveResponse: $ref: paths/customer/location/remove/response.yaml CustomerLocationSetDefaultResponse: @@ -268,8 +264,6 @@ components: $ref: paths/location/get-coordinates/response.yaml LocationGetTravelTimeResponse: $ref: paths/location/get-travel-time/response.yaml - LocationValidateAddressResponse: - $ref: paths/location/validate-address/response.yaml # Shipping Shipping: @@ -388,8 +382,6 @@ paths: $ref: "./paths/meta/specialties/index.yaml" # locations - /customer/{customerId}/locations/get-all-origins: - $ref: "./paths/customer/location/get-all-origins/index.yaml" /customer/{customerId}/location/{locationId}/setDefault: $ref: "./paths/customer/location/set-default/index.yaml" /customer/{customerId}/location/{locationId}: @@ -398,8 +390,6 @@ paths: $ref: "./paths/customer/location/create-list.yaml" /location/get-coordinates: $ref: "./paths/location/get-coordinates/index.yaml" - /location/validate-address: - $ref: "./paths/location/validate-address/index.yaml" /location/get-travel-time: $ref: "./paths/location/get-travel-time/index.yaml" diff --git a/openapi/paths/customer/location/add/index.yaml b/openapi/paths/customer/location/add/index.yaml deleted file mode 100644 index b265ba51..00000000 --- a/openapi/paths/customer/location/add/index.yaml +++ /dev/null @@ -1,33 +0,0 @@ -post: - parameters: - - name: customerId - in: path - required: true - schema: - type: string - - name: locationId - in: path - required: true - schema: - type: string - tags: - - CustomerLocation - operationId: customerLocationAdd - summary: POST Add location to user - description: This endpoint add new location - - responses: - "200": - description: Response - content: - application/json: - schema: - $ref: "./response.yaml" - "400": - $ref: "../../../../responses/bad.yaml" - "401": - $ref: "../../../../responses/unauthorized.yaml" - "403": - $ref: "../../../../responses/forbidden.yaml" - - security: [] diff --git a/openapi/paths/customer/location/add/response.yaml b/openapi/paths/customer/location/add/response.yaml deleted file mode 100644 index 9d37f255..00000000 --- a/openapi/paths/customer/location/add/response.yaml +++ /dev/null @@ -1,10 +0,0 @@ -type: object -properties: - success: - type: boolean - example: true - payload: - $ref: ../../../user/_types/user.yaml -required: - - success - - payload diff --git a/openapi/paths/customer/location/get-all-origins/index.yaml b/openapi/paths/customer/location/get-all-origins/index.yaml deleted file mode 100644 index 65f96960..00000000 --- a/openapi/paths/customer/location/get-all-origins/index.yaml +++ /dev/null @@ -1,29 +0,0 @@ -get: - parameters: - - name: customerId - in: path - required: true - schema: - type: string - tags: - - CustomerLocation - operationId: customerLocationGetAllOrigins - summary: GET Get all origin locations - description: This endpoint get all origin locations - responses: - "200": - description: "Response" - content: - application/json: - schema: - $ref: "./response.yaml" - "400": - $ref: "../../../../responses/bad.yaml" - "401": - $ref: "../../../../responses/unauthorized.yaml" - "403": - $ref: "../../../../responses/forbidden.yaml" - "404": - $ref: "../../../../responses/not-found.yaml" - - security: [] diff --git a/openapi/paths/customer/location/get-all-origins/response.yaml b/openapi/paths/customer/location/get-all-origins/response.yaml deleted file mode 100644 index 001779a6..00000000 --- a/openapi/paths/customer/location/get-all-origins/response.yaml +++ /dev/null @@ -1,13 +0,0 @@ -type: object -properties: - success: - type: boolean - example: true - payload: - type: array - items: - $ref: ../_types/location.yaml - -required: - - success - - payload diff --git a/openapi/paths/customer/location/get-delete-update-add.yaml b/openapi/paths/customer/location/get-delete-update-add.yaml index e6412931..cbb229c3 100644 --- a/openapi/paths/customer/location/get-delete-update-add.yaml +++ b/openapi/paths/customer/location/get-delete-update-add.yaml @@ -2,7 +2,5 @@ get: $ref: "./get/index.yaml#/get" delete: $ref: "./remove/index.yaml#/delete" -post: - $ref: "./add/index.yaml#/post" put: $ref: "./update/index.yaml#/put" diff --git a/openapi/paths/location/validate-address/index.yaml b/openapi/paths/location/validate-address/index.yaml deleted file mode 100644 index 97efefa9..00000000 --- a/openapi/paths/location/validate-address/index.yaml +++ /dev/null @@ -1,33 +0,0 @@ -get: - parameters: - - name: name - in: query - schema: - type: string - - name: fullAddress - in: query - schema: - type: string - tags: - - Location - operationId: locationValidateAddress - summary: GET location validate address - description: This endpoint validate address - responses: - "200": - description: Response with payload - content: - application/json: - schema: - $ref: "./response.yaml" - - "400": - $ref: "../../../responses/bad.yaml" - "401": - $ref: "../../../responses/unauthorized.yaml" - "403": - $ref: "../../../responses/forbidden.yaml" - "404": - $ref: "../../../responses/not-found.yaml" - - security: [] diff --git a/openapi/paths/location/validate-address/response.yaml b/openapi/paths/location/validate-address/response.yaml deleted file mode 100644 index fbb7effb..00000000 --- a/openapi/paths/location/validate-address/response.yaml +++ /dev/null @@ -1,10 +0,0 @@ -type: object -properties: - success: - type: boolean - example: true - payload: - $ref: "../_types/coordinates.yaml" -required: - - success - - payload diff --git a/src/functions/customer-location.function.ts b/src/functions/customer-location.function.ts index 4aea38ef..a42f353e 100644 --- a/src/functions/customer-location.function.ts +++ b/src/functions/customer-location.function.ts @@ -3,23 +3,14 @@ import "module-alias/register"; import { app } from "@azure/functions"; import { - CustomerLocationControllerAdd, CustomerLocationControllerCreate, CustomerLocationControllerGetAll, - CustomerLocationControllerGetAllOrigins, CustomerLocationControllerGetOne, CustomerLocationControllerRemove, CustomerLocationControllerSetDefault, CustomerLocationControllerUpdate, } from "./customer/controllers/location"; -app.http("customerLocationGetAllOrigins", { - methods: ["GET"], - authLevel: "anonymous", - route: "customer/{customerId}/locations/get-all-origins", - handler: CustomerLocationControllerGetAllOrigins, -}); - app.http("customerLocationList", { methods: ["GET"], authLevel: "anonymous", @@ -48,13 +39,6 @@ app.http("customerLocationCreate", { handler: CustomerLocationControllerCreate, }); -app.http("customerLocationAdd", { - methods: ["POST"], - authLevel: "anonymous", - route: "customer/{customerId}/location/{locationId}", - handler: CustomerLocationControllerAdd, -}); - app.http("customerLocationRemove", { methods: ["DELETE"], authLevel: "anonymous", diff --git a/src/functions/customer/controllers/location/add.ts b/src/functions/customer/controllers/location/add.ts deleted file mode 100644 index 13006554..00000000 --- a/src/functions/customer/controllers/location/add.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { z } from "zod"; -import { CustomerLocationServiceAdd } from "~/functions/customer/services/location"; -import { LocationZodSchema } from "~/functions/location/location.types"; -import { _ } from "~/library/handler"; -import { StringOrObjectIdType } from "~/library/zod"; - -export type CustomerLocationControllerAddRequest = { - query: z.infer; -}; - -export const LocationServiceAddQuerySchema = z.object({ - locationId: StringOrObjectIdType, - customerId: LocationZodSchema.shape.customerId, -}); - -export type CustomerLocationControllerAddResponse = Awaited< - ReturnType ->; - -export const CustomerLocationControllerAdd = _( - ({ query }: CustomerLocationControllerAddRequest) => { - const validateData = LocationServiceAddQuerySchema.parse(query); - return CustomerLocationServiceAdd(validateData); - } -); diff --git a/src/functions/customer/controllers/location/create.spec.ts b/src/functions/customer/controllers/location/create.spec.ts deleted file mode 100644 index a2656bbc..00000000 --- a/src/functions/customer/controllers/location/create.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { HttpRequest, InvocationContext } from "@azure/functions"; - -import { LocationTypes } from "~/functions/location"; -import { LocationServiceValidateAddress } from "~/functions/location/services/validate-address"; -import { - HttpSuccessResponse, - createContext, - createHttpRequest, -} from "~/library/jest/azure"; -import { createUser } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { - CustomerLocationControllerCreate, - CustomerLocationControllerCreateRequest, - CustomerLocationControllerCreateResponse, -} from "./create"; - -require("~/library/jest/mongoose/mongodb.jest"); -jest.mock("~/functions/location/services/validate-address"); - -const mockedLocationServiceValidateAddress = - LocationServiceValidateAddress as jest.MockedFunction< - typeof LocationServiceValidateAddress - >; - -describe("CustomerLocationControllerCreate", () => { - let context: InvocationContext; - let request: HttpRequest; - const customerId = 123; - - beforeEach(async () => { - context = createContext(); - - await createUser({ customerId }); - - mockedLocationServiceValidateAddress.mockImplementationOnce( - async (fullAddress: string, excludeLocationId?: string) => ({ - fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", - latitude: 56.15563438, - longitude: 10.12961271, - }) - ); - }); - - it("should be able to create location origin", async () => { - request = await createHttpRequest({ - query: { - customerId, - }, - body: getLocationObject({ customerId }), - }); - - const res: HttpSuccessResponse = - await CustomerLocationControllerCreate(request, context); - - expect(res.jsonBody?.success).toBeTruthy(); - expect(res.jsonBody?.payload.locationType).toEqual(LocationTypes.ORIGIN); - }); - - it("should be able to create location destination", async () => { - request = await createHttpRequest({ - query: { - customerId, - }, - body: getLocationObject({ - customerId, - locationType: LocationTypes.DESTINATION, - }), - }); - - const res: HttpSuccessResponse = - await CustomerLocationControllerCreate(request, context); - - expect(res.jsonBody?.success).toBeTruthy(); - expect(res.jsonBody?.payload.locationType).toEqual( - LocationTypes.DESTINATION - ); - expect(res.jsonBody?.payload.distanceForFree).toBeDefined(); - }); -}); diff --git a/src/functions/customer/controllers/location/create.ts b/src/functions/customer/controllers/location/create.ts index 3a15d638..944b25fe 100644 --- a/src/functions/customer/controllers/location/create.ts +++ b/src/functions/customer/controllers/location/create.ts @@ -1,8 +1,8 @@ import { z } from "zod"; import { LocationZodSchema } from "~/functions/location/location.types"; -import { LocationServiceCreate } from "~/functions/location/services/create"; import { _ } from "~/library/handler"; +import { CustomerLocationServiceCreate } from "../../services/location/create"; export type CustomerLocationControllerCreateRequest = { query: z.infer; @@ -19,7 +19,7 @@ export const CustomerLocationControllerCreateQuerySchema = z.object({ }); export type CustomerLocationControllerCreateResponse = Awaited< - ReturnType + ReturnType >; export const CustomerLocationControllerCreate = _( @@ -29,7 +29,7 @@ export const CustomerLocationControllerCreate = _( const validateBody = CustomerLocationControllerCreateBodySchema.parse(body); - return LocationServiceCreate({ + return CustomerLocationServiceCreate({ ...validateData, ...validateBody, }); diff --git a/src/functions/customer/controllers/location/get-all-origins.ts b/src/functions/customer/controllers/location/get-all-origins.ts deleted file mode 100644 index b34add73..00000000 --- a/src/functions/customer/controllers/location/get-all-origins.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { z } from "zod"; -import { LocationZodSchema } from "~/functions/location"; -import { _ } from "~/library/handler"; -import { CustomerLocationServiceGetAllOrigins } from "../../services/location"; - -export type CustomerLocationControllerGetAllOriginsRequest = { - query: z.infer; -}; - -export const CustomerLocationServiceQuerySchema = z.object({ - customerId: LocationZodSchema.shape.customerId, -}); - -export type CustomerLocationControllerGetAllOriginsResponse = Awaited< - ReturnType ->; - -export const CustomerLocationControllerGetAllOrigins = _( - ({ query }: CustomerLocationControllerGetAllOriginsRequest) => { - const validateData = CustomerLocationServiceQuerySchema.parse(query); - return CustomerLocationServiceGetAllOrigins(validateData); - } -); diff --git a/src/functions/customer/controllers/location/get.ts b/src/functions/customer/controllers/location/get.ts index 8da5658d..a98414ad 100644 --- a/src/functions/customer/controllers/location/get.ts +++ b/src/functions/customer/controllers/location/get.ts @@ -1,8 +1,9 @@ import { z } from "zod"; -import { CustomerLocationServiceGetOne } from "~/functions/customer/services/location"; + import { LocationZodSchema } from "~/functions/location/location.types"; import { _ } from "~/library/handler"; import { StringOrObjectIdType } from "~/library/zod"; +import { CustomerLocationServiceGet } from "../../services/location/get"; export type CustomerLocationControllerGetOneRequest = { query: z.infer; @@ -14,12 +15,12 @@ export const LocationServiceGetOneQuerySchema = z.object({ }); export type CustomerLocationControllerGetOneResponse = Awaited< - ReturnType + ReturnType >; export const CustomerLocationControllerGetOne = _( ({ query }: CustomerLocationControllerGetOneRequest) => { const validateData = LocationServiceGetOneQuerySchema.parse(query); - return CustomerLocationServiceGetOne(validateData); + return CustomerLocationServiceGet(validateData); } ); diff --git a/src/functions/customer/controllers/location/index.ts b/src/functions/customer/controllers/location/index.ts index 6a74b285..6f6a3501 100644 --- a/src/functions/customer/controllers/location/index.ts +++ b/src/functions/customer/controllers/location/index.ts @@ -1,7 +1,5 @@ -export * from "./add"; export * from "./create"; export * from "./get"; -export * from "./get-all-origins"; export * from "./list"; export * from "./remove"; export * from "./set-default"; diff --git a/src/functions/customer/controllers/location/list.ts b/src/functions/customer/controllers/location/list.ts index a9efca2c..af83e69b 100644 --- a/src/functions/customer/controllers/location/list.ts +++ b/src/functions/customer/controllers/location/list.ts @@ -1,7 +1,8 @@ import { z } from "zod"; -import { CustomerLocationServiceGetAll } from "~/functions/customer/services/location"; + import { LocationZodSchema } from "~/functions/location/location.types"; import { _ } from "~/library/handler"; +import { CustomerLocationServiceList } from "../../services/location/list"; export type CustomerLocationControllerGetAllRequest = { query: z.infer; @@ -12,13 +13,13 @@ export const CustomerLocationControllerGetAllQuerySchema = z.object({ }); export type CustomerLocationControllerGetAllResponse = Awaited< - ReturnType + ReturnType >; export const CustomerLocationControllerGetAll = _( ({ query }: CustomerLocationControllerGetAllRequest) => { const validateData = CustomerLocationControllerGetAllQuerySchema.parse(query); - return CustomerLocationServiceGetAll(validateData); + return CustomerLocationServiceList(validateData); } ); diff --git a/src/functions/customer/controllers/location/remove.ts b/src/functions/customer/controllers/location/remove.ts index e4699cc7..46813284 100644 --- a/src/functions/customer/controllers/location/remove.ts +++ b/src/functions/customer/controllers/location/remove.ts @@ -1,8 +1,9 @@ import { z } from "zod"; -import { CustomerLocationServiceRemove } from "~/functions/customer/services/location"; + import { LocationZodSchema } from "~/functions/location/location.types"; import { _ } from "~/library/handler"; import { StringOrObjectIdType } from "~/library/zod"; +import { CustomerLocationServiceDestroy } from "../../services/location/destroy"; export type CustomerLocationControllerRemoveRequest = { query: z.infer; @@ -14,12 +15,12 @@ export const LocationServiceRemoveQuerySchema = z.object({ }); export type CustomerLocationControllerRemoveResponse = Awaited< - ReturnType + ReturnType >; export const CustomerLocationControllerRemove = _( ({ query }: CustomerLocationControllerRemoveRequest) => { const validateData = LocationServiceRemoveQuerySchema.parse(query); - return CustomerLocationServiceRemove(validateData); + return CustomerLocationServiceDestroy(validateData); } ); diff --git a/src/functions/customer/controllers/location/set-default.ts b/src/functions/customer/controllers/location/set-default.ts index 38486a05..56494acf 100644 --- a/src/functions/customer/controllers/location/set-default.ts +++ b/src/functions/customer/controllers/location/set-default.ts @@ -1,8 +1,8 @@ import { z } from "zod"; -import { CustomerLocationServiceSetDefault } from "~/functions/customer/services/location"; import { LocationZodSchema } from "~/functions/location/location.types"; import { _ } from "~/library/handler"; import { StringOrObjectIdType } from "~/library/zod"; +import { CustomerLocationServiceSetDefault } from "../../services/location/set-default"; export type CustomerLocationControllerSetDefaultRequest = { query: z.infer; diff --git a/src/functions/customer/controllers/location/update.spec.ts b/src/functions/customer/controllers/location/update.spec.ts deleted file mode 100644 index 138eee14..00000000 --- a/src/functions/customer/controllers/location/update.spec.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { HttpRequest, InvocationContext } from "@azure/functions"; - -import { LocationTypes } from "~/functions/location"; -import { LocationServiceValidateAddress } from "~/functions/location/services/validate-address"; -import { - HttpSuccessResponse, - createContext, - createHttpRequest, -} from "~/library/jest/azure"; -import { createUser } from "~/library/jest/helpers"; -import { - createLocation, - getLocationObject, -} from "~/library/jest/helpers/location"; -import { - CustomerLocationControllerUpdate, - CustomerLocationControllerUpdateRequest, - CustomerLocationControllerUpdateResponse, -} from "./update"; - -require("~/library/jest/mongoose/mongodb.jest"); - -jest.mock("~/functions/location/services/validate-address"); - -const mockedLocationServiceValidateAddress = - LocationServiceValidateAddress as jest.MockedFunction< - typeof LocationServiceValidateAddress - >; - -describe("CustomerLocationControllerUpdate", () => { - let context: InvocationContext; - let request: HttpRequest; - const customerId = 123; - - beforeEach(async () => { - context = createContext(); - - await createUser({ customerId }); - - mockedLocationServiceValidateAddress.mockImplementationOnce( - async (fullAddress: string, excludeLocationId?: string) => ({ - fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", - latitude: 56.15563438, - longitude: 10.12961271, - }) - ); - }); - - it("should be able to update location origin", async () => { - const location = await createLocation({ customerId }); - const { - customerId: x, - locationType, - ...locationBody - } = getLocationObject({ - customerId, - }); - - request = await createHttpRequest({ - query: { - customerId, - locationId: location._id, - }, - body: locationBody, - }); - - const res: HttpSuccessResponse = - await CustomerLocationControllerUpdate(request, context); - - expect(res.jsonBody?.success).toBeTruthy(); - expect(res.jsonBody?.payload.locationType).toEqual(LocationTypes.ORIGIN); - - expect(res.jsonBody?.payload).toMatchObject({ - ...locationBody, - fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", - }); - }); - - it("should be able to update location destination", async () => { - const location = await createLocation({ - customerId, - locationType: LocationTypes.DESTINATION, - }); - const { - customerId: x, - locationType, - ...locationBody - } = getLocationObject({ - customerId, - locationType: LocationTypes.DESTINATION, - }); - - request = await createHttpRequest({ - query: { - customerId, - locationId: location._id, - }, - body: locationBody, - }); - - const res: HttpSuccessResponse = - await CustomerLocationControllerUpdate(request, context); - - expect(res.jsonBody?.success).toBeTruthy(); - expect(res.jsonBody?.payload.locationType).toEqual( - LocationTypes.DESTINATION - ); - expect(res.jsonBody?.payload.distanceForFree).toBeDefined(); - - expect(res.jsonBody?.payload).toMatchObject({ - ...locationBody, - fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", - }); - }); -}); diff --git a/src/functions/customer/controllers/location/update.ts b/src/functions/customer/controllers/location/update.ts index ed5f4793..193a28b8 100644 --- a/src/functions/customer/controllers/location/update.ts +++ b/src/functions/customer/controllers/location/update.ts @@ -1,9 +1,9 @@ import { z } from "zod"; import { LocationZodSchema } from "~/functions/location/location.types"; -import { LocationServiceUpdate } from "~/functions/location/services/update"; import { _ } from "~/library/handler"; import { StringOrObjectIdType } from "~/library/zod"; +import { CustomerLocationServiceUpdate } from "../../services/location/update"; // should be PATCH and UPSERT export type CustomerLocationControllerUpdateRequest = { @@ -23,7 +23,7 @@ export const CustomerLocationControllerUpdateQuerySchema = z.object({ }); export type CustomerLocationControllerUpdateResponse = Awaited< - ReturnType + ReturnType >; export const CustomerLocationControllerUpdate = _( @@ -33,6 +33,6 @@ export const CustomerLocationControllerUpdate = _( const validateBody = CustomerLocationControllerUpdateBodySchema.parse(body) || {}; - return LocationServiceUpdate(validateData, validateBody); + return CustomerLocationServiceUpdate(validateData, validateBody); } ); diff --git a/src/functions/customer/services/customer.ts b/src/functions/customer/services/customer.ts index 418748e5..c506af01 100644 --- a/src/functions/customer/services/customer.ts +++ b/src/functions/customer/services/customer.ts @@ -80,6 +80,7 @@ export const CustomerServiceStatus = async ({ const user = await UserModel.findOne({ customerId }); if (user) { const schedule = await ScheduleModel.count({ customerId }); + const locations = await ScheduleModel.count({ customerId }); const services = await ScheduleModel.count({ customerId, "products.0": { $exists: true }, @@ -91,7 +92,7 @@ export const CustomerServiceStatus = async ({ return { profile: aboutMe && shortDescription && professions, - locations: user.locations && user.locations?.length > 0, + locations: locations > 0, schedules: schedule > 0, services: services > 0, profileImage: user.images?.profile?.url !== undefined, diff --git a/src/functions/customer/services/location.spec.ts b/src/functions/customer/services/location.spec.ts deleted file mode 100644 index cd080fe7..00000000 --- a/src/functions/customer/services/location.spec.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { faker } from "@faker-js/faker"; -import { - Location, - LocationModel, - LocationOriginTypes, - LocationTypes, -} from "~/functions/location"; - -import { LocationServiceCreate } from "~/functions/location/services/create"; -import { createUser } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { CustomerServiceGet } from "./customer"; -import { - CustomerLocationServiceCreate, - CustomerLocationServiceGetAll, - CustomerLocationServiceGetAllOrigins, - CustomerLocationServiceGetOne, - CustomerLocationServiceRemove, - CustomerLocationServiceSetDefault, -} from "./location"; - -require("~/library/jest/mongoose/mongodb.jest"); - -jest.mock("~/functions/location/services/create"); -const mockedLocationServiceCreate = - LocationServiceCreate as jest.MockedFunction; - -describe("CustomerLocationService", () => { - const customerId = faker.number.int(); - - const location1: Location = getLocationObject({ - locationType: LocationTypes.ORIGIN, - originType: LocationOriginTypes.COMMERCIAL, - customerId, - }); - - const location2: Location = getLocationObject({ - locationType: LocationTypes.ORIGIN, - originType: LocationOriginTypes.COMMERCIAL, - customerId, - }); - - const location3: Location = getLocationObject({ - locationType: LocationTypes.DESTINATION, - originType: LocationOriginTypes.COMMERCIAL, - customerId, - }); - - beforeEach(() => { - jest.clearAllMocks(); - return createUser({ customerId }); - }); - - it("Should be able to get one location for user", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location3, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - await CustomerLocationServiceCreate(location1); - const location3doc = await CustomerLocationServiceCreate(location3); - - const user = await CustomerServiceGet({ customerId }); - const location = await CustomerLocationServiceGetOne({ - locationId: location3doc._id.toString(), - customerId: user.customerId, - }); - - expect(location).toBeDefined(); - expect(location?.distanceHourlyRate).toEqual(location3.distanceHourlyRate); - expect(location?.isDefault).toBeFalsy(); - }); - - it("Should be able to get all locations for user", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location3, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - await CustomerLocationServiceCreate(location1); - await CustomerLocationServiceCreate(location3); - - const user = await CustomerServiceGet({ customerId }); - - const locations = await CustomerLocationServiceGetAll({ - customerId: user.customerId, - }); - - const location = locations.find((l) => l.isDefault); - - expect(location).toBeDefined(); - expect(locations).toHaveLength(2); - }); - - it("Should be able create location and add to user", async () => { - mockedLocationServiceCreate.mockImplementation(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - const response = await CustomerLocationServiceCreate(location1); - - const user = await CustomerServiceGet({ customerId }); - const firstLocation = user.locations?.find( - (loc) => loc.location.toString() === response._id.toString() - ); - - expect(firstLocation).toBeDefined(); - expect(firstLocation?.isDefault).toBeTruthy(); - expect(user.locations).toHaveLength(1); - }); - - it("Should be able create additional location and add to user", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location2, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - await CustomerLocationServiceCreate(location1); - const response = await CustomerLocationServiceCreate(location2); - - const user = await CustomerServiceGet({ customerId }); - const secondLocation = user.locations?.find( - (loc) => loc.location.toString() === response._id.toString() - ); - - expect(secondLocation).toBeDefined(); - expect(secondLocation?.isDefault).toBeFalsy(); - expect(user.locations).toHaveLength(2); - }); - - it("Should be able move default to another one when default is removed", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location2, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - const location1doc = await CustomerLocationServiceCreate(location1); - const location2doc = await CustomerLocationServiceCreate(location2); - - await CustomerLocationServiceRemove({ - locationId: location1doc._id.toString(), - customerId: location1doc.customerId, - }); - - const user = await CustomerServiceGet({ customerId }); - const secondLocation = user.locations?.find( - (loc) => loc.location.toString() === location2doc._id.toString() - ); - - expect(secondLocation?.isDefault).toBeTruthy(); - expect(user.locations).toHaveLength(1); - }); - - it("Should be able to set new default location", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location2, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - const location1doc = await CustomerLocationServiceCreate(location1); - const location2doc = await CustomerLocationServiceCreate(location2); - - await CustomerLocationServiceSetDefault({ - locationId: location2doc._id.toString(), - customerId: location2doc.customerId, - }); - - const user = await CustomerServiceGet({ customerId }); - const secondLocation = user.locations?.find( - (loc) => loc.location.toString() === location2doc._id.toString() - ); - - expect(secondLocation?.isDefault).toBeTruthy(); - expect(user.locations).toHaveLength(2); - }); - - it("should be able to get all origins", async () => { - await createUser({ customerId: 2 }); - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location2, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - customerId: 2, - }) - ); - - await CustomerLocationServiceCreate(location1); - await CustomerLocationServiceCreate({ ...location2, customerId: 2 }); - - const response = await CustomerLocationServiceGetAllOrigins(location1); - expect(response).toHaveLength(1); - }); -}); diff --git a/src/functions/customer/services/location.ts b/src/functions/customer/services/location.ts deleted file mode 100644 index 19642383..00000000 --- a/src/functions/customer/services/location.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - ILocationDocument, - Location, - LocationModel, - LocationTypes, -} from "~/functions/location"; - -import { - LocationServiceCreate, - LocationServiceCreateProps, -} from "~/functions/location/services/create"; -import { - LocationServiceUpdate, - LocationUpdateBody, - LocationUpdateFilterProps, -} from "~/functions/location/services/update"; -import { - UserModel, - UserServiceGetLocations, - UserServiceLocationsAdd, - UserServiceLocationsRemove, - UserServiceLocationsSetDefault, -} from "~/functions/user"; -import { NotFoundError } from "~/library/handler"; -import { CustomerProductServiceRemoveLocationFromAll } from "./product/remove-location-from-all"; - -export const CustomerLocationServiceCreate = async ( - body: LocationServiceCreateProps -) => { - const location = await LocationServiceCreate(body); - await UserServiceLocationsAdd({ - _id: location._id.toString(), - customerId: location.customerId, - }); - return location; -}; - -export const CustomerLocationServiceUpdate = ( - filter: LocationUpdateFilterProps, - body: LocationUpdateBody -) => { - return LocationServiceUpdate(filter, body); -}; - -export type CustomerLocationServiceProps = { - locationId: ILocationDocument["_id"]; - customerId: Location["customerId"]; -}; - -export const CustomerLocationServiceSetDefault = ( - location: CustomerLocationServiceProps -) => { - return UserServiceLocationsSetDefault({ - _id: location.locationId, - customerId: location.customerId, - }); -}; - -export const CustomerLocationServiceAdd = ( - location: CustomerLocationServiceProps -) => { - return UserServiceLocationsAdd({ - _id: location.locationId, - customerId: location.customerId, - }); -}; - -export const CustomerLocationServiceRemove = async ( - location: CustomerLocationServiceProps -) => { - await CustomerProductServiceRemoveLocationFromAll({ - locationId: location.locationId.toString(), - customerId: location.customerId, - }); - return UserServiceLocationsRemove(location); -}; - -export const CustomerLocationServiceGetAll = ( - props: Pick -) => { - return UserServiceGetLocations(props); -}; - -export const CustomerLocationServiceGetOne = async ( - props: CustomerLocationServiceProps -) => { - const locations = await UserServiceGetLocations(props); - const location = locations.find( - (l) => l.location.toString() === props.locationId.toString() - ); - if (!location) { - new NotFoundError([ - { - path: ["locationId", "customerId"], - message: "LOCATION_NOT_FOUND_IN_USER", - code: "custom", - }, - ]); - } - return location; -}; - -export const CustomerLocationServiceGetAllOrigins = async ({ - customerId, -}: Pick) => { - const user = await UserModel.findOne({ customerId }); - return LocationModel.find({ - _id: { $nin: user?.locations?.map((l) => l.location) }, - locationType: LocationTypes.ORIGIN, - }); -}; diff --git a/src/functions/customer/services/location/create.spec.ts b/src/functions/customer/services/location/create.spec.ts new file mode 100644 index 00000000..41e1afc2 --- /dev/null +++ b/src/functions/customer/services/location/create.spec.ts @@ -0,0 +1,91 @@ +import { LocationOriginTypes, LocationTypes } from "~/functions/location"; +import { LocationServiceGetCoordinates } from "~/functions/location/services/get-coordinates"; +import { omitObjectIdProps } from "~/library/jest/helpers"; +import { getLocationObject } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceCreate } from "./create"; + +require("~/library/jest/mongoose/mongodb.jest"); + +jest.mock("~/functions/location/services/get-coordinates", () => ({ + LocationServiceGetCoordinates: jest.fn(), +})); + +type LocationServiceGetCoordinatesMock = jest.Mock< + Promise<{ + longitude: number; + latitude: number; + fullAddress: string; + }> +>; + +const mockGetCoordinates = + LocationServiceGetCoordinates as LocationServiceGetCoordinatesMock; + +const customerId = 1; + +describe("CustomerLocationServiceCreate", () => { + beforeEach(() => { + mockGetCoordinates.mockClear(); + }); + + it("create should be able to create origin", async () => { + mockGetCoordinates.mockResolvedValue({ + longitude: 10.12961271, + latitude: 56.15563438, + fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", + }); + + const response = await CustomerLocationServiceCreate( + getLocationObject({ + name: "Falafel", + fullAddress: "Sigridsvej 45 1, 8220 Brabrand", + originType: LocationOriginTypes.COMMERCIAL, + locationType: LocationTypes.ORIGIN, + customerId, + distanceHourlyRate: 1, + fixedRatePerKm: 10, + distanceForFree: 10, + }) + ); + + expect(omitObjectIdProps(response.toObject())).toEqual( + expect.objectContaining({ + locationType: LocationTypes.ORIGIN, + customerId: 1, + fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", + geoLocation: { coordinates: [10.12961271, 56.15563438], type: "Point" }, + }) + ); + }); + + it("create should be able to create destination", async () => { + mockGetCoordinates.mockResolvedValue({ + longitude: 123.45, + latitude: 67.89, + fullAddress: "Sigridsvej 45 1, 8220 Brabrand", + }); + + const response = await CustomerLocationServiceCreate( + getLocationObject({ + name: "remote", + fullAddress: "Sigridsvej 45 1, 8220 Brabrand", + locationType: LocationTypes.DESTINATION, + originType: LocationOriginTypes.COMMERCIAL, + distanceHourlyRate: 1, + fixedRatePerKm: 10, + distanceForFree: 10, + customerId, + }) + ); + + expect(omitObjectIdProps(response.toObject())).toEqual( + expect.objectContaining({ + locationType: LocationTypes.DESTINATION, + customerId: 1, + distanceHourlyRate: 1, + fixedRatePerKm: 10, + distanceForFree: 10, + }) + ); + }); +}); diff --git a/src/functions/customer/services/location/create.ts b/src/functions/customer/services/location/create.ts new file mode 100644 index 00000000..4bb0a0da --- /dev/null +++ b/src/functions/customer/services/location/create.ts @@ -0,0 +1,23 @@ +import { Location, LocationModel } from "~/functions/location"; +import { LocationServiceGetCoordinates } from "~/functions/location/services/get-coordinates"; + +export type LocationServiceCreateProps = Location; + +export const CustomerLocationServiceCreate = async ( + body: LocationServiceCreateProps +) => { + const result = await LocationServiceGetCoordinates(body); + const location = new LocationModel(body); + location.geoLocation.type = "Point"; + location.geoLocation.coordinates = [result.longitude, result.latitude]; + location.fullAddress = result.fullAddress; + location.handle = createSlug(body.name); + return location.save(); +}; + +function createSlug(name: string) { + return name + .toLowerCase() + .replace(/[^\w ]+/g, "") + .replace(/ +/g, "-"); +} diff --git a/src/functions/customer/services/location/destroy.spec.ts b/src/functions/customer/services/location/destroy.spec.ts new file mode 100644 index 00000000..c9970bd0 --- /dev/null +++ b/src/functions/customer/services/location/destroy.spec.ts @@ -0,0 +1,34 @@ +import { faker } from "@faker-js/faker"; + +import { createLocation } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceDestroy } from "./destroy"; +import { CustomerLocationServiceGet } from "./get"; + +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerLocationServiceDestroy", () => { + it("Should be able to destroy location", async () => { + const customerId = faker.number.int(); + + const document = await createLocation({ customerId }); + + let location = await CustomerLocationServiceGet({ + locationId: document._id.toString(), + customerId: customerId, + }); + + expect(location).toBeDefined(); + + await CustomerLocationServiceDestroy({ + locationId: document._id.toString(), + customerId: customerId, + }); + + await expect( + CustomerLocationServiceGet({ + locationId: document._id.toString(), + customerId: customerId, + }) + ).rejects.toThrow(); + }); +}); diff --git a/src/functions/customer/services/location/destroy.ts b/src/functions/customer/services/location/destroy.ts new file mode 100644 index 00000000..5e247ca9 --- /dev/null +++ b/src/functions/customer/services/location/destroy.ts @@ -0,0 +1,30 @@ +import { LocationModel } from "~/functions/location"; +import { StringOrObjectId } from "~/library/zod"; +import { CustomerProductServiceRemoveLocationFromAll } from "../product/remove-location-from-all"; + +export type CustomerLocationServiceDestroyProps = { + locationId: StringOrObjectId; + customerId: number; +}; + +/* + * choose another default if the deleted is default? + */ +export const CustomerLocationServiceDestroy = async ( + props: CustomerLocationServiceDestroyProps +) => { + await CustomerProductServiceRemoveLocationFromAll({ + locationId: props.locationId.toString(), + customerId: props.customerId, + }); + + return LocationModel.updateOne( + { + _id: props.locationId, + customerId: props.customerId, + }, + { + deletedAt: new Date(), + } + ); +}; diff --git a/src/functions/customer/services/location/get.spec.ts b/src/functions/customer/services/location/get.spec.ts new file mode 100644 index 00000000..bcebe348 --- /dev/null +++ b/src/functions/customer/services/location/get.spec.ts @@ -0,0 +1,21 @@ +import { faker } from "@faker-js/faker"; + +import { createLocation } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceGet } from "./get"; + +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerLocationServiceGet", () => { + it("Should be able to get location", async () => { + const customerId = faker.number.int(); + + const document = await createLocation({ customerId }); + + let location = await CustomerLocationServiceGet({ + locationId: document._id.toString(), + customerId: customerId, + }); + + expect(location).toBeDefined(); + }); +}); diff --git a/src/functions/customer/services/location/get.ts b/src/functions/customer/services/location/get.ts new file mode 100644 index 00000000..ed6ad041 --- /dev/null +++ b/src/functions/customer/services/location/get.ts @@ -0,0 +1,27 @@ +import { LocationModel } from "~/functions/location"; + +import { NotFoundError } from "~/library/handler"; +import { StringOrObjectId } from "~/library/zod"; + +export type CustomerLocationServiceGetProps = { + locationId: StringOrObjectId; + customerId: number; +}; + +export const CustomerLocationServiceGet = async ( + props: CustomerLocationServiceGetProps +) => { + return LocationModel.findOne({ + _id: props.locationId, + customerId: props.customerId, + deletedAt: null, + }).orFail( + new NotFoundError([ + { + path: ["locationId", "customerId"], + message: "LOCATION_NOT_FOUND_IN_USER", + code: "custom", + }, + ]) + ); +}; diff --git a/src/functions/customer/services/location/list.spec.ts b/src/functions/customer/services/location/list.spec.ts new file mode 100644 index 00000000..017d6f49 --- /dev/null +++ b/src/functions/customer/services/location/list.spec.ts @@ -0,0 +1,22 @@ +import { faker } from "@faker-js/faker"; + +import { createLocation } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceList } from "./list"; + +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerLocationServiceList", () => { + it("Should be able to get all locations for user", async () => { + const customerId = faker.number.int(); + + await createLocation({ customerId }); + await createLocation({ customerId }); + await createLocation({ customerId }); + + const locations = await CustomerLocationServiceList({ + customerId, + }); + + expect(locations).toHaveLength(3); + }); +}); diff --git a/src/functions/customer/services/location/list.ts b/src/functions/customer/services/location/list.ts new file mode 100644 index 00000000..e1d8f9ae --- /dev/null +++ b/src/functions/customer/services/location/list.ts @@ -0,0 +1,11 @@ +import { LocationModel } from "~/functions/location"; + +export type CustomerLocationServiceListProps = { + customerId: number; +}; + +export const CustomerLocationServiceList = ( + props: CustomerLocationServiceListProps +) => { + return LocationModel.find(props); +}; diff --git a/src/functions/customer/services/location/set-default.spec.ts b/src/functions/customer/services/location/set-default.spec.ts new file mode 100644 index 00000000..32ba0566 --- /dev/null +++ b/src/functions/customer/services/location/set-default.spec.ts @@ -0,0 +1,27 @@ +import { faker } from "@faker-js/faker"; + +import { createLocation } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceGet } from "./get"; +import { CustomerLocationServiceSetDefault } from "./set-default"; + +require("~/library/jest/mongoose/mongodb.jest"); + +describe("CustomerLocationServiceDestroy", () => { + it("Should be able to destroy location", async () => { + const customerId = faker.number.int(); + + const document = await createLocation({ customerId }); + + await CustomerLocationServiceSetDefault({ + locationId: document._id.toString(), + customerId: customerId, + }); + + const location = await CustomerLocationServiceGet({ + locationId: document._id.toString(), + customerId: customerId, + }); + + expect(location.isDefault).toBe(true); + }); +}); diff --git a/src/functions/customer/services/location/set-default.ts b/src/functions/customer/services/location/set-default.ts new file mode 100644 index 00000000..c454157c --- /dev/null +++ b/src/functions/customer/services/location/set-default.ts @@ -0,0 +1,33 @@ +import { + ILocationDocument, + Location, + LocationModel, +} from "~/functions/location"; +import { NotFoundError } from "~/library/handler"; + +export type CustomerLocationServiceProps = { + locationId: ILocationDocument["_id"]; + customerId: Location["customerId"]; +}; + +export const CustomerLocationServiceSetDefault = ( + location: CustomerLocationServiceProps +) => { + return LocationModel.updateOne( + { + _id: location.locationId, + customerId: location.customerId, + }, + { + isDefault: true, + } + ).orFail( + new NotFoundError([ + { + code: "custom", + message: "LOCATION_NOT_FOUND", + path: ["location"], + }, + ]) + ); +}; diff --git a/src/functions/customer/services/location/update.spec.ts b/src/functions/customer/services/location/update.spec.ts new file mode 100644 index 00000000..02e09e68 --- /dev/null +++ b/src/functions/customer/services/location/update.spec.ts @@ -0,0 +1,52 @@ +import { faker } from "@faker-js/faker"; +import { LocationServiceGetCoordinates } from "~/functions/location/services/get-coordinates"; +import { createLocation } from "~/library/jest/helpers/location"; +import { CustomerLocationServiceUpdate } from "./update"; + +require("~/library/jest/mongoose/mongodb.jest"); + +jest.mock("~/functions/location/services/get-coordinates", () => ({ + LocationServiceGetCoordinates: jest.fn(), +})); + +type LocationServiceGetCoordinatesMock = jest.Mock< + Promise<{ + longitude: number; + latitude: number; + fullAddress: string; + }> +>; + +const mockGetCoordinates = + LocationServiceGetCoordinates as LocationServiceGetCoordinatesMock; + +describe("CustomerLocationServiceUpdate", () => { + beforeEach(() => { + mockGetCoordinates.mockClear(); + }); + + it("update should be able to update destination", async () => { + const customerId = faker.number.int(); + + const document = await createLocation({ customerId }); + + mockGetCoordinates.mockResolvedValue({ + longitude: 10.12961271, + latitude: 56.15563438, + fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", + }); + + const update = await CustomerLocationServiceUpdate( + { locationId: document._id, customerId }, + { + name: "test", + fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", + distanceHourlyRate: 5, + fixedRatePerKm: 5, + distanceForFree: 5, + } + ); + + expect(update.geoLocation.coordinates).toEqual([10.12961271, 56.15563438]); + }); +}); diff --git a/src/functions/customer/services/location/update.ts b/src/functions/customer/services/location/update.ts new file mode 100644 index 00000000..f8130c39 --- /dev/null +++ b/src/functions/customer/services/location/update.ts @@ -0,0 +1,49 @@ +import mongoose from "mongoose"; +import { ILocation, LocationModel } from "~/functions/location"; +import { LocationServiceGetCoordinates } from "~/functions/location/services/get-coordinates"; +import { NotFoundError } from "~/library/handler"; +import { StringOrObjectId } from "~/library/zod"; + +export type CustomerLocationUpdateFilterProps = { + locationId: StringOrObjectId; + customerId: number; +}; + +export type CustomerLocationUpdateBody = Partial; + +export const CustomerLocationServiceUpdate = async ( + filter: CustomerLocationUpdateFilterProps, + body: CustomerLocationUpdateBody +) => { + if (body.fullAddress) { + const result = await LocationServiceGetCoordinates({ + fullAddress: body.fullAddress, + }); + + body = { + ...body, + fullAddress: result.fullAddress, + geoLocation: { + type: "Point", + coordinates: [result.longitude, result.latitude], + }, + }; + } + + return LocationModel.findOneAndUpdate( + { + _id: new mongoose.Types.ObjectId(filter.locationId), + customerId: filter.customerId, + }, + body, + { new: true } + ).orFail( + new NotFoundError([ + { + code: "custom", + message: "LOCATION_NOT_FOUND", + path: ["location"], + }, + ]) + ); +}; diff --git a/src/functions/location/controllers/index.ts b/src/functions/location/controllers/index.ts index 725df026..4e6cb044 100644 --- a/src/functions/location/controllers/index.ts +++ b/src/functions/location/controllers/index.ts @@ -1,3 +1,2 @@ export * from "./get-coordinates"; export * from "./get-travel-time"; -export * from "./validate-address"; diff --git a/src/functions/location/controllers/validate-address.ts b/src/functions/location/controllers/validate-address.ts deleted file mode 100644 index 2f48dc41..00000000 --- a/src/functions/location/controllers/validate-address.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { z } from "zod"; -import { _ } from "~/library/handler"; -import { LocationZodSchema } from "../location.types"; -import { LocationServiceValidateAddress } from "../services/validate-address"; - -export type LocationControllerValidateAddressRequest = { - query: z.infer; -}; - -export const LocationServiceValidateAddressSchema = LocationZodSchema.pick({ - fullAddress: true, -}); - -export type LocationControllerValidateAddressResponse = Awaited< - ReturnType ->; - -export const LocationControllerValidateAddress = _( - ({ query }: LocationControllerValidateAddressRequest) => { - const validateData = LocationServiceValidateAddressSchema.parse(query); - return LocationServiceValidateAddress(validateData.fullAddress); - } -); diff --git a/src/functions/location/index.ts b/src/functions/location/index.ts index f80f6fdb..cd911600 100644 --- a/src/functions/location/index.ts +++ b/src/functions/location/index.ts @@ -1,4 +1,4 @@ export * from "./controllers"; export * from "./location.model"; +export * from "./location.schema"; export * from "./location.types"; -export * from "./schemas"; diff --git a/src/functions/location/location.model.ts b/src/functions/location/location.model.ts index 5700cf06..5d339479 100644 --- a/src/functions/location/location.model.ts +++ b/src/functions/location/location.model.ts @@ -1,5 +1,5 @@ import { Model, model } from "mongoose"; -import { ILocationDocument, LocationMongooseSchema } from "./schemas"; +import { ILocationDocument, LocationMongooseSchema } from "./location.schema"; export const LocationModel = model>( "location", diff --git a/src/functions/location/schemas/location.schema.ts b/src/functions/location/location.schema.ts similarity index 89% rename from src/functions/location/schemas/location.schema.ts rename to src/functions/location/location.schema.ts index 7fc5c913..fedbe028 100644 --- a/src/functions/location/schemas/location.schema.ts +++ b/src/functions/location/location.schema.ts @@ -1,9 +1,5 @@ import mongoose, { Document, Model } from "mongoose"; -import { - Location, - LocationOriginTypes, - LocationTypes, -} from "../location.types"; +import { Location, LocationOriginTypes, LocationTypes } from "./location.types"; export interface ILocation extends Location { geoLocation: { @@ -22,6 +18,7 @@ export const LocationMongooseSchema = new mongoose.Schema< Model >( { + isDefault: { type: Boolean, default: false }, locationType: { type: String, enum: [LocationTypes.DESTINATION, LocationTypes.ORIGIN], @@ -85,6 +82,10 @@ export const LocationMongooseSchema = new mongoose.Schema< type: String, unique: true, }, + deletedAt: { + type: Date, + default: null, + }, }, { timestamps: true } ); diff --git a/src/functions/location/location.types.ts b/src/functions/location/location.types.ts index f04b5d4a..913a39eb 100644 --- a/src/functions/location/location.types.ts +++ b/src/functions/location/location.types.ts @@ -1,5 +1,9 @@ import { z } from "zod"; -import { GidFormat, NumberOrStringType } from "~/library/zod"; +import { + BooleanOrStringType, + GidFormat, + NumberOrStringType, +} from "~/library/zod"; export enum LocationTypes { ORIGIN = "origin", @@ -11,6 +15,7 @@ export enum LocationOriginTypes { COMMERCIAL = "commercial", } export const LocationZodSchema = z.object({ + isDefault: BooleanOrStringType, locationType: z.nativeEnum(LocationTypes), customerId: GidFormat, name: z.string(), @@ -22,6 +27,7 @@ export const LocationZodSchema = z.object({ minDriveDistance: NumberOrStringType, maxDriveDistance: NumberOrStringType, startFee: NumberOrStringType, + deletedAt: z.coerce.date().optional(), }); export type Location = z.infer; diff --git a/src/functions/location/schemas/index.ts b/src/functions/location/schemas/index.ts deleted file mode 100644 index fc5af74f..00000000 --- a/src/functions/location/schemas/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./location.schema"; diff --git a/src/functions/location/services/create.spec.ts b/src/functions/location/services/create.spec.ts deleted file mode 100644 index 876dacbf..00000000 --- a/src/functions/location/services/create.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import axios from "axios"; -import { createUser, omitObjectIdProps } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { - Location, - LocationOriginTypes, - LocationTypes, -} from "../location.types"; -import { LocationServiceCreate } from "./create"; -import { ForsyningResponse } from "./get-coordinates"; - -require("~/library/jest/mongoose/mongodb.jest"); -jest.mock("axios"); - -const mockedAxios = axios as jest.Mocked; - -const customerId = 1; -const getCoordinatesData: ForsyningResponse = [ - { - id: "", - adressebetegnelse: "Sigridsvej 45, 1. th, 8220 Brabrand", - adgangsadresse: { - adgangspunkt: { - koordinater: [10.12961271, 56.15563438], - }, - }, - }, -]; - -const originData: Location = getLocationObject({ - name: "Falafel", - fullAddress: "Sigridsvej 45 1, 8220 Brabrand", - originType: LocationOriginTypes.COMMERCIAL, - locationType: LocationTypes.ORIGIN, - customerId, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, -}); - -const destinationData: Location = getLocationObject({ - name: "remote", - fullAddress: "Sigridsvej 45 1, 8220 Brabrand", - locationType: LocationTypes.DESTINATION, - originType: LocationOriginTypes.COMMERCIAL, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, - customerId, -}); - -describe("LocationServiceCreate", () => { - afterEach(() => { - mockedAxios.get.mockClear(); - mockedAxios.get.mockReset(); - }); - - beforeEach(() => { - return createUser({ customerId }); - }); - - it("create should be able to create origin", async () => { - mockedAxios.get.mockResolvedValueOnce({ - data: getCoordinatesData, - }); - - const response = await LocationServiceCreate(originData); - - expect(omitObjectIdProps(response.toObject())).toEqual( - expect.objectContaining({ - locationType: LocationTypes.ORIGIN, - customerId: 1, - fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand", - geoLocation: { coordinates: [10.12961271, 56.15563438], type: "Point" }, - }) - ); - }); - - it("create should be able to create destination", async () => { - mockedAxios.get.mockResolvedValueOnce({ - data: getCoordinatesData, - }); - - const response = await LocationServiceCreate(destinationData); - - expect(omitObjectIdProps(response.toObject())).toEqual( - expect.objectContaining({ - locationType: LocationTypes.DESTINATION, - customerId: 1, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, - }) - ); - }); -}); diff --git a/src/functions/location/services/create.ts b/src/functions/location/services/create.ts deleted file mode 100644 index 46cbed47..00000000 --- a/src/functions/location/services/create.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { UserServiceLocationsAdd } from "~/functions/user"; -import { LocationModel } from "../location.model"; -import { Location } from "../location.types"; -import { LocationServiceValidateAddress } from "./validate-address"; - -export type LocationServiceCreateProps = Location; - -export const LocationServiceCreate = async ( - body: LocationServiceCreateProps -) => { - let result = await LocationServiceValidateAddress(body.fullAddress); - const location = new LocationModel(body); - location.geoLocation.type = "Point"; - location.geoLocation.coordinates = [result.longitude, result.latitude]; - location.fullAddress = result.fullAddress; - location.handle = createSlug(body.name); - const newLocationDoc = await location.save(); - await UserServiceLocationsAdd({ - _id: newLocationDoc._id.toString(), - customerId: newLocationDoc.customerId, - }); - return newLocationDoc; -}; - -function createSlug(name: string) { - return name - .toLowerCase() - .replace(/[^\w ]+/g, "") - .replace(/ +/g, "-"); -} diff --git a/src/functions/location/services/update.spec.ts b/src/functions/location/services/update.spec.ts deleted file mode 100644 index 03e4bbb7..00000000 --- a/src/functions/location/services/update.spec.ts +++ /dev/null @@ -1,152 +0,0 @@ -import axios from "axios"; -import { createUser } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { - Location, - LocationOriginTypes, - LocationTypes, -} from "../location.types"; -import { LocationServiceCreate } from "./create"; -import { ForsyningResponse } from "./get-coordinates"; -import { LocationServiceUpdate } from "./update"; - -require("~/library/jest/mongoose/mongodb.jest"); -jest.mock("axios"); - -const mockedAxios = axios as jest.Mocked; - -const customerId = 1; -const getCoordinatesData: ForsyningResponse = [ - { - id: "", - adressebetegnelse: "Sigridsvej 45, 1. th, 8220 Brabrand", - adgangsadresse: { - adgangspunkt: { - koordinater: [10.12961271, 56.15563438], - }, - }, - }, -]; - -const originData: Location = getLocationObject({ - name: "Falafel", - fullAddress: "Sigridsvej 45 1, 8220 Brabrand", - originType: LocationOriginTypes.COMMERCIAL, - locationType: LocationTypes.ORIGIN, - customerId, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, -}); - -const destinationData: Location = getLocationObject({ - name: "remote", - fullAddress: "Sigridsvej 45 1, 8220 Brabrand", - locationType: LocationTypes.DESTINATION, - originType: LocationOriginTypes.COMMERCIAL, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, - customerId, -}); - -describe("LocationServiceUpdate", () => { - afterEach(() => { - mockedAxios.get.mockClear(); - mockedAxios.get.mockReset(); - }); - - beforeEach(() => { - return createUser({ customerId }); - }); - - it("update should be able to update origin", async () => { - const getCoordinatesUpdateData = [ - { - id: "", - adressebetegnelse: "Dortesvej 21, 1. th, 8220 Brabrand", - adgangsadresse: { - adgangspunkt: { - koordinater: [11.12961271, 57.15563438], - }, - }, - }, - ]; - - mockedAxios.get - .mockResolvedValueOnce({ - data: getCoordinatesData, - }) - .mockResolvedValueOnce({ - data: getCoordinatesUpdateData, - }); - - const response = await LocationServiceCreate(originData); - - const update = await LocationServiceUpdate( - { locationId: response._id.toString(), customerId: 1 }, - { - name: "Falafel 2", - fullAddress: "Dortesvej 21 1, 8220 Brabrand", - originType: LocationOriginTypes.COMMERCIAL, - } - ); - - expect(update).toEqual( - expect.objectContaining({ - locationType: LocationTypes.ORIGIN, - customerId: 1, - fullAddress: getCoordinatesUpdateData[0].adressebetegnelse, - geoLocation: { - coordinates: - getCoordinatesUpdateData[0].adgangsadresse.adgangspunkt.koordinater, - type: "Point", - }, - }) - ); - }); - - it("update should be able to update destination", async () => { - const getCoordinatesUpdateData = [ - { - id: "", - adressebetegnelse: "Dortesvej 21, 1. th, 8220 Brabrand", - adgangsadresse: { - adgangspunkt: { - koordinater: [11.12961271, 57.15563438], - }, - }, - }, - ]; - - mockedAxios.get - .mockResolvedValueOnce({ - data: getCoordinatesData, - }) - .mockResolvedValueOnce({ - data: getCoordinatesUpdateData, - }); - - const response = await LocationServiceCreate(destinationData); - - const update = await LocationServiceUpdate( - { locationId: response._id.toString(), customerId: 1 }, - { - name: "test", - distanceHourlyRate: 5, - fixedRatePerKm: 5, - distanceForFree: 5, - } - ); - - expect(update).toEqual( - expect.objectContaining({ - locationType: LocationTypes.DESTINATION, - customerId: 1, - distanceHourlyRate: 5, - fixedRatePerKm: 5, - distanceForFree: 5, - }) - ); - }); -}); diff --git a/src/functions/location/services/update.ts b/src/functions/location/services/update.ts deleted file mode 100644 index 41419bff..00000000 --- a/src/functions/location/services/update.ts +++ /dev/null @@ -1,80 +0,0 @@ -import mongoose from "mongoose"; -import { NotFoundError } from "~/library/handler"; -import { LocationModel } from "../location.model"; -import { Location } from "../location.types"; -import { ILocation, ILocationDocument } from "../schemas"; -import { LocationServiceValidateAddress } from "./validate-address"; - -export type LocationUpdateFilterProps = { - locationId: ILocationDocument["_id"]; - customerId: Location["customerId"]; -}; - -export type LocationUpdateBody = Partial; - -export const LocationServiceUpdate = async ( - filter: LocationUpdateFilterProps, - body: LocationUpdateBody -) => { - if (body.fullAddress) { - const existingLocation = await LocationModel.findOne({ - _id: new mongoose.Types.ObjectId(filter.locationId), - customerId: filter.customerId, - }); - - if (!existingLocation) { - throw new NotFoundError([ - { - code: "custom", - message: "LOCATION_NOT_FOUND", - path: ["location"], - }, - ]); - } - - if (body.fullAddress !== existingLocation.fullAddress) { - const result = await LocationServiceValidateAddress( - body.fullAddress, - filter.locationId.toString() - ); - - body = { - ...body, - fullAddress: result.fullAddress, - geoLocation: { - type: "Point", - coordinates: [result.longitude, result.latitude], - }, - handle: createSlug(body.name || existingLocation.name), - }; - } - } - - const updatedLocation = await LocationModel.findOneAndUpdate( - { - _id: new mongoose.Types.ObjectId(filter.locationId), - customerId: filter.customerId, - }, - body, - { new: true } - ); - - if (!updatedLocation) { - throw new NotFoundError([ - { - code: "custom", - message: "LOCATION_NOT_FOUND", - path: ["location"], - }, - ]); - } - - return updatedLocation; -}; - -function createSlug(name: string) { - return name - .toLowerCase() - .replace(/[^\w ]+/g, "") - .replace(/ +/g, "-"); -} diff --git a/src/functions/location/services/validate-address.spec.ts b/src/functions/location/services/validate-address.spec.ts deleted file mode 100644 index 1a6358c4..00000000 --- a/src/functions/location/services/validate-address.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import axios from "axios"; -import { BadError } from "~/library/handler"; -import { createUser } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { - Location, - LocationOriginTypes, - LocationTypes, -} from "../location.types"; -import { LocationServiceCreate } from "./create"; -import { ForsyningResponse } from "./get-coordinates"; -import { LocationServiceValidateAddress } from "./validate-address"; - -require("~/library/jest/mongoose/mongodb.jest"); -jest.mock("axios"); - -const mockedAxios = axios as jest.Mocked; - -const customerId = 1; -const getCoordinatesData: ForsyningResponse = [ - { - id: "", - adressebetegnelse: "Sigridsvej 45, 1. th, 8220 Brabrand", - adgangsadresse: { - adgangspunkt: { - koordinater: [10.12961271, 56.15563438], - }, - }, - }, -]; - -const originData: Location = getLocationObject({ - name: "Falafel", - fullAddress: "Sigridsvej 45 1, 8220 Brabrand", - originType: LocationOriginTypes.COMMERCIAL, - locationType: LocationTypes.ORIGIN, - customerId, - distanceHourlyRate: 1, - fixedRatePerKm: 10, - distanceForFree: 10, -}); - -describe("LocationServiceValidateAddress", () => { - afterEach(() => { - mockedAxios.get.mockClear(); - mockedAxios.get.mockReset(); - }); - - beforeEach(() => { - return createUser({ customerId }); - }); - - it("should respond with data", async () => { - mockedAxios.get.mockResolvedValueOnce({ - data: getCoordinatesData, - }); - - const response = await LocationServiceValidateAddress( - "Sigridsvej 45 1th, 8220 brabrand" - ); - - expect(response).toBeDefined(); - }); - - it("should throw error when name or fullAddress already exist", async () => { - mockedAxios.get.mockResolvedValueOnce({ - data: getCoordinatesData, - }); - - await LocationServiceCreate({ - ...originData, - locationType: LocationTypes.ORIGIN, - customerId: 1, - }); - - mockedAxios.get.mockResolvedValueOnce({ - data: getCoordinatesData, - }); - - await expect( - LocationServiceValidateAddress(originData.fullAddress) - ).rejects.toThrow(BadError); - }); -}); diff --git a/src/functions/location/services/validate-address.ts b/src/functions/location/services/validate-address.ts deleted file mode 100644 index 360c9950..00000000 --- a/src/functions/location/services/validate-address.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BadError } from "~/library/handler"; -import { LocationModel } from "../location.model"; -import { LocationServiceGetCoordinates } from "./get-coordinates"; - -export const LocationServiceValidateAddress = async ( - fullAddress: string, - excludeLocationId?: string -) => { - const response = await LocationServiceGetCoordinates({ fullAddress }); - const query: Record = { - $or: [{ fullAddress: response.fullAddress }], - }; - - if (excludeLocationId) { - query["_id"] = { $ne: excludeLocationId }; - } - - const location = await LocationModel.findOne(query); - - if (location) { - throw new BadError([ - { - code: "custom", - message: "LOCATION_ALREADY_EXIST", - path: ["fullAddress"], - }, - ]); - } - - return response; -}; diff --git a/src/functions/user/services/availability/generate.ts b/src/functions/user/services/availability/generate.ts index 5cb5a41d..e5dea77a 100644 --- a/src/functions/user/services/availability/generate.ts +++ b/src/functions/user/services/availability/generate.ts @@ -62,5 +62,12 @@ export const UserAvailabilityServiceGenerate = async ( end: date.endDate, }); + /* + * TODO: + * find customerId if he bought any treatments and block time + * find blocked/vacations and block time + * cart booking time? + */ + return removeBookedSlots(availability, booked); }; diff --git a/src/functions/user/services/location.spec.ts b/src/functions/user/services/location.spec.ts deleted file mode 100644 index 6e8780aa..00000000 --- a/src/functions/user/services/location.spec.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { faker } from "@faker-js/faker"; -import { CustomerLocationServiceCreate } from "~/functions/customer/services/location"; -import { - Location, - LocationModel, - LocationOriginTypes, - LocationTypes, -} from "~/functions/location"; - -import { CustomerServiceGet } from "~/functions/customer/services/customer"; -import { LocationServiceCreate } from "~/functions/location/services/create"; -import { createUser } from "~/library/jest/helpers"; -import { getLocationObject } from "~/library/jest/helpers/location"; -import { UserLocationServiceGetOne } from "./location"; - -require("~/library/jest/mongoose/mongodb.jest"); - -jest.mock("~/functions/location/services/create"); -const mockedLocationServiceCreate = - LocationServiceCreate as jest.MockedFunction; - -describe("UserLocationServiceGetOne", () => { - const customerId = faker.number.int(); - - const location1: Location = getLocationObject({ - locationType: LocationTypes.ORIGIN, - originType: LocationOriginTypes.COMMERCIAL, - customerId, - }); - - const location3: Location = getLocationObject({ - locationType: LocationTypes.DESTINATION, - originType: LocationOriginTypes.COMMERCIAL, - customerId, - }); - - beforeEach(() => { - jest.clearAllMocks(); - return createUser({ customerId }); - }); - - it("Should be able to get one location for user", async () => { - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location1, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - mockedLocationServiceCreate.mockImplementationOnce(() => - LocationModel.create({ - ...location3, - geoLocation: { - coordinates: [2, 3], - type: "Point", - }, - handle: faker.internet.userName(), - }) - ); - - await CustomerLocationServiceCreate(location1); - const location3doc = await CustomerLocationServiceCreate(location3); - - const user = await CustomerServiceGet({ customerId }); - const location = await UserLocationServiceGetOne({ - locationId: location3doc._id.toString(), - username: user.username!, - }); - - expect(location).toBeDefined(); - expect(location?.distanceHourlyRate).toEqual(location3.distanceHourlyRate); - expect(location?.isDefault).toBeFalsy(); - }); -}); diff --git a/src/functions/user/services/location.ts b/src/functions/user/services/location.ts index e52c93a5..993e884f 100644 --- a/src/functions/user/services/location.ts +++ b/src/functions/user/services/location.ts @@ -1,27 +1,26 @@ +import { LocationModel } from "~/functions/location"; import { NotFoundError } from "~/library/handler"; import { StringOrObjectId } from "~/library/zod"; -import { UserServiceGetLocations } from "./user"; +import { UserServiceGet } from "./user"; -export const UserLocationServiceGetOne = async ({ +export const UserLocationServiceGetOne = async ({ username, locationId, }: { username: string; locationId: StringOrObjectId; }) => { - const locations = await UserServiceGetLocations({ username }); - const location = locations.find( - (l) => l.location.toString() === locationId.toString() - ); - - if (!location) { + const user = await UserServiceGet({ username }); + return LocationModel.findOne({ + _id: locationId.toString(), + customerId: user.customerId, + }).orFail( new NotFoundError([ { path: ["locationId", "username"], message: "LOCATION_NOT_FOUND_IN_USER", code: "custom", }, - ]); - } - return location; + ]) + ); }; diff --git a/src/functions/user/services/user.ts b/src/functions/user/services/user.ts index 0ff3615a..6fbdcacf 100644 --- a/src/functions/user/services/user.ts +++ b/src/functions/user/services/user.ts @@ -1,10 +1,9 @@ import { FilterQuery } from "mongoose"; -import { ILocationDocument } from "~/functions/location/schemas/location.schema"; import { NotFoundError } from "~/library/handler"; import { UserModel } from "../user.model"; import { IUserDocument } from "../user.schema"; -import { User, UserLocations } from "../user.types"; +import { User } from "../user.types"; export type UserServiceUsernameTakenProps = Required>; @@ -112,120 +111,6 @@ export const UserServiceProfessions = async () => { return professionCountFormatted; }; -export const UserServiceLocationsAdd = async (location: { - _id: ILocationDocument["_id"]; - customerId: number; -}) => { - const user = await UserServiceFindCustomerOrFail(location); - const isDefault = user.locations?.length === 0; - user.locations?.push({ location: location._id.toString(), isDefault }); - return user.save(); -}; - -export const UserServiceLocationsSetDefault = async (location: { - _id: ILocationDocument["_id"]; - customerId: number; -}) => { - const user = await UserServiceFindCustomerOrFail(location); - - const locationOldDefault = user.locations?.find((l) => l.isDefault); - if (locationOldDefault && locationOldDefault.isDefault) { - locationOldDefault.isDefault = false; - } - - const locationToSetDefault = user.locations?.find( - (l) => l.location.toString() === location._id.toString() - ); - - if (locationToSetDefault && !locationToSetDefault.isDefault) { - locationToSetDefault.isDefault = true; - } - - return user.save(); -}; - -export const UserServiceLocationsRemove = async (location: { - locationId: ILocationDocument["_id"]; - customerId: number; -}) => { - const user = await UserServiceFindCustomerOrFail(location); - // Get the location that will be removed - const locationToRemove = user.locations?.find( - (l) => l.location.toString() === location.locationId.toString() - ); - - if (locationToRemove && locationToRemove.isDefault) { - // If the location is the default one, change isDefault flag on first non-default location - const firstNonDefault = user.locations?.find( - (l) => - l.location.toString() !== location.locationId.toString() && !l.isDefault - ); - if (firstNonDefault) firstNonDefault.isDefault = true; - } - - user.locations = user.locations?.filter( - (l) => l.location.toString() !== location.locationId.toString() - ); - return user.save(); -}; - -export const UserServiceGetLocations = async ({ - customerId, - username, -}: { - customerId?: number; - username?: string; -}) => { - const pipeline = []; - if (customerId) { - pipeline.push({ $match: { customerId } }); - } - - if (username) { - pipeline.push({ $match: { username } }); - } - - pipeline.push( - { $unwind: "$locations" }, - { - $lookup: { - from: "Location", - localField: "locations.location", - foreignField: "_id", - as: "locations.location", - }, - }, - { $unwind: "$locations.location" }, - { - $addFields: { - "locations.location.isDefault": "$locations.isDefault", - "locations.location.location": "$locations.location._id", - }, - }, - { - $group: { - _id: "$_id", - locations: { $push: "$locations.location" }, - }, - }, - { - $project: { - _id: 0, - locations: 1, - }, - } - ); - - const locations = await UserModel.aggregate<{ - locations: Array; - }>(pipeline).exec(); - if (locations.length > 0) { - return locations[0].locations; - } - - return []; -}; - export const UserServiceFindCustomerOrFail = ({ customerId, }: { diff --git a/src/functions/user/user.schema.ts b/src/functions/user/user.schema.ts index 42088ca6..8879b4eb 100644 --- a/src/functions/user/user.schema.ts +++ b/src/functions/user/user.schema.ts @@ -68,19 +68,6 @@ export const UserMongooseSchema = new mongoose.Schema< type: [String], default: [], }, - locations: { - type: [ - { - location: { - type: mongoose.Schema.Types.ObjectId, - ref: "Location", - required: true, - }, - isDefault: { type: Boolean, default: false }, - }, - ], - default: [], - }, }, { timestamps: true } ); diff --git a/src/functions/user/user.types.ts b/src/functions/user/user.types.ts index 08f92872..96c5b90b 100644 --- a/src/functions/user/user.types.ts +++ b/src/functions/user/user.types.ts @@ -1,9 +1,5 @@ import { z } from "zod"; -import { - BooleanOrStringType, - GidFormat, - NumberOrStringType, -} from "~/library/zod"; +import { GidFormat, NumberOrStringType } from "~/library/zod"; export enum Professions { MAKEUP_ARTIST = "makeup_artist", @@ -90,14 +86,6 @@ export const UserZodSchema = z.object({ .optional(), }) .optional(), - locations: z - .array( - z.object({ - location: z.string(), - isDefault: BooleanOrStringType, - }) - ) - .optional(), speaks: z.array(z.string()).optional(), fullname: z.string(), active: z.boolean(), @@ -109,7 +97,3 @@ export type User = z.infer; type ArrayElement = ArrayType extends readonly (infer ElementType)[] ? ElementType : never; - -export type UserLocations = ArrayElement< - NonNullable> ->; diff --git a/src/library/jest/helpers/user.ts b/src/library/jest/helpers/user.ts index b5276151..5e857c84 100644 --- a/src/library/jest/helpers/user.ts +++ b/src/library/jest/helpers/user.ts @@ -25,7 +25,6 @@ export const getUserObject = ( }, }, speaks: [faker.location.countryCode()], - locations: [], customerId: faker.number.int({ min: 1, max: 10000000 }), ...props, });