Skip to content

Commit

Permalink
Merge pull request #160 from jamalsoueidan/add-geo-location-metaobject
Browse files Browse the repository at this point in the history
 Add durable client input and orchestration for customer location upd…
  • Loading branch information
jamalsoueidan authored Jun 5, 2024
2 parents ddac376 + 7f5451a commit 05daf73
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 158 deletions.
1 change: 1 addition & 0 deletions src/functions/customer-location.function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ app.http("customerLocationUpdate", {
authLevel: "anonymous",
route: "customer/{customerId}/location/{locationId?}",
handler: CustomerLocationControllerUpdate,
extraInputs: [df.input.durableClient()],
});

app.http("customerLocationCreate", {
Expand Down
18 changes: 15 additions & 3 deletions src/functions/customer/controllers/location/update.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { z } from "zod";
import { LocationZodSchema } from "~/functions/location/location.types";

import { InvocationContext } from "@azure/functions";
import { _ } from "~/library/handler";
import { StringOrObjectId } from "~/library/zod";
import { CustomerLocationUpdateOrchestration } from "../../orchestrations/location/update";
import { CustomerLocationServiceUpdate } from "../../services/location/update";

// should be PATCH and UPSERT
export type CustomerLocationControllerUpdateRequest = {
query: z.infer<typeof CustomerLocationControllerUpdateQuerySchema>;
body: z.infer<typeof CustomerLocationControllerUpdateBodySchema>;
context: InvocationContext;
};

export const CustomerLocationControllerUpdateBodySchema =
Expand All @@ -30,12 +32,22 @@ export type CustomerLocationControllerUpdateResponse = Awaited<
>;

export const CustomerLocationControllerUpdate = _(
({ query, body }: CustomerLocationControllerUpdateRequest) => {
async ({ query, body, context }: CustomerLocationControllerUpdateRequest) => {
const validateData =
CustomerLocationControllerUpdateQuerySchema.parse(query);
const validateBody =
CustomerLocationControllerUpdateBodySchema.parse(body) || {};

return CustomerLocationServiceUpdate(validateData, validateBody);
const location = await CustomerLocationServiceUpdate(
validateData,
validateBody
);

await CustomerLocationUpdateOrchestration(
{ locationId: location._id },
context
);

return location;
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ jest.mock("~/library/shopify", () => ({

const mockRequest = shopifyAdmin().request as jest.Mock;

describe("CustomerUpdateOrchestration", () => {
describe("CustomerLocationCreateOrchestration", () => {
beforeAll(async () => {
jest.clearAllMocks();
});

it("updateUserMetaobject", async () => {
it("createLocationMetafield", async () => {
const coordinates = {
longitude: 10.12961271,
latitude: 56.15563438,
Expand Down Expand Up @@ -101,6 +101,10 @@ describe("CustomerUpdateOrchestration", () => {
value: location.startFee.toString(),
key: "start_fee",
},
{
key: "geo_location",
value: JSON.stringify(location.geoLocation),
},
],
},
},
Expand Down Expand Up @@ -163,6 +167,10 @@ describe("CustomerUpdateOrchestration", () => {
value: location.startFee.toString(),
key: "start_fee",
},
{
key: "geo_location",
value: JSON.stringify(location.geoLocation),
},
],
}),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export const createLocationMetafield = async ({
key: "start_fee",
value: location.startFee.toString(),
},
{
key: "geo_location",
value: JSON.stringify(location.geoLocation),
},
],
},
});
Expand Down
50 changes: 50 additions & 0 deletions src/functions/customer/orchestrations/location/update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { InvocationContext } from "@azure/functions";
import * as df from "durable-functions";
import { OrchestrationContext } from "durable-functions";
import { activityType } from "~/library/orchestration";
import { StringOrObjectIdType } from "~/library/zod";
import {
updateLocationMetafield,
updateLocationMetafieldName,
} from "./update/update-location-metafield";

df.app.activity(updateLocationMetafieldName, {
handler: updateLocationMetafield,
});

const orchestrator: df.OrchestrationHandler = function* (
context: OrchestrationContext
) {
const input = context.df.getInput() as Input;

const metafield: Awaited<ReturnType<typeof updateLocationMetafield>> =
yield context.df.callActivity(
updateLocationMetafieldName,
activityType<typeof updateLocationMetafield>(input)
);

return { metafield };
};

df.app.orchestration("CustomerLocationUpdateOrchestration", orchestrator);

type Input = {
locationId: StringOrObjectIdType;
};

export const CustomerLocationUpdateOrchestration = async (
input: Input,
context: InvocationContext
): Promise<string> => {
const client = df.getClient(context);
const instanceId: string = await client.startNew(
"CustomerLocationUpdateOrchestration",
{
input,
}
);

context.log(`Started orchestration with ID = '${instanceId}'.`);

return instanceId;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { LocationOriginTypes, LocationTypes } from "~/functions/location";
import { createLocation } from "~/library/jest/helpers/location";
import { ensureType } from "~/library/jest/helpers/mock";
import { shopifyAdmin } from "~/library/shopify";
import {
UpdateLocationMetaobjectMutation,
UpdateLocationMetaobjectMutationVariables,
} from "~/types/admin.generated";
import {
UPDATE_LOCATION_METAOBJECT,
updateLocationMetafield,
} from "./update-location-metafield";

require("~/library/jest/mongoose/mongodb.jest");

jest.mock("~/library/shopify", () => ({
shopifyAdmin: jest.fn().mockReturnValue({
request: jest.fn(),
}),
}));

const mockRequest = shopifyAdmin().request as jest.Mock;

describe("CustomerLocationUpdateOrchestration", () => {
beforeAll(async () => {
jest.clearAllMocks();
});

it("updateLocationMetafield", async () => {
const coordinates = {
longitude: 10.12961271,
latitude: 56.15563438,
fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand",
city: "Aarhus",
country: "Denmark",
};

const location = await createLocation({
name: "Falafel",
fullAddress: "Sigridsvej 45, 1. th, 8220 Brabrand",
originType: LocationOriginTypes.COMMERCIAL,
locationType: LocationTypes.ORIGIN,
customerId: 12,
distanceHourlyRate: 1,
fixedRatePerKm: 10,
distanceForFree: 10,
});

mockRequest.mockResolvedValueOnce({
data: ensureType<UpdateLocationMetaobjectMutation>({
metaobjectUpdate: {
metaobject: {
fields: [
{
value: location.locationType,
key: "location_type",
},
{
value: location.name,
key: "name",
},
{
value: coordinates.fullAddress,
key: "full_address",
},
{
value: coordinates.city,
key: "city",
},
{
value: coordinates.country,
key: "country",
},
{
value: location.originType,
key: "origin_type",
},
{
value: location.distanceForFree.toString(),
key: "distance_for_free",
},
{
value: location.distanceHourlyRate.toString(),
key: "distance_hourly_rate",
},
{
value: location.fixedRatePerKm.toString(),
key: "fixed_rate_per_km",
},
{
value: location.minDriveDistance.toString(),
key: "min_drive_distance",
},
{
value: location.maxDriveDistance.toString(),
key: "max_drive_distance",
},
{
value: location.startFee.toString(),
key: "start_fee",
},
{
key: "geo_location",
value: JSON.stringify(location.geoLocation),
},
],
},
},
}),
});

await updateLocationMetafield({ locationId: location._id });

expect(mockRequest).toHaveBeenCalledTimes(1);

expect(mockRequest).toHaveBeenNthCalledWith(1, UPDATE_LOCATION_METAOBJECT, {
variables: ensureType<UpdateLocationMetaobjectMutationVariables>({
id: location.metafieldId || "",
fields: [
{
value: location.locationType,
key: "location_type",
},
{
value: location.name,
key: "name",
},
{
value: location.fullAddress,
key: "full_address",
},
{
value: location.city,
key: "city",
},
{
value: location.country,
key: "country",
},
{
value: location.originType,
key: "origin_type",
},
{
value: location.distanceForFree.toString(),
key: "distance_for_free",
},
{
value: location.distanceHourlyRate.toString(),
key: "distance_hourly_rate",
},
{
value: location.fixedRatePerKm.toString(),
key: "fixed_rate_per_km",
},
{
value: location.minDriveDistance.toString(),
key: "min_drive_distance",
},
{
value: location.maxDriveDistance.toString(),
key: "max_drive_distance",
},
{
value: location.startFee.toString(),
key: "start_fee",
},
{
key: "geo_location",
value: JSON.stringify(location.geoLocation),
},
],
}),
});
});
});
Loading

0 comments on commit 05daf73

Please sign in to comment.