feat(medusa): List batch jobs + Introduce composable handler pattern (#1541)
This commit is contained in:
1 parent
f0ecef6b9a
commit
4489b75f5a
15 files changed
+521
-10
No files matched your search
@@ -0,0 +1,44 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`/admin/batch GET /admin/batch lists batch jobs created by the user 1`] = `
|
||||||
|
Object {
|
||||||
|
"batch_jobs": Array [
|
||||||
|
Object {
|
||||||
|
"context": Object {},
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"created_by": "admin_user",
|
||||||
|
"deleted_at": null,
|
||||||
|
"id": "job_3",
|
||||||
|
"result": null,
|
||||||
|
"status": "created",
|
||||||
|
"type": "batch_2",
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"context": Object {},
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"created_by": "admin_user",
|
||||||
|
"deleted_at": null,
|
||||||
|
"id": "job_2",
|
||||||
|
"result": null,
|
||||||
|
"status": "created",
|
||||||
|
"type": "batch_2",
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"context": Object {},
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"created_by": "admin_user",
|
||||||
|
"deleted_at": null,
|
||||||
|
"id": "job_1",
|
||||||
|
"result": null,
|
||||||
|
"status": "created",
|
||||||
|
"type": "batch_1",
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"count": 3,
|
||||||
|
"limit": 10,
|
||||||
|
"offset": 0,
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||||
|
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const { simpleBatchJobFactory } = require("../../factories")
|
||||||
|
|
||||||
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
|
const adminReqConfig = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("/admin/batch", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd })
|
||||||
|
medusaProcess = await setupServer({ cwd, verbose: false })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /admin/batch", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await simpleBatchJobFactory(dbConnection, {
|
||||||
|
id: "job_1",
|
||||||
|
type: "batch_1",
|
||||||
|
created_by: "admin_user",
|
||||||
|
})
|
||||||
|
await simpleBatchJobFactory(dbConnection, {
|
||||||
|
id: "job_2",
|
||||||
|
type: "batch_2",
|
||||||
|
created_by: "admin_user",
|
||||||
|
})
|
||||||
|
await simpleBatchJobFactory(dbConnection, {
|
||||||
|
id: "job_3",
|
||||||
|
type: "batch_2",
|
||||||
|
created_by: "admin_user",
|
||||||
|
})
|
||||||
|
await simpleBatchJobFactory(dbConnection, {
|
||||||
|
id: "job_4",
|
||||||
|
type: "batch_1",
|
||||||
|
created_by: "not_this_user",
|
||||||
|
})
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("lists batch jobs created by the user", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
const response = await api.get("/admin/batch", adminReqConfig)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.batch_jobs.length).toEqual(3)
|
||||||
|
expect(response.data).toMatchSnapshot({
|
||||||
|
batch_jobs: [
|
||||||
|
{
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./simple-payment-factory"
|
export * from "./simple-payment-factory"
|
||||||
|
export * from "./simple-batch-job-factory"
|
||||||
export * from "./simple-order-factory"
|
export * from "./simple-order-factory"
|
||||||
export * from "./simple-cart-factory"
|
export * from "./simple-cart-factory"
|
||||||
export * from "./simple-region-factory"
|
export * from "./simple-region-factory"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Connection } from "typeorm"
|
||||||
|
import { BatchJob, BatchJobStatus } from "@medusajs/medusa"
|
||||||
|
|
||||||
|
export type BatchJobFactoryData = {
|
||||||
|
id?: string
|
||||||
|
type?: string
|
||||||
|
status?: BatchJobStatus
|
||||||
|
created_by?: string
|
||||||
|
context?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const simpleBatchJobFactory = async (
|
||||||
|
connection: Connection,
|
||||||
|
data: BatchJobFactoryData = {}
|
||||||
|
): Promise<BatchJob> => {
|
||||||
|
const manager = connection.manager
|
||||||
|
|
||||||
|
const job = manager.create(BatchJob, {
|
||||||
|
id: data.id,
|
||||||
|
status: data.status ?? BatchJobStatus.CREATED,
|
||||||
|
type: data.type ?? "test-job",
|
||||||
|
created_by: data.created_by ?? null,
|
||||||
|
context: data.context ?? {},
|
||||||
|
})
|
||||||
|
|
||||||
|
return await manager.save(job)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
import BatchJobService from "../../../services/batch-job"
|
||||||
|
|
||||||
|
export async function canAccessBatchJob(req, res, next) {
|
||||||
|
const id = req.params.id
|
||||||
|
const batchJobService: BatchJobService = req.scope.resolve("batchJobService")
|
||||||
|
const batch_job = req.batch_job ?? (await batchJobService.retrieve(id))
|
||||||
|
|
||||||
|
const userId = req.user.id ?? req.user.userId
|
||||||
|
if (batch_job.created_by !== userId) {
|
||||||
|
return next(
|
||||||
|
new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
"Cannot access a batch job that does not belong to the logged in user"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import BatchJobService from "../../../services/batch-job"
|
||||||
|
|
||||||
|
export async function getRequestedBatchJob(req, res, next) {
|
||||||
|
const id = req.params.id
|
||||||
|
const batchJobService: BatchJobService = req.scope.resolve("batchJobService")
|
||||||
|
|
||||||
|
try {
|
||||||
|
req.batch_job = await batchJobService.retrieve(id)
|
||||||
|
} catch (error) {
|
||||||
|
return next(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
next()
|
||||||
|
}
|
||||||
@@ -3,6 +3,9 @@ import { default as authenticate } from "./authenticate"
|
|||||||
import { default as normalizeQuery } from "./normalized-query"
|
import { default as normalizeQuery } from "./normalized-query"
|
||||||
import { default as wrap } from "./await-middleware"
|
import { default as wrap } from "./await-middleware"
|
||||||
|
|
||||||
|
export { getRequestedBatchJob } from "./batch-job/get-requested-batch-job"
|
||||||
|
export { canAccessBatchJob } from "./batch-job/can-access-batch-job"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
authenticate,
|
authenticate,
|
||||||
authenticateCustomer,
|
authenticateCustomer,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import { BatchJob } from "../../../.."
|
||||||
|
import { DeleteResponse, PaginatedResponse } from "../../../../types/common"
|
||||||
|
import middlewares from "../../../middlewares"
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
app.use("/batch", route)
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
"/",
|
||||||
|
middlewares.normalizeQuery(),
|
||||||
|
middlewares.wrap(require("./list-batch-jobs").default)
|
||||||
|
)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AdminBatchJobRes = {
|
||||||
|
batch_job: BatchJob
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AdminBatchJobDeleteRes = DeleteResponse
|
||||||
|
|
||||||
|
export type AdminBatchJobListRes = PaginatedResponse & {
|
||||||
|
batch_jobs: BatchJob[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultAdminBatchFields = [
|
||||||
|
"id",
|
||||||
|
"status",
|
||||||
|
"type",
|
||||||
|
"context",
|
||||||
|
"result",
|
||||||
|
"created_by",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"deleted_at",
|
||||||
|
]
|
||||||
|
|
||||||
|
export * from "./list-batch-jobs"
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
import { Type } from "class-transformer"
|
||||||
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsEnum,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
ValidateNested,
|
||||||
|
} from "class-validator"
|
||||||
|
import { pickBy, omit, identity } from "lodash"
|
||||||
|
import { defaultAdminBatchFields } from "."
|
||||||
|
import BatchJobService from "../../../../services/batch-job"
|
||||||
|
import { BatchJob } from "../../../../models"
|
||||||
|
import { BatchJobStatus } from "../../../../types/batch-job"
|
||||||
|
import { DateComparisonOperator } from "../../../../types/common"
|
||||||
|
import { IsType } from "../../../../utils/validators/is-type"
|
||||||
|
import { getListConfig } from "../../../../utils/get-query-config"
|
||||||
|
import { validator } from "../../../../utils/validator"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @oas [get] /batch
|
||||||
|
* operationId: "GetBatch"
|
||||||
|
* summary: "List Batch Jobs"
|
||||||
|
* description: "Retrieve a list of Batch Jobs."
|
||||||
|
* x-authenticated: true
|
||||||
|
* parameters:
|
||||||
|
* - (query) limit {string} The number of collections to return.
|
||||||
|
* - (query) offset {string} The offset of collections to return.
|
||||||
|
* - (query) type {string | string[]} Filter by the batch type
|
||||||
|
* - (query) status {string} Filter by the status of the batch operation
|
||||||
|
* - (query) order {string} Order used when retrieving batch jobs
|
||||||
|
* - (query) expand[] {string} (Comma separated) Which fields should be expanded in each order of the result.
|
||||||
|
* - (query) fields[] {string} (Comma separated) Which fields should be included in each order of the result.
|
||||||
|
* - (query) deleted_at {DateComparisonOperator} Date comparison for when resulting collections was deleted, i.e. less than, greater than etc.
|
||||||
|
* - (query) created_at {DateComparisonOperator} Date comparison for when resulting collections was created, i.e. less than, greater than etc.
|
||||||
|
* - (query) updated_at {DateComparisonOperator} Date comparison for when resulting collections was updated, i.e. less than, greater than etc.
|
||||||
|
* tags:
|
||||||
|
* - Batch Job
|
||||||
|
* responses:
|
||||||
|
* "200":
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* batch_job:
|
||||||
|
* $ref: "#/components/schemas/batch_job"
|
||||||
|
*/
|
||||||
|
export default async (req, res) => {
|
||||||
|
const { fields, expand, order, limit, offset, ...filterableFields } =
|
||||||
|
await validator(AdminGetBatchParams, req.query)
|
||||||
|
|
||||||
|
const batchService: BatchJobService = req.scope.resolve("batchJobService")
|
||||||
|
|
||||||
|
let orderBy: { [k: symbol]: "DESC" | "ASC" } | undefined
|
||||||
|
if (typeof order !== "undefined") {
|
||||||
|
if (order.startsWith("-")) {
|
||||||
|
const [, field] = order.split("-")
|
||||||
|
orderBy = { [field]: "DESC" }
|
||||||
|
} else {
|
||||||
|
orderBy = { [order]: "ASC" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listConfig = getListConfig<BatchJob>(
|
||||||
|
defaultAdminBatchFields as (keyof BatchJob)[],
|
||||||
|
[],
|
||||||
|
fields?.split(",") as (keyof BatchJob)[],
|
||||||
|
expand?.split(","),
|
||||||
|
limit,
|
||||||
|
offset,
|
||||||
|
orderBy
|
||||||
|
)
|
||||||
|
|
||||||
|
const created_by: string = req.user.id || req.user.userId
|
||||||
|
|
||||||
|
const [jobs, count] = await batchService.listAndCount(
|
||||||
|
pickBy(
|
||||||
|
{ created_by, ...filterableFields },
|
||||||
|
(val) => typeof val !== "undefined"
|
||||||
|
),
|
||||||
|
listConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
batch_jobs: jobs,
|
||||||
|
count,
|
||||||
|
offset: offset,
|
||||||
|
limit: limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminGetBatchPaginationParams {
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
limit = 10
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
expand?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
fields?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
order?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminGetBatchParams extends AdminGetBatchPaginationParams {
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@IsType([String, [String]])
|
||||||
|
id?: string | string[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@IsEnum(BatchJobStatus, { each: true })
|
||||||
|
status?: BatchJobStatus[]
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsOptional()
|
||||||
|
type?: string[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
created_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
updated_at?: DateComparisonOperator
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import noteRoutes from "./notes"
|
|||||||
import notificationRoutes from "./notifications"
|
import notificationRoutes from "./notifications"
|
||||||
import orderRoutes from "./orders"
|
import orderRoutes from "./orders"
|
||||||
import priceListRoutes from "./price-lists"
|
import priceListRoutes from "./price-lists"
|
||||||
|
import batchRoutes from "./batch"
|
||||||
import productTagRoutes from "./product-tags"
|
import productTagRoutes from "./product-tags"
|
||||||
import productTypesRoutes from "./product-types"
|
import productTypesRoutes from "./product-types"
|
||||||
import productRoutes from "./products"
|
import productRoutes from "./products"
|
||||||
@@ -63,6 +64,7 @@ export default (app, container, config) => {
|
|||||||
|
|
||||||
appRoutes(route)
|
appRoutes(route)
|
||||||
productRoutes(route)
|
productRoutes(route)
|
||||||
|
batchRoutes(route)
|
||||||
userRoutes(route)
|
userRoutes(route)
|
||||||
regionRoutes(route)
|
regionRoutes(route)
|
||||||
shippingOptionRoutes(route)
|
shippingOptionRoutes(route)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export * from "./api"
|
export * from "./api"
|
||||||
export * from "./interfaces"
|
export * from "./interfaces"
|
||||||
export * from "./types/price-list"
|
export * from "./types/price-list"
|
||||||
|
export * from "./types/batch-job"
|
||||||
export * from "./models"
|
export * from "./models"
|
||||||
export * from "./services"
|
export * from "./services"
|
||||||
@@ -1,11 +1,5 @@
|
|||||||
export * from "./shipping-tax-rate"
|
|
||||||
export * from "./product-tax-rate"
|
|
||||||
export * from "./product-type-tax-rate"
|
|
||||||
export * from "./tax-rate"
|
|
||||||
export * from "./shipping-method-tax-line"
|
|
||||||
export * from "./line-item-tax-line"
|
|
||||||
export * from "./line-item-adjustment"
|
|
||||||
export * from "./address"
|
export * from "./address"
|
||||||
|
export * from "./batch-job"
|
||||||
export * from "./cart"
|
export * from "./cart"
|
||||||
export * from "./claim-image"
|
export * from "./claim-image"
|
||||||
export * from "./claim-item"
|
export * from "./claim-item"
|
||||||
@@ -17,12 +11,12 @@ export * from "./custom-shipping-option"
|
|||||||
export * from "./customer"
|
export * from "./customer"
|
||||||
export * from "./customer-group"
|
export * from "./customer-group"
|
||||||
export * from "./discount"
|
export * from "./discount"
|
||||||
|
export * from "./discount-condition"
|
||||||
export * from "./discount-condition-customer-group"
|
export * from "./discount-condition-customer-group"
|
||||||
|
export * from "./discount-condition-product"
|
||||||
export * from "./discount-condition-product-collection"
|
export * from "./discount-condition-product-collection"
|
||||||
export * from "./discount-condition-product-tag"
|
export * from "./discount-condition-product-tag"
|
||||||
export * from "./discount-condition-product-type"
|
export * from "./discount-condition-product-type"
|
||||||
export * from "./discount-condition-product"
|
|
||||||
export * from "./discount-condition"
|
|
||||||
export * from "./discount-rule"
|
export * from "./discount-rule"
|
||||||
export * from "./draft-order"
|
export * from "./draft-order"
|
||||||
export * from "./fulfillment"
|
export * from "./fulfillment"
|
||||||
@@ -34,6 +28,8 @@ export * from "./idempotency-key"
|
|||||||
export * from "./image"
|
export * from "./image"
|
||||||
export * from "./invite"
|
export * from "./invite"
|
||||||
export * from "./line-item"
|
export * from "./line-item"
|
||||||
|
export * from "./line-item-adjustment"
|
||||||
|
export * from "./line-item-tax-line"
|
||||||
export * from "./money-amount"
|
export * from "./money-amount"
|
||||||
export * from "./note"
|
export * from "./note"
|
||||||
export * from "./notification"
|
export * from "./notification"
|
||||||
@@ -48,7 +44,9 @@ export * from "./product-collection"
|
|||||||
export * from "./product-option"
|
export * from "./product-option"
|
||||||
export * from "./product-option-value"
|
export * from "./product-option-value"
|
||||||
export * from "./product-tag"
|
export * from "./product-tag"
|
||||||
|
export * from "./product-tax-rate"
|
||||||
export * from "./product-type"
|
export * from "./product-type"
|
||||||
|
export * from "./product-type-tax-rate"
|
||||||
export * from "./product-variant"
|
export * from "./product-variant"
|
||||||
export * from "./refund"
|
export * from "./refund"
|
||||||
export * from "./region"
|
export * from "./region"
|
||||||
@@ -56,11 +54,14 @@ export * from "./return"
|
|||||||
export * from "./return-item"
|
export * from "./return-item"
|
||||||
export * from "./return-reason"
|
export * from "./return-reason"
|
||||||
export * from "./shipping-method"
|
export * from "./shipping-method"
|
||||||
|
export * from "./shipping-method-tax-line"
|
||||||
export * from "./shipping-option"
|
export * from "./shipping-option"
|
||||||
export * from "./shipping-option-requirement"
|
export * from "./shipping-option-requirement"
|
||||||
export * from "./shipping-profile"
|
export * from "./shipping-profile"
|
||||||
|
export * from "./shipping-tax-rate"
|
||||||
export * from "./staged-job"
|
export * from "./staged-job"
|
||||||
export * from "./store"
|
export * from "./store"
|
||||||
export * from "./swap"
|
export * from "./swap"
|
||||||
export * from "./user"
|
|
||||||
export * from "./tax-provider"
|
export * from "./tax-provider"
|
||||||
|
export * from "./tax-rate"
|
||||||
|
export * from "./user"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { EntityRepository, Repository } from "typeorm"
|
||||||
|
import { BatchJob } from "../models"
|
||||||
|
|
||||||
|
@EntityRepository(BatchJob)
|
||||||
|
export class BatchJobRepository extends Repository<BatchJob> {}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { EntityManager } from "typeorm"
|
||||||
|
|
||||||
|
import { BatchJob } from "../models"
|
||||||
|
import { BatchJobRepository } from "../repositories/batch-job"
|
||||||
|
import { FilterableBatchJobProps } from "../types/batch-job"
|
||||||
|
import { FindConfig } from "../types/common"
|
||||||
|
import { TransactionBaseService } from "../interfaces"
|
||||||
|
import { buildQuery, validateId } from "../utils"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
manager: EntityManager
|
||||||
|
batchJobRepository: typeof BatchJobRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
class BatchJobService extends TransactionBaseService<BatchJobService> {
|
||||||
|
protected manager_: EntityManager
|
||||||
|
protected transactionManager_: EntityManager | undefined
|
||||||
|
protected readonly batchJobRepository_: typeof BatchJobRepository
|
||||||
|
|
||||||
|
static readonly Events = {
|
||||||
|
CREATED: "batch.created",
|
||||||
|
UPDATED: "batch.updated",
|
||||||
|
CANCELED: "batch.canceled",
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor({ manager, batchJobRepository }: InjectedDependencies) {
|
||||||
|
super({ manager, batchJobRepository })
|
||||||
|
|
||||||
|
this.manager_ = manager
|
||||||
|
this.batchJobRepository_ = batchJobRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
async retrieve(
|
||||||
|
batchJobId: string,
|
||||||
|
config: FindConfig<BatchJob> = {}
|
||||||
|
): Promise<BatchJob | never> {
|
||||||
|
return await this.atomicPhase_(
|
||||||
|
async (transactionManager: EntityManager) => {
|
||||||
|
const batchJobRepo = transactionManager.getCustomRepository(
|
||||||
|
this.batchJobRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const query = buildQuery<BatchJob>({ id: batchJobId }, config)
|
||||||
|
const batchJob = await batchJobRepo.findOne(query)
|
||||||
|
|
||||||
|
if (!batchJob) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Batch job with id ${batchJobId} was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return batchJob
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async listAndCount(
|
||||||
|
selector: FilterableBatchJobProps = {},
|
||||||
|
config: FindConfig<BatchJob> = { skip: 0, take: 20 }
|
||||||
|
): Promise<[BatchJob[], number]> {
|
||||||
|
return await this.atomicPhase_(
|
||||||
|
async (manager: EntityManager): Promise<[BatchJob[], number]> => {
|
||||||
|
const batchJobRepo = manager.getCustomRepository(
|
||||||
|
this.batchJobRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const query = buildQuery(selector, config)
|
||||||
|
return await batchJobRepo.findAndCount(query)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BatchJobService
|
||||||
@@ -1,6 +1,46 @@
|
|||||||
|
import { Type } from "class-transformer"
|
||||||
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsEnum,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
ValidateNested,
|
||||||
|
} from "class-validator"
|
||||||
|
import { IsType } from "../utils/validators/is-type"
|
||||||
|
import { DateComparisonOperator } from "./common"
|
||||||
|
|
||||||
export enum BatchJobStatus {
|
export enum BatchJobStatus {
|
||||||
CREATED = "created",
|
CREATED = "created",
|
||||||
PROCESSING = "processing",
|
PROCESSING = "processing",
|
||||||
AWAITING_CONFIRMATION = "awaiting_confirmation",
|
AWAITING_CONFIRMATION = "awaiting_confirmation",
|
||||||
COMPLETED = "completed",
|
COMPLETED = "completed",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FilterableBatchJobProps {
|
||||||
|
@IsOptional()
|
||||||
|
@IsType([String, [String]])
|
||||||
|
id?: string | string[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(BatchJobStatus, { each: true })
|
||||||
|
status?: BatchJobStatus[]
|
||||||
|
|
||||||
|
@IsArray()
|
||||||
|
@IsOptional()
|
||||||
|
type?: string[]
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
@IsType([String, [String]])
|
||||||
|
created_by?: string | string[]
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
created_at?: DateComparisonOperator
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => DateComparisonOperator)
|
||||||
|
updated_at?: DateComparisonOperator
|
||||||
|
}
|
||||||
Reference in new issue
Block a user