Skip to content

Commit

Permalink
feat(order): add service to get order by line-item for customer
Browse files Browse the repository at this point in the history
feat(order): add service to list orders for customer on specific year/month

chore(order.schema.ts): reformat code for better readability
feat(order.schema.ts): add types for OrderFulfillment, OrderRefundLineItem, and OrderRefund
  • Loading branch information
jamalsoueidan committed Dec 9, 2023
1 parent e548a12 commit d1fb32f
Show file tree
Hide file tree
Showing 6 changed files with 451 additions and 237 deletions.
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);
});
});
145 changes: 101 additions & 44 deletions src/functions/customer/services/order/get.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { OrderModel } from "~/functions/order/order.models";
import { NotFoundError } from "~/library/handler";
import { CustomerOrderServiceListAggregate } from "./list";

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

export const CustomerOrderServiceGet = async ({
customerId,
lineItem,
lineItemId,
}: CustomerOrderServiceGetProps) => {
return OrderModel.aggregate([
const orders = await OrderModel.aggregate<CustomerOrderServiceListAggregate>([
{
$match: {
$and: [
Expand All @@ -19,7 +21,9 @@ export const CustomerOrderServiceGet = async ({
},
},
{
"line_items.id": lineItem,
line_items: {
$elemMatch: { id: lineItemId },
},
},
],
},
Expand All @@ -34,69 +38,108 @@ export const CustomerOrderServiceGet = async ({
},
},
{
"line_items.id": lineItem,
"line_items.id": lineItemId,
},
],
},
},
{
$addFields: {
"line_items.refunds": {
refunds: {
$map: {
input: {
$filter: {
input: {
$reduce: {
input: "$refunds",
initialValue: [],
in: {
$concatArrays: ["$$value", "$$this.refund_line_items"],
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",
],
},
},
},
},
as: "refund_line_item",
cond: {
$eq: ["$$refund_line_item.line_item_id", "$line_items._id"],
},
},
},
as: "refund",
as: "filtered_refund",
in: {
_id: "$$refund._id",
line_item_id: "$$refund.line_item_id",
location_id: "$$refund.location_id",
quantity: "$$refund.quantity",
restock_type: "$$refund.restock_type",
subtotal: "$$refund.subtotal",
subtotal_set: "$$refund.subtotal_set",
total_tax: "$$refund.total_tax",
total_tax_set: "$$refund.total_tax_set",
id: "$$filtered_refund.id",
admin_graphql_api_id: "$$filtered_refund.admin_graphql_api_id",
created_at: "$$filtered_refund.created_at",
note: "$$filtered_refund.note",
order_id: "$$filtered_refund.order_id",
processed_at: "$$filtered_refund.processed_at",
restock: "$$filtered_refund.restock",
total_duties_set: "$$filtered_refund.total_duties_set",
user_id: "$$filtered_refund.user_id",
order_adjustments: "$$filtered_refund.order_adjustments",
transactions: "$$filtered_refund.transactions",
duties: "$$filtered_refund.duties",
refund_line_items: {
$map: {
input: "$$filtered_refund.refund_line_items",
as: "refund_line_item",
in: {
id: "$$refund_line_item.id",
line_item_id: "$$refund_line_item.line_item_id",
location_id: "$$refund_line_item.location_id",
quantity: "$$refund_line_item.quantity",
restock_type: "$$refund_line_item.restock_type",
subtotal: "$$refund_line_item.subtotal",
subtotal_set: "$$refund_line_item.subtotal_set",
total_tax: "$$refund_line_item.total_tax",
total_tax_set: "$$refund_line_item.total_tax_set",
// Excluding the 'line_item' field
},
},
},
},
},
},
},
},
{
$addFields: {
"line_items.fulfillments": {
$cond: {
if: { $eq: [{ $size: "$line_items.refunds" }, 0] },
then: {
fulfillments: {
$map: {
input: {
$filter: {
input: {
$reduce: {
input: "$fulfillments",
initialValue: [],
in: { $concatArrays: ["$$value", "$$this.line_items"] },
},
},
as: "fulfillment_line_item",
input: "$fulfillments",
as: "fulfillment",
cond: {
$eq: ["$$fulfillment_line_item._id", "$line_items._id"],
$anyElementTrue: {
$map: {
input: "$$fulfillment.line_items",
as: "fulfillment_line_item",
in: {
$eq: ["$$fulfillment_line_item.id", "$line_items.id"],
},
},
},
},
},
},
else: [],
as: "fulfillment",
in: {
id: "$$fulfillment.id",
admin_graphql_api_id: "$$fulfillment.admin_graphql_api_id",
created_at: "$$fulfillment.created_at",
location_id: "$$fulfillment.location_id",
name: "$$fulfillment.name",
order_id: "$$fulfillment.order_id",
service: "$$fulfillment.service",
shipment_status: "$$fulfillment.shipment_status",
status: "$$fulfillment.status",
tracking_company: "$$fulfillment.tracking_company",
tracking_number: "$$fulfillment.tracking_number",
tracking_numbers: "$$fulfillment.tracking_numbers",
tracking_url: "$$fulfillment.tracking_url",
tracking_urls: "$$fulfillment.tracking_urls",
updated_at: "$$fulfillment.updated_at",
// Excluding the 'line_items' field
},
},
},
},
Expand All @@ -115,7 +158,21 @@ export const CustomerOrderServiceGet = async ({
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];
};
6 changes: 3 additions & 3 deletions src/functions/customer/services/order/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { orderWithfulfillmentAndRefunds } from "~/functions/webhook/data-ordre-w
import { CustomerOrderServiceList } from "./list";
require("~/library/jest/mongoose/mongodb.jest");

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

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

expect(orders.length).toBe(1);
Expand Down
75 changes: 58 additions & 17 deletions src/functions/customer/services/order/list.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
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,
Expand All @@ -14,7 +34,7 @@ export const CustomerOrderServiceList = async ({
const firstDayOfMonth = new Date(Date.UTC(year, month - 1, 1));
const lastDayOfMonth = new Date(Date.UTC(year, month, 0));

return OrderModel.aggregate([
return OrderModel.aggregate<CustomerOrderServiceListAggregate>([
{
$match: {
$and: [
Expand Down Expand Up @@ -92,29 +112,50 @@ export const CustomerOrderServiceList = async ({
$anyElementTrue: {
$map: {
input: "$$refund.refund_line_items",
as: "refund_refund_line_items",
as: "refund_line_item",
in: {
$eq: [
"$$refund_refund_line_items.line_item_id",
"$line_items._id",
"$$refund_line_item.line_item_id",
"$line_items.id",
],
},
},
},
},
},
},
as: "refund",
as: "filtered_refund",
in: {
_id: "$$refund._id",
line_item_id: "$$refund.line_item_id",
location_id: "$$refund.location_id",
quantity: "$$refund.quantity",
restock_type: "$$refund.restock_type",
subtotal: "$$refund.subtotal",
subtotal_set: "$$refund.subtotal_set",
total_tax: "$$refund.total_tax",
total_tax_set: "$$refund.total_tax_set",
id: "$$filtered_refund.id",
admin_graphql_api_id: "$$filtered_refund.admin_graphql_api_id",
created_at: "$$filtered_refund.created_at",
note: "$$filtered_refund.note",
order_id: "$$filtered_refund.order_id",
processed_at: "$$filtered_refund.processed_at",
restock: "$$filtered_refund.restock",
total_duties_set: "$$filtered_refund.total_duties_set",
user_id: "$$filtered_refund.user_id",
order_adjustments: "$$filtered_refund.order_adjustments",
transactions: "$$filtered_refund.transactions",
duties: "$$filtered_refund.duties",
refund_line_items: {
$map: {
input: "$$filtered_refund.refund_line_items",
as: "refund_line_item",
in: {
id: "$$refund_line_item.id",
line_item_id: "$$refund_line_item.line_item_id",
location_id: "$$refund_line_item.location_id",
quantity: "$$refund_line_item.quantity",
restock_type: "$$refund_line_item.restock_type",
subtotal: "$$refund_line_item.subtotal",
subtotal_set: "$$refund_line_item.subtotal_set",
total_tax: "$$refund_line_item.total_tax",
total_tax_set: "$$refund_line_item.total_tax_set",
// Excluding the 'line_item' field
},
},
},
},
},
},
Expand All @@ -130,7 +171,7 @@ export const CustomerOrderServiceList = async ({
input: "$$fulfillment.line_items",
as: "fulfillment_line_item",
in: {
$eq: ["$$fulfillment_line_item._id", "$line_items._id"],
$eq: ["$$fulfillment_line_item.id", "$line_items.id"],
},
},
},
Expand All @@ -139,7 +180,7 @@ export const CustomerOrderServiceList = async ({
},
as: "fulfillment",
in: {
_id: "$$fulfillment._id",
id: "$$fulfillment.id",
admin_graphql_api_id: "$$fulfillment.admin_graphql_api_id",
created_at: "$$fulfillment.created_at",
location_id: "$$fulfillment.location_id",
Expand All @@ -154,12 +195,12 @@ export const CustomerOrderServiceList = async ({
tracking_url: "$$fulfillment.tracking_url",
tracking_urls: "$$fulfillment.tracking_urls",
updated_at: "$$fulfillment.updated_at",
// Excluding the 'line_items' field
},
},
},
},
},

{
$project: {
id: 1,
Expand Down
Loading

0 comments on commit d1fb32f

Please sign in to comment.