diff --git a/packages/db-mongodb/src/updateVersion.ts b/packages/db-mongodb/src/updateVersion.ts index 94241118604..768a0b7b0f0 100644 --- a/packages/db-mongodb/src/updateVersion.ts +++ b/packages/db-mongodb/src/updateVersion.ts @@ -1,4 +1,4 @@ -import type { MongooseUpdateQueryOptions } from 'mongoose' +import type { MongooseUpdateQueryOptions, UpdateQuery } from 'mongoose' import { buildVersionCollectionFields, type UpdateVersion } from 'payload' @@ -8,6 +8,7 @@ import { buildQuery } from './queries/buildQuery.js' import { buildProjectionFromSelect } from './utilities/buildProjectionFromSelect.js' import { getCollection } from './utilities/getEntity.js' import { getSession } from './utilities/getSession.js' +import { handleError } from './utilities/handleError.js' import { transform } from './utilities/transform.js' export const updateVersion: UpdateVersion = async function updateVersion( @@ -42,7 +43,42 @@ export const updateVersion: UpdateVersion = async function updateVersion( where: whereToUse, }) - transform({ adapter: this, data: versionData, fields, operation: 'write' }) + let updateData: UpdateQuery = versionData + + const $inc: Record = {} + const $push: Record = {} + const $addToSet: Record = {} + const $pull: Record = {} + + transform({ + $addToSet, + $inc, + $pull, + $push, + adapter: this, + data: versionData, + fields, + operation: 'write', + }) + + const updateOps: UpdateQuery = {} + + if (Object.keys($inc).length) { + updateOps.$inc = $inc + } + if (Object.keys($push).length) { + updateOps.$push = $push + } + if (Object.keys($addToSet).length) { + updateOps.$addToSet = $addToSet + } + if (Object.keys($pull).length) { + updateOps.$pull = $pull + } + if (Object.keys(updateOps).length) { + updateOps.$set = updateData + updateData = updateOps + } const options: MongooseUpdateQueryOptions = { ...optionsArgs, @@ -58,18 +94,27 @@ export const updateVersion: UpdateVersion = async function updateVersion( timestamps: false, } + let result + + try { + if (returning === false) { + await Model.updateOne(query, updateData, options) + } else { + result = await Model.findOneAndUpdate(query, updateData, options) + } + } catch (error) { + handleError({ collection: collectionSlug, error, req }) + } + if (returning === false) { - await Model.updateOne(query, versionData, options) return null } - const doc = await Model.findOneAndUpdate(query, versionData, options) - - if (!doc) { + if (!result) { return null } - transform({ adapter: this, data: doc, fields, operation: 'read' }) + transform({ adapter: this, data: result, fields, operation: 'read' }) - return doc + return result } diff --git a/packages/plugin-ecommerce/src/endpoints/confirmOrder.ts b/packages/plugin-ecommerce/src/endpoints/confirmOrder.ts index 99bafd80c56..f940d809b10 100644 --- a/packages/plugin-ecommerce/src/endpoints/confirmOrder.ts +++ b/packages/plugin-ecommerce/src/endpoints/confirmOrder.ts @@ -1,4 +1,11 @@ -import { addDataAndFileToRequest, type DefaultDocumentIDType, type Endpoint } from 'payload' +import { + addDataAndFileToRequest, + type DefaultDocumentIDType, + type Endpoint, + type Payload, + type PayloadRequest, +} from 'payload' +import { hasDraftsEnabled } from 'payload/shared' import type { CurrenciesConfig, PaymentAdapter, ProductsValidation } from '../types/index.js' @@ -37,6 +44,60 @@ type Args = { type ConfirmOrderHandler = (args: Args) => Endpoint['handler'] +type DecrementInventoryArgs = { + collectionSlug: string + id: DefaultDocumentIDType + payload: Payload + quantity: number + req: PayloadRequest +} + +async function decrementInventoryForOrder({ + id, + collectionSlug, + payload, + quantity, + req, +}: DecrementInventoryArgs) { + const inventoryUpdate = { + inventory: { + $inc: quantity * -1, + }, + } + + await payload.db.updateOne({ + id, + collection: collectionSlug, + data: inventoryUpdate, + req, + }) + + const collectionConfig = payload.collections[collectionSlug]?.config + if (!collectionConfig || !hasDraftsEnabled(collectionConfig)) { + return + } + + if (payload.db.name !== 'mongoose') { + return + } + + await payload.db.updateVersion({ + collection: collectionSlug, + req, + returning: false, + versionData: { + version: { + inventory: { + $inc: quantity * -1, + }, + }, + }, + where: { + and: [{ latest: { equals: true } }, { parent: { equals: id } }], + }, + }) +} + /** * Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider. * This is the first step in the payment process. @@ -184,26 +245,22 @@ export const confirmOrderHandler: ConfirmOrderHandler = if (item.variant) { const id = typeof item.variant === 'object' ? item.variant.id : item.variant - await payload.db.updateOne({ + await decrementInventoryForOrder({ id, - collection: variantsSlug, - data: { - inventory: { - $inc: item.quantity * -1, - }, - }, + collectionSlug: variantsSlug, + payload, + quantity: item.quantity, + req, }) } else if (item.product) { const id = typeof item.product === 'object' ? item.product.id : item.product - await payload.db.updateOne({ + await decrementInventoryForOrder({ id, - collection: productsSlug, - data: { - inventory: { - $inc: item.quantity * -1, - }, - }, + collectionSlug: productsSlug, + payload, + quantity: item.quantity, + req, }) } }