Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions packages/plugin-import-export/src/import/batchProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,16 @@ async function processImportBatch({
delete updateData.createdAt
delete updateData.updatedAt

// Only handle _status for versioned collections
let draftOption: boolean | undefined
if (collectionHasVersions) {
// Use defaultVersionStatus from config if _status not provided
const statusValue = updateData._status || options.defaultVersionStatus
const isPublished = statusValue !== 'draft'
draftOption = !isPublished
updateData._status = statusValue
}

// Check if we have multi-locale data and extract it
const { flatData, hasMultiLocale, localeUpdates } = extractMultiLocaleData(
updateData,
Expand Down Expand Up @@ -389,7 +399,7 @@ async function processImportBatch({
collection: collectionSlug,
data: flatData,
depth: 0,
// Don't specify draft - this creates a new draft for versioned collections
draft: draftOption,
overrideAccess: false,
req: defaultLocaleReq,
user,
Expand Down Expand Up @@ -428,14 +438,12 @@ async function processImportBatch({
})
}

// Update the document - don't specify draft to let Payload handle versions properly
// This will create a new draft version for collections with versions enabled
savedDocument = await req.payload.update({
id: existingDoc.id as number | string,
collection: collectionSlug,
data: updateData,
depth: 0,
// Don't specify draft - this creates a new draft for versioned collections
draft: draftOption,
overrideAccess: false,
req,
user,
Expand Down
76 changes: 76 additions & 0 deletions test/plugin-import-export/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3298,6 +3298,13 @@ describe('@payloadcms/plugin-import-export', () => {
expect(draftPage.title).toBe(`Upsert Test ${timestamp} Updated`)
expect(draftPage.excerpt).toBe('updated')

// Pages has no defaultVersionStatus override, so it falls back to 'published' -
// the update is expected to apply directly to the published version too.
expect(publishedPage).toBeDefined()
expect(publishedPage._status).toBe('published')
expect(publishedPage.title).toBe(`Upsert Test ${timestamp} Updated`)
expect(publishedPage.excerpt).toBe('updated')

const newPages = await payload.find({
collection: 'pages',
where: {
Expand Down Expand Up @@ -6197,6 +6204,75 @@ describe('@payloadcms/plugin-import-export', () => {
},
})
})

it('should preserve the published version and create a draft when updating with defaultVersionStatus draft', async () => {
const timestamp = Date.now()
const existingDoc = await payload.create({
collection: 'posts-imports-only',
draft: false,
data: {
title: `Draft Status Update Test ${timestamp}`,
_status: 'published',
},
})

const csvContent =
'id,title\n' + `${existingDoc.id},"Draft Status Update Test ${timestamp} Updated"`
const csvBuffer = Buffer.from(csvContent)

let importDoc = await payload.create({
collection: 'imports',
user,
data: {
collectionSlug: 'posts-imports-only',
importMode: 'update',
matchField: 'id',
},
file: {
data: csvBuffer,
mimetype: 'text/csv',
name: 'draft-status-update-test.csv',
size: csvBuffer.length,
},
})

await payload.jobs.run()

importDoc = await payload.findByID({
collection: 'imports',
id: importDoc.id,
})

expect(importDoc.status).toBe('completed')
expect(importDoc.summary?.updated).toBe(1)
expect(importDoc.summary?.issues).toBe(0)

// The row omitted `_status`, so the plugin's `defaultVersionStatus: 'draft'`
// config for this collection should apply - the published version must stay
// untouched and the incoming data should land in a new draft version instead.
const publishedDoc = await payload.findByID({
collection: 'posts-imports-only',
id: existingDoc.id,
draft: false,
})

expect(publishedDoc._status).toBe('published')
expect(publishedDoc.title).toBe(`Draft Status Update Test ${timestamp}`)

const draftDoc = await payload.findByID({
collection: 'posts-imports-only',
id: existingDoc.id,
draft: true,
})

expect(draftDoc._status).toBe('draft')
expect(draftDoc.title).toBe(`Draft Status Update Test ${timestamp} Updated`)

await payload.delete({
collection: 'posts-imports-only',
id: existingDoc.id,
})
})
})
})

Expand Down
Loading