@open-mercato/core 0.6.1-develop.3219.1.ae5c8a5935 → 0.6.1-develop.3246.1.dbef9d7392

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/cli.js +91 -8
  3. package/dist/modules/auth/cli.js.map +2 -2
  4. package/dist/modules/auth/lib/setup-app.js +21 -0
  5. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  6. package/dist/modules/customers/api/companies/route.js +11 -1
  7. package/dist/modules/customers/api/companies/route.js.map +2 -2
  8. package/dist/modules/customers/api/people/route.js +11 -1
  9. package/dist/modules/customers/api/people/route.js.map +2 -2
  10. package/dist/modules/customers/backend/customers/companies/page.js +78 -35
  11. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  12. package/dist/modules/customers/backend/customers/deals/page.js +74 -30
  13. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  14. package/dist/modules/customers/backend/customers/people/page.js +78 -35
  15. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  16. package/dist/modules/customers/commands/people.js +20 -0
  17. package/dist/modules/customers/commands/people.js.map +2 -2
  18. package/package.json +5 -5
  19. package/src/modules/auth/AGENTS.md +23 -0
  20. package/src/modules/auth/cli.ts +117 -8
  21. package/src/modules/auth/lib/setup-app.ts +28 -0
  22. package/src/modules/customers/api/companies/route.ts +10 -0
  23. package/src/modules/customers/api/people/route.ts +10 -0
  24. package/src/modules/customers/backend/customers/companies/page.tsx +95 -35
  25. package/src/modules/customers/backend/customers/deals/page.tsx +91 -30
  26. package/src/modules/customers/backend/customers/people/page.tsx +96 -35
  27. package/src/modules/customers/commands/people.ts +30 -0
  28. package/src/modules/customers/i18n/de.json +8 -0
  29. package/src/modules/customers/i18n/en.json +8 -0
  30. package/src/modules/customers/i18n/es.json +8 -0
  31. package/src/modules/customers/i18n/pl.json +8 -0
@@ -10,6 +10,9 @@ import { Button } from '@open-mercato/ui/primitives/button'
10
10
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
11
11
  import { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
12
12
  import { buildCrudExportUrl } from '@open-mercato/ui/backend/utils/crud'
13
+ import { groupBulkDeleteFailures, runBulkDelete } from '@open-mercato/ui/backend/utils/bulkDelete'
14
+ import { coalesceLastOperations } from '@open-mercato/ui/backend/operations/store'
15
+ import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
13
16
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
14
17
  import { E } from '#generated/entities.ids.generated'
15
18
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
@@ -167,6 +170,27 @@ export default function CustomersPeoplePage() {
167
170
  setPageSize(newSize)
168
171
  setPage(1)
169
172
  }, [])
173
+
174
+ const bulkMutationContextId = 'customers-people-list:bulk-delete'
175
+ const { runMutation: runBulkMutation, retryLastMutation: retryBulkMutation } = useGuardedMutation<{
176
+ formId: string
177
+ resourceKind: string
178
+ retryLastMutation: () => Promise<boolean>
179
+ }>({
180
+ contextId: bulkMutationContextId,
181
+ blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),
182
+ })
183
+ const singleMutationContextId = 'customers-people-list:single-delete'
184
+ const { runMutation: runSingleMutation, retryLastMutation: retrySingleMutation } = useGuardedMutation<{
185
+ formId: string
186
+ resourceKind: string
187
+ resourceId: string
188
+ retryLastMutation: () => Promise<boolean>
189
+ }>({
190
+ contextId: singleMutationContextId,
191
+ blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),
192
+ })
193
+
170
194
  const fetchDictionaryEntries = React.useCallback(async (kind: DictionaryKindKey) => {
171
195
  try {
172
196
  const data = await ensureCustomerDictionary(queryClient, kind, scopeVersion)
@@ -467,14 +491,24 @@ export default function CustomersPeoplePage() {
467
491
  })
468
492
  if (!confirmed) return
469
493
  try {
470
- await apiCallOrThrow(
471
- `/api/customers/people?id=${encodeURIComponent(person.id)}`,
472
- {
473
- method: 'DELETE',
474
- headers: { 'content-type': 'application/json' },
494
+ await runSingleMutation({
495
+ operation: async () => {
496
+ await apiCallOrThrow(
497
+ `/api/customers/people?id=${encodeURIComponent(person.id)}`,
498
+ {
499
+ method: 'DELETE',
500
+ headers: { 'content-type': 'application/json' },
501
+ },
502
+ { errorMessage: t('customers.people.list.deleteError') },
503
+ )
475
504
  },
476
- { errorMessage: t('customers.people.list.deleteError') },
477
- )
505
+ context: {
506
+ formId: singleMutationContextId,
507
+ resourceKind: 'customers.person',
508
+ resourceId: person.id,
509
+ retryLastMutation: retrySingleMutation,
510
+ },
511
+ })
478
512
  setRows((prev) => prev.filter((row) => row.id !== person.id))
479
513
  setTotal((prev) => Math.max(prev - 1, 0))
480
514
  handleRefresh()
@@ -483,7 +517,7 @@ export default function CustomersPeoplePage() {
483
517
  const message = err instanceof Error ? err.message : t('customers.people.list.deleteError')
484
518
  flash(message, 'error')
485
519
  }
486
- }, [confirm, handleRefresh, t])
520
+ }, [confirm, handleRefresh, retrySingleMutation, runSingleMutation, singleMutationContextId, t])
487
521
 
