Files
bartool fb08705883 feat: Implement initial structure for Directus Mayo API extension
- Added main router in src/index.js to register endpoints.
- Implemented GET /mayo-api/products to fetch product list with pagination and filters.
- Implemented GET /mayo-api/dictionaries to fetch various dictionaries for frontend use.
- Created separate files for routes, repositories, serializers, and utilities to maintain clean architecture.
- Added utility functions for async handling, pagination, and order search parsing.
- Introduced serializers for products and dictionaries to format data for frontend consumption.
- Established repository functions for database queries related to products and dictionaries.
- Updated package.json to include license information.
- Created documentation for the API extension detailing current state and future implementation plans.
2026-05-20 22:38:51 +02:00

253 lines
7.2 KiB
JavaScript

export default {
id: "mayo-api",
handler: (router, context) => {
const { services, getSchema, database } = context;
const { ItemsService } = services;
router.get("/products", async (req, res) => {
const productsService = new ItemsService("mayo_products", {
schema: await getSchema(),
accountability: req.accountability,
});
const partsService = new ItemsService("mayo_parts", {
schema: await getSchema(),
accountability: req.accountability,
});
try {
const products = await productsService.readByQuery({
fields: [
"id",
"note",
"model_id.name",
"model_id.strings_count",
"model_id.scale",
],
limit: -1,
});
const productIds = products.map((product) => product.id);
const parts = await partsService.readByQuery({
fields: [
"id",
"product_id",
"part_type",
"top_color_id.name",
"back_color_id.name",
"top_finish",
"back_finish",
],
filter: {
product_id: {
_in: productIds,
},
},
limit: -1,
});
const partsByProductId = new Map();
for (const part of parts) {
const productId =
typeof part.product_id === "object"
? part.product_id.id
: part.product_id;
if (!partsByProductId.has(productId)) {
partsByProductId.set(productId, []);
}
partsByProductId.get(productId).push(part);
}
const response = products.map((product) => ({
...product,
parts: partsByProductId.get(product.id) ?? [],
}));
res.json(response);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
router.get("/products-new", async (req, res) => {
try {
const products = await database("mayo_products as product")
.select(
"product.id",
"product.note",
"model.name as model_name",
"model.strings_count as model_strings_count",
"model.scale as model_scale",
)
.leftJoin("mayo_models as model", "product.model_id", "model.id");
const productIds = products.map((product) => product.id);
const parts = productIds.length
? await database("mayo_parts as part")
.select(
"part.id",
"part.product_id",
"part.part_type",
"part.top_finish",
"part.back_finish",
"top_color.name as top_color_name",
"back_color.name as back_color_name",
)
.leftJoin(
"mayo_colors as top_color",
"part.top_color_id",
"top_color.id",
)
.leftJoin(
"mayo_colors as back_color",
"part.back_color_id",
"back_color.id",
)
.whereIn("part.product_id", productIds)
: [];
const partsByProductId = new Map();
for (const part of parts) {
if (!partsByProductId.has(part.product_id)) {
partsByProductId.set(part.product_id, []);
}
partsByProductId.get(part.product_id).push({
id: part.id,
product_id: part.product_id,
part_type: part.part_type,
top_color_id: {
name: part.top_color_name,
},
back_color_id: {
name: part.back_color_name,
},
top_finish: part.top_finish,
back_finish: part.back_finish,
});
}
const response = products.map((product) => ({
id: product.id,
note: product.note,
model_id: {
name: product.model_name,
strings_count: product.model_strings_count,
scale: product.model_scale,
},
parts: partsByProductId.get(product.id) ?? [],
}));
res.json(response);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
router.get("/orders", async (req, res) => {
const itemsService = new ItemsService("mayo_order_products", {
schema: await getSchema(),
accountability: req.accountability,
});
try {
const items = await itemsService.readByQuery({
fields: [
"id",
"product_order_index",
"order_id.order_number",
"order_id.order_year",
"order_id.client_id.name",
"product_id.id",
"product_id.note",
"product_id.model_id.name",
"product_id.model_id.strings_count",
"product_id.model_id.scale",
],
limit: -1,
});
res.json(items);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
router.get("/my-products", async (req, res) => {
try {
const products = await database("mayo_products as mp")
.select(
"mp.id",
"mm.name as model",
"mo.order_number",
"mo.order_year",
"mop.product_order_index as order_index",
)
.leftJoin("mayo_order_products as mop", "mop.product_id", "mp.id")
.leftJoin("mayo_orders as mo", "mo.id", "mop.order_id")
.leftJoin("mayo_models as mm", "mm.id", "mp.model_id");
const productIds = products.map((product) => product.id);
const parts = productIds.length
? await database("mayo_parts as part")
.select("part.product_id", "part.part_type")
.whereIn("part.product_id", productIds)
: [];
const partTypesByProductId = new Map();
for (const part of parts) {
if (!partTypesByProductId.has(part.product_id)) {
partTypesByProductId.set(part.product_id, []);
}
if (part.part_type) {
partTypesByProductId.get(part.product_id).push(part.part_type);
}
}
const response = products.map((product) => ({
...product,
part_types: partTypesByProductId.get(product.id) ?? [],
}));
res.json(response);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
router.get("/my-products2", async (req, res) => {
const productsService = new ItemsService("mayo_products", {
schema: await getSchema(),
accountability: req.accountability,
});
const partsService = new ItemsService("mayo_parts", {
schema: await getSchema(),
accountability: req.accountability,
});
try {
const products = await productsService.readByQuery({
fields: [
"id",
"note",
"model_id.name",
"model_id.strings_count",
"model_id.scale",
],
limit: -1,
});
res.json(products);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
},
};