Skip to content

Commit

Permalink
Merge pull request #91 from jamalsoueidan/customer-orders-endpoint
Browse files Browse the repository at this point in the history
feat(order.spec.ts)
  • Loading branch information
jamalsoueidan authored Dec 9, 2023
2 parents 0704d4f + 272d052 commit 810ebb7
Show file tree
Hide file tree
Showing 11 changed files with 1,123 additions and 514 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"~": "dist/src"
},
"scripts": {
"tunnel": "ssh -R 80:localhost:7071 serveo.net",
"prebuild": "npm run clean",
"build": "tsc --project tsconfig.build.json",
"watch": "tsc -w",
Expand Down
27 changes: 27 additions & 0 deletions src/functions/customer/services/order/get.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { OrderModel } from "~/functions/order/order.models";
import { Order } from "~/functions/order/order.types";
import { orderWithfulfillmentAndRefunds } from "~/functions/webhook/data-ordre-with-fullfilment-and-refunds";
import { CustomerOrderServiceGet } from "./get";
require("~/library/jest/mongoose/mongodb.jest");

describe("CustomerOrderServiceGet", () => {
it("should return order by line-item for customer", async () => {
const dumbData = Order.parse(orderWithfulfillmentAndRefunds);
const response = await OrderModel.create(dumbData);

const lineItemId = response.line_items[0].id;

const customerId = response.line_items[0].properties?.find(
(p) => p.name === "_customerId"
)?.value as number | undefined;

const order = await CustomerOrderServiceGet({
customerId: customerId || 0,
lineItemId,
});

expect(order.line_items.id).toEqual(lineItemId);
expect(order.fulfillments.length).toBe(1);
expect(order.refunds.length).toBe(1);
});
});
115 changes: 115 additions & 0 deletions src/functions/customer/services/order/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { OrderModel } from "~/functions/order/order.models";
import { NotFoundError } from "~/library/handler";
import { CustomerOrderServiceListAggregate } from "./list";

export type CustomerOrderServiceGetProps = {
customerId: number;
lineItemId: number;
};

export const CustomerOrderServiceGet = async ({
customerId,
lineItemId,
}: CustomerOrderServiceGetProps) => {
const orders = await OrderModel.aggregate<CustomerOrderServiceListAggregate>([
{
$match: {
$and: [
{
"line_items.properties": {
$elemMatch: { name: "_customerId", value: customerId },
},
},
{
line_items: {
$elemMatch: { id: lineItemId },
},
},
],
},
},
{ $unwind: "$line_items" },
{
$match: {
$and: [
{
"line_items.properties": {
$elemMatch: { name: "_customerId", value: customerId },
},
},
{
"line_items.id": lineItemId,
},
],
},
},
{
$addFields: {
refunds: {
$filter: {
input: "$refunds",
as: "refund",
cond: {
$anyElementTrue: {
$map: {
input: "$$refund.refund_line_items",
as: "refund_line_item",
in: {
$eq: ["$$refund_line_item.line_item_id", "$line_items.id"],
},
},
},
},
},
},
fulfillments: {
$filter: {
input: "$fulfillments",
as: "fulfillment",
cond: {
$anyElementTrue: {
$map: {
input: "$$fulfillment.line_items",
as: "fulfillment_line_item",
in: {
$eq: ["$$fulfillment_line_item.id", "$line_items.id"],
},
},
},
},
},
},
},
},
{
$project: {
id: 1,
line_items: 1,
customer: 1,
order_number: 1,
fulfillment_status: 1,
financial_status: 1,
created_at: 1,
updated_at: 1,
cancel_reason: 1,
cancelled_at: 1,
note: 1,
note_attributes: 1,
fulfillments: 1,
refunds: 1,
},
},
]);

if (orders.length === 0) {
throw new NotFoundError([
{
code: "custom",
message: "ORDER_NOT_FOUND",
path: ["lineItemId"],
},
]);
}

return orders[0];
};
24 changes: 24 additions & 0 deletions src/functions/customer/services/order/list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { OrderModel } from "~/functions/order/order.models";
import { Order } from "~/functions/order/order.types";
import { orderWithfulfillmentAndRefunds } from "~/functions/webhook/data-ordre-with-fullfilment-and-refunds";
import { CustomerOrderServiceList } from "./list";
require("~/library/jest/mongoose/mongodb.jest");

describe("CustomerOrderServiceList", () => {
it("should return orders for customer on specific year/month", async () => {
const dumbData = Order.parse(orderWithfulfillmentAndRefunds);
const response = await OrderModel.create(dumbData);

const customerId = response.line_items[0].properties?.find(
(p) => p.name === "_customerId"
)?.value as number | undefined;

const orders = await CustomerOrderServiceList({
customerId: customerId || 0,
year: 2023,
month: 12,
});

expect(orders.length).toBe(1);
});
});
160 changes: 160 additions & 0 deletions src/functions/customer/services/order/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { OrderModel } from "~/functions/order/order.models";
import {
Order,
OrderFulfillment,
OrderLineItem,
OrderRefund,
OrderRefundLineItem,
} from "~/functions/order/order.types";

export type CustomerOrderServiceListProps = {
customerId: number;
year: number;
month: number;
};

export type CustomerOrderServiceListAggregate = Omit<
Order,
"line_items" | "refunds" | "fulfillments"
> & {
line_items: OrderLineItem;
fulfillments: Array<Omit<OrderFulfillment, "line_items">>;
refunds: Array<
Omit<OrderRefund, "refund_line_items"> & {
refund_line_items: Array<Omit<OrderRefundLineItem, "line_item">>;
}
>;
};

export const CustomerOrderServiceList = async ({
customerId,
year,
month,
}: CustomerOrderServiceListProps) => {
const firstDayOfMonth = new Date(Date.UTC(year, month - 1, 1));
const lastDayOfMonth = new Date(Date.UTC(year, month, 0));

return OrderModel.aggregate<CustomerOrderServiceListAggregate>([
{
$match: {
$and: [
{
"line_items.properties": {
$elemMatch: { name: "_customerId", value: customerId },
},
},
{
"line_items.properties": {
$elemMatch: {
name: "_from",
value: {
$gte: firstDayOfMonth,
$lte: lastDayOfMonth,
},
},
},
},
],
},
},
{ $unwind: "$line_items" },
{
$match: {
$and: [
{
"line_items.properties": {
$elemMatch: { name: "_customerId", value: customerId },
},
},
{
"line_items.properties": {
$elemMatch: {
name: "_from",
value: {
$gte: firstDayOfMonth,
$lte: lastDayOfMonth,
},
},
},
},
],
},
},
{
$addFields: {
"line_items._from": {
$reduce: {
input: "$line_items.properties",
initialValue: null,
in: {
$cond: {
if: { $eq: ["$$this.name", "_from"] },
then: "$$this.value",
else: "$$value",
},
},
},
},
},
},
{
$sort: { "line_items._from": 1 }, // 1 for ascending order, -1 for descending
},
{
$addFields: {
refunds: {
$filter: {
input: "$refunds",
as: "refund",
cond: {
$anyElementTrue: {
$map: {
input: "$$refund.refund_line_items",
as: "refund_line_item",
in: {
$eq: ["$$refund_line_item.line_item_id", "$line_items.id"],
},
},
},
},
},
},
fulfillments: {
$filter: {
input: "$fulfillments",
as: "fulfillment",
cond: {
$anyElementTrue: {
$map: {
input: "$$fulfillment.line_items",
as: "fulfillment_line_item",
in: {
$eq: ["$$fulfillment_line_item.id", "$line_items.id"],
},
},
},
},
},
},
},
},
{
$project: {
id: 1,
line_items: 1,
customer: 1,
order_number: 1,
fulfillment_status: 1,
financial_status: 1,
created_at: 1,
updated_at: 1,
cancel_reason: 1,
cancelled_at: 1,
note: 1,
note_attributes: 1,
fulfillments: 1,
refunds: 1,
},
},
]);
};
Loading

0 comments on commit 810ebb7

Please sign in to comment.