488
522
  const handleBulkDelete = React.useCallback(async (selectedRows: PersonRow[]) => {
489
523
  const confirmed = await confirm({
@@ -492,44 +526,71 @@ export default function CustomersPeoplePage() {
492
526
  variant: 'destructive',
493
527
  })
494
528
  if (!confirmed) return false
495
- let deletedCount = 0
496
- const failedIds: string[] = []
497
- for (const row of selectedRows) {
498
- try {
499
- await apiCallOrThrow(`/api/customers/people?id=${encodeURIComponent(row.id)}`, {
500
- method: 'DELETE',
501
- headers: { 'content-type': 'application/json' },
529
+
530
+ const { succeeded, failures } = await runBulkMutation({
531
+ operation: async () =>
532
+ runBulkDelete(
533
+ selectedRows,
534
+ async (row) => {
535
+ await apiCallOrThrow(`/api/customers/people?id=${encodeURIComponent(row.id)}`, {
536
+ method: 'DELETE',
537
+ headers: { 'content-type': 'application/json' },
538
+ })
539
+ },
540
+ {
541
+ fallbackErrorMessage: t('customers.people.list.deleteError', 'Failed to delete person.'),
542
+ logTag: 'customers.people.list',
543
+ },
544
+ ),
545
+ context: {
546
+ formId: bulkMutationContextId,
547
+ resourceKind: 'customers.person',
548
+ retryLastMutation: retryBulkMutation,
549
+ },
550
+ })
551
+
552
+ if (succeeded.length > 0) {
553
+ const succeededIds = new Set(succeeded.map((r) => r.id))
554
+ setRows((prev) => prev.filter((r) => !succeededIds.has(r.id)))
555
+ setTotal((prev) => Math.max(0, prev - succeeded.length))
556
+ setReloadToken((prev) => prev + 1)
557
+ if (succeeded.length > 1) {
558
+ coalesceLastOperations(succeeded.length, {
559
+ commandId: 'customers.people.delete',
560
+ actionLabel: t('customers.people.list.bulkDelete.operationLabel', 'Delete {count} people', { count: succeeded.length }),
561
+ resourceKind: 'customers.person',
502
562
  })
503
- deletedCount++
504
- } catch (err) {
505
- failedIds.push(row.id)
506
- console.warn('[customers.people.list] bulk delete failed', row.id, err)
507
563
  }
508
- }
509
- if (deletedCount > 0) {
510
- setRows((prev) => {
511
- const succeeded = new Set(selectedRows.map((r) => r.id).filter((id) => !failedIds.includes(id)))
512
- return prev.filter((r) => !succeeded.has(r.id))
513
- })
514
- setTotal((prev) => Math.max(0, prev - deletedCount))
515
- if (failedIds.length === 0) {
516
- flash(t('customers.people.list.bulkDelete.success', '{count} people deleted', { count: deletedCount }), 'success')
564
+ if (failures.length === 0) {
565
+ flash(
566
+ t('customers.people.list.bulkDelete.success', '{count} people deleted', { count: succeeded.length }),
567
+ 'success',
568
+ )
517
569
  } else {
518
570
  flash(
519
571
  t('customers.people.list.bulkDelete.partial', '{deleted} of {total} people deleted; {failed} failed', {
520
- deleted: deletedCount,
572
+ deleted: succeeded.length,
521
573
  total: selectedRows.length,
522
- failed: failedIds.length,
574
+ failed: failures.length,
523
575
  }),
524
576
  'warning',
525
577
  )
526
578
  }
527
- setReloadToken((prev) => prev + 1)
528
- } else if (failedIds.length > 0) {
529
- flash(t('customers.people.list.bulkDelete.failed', 'Failed to delete {count} people', { count: failedIds.length }), 'error')
530
579
  }
531
- return deletedCount > 0
532
- }, [confirm, t])
580
+
581
+ for (const group of groupBulkDeleteFailures(failures)) {
582
+ const message = group.count === 1
583
+ ? group.sampleMessage
584
+ : t(
585
+ 'customers.people.list.bulkDelete.failedGroup',
586
+ '{count} people could not be deleted: {message}',
587
+ { count: group.count, message: group.sampleMessage },
588
+ )
589
+ flash(message, 'error')
590
+ }
591
+
592
+ return succeeded.length > 0
593
+ }, [bulkMutationContextId, confirm, retryBulkMutation, runBulkMutation, t])
533
594
 
534
595
  const handleFiltersApply = React.useCallback((values: FilterValues) => {
535
596
  const next: FilterValues = {}
@@ -234,6 +234,29 @@ function normalizeEmail(value: string | null | undefined): string | null {
234
234
  return normalized ? normalized.toLowerCase() : null
235
235
  }
236
236
 
237
+ type PersonDeleteBlockerCounts = {
238
+ dealLinks: number
239
+ }
240
+
241
+ function buildPersonHasDependentsError(
242
+ translate: (key: string, fallback?: string, params?: Record<string, string | number>) => string,
243
+ counts: PersonDeleteBlockerCounts,
244
+ ): CrudHttpError {
245
+ const blockers: string[] = []
246
+ if (counts.dealLinks > 0) {
247
+ blockers.push(
248
+ translate('customers.people.delete.blockers.deals', 'linked deals ({{count}})', { count: counts.dealLinks }),
249
+ )
250
+ }
251
+ const summary = blockers.join(', ')
252
+ const message = translate(
253
+ 'customers.people.delete.blocked',
254
+ 'Cannot delete person: {{blockers}}. Please unlink or reassign first.',
255
+ { blockers: summary },
256
+ )
257
+ return new CrudHttpError(422, { error: message, code: 'PERSON_HAS_DEPENDENTS' })
258
+ }
259
+
237
260
  function serializePersonSnapshot(
238
261
  entity: CustomerEntity,
239
262
  profile: CustomerPersonProfile,
@@ -1010,6 +1033,13 @@ const deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; quer
1010
1033
  const record = assertFound(entity, 'Person not found')
1011
1034
  ensureTenantScope(ctx, record.tenantId)
1012
1035
  ensureOrganizationScope(ctx, record.organizationId)
1036
+
1037
+ const dealLinks = await em.count(CustomerDealPersonLink, { person: record })
1038
+ if (dealLinks > 0) {
1039
+ const { translate } = await resolveTranslations()
1040
+ throw buildPersonHasDependentsError(translate, { dealLinks })
1041
+ }
1042
+
1013
1043
  const profile = await em.findOne(CustomerPersonProfile, { entity: record })
1014
1044
  if (profile) em.remove(profile)
1015
1045
  await em.nativeDelete(CustomerAddress, { entity: record, organizationId: record.organizationId, tenantId: record.tenantId })
@@ -518,6 +518,8 @@
518
518
  "customers.companies.list.bulkDelete.action": "Delete selected",
519
519
  "customers.companies.list.bulkDelete.description": "This action cannot be undone.",
520
520
  "customers.companies.list.bulkDelete.failed": "{count} Unternehmen konnten nicht gelöscht werden",
521
+ "customers.companies.list.bulkDelete.failedGroup": "{count} Unternehmen konnten nicht gelöscht werden: {message}",
522
+ "customers.companies.list.bulkDelete.operationLabel": "{count} Unternehmen löschen",
521
523
  "customers.companies.list.bulkDelete.partial": "{deleted} von {total} Unternehmen gelöscht; {failed} fehlgeschlagen",
522
524
  "customers.companies.list.bulkDelete.success": "{count} companies deleted",
523
525
  "customers.companies.list.bulkDelete.title": "Delete {count} companies?",
@@ -847,6 +849,8 @@
847
849
  "customers.deals.list.bulkDelete.action": "Delete selected",
848
850
  "customers.deals.list.bulkDelete.description": "This action cannot be undone.",
849
851
  "customers.deals.list.bulkDelete.failed": "{count} Deals konnten nicht gelöscht werden",
852
+ "customers.deals.list.bulkDelete.failedGroup": "{count} Deals konnten nicht gelöscht werden: {message}",
853
+ "customers.deals.list.bulkDelete.operationLabel": "{count} Deals löschen",
850
854
  "customers.deals.list.bulkDelete.partial": "{deleted} von {total} Deals gelöscht; {failed} fehlgeschlagen",
851
855
  "customers.deals.list.bulkDelete.success": "{count} deals deleted",
852
856
  "customers.deals.list.bulkDelete.title": "Delete {count} deals?",
@@ -1096,6 +1100,8 @@
1096
1100
  "customers.people.decisionMakers.label": "Decision Makers",
1097
1101
  "customers.people.decisionMakers.more": "more",
1098
1102
  "customers.people.decisionMakers.sendInvitation": "Send invitation",
1103
+ "customers.people.delete.blocked": "Person kann nicht gelöscht werden: {{blockers}}. Bitte zuerst entkoppeln oder neu zuweisen.",
1104
+ "customers.people.delete.blockers.deals": "verknüpfte Deals ({{count}})",
1099
1105
  "customers.people.detail.actions.addDeal": "Deal hinzufügen",
1100
1106
  "customers.people.detail.actions.backToList": "Zurück zur Personenliste",
1101
1107
  "customers.people.detail.actions.cancel": "Abbrechen",
@@ -1637,6 +1643,8 @@
1637
1643
  "customers.people.list.bulkDelete.action": "Delete selected",
1638
1644
  "customers.people.list.bulkDelete.description": "This action cannot be undone.",
1639
1645
  "customers.people.list.bulkDelete.failed": "{count} Personen konnten nicht gelöscht werden",
1646
+ "customers.people.list.bulkDelete.failedGroup": "{count} Personen konnten nicht gelöscht werden: {message}",
1647
+ "customers.people.list.bulkDelete.operationLabel": "{count} Personen löschen",
1640
1648
  "customers.people.list.bulkDelete.partial": "{deleted} von {total} Personen gelöscht; {failed} fehlgeschlagen",
1641
1649
  "customers.people.list.bulkDelete.success": "{count} people deleted",
1642
1650
  "customers.people.list.bulkDelete.title": "Delete {count} people?",
@@ -518,6 +518,8 @@
518
518
  "customers.companies.list.bulkDelete.action": "Delete selected",
519
519
  "customers.companies.list.bulkDelete.description": "This action cannot be undone.",
520
520
  "customers.companies.list.bulkDelete.failed": "Failed to delete {count} companies",
521
+ "customers.companies.list.bulkDelete.failedGroup": "{count} companies could not be deleted: {message}",
522
+ "customers.companies.list.bulkDelete.operationLabel": "Delete {count} companies",
521
523
  "customers.companies.list.bulkDelete.partial": "{deleted} of {total} companies deleted; {failed} failed",
522
524
  "customers.companies.list.bulkDelete.success": "{count} companies deleted",
523
525
  "customers.companies.list.bulkDelete.title": "Delete {count} companies?",
@@ -847,6 +849,8 @@
847
849
  "customers.deals.list.bulkDelete.action": "Delete selected",
848
850
  "customers.deals.list.bulkDelete.description": "This action cannot be undone.",
849
851
  "customers.deals.list.bulkDelete.failed": "Failed to delete {count} deals",
852
+ "customers.deals.list.bulkDelete.failedGroup": "{count} deals could not be deleted: {message}",
853
+ "customers.deals.list.bulkDelete.operationLabel": "Delete {count} deals",
850
854
  "customers.deals.list.bulkDelete.partial": "{deleted} of {total} deals deleted; {failed} failed",
851
855
  "customers.deals.list.bulkDelete.success": "{count} deals deleted",
852
856
  "customers.deals.list.bulkDelete.title": "Delete {count} deals?",
@@ -1096,6 +1100,8 @@
1096
1100
  "customers.people.decisionMakers.label": "Decision Makers",
1097
1101
  "customers.people.decisionMakers.more": "more",
1098
1102
  "customers.people.decisionMakers.sendInvitation": "Send invitation",
1103
+ "customers.people.delete.blocked": "Cannot delete person: {{blockers}}. Please unlink or reassign first.",
1104
+ "customers.people.delete.blockers.deals": "linked deals ({{count}})",
1099
1105
  "customers.people.detail.actions.addDeal": "Add deal",
1100
1106
  "customers.people.detail.actions.backToList": "Back to people",
1101
1107
  "customers.people.detail.actions.cancel": "Cancel",
@@ -1637,6 +1643,8 @@
1637
1643
  "customers.people.list.bulkDelete.action": "Delete selected",
1638
1644
  "customers.people.list.bulkDelete.description": "This action cannot be undone.",
1639
1645
  "customers.people.list.bulkDelete.failed": "Failed to delete {count} people",
1646
+ "customers.people.list.bulkDelete.failedGroup": "{count} people could not be deleted: {message}",
1647
+ "customers.people.list.bulkDelete.operationLabel": "Delete {count} people",
1640
1648
  "customers.people.list.bulkDelete.partial": "{deleted} of {total} people deleted; {failed} failed",
1641
1649
  "customers.people.list.bulkDelete.success": "{count} people deleted",
1642
1650
  "customers.people.list.bulkDelete.title": "Delete {count} people?",
@@ -518,6 +518,8 @@
518
518
  "customers.companies.list.bulkDelete.action": "Delete selected",
519
519
  "customers.companies.list.bulkDelete.description": "This action cannot be undone.",
520
520
  "customers.companies.list.bulkDelete.failed": "No se pudieron eliminar {count} empresas",
521
+ "customers.companies.list.bulkDelete.failedGroup": "No se pudieron eliminar {count} empresas: {message}",
522
+ "customers.companies.list.bulkDelete.operationLabel": "Eliminar {count} empresas",
521
523
  "customers.companies.list.bulkDelete.partial": "{deleted} de {total} empresas eliminadas; {failed} fallaron",
522
524
  "customers.companies.list.bulkDelete.success": "{count} companies deleted",
523
525
  "customers.companies.list.bulkDelete.title": "Delete {count} companies?",
@@ -847,6 +849,8 @@
847
849
  "customers.deals.list.bulkDelete.action": "Delete selected",
848
850
  "customers.deals.list.bulkDelete.description": "This action cannot be undone.",
849
851
  "customers.deals.list.bulkDelete.failed": "No se pudieron eliminar {count} deals",
852
+ "customers.deals.list.bulkDelete.failedGroup": "No se pudieron eliminar {count} deals: {message}",
853
+ "customers.deals.list.bulkDelete.operationLabel": "Eliminar {count} deals",
850
854
  "customers.deals.list.bulkDelete.partial": "{deleted} de {total} deals eliminados; {failed} fallaron",
851
855
  "customers.deals.list.bulkDelete.success": "{count} deals deleted",
852
856
  "customers.deals.list.bulkDelete.title": "Delete {count} deals?",
@@ -1096,6 +1100,8 @@
1096
1100
  "customers.people.decisionMakers.label": "Decision Makers",
1097
1101
  "customers.people.decisionMakers.more": "more",
1098
1102
  "customers.people.decisionMakers.sendInvitation": "Send invitation",
1103
+ "customers.people.delete.blocked": "No se puede eliminar la persona: {{blockers}}. Primero desvincula o reasigna.",
1104
+ "customers.people.delete.blockers.deals": "oportunidades vinculadas ({{count}})",
1099
1105
  "customers.people.detail.actions.addDeal": "Agregar oportunidad",
1100
1106
  "customers.people.detail.actions.backToList": "Volver a personas",
1101
1107
  "customers.people.detail.actions.cancel": "Cancelar",
@@ -1637,6 +1643,8 @@
1637
1643
  "customers.people.list.bulkDelete.action": "Delete selected",
1638
1644
  "customers.people.list.bulkDelete.description": "This action cannot be undone.",
1639
1645
  "customers.people.list.bulkDelete.failed": "No se pudieron eliminar {count} personas",
1646
+ "customers.people.list.bulkDelete.failedGroup": "No se pudieron eliminar {count} personas: {message}",
1647
+ "customers.people.list.bulkDelete.operationLabel": "Eliminar {count} personas",
1640
1648
  "customers.people.list.bulkDelete.partial": "{deleted} de {total} personas eliminadas; {failed} fallaron",
1641
1649
  "customers.people.list.bulkDelete.success": "{count} people deleted",
1642
1650
  "customers.people.list.bulkDelete.title": "Delete {count} people?",
@@ -518,6 +518,8 @@
518
518
  "customers.companies.list.bulkDelete.action": "Delete selected",
519
519
  "customers.companies.list.bulkDelete.description": "This action cannot be undone.",
520
520
  "customers.companies.list.bulkDelete.failed": "Nie udało się usunąć {count} firm",
521
+ "customers.companies.list.bulkDelete.failedGroup": "Nie udało się usunąć {count} firm: {message}",
522
+ "customers.companies.list.bulkDelete.operationLabel": "Usuń {count} firm",
521
523
  "customers.companies.list.bulkDelete.partial": "Usunięto {deleted} z {total} firm; {failed} nie powiodło się",
522
524
  "customers.companies.list.bulkDelete.success": "{count} companies deleted",
523
525
  "customers.companies.list.bulkDelete.title": "Delete {count} companies?",
@@ -847,6 +849,8 @@
847
849
  "customers.deals.list.bulkDelete.action": "Delete selected",
848
850
  "customers.deals.list.bulkDelete.description": "This action cannot be undone.",
849
851
  "customers.deals.list.bulkDelete.failed": "Nie udało się usunąć {count} transakcji",
852
+ "customers.deals.list.bulkDelete.failedGroup": "Nie udało się usunąć {count} transakcji: {message}",
853
+ "customers.deals.list.bulkDelete.operationLabel": "Usuń {count} transakcji",
850
854
  "customers.deals.list.bulkDelete.partial": "Usunięto {deleted} z {total} transakcji; {failed} nie powiodło się",
851
855
  "customers.deals.list.bulkDelete.success": "{count} deals deleted",
852
856
  "customers.deals.list.bulkDelete.title": "Delete {count} deals?",
@@ -1096,6 +1100,8 @@
1096
1100
  "customers.people.decisionMakers.label": "Decydenci",
1097
1101
  "customers.people.decisionMakers.more": "more",
1098
1102
  "customers.people.decisionMakers.sendInvitation": "Wyślij zaproszenie",
1103
+ "customers.people.delete.blocked": "Nie można usunąć osoby: {{blockers}}. Najpierw rozłącz lub przypisz ponownie.",
1104
+ "customers.people.delete.blockers.deals": "powiązane transakcje ({{count}})",
1099
1105
  "customers.people.detail.actions.addDeal": "Dodaj szansę",
1100
1106
  "customers.people.detail.actions.backToList": "Powrót do listy osób",
1101
1107
  "customers.people.detail.actions.cancel": "Anuluj",
@@ -1637,6 +1643,8 @@
1637
1643
  "customers.people.list.bulkDelete.action": "Delete selected",
1638
1644
  "customers.people.list.bulkDelete.description": "This action cannot be undone.",
1639
1645
  "customers.people.list.bulkDelete.failed": "Nie udało się usunąć {count} osób",
1646
+ "customers.people.list.bulkDelete.failedGroup": "Nie udało się usunąć {count} osób: {message}",
1647
+ "customers.people.list.bulkDelete.operationLabel": "Usuń {count} osób",
1640
1648
  "customers.people.list.bulkDelete.partial": "Usunięto {deleted} z {total} osób; {failed} nie powiodło się",
1641
1649
  "customers.people.list.bulkDelete.success": "{count} people deleted",
1642
1650
  "customers.people.list.bulkDelete.title": "Delete {count} people?",