@open-mercato/core 0.6.6-develop.6543.1.49fadb4c31 → 0.6.6
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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/api_keys/api/keys/route.js +9 -23
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/cli.js +1 -2
- package/dist/modules/api_keys/cli.js.map +2 -2
- package/dist/modules/attachments/api/file/[id]/route.js +7 -9
- package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -9
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +17 -21
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +2 -6
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/cli.js +2 -3
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +0 -22
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +2 -0
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -7
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +7 -11
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/dashboards/api/roles/widgets/route.js +3 -22
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +3 -22
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/cli.js +3 -4
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js +1 -9
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js.map +2 -2
- package/dist/modules/dictionaries/commands/entries.js +14 -7
- package/dist/modules/dictionaries/commands/entries.js.map +2 -2
- package/dist/modules/dictionaries/commands/entry-operations.js +16 -7
- package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
- package/dist/modules/dictionaries/commands/factory.js +3 -9
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +41 -56
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +3 -10
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -5
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +0 -1
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +0 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/cli.js +1 -2
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/query_index/api/status.js +8 -2
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -44
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +27 -2
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +2 -6
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +0 -1
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +0 -9
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +0 -44
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +38 -59
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/lib/shipments/snapshots.js +1 -27
- package/dist/modules/sales/lib/shipments/snapshots.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -1
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +1 -1
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/find-definition.js +18 -2
- package/dist/modules/workflows/lib/find-definition.js.map +2 -2
- package/dist/modules/workflows/lib/signal-handler.js +3 -2
- package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +4 -8
- package/dist/modules/workflows/lib/step-handler.js.map +2 -2
- package/dist/modules/workflows/lib/task-handler.js +3 -5
- package/dist/modules/workflows/lib/task-handler.js.map +2 -2
- package/dist/modules/workflows/lib/timer-handler.js +2 -1
- package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +5 -13
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js +11 -9
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/dist/modules/workflows/migrations/Migration20260715120000.js +68 -0
- package/dist/modules/workflows/migrations/Migration20260715120000.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260716120000.js +24 -0
- package/dist/modules/workflows/migrations/Migration20260716120000.js.map +7 -0
- package/dist/modules/workflows/workflows.js +2 -0
- package/dist/modules/workflows/workflows.js.map +2 -2
- package/package.json +8 -9
- package/src/modules/api_keys/api/keys/route.ts +9 -27
- package/src/modules/api_keys/cli.ts +3 -2
- package/src/modules/attachments/api/file/[id]/route.ts +7 -11
- package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -11
- package/src/modules/attachments/api/route.ts +21 -26
- package/src/modules/auth/api/users/route.ts +2 -11
- package/src/modules/auth/cli.ts +2 -3
- package/src/modules/configs/i18n/de.json +1 -5
- package/src/modules/configs/i18n/en.json +1 -5
- package/src/modules/configs/i18n/es.json +1 -5
- package/src/modules/configs/i18n/pl.json +1 -5
- package/src/modules/configs/lib/upgrade-actions.ts +0 -24
- package/src/modules/customer_accounts/AGENTS.md +6 -8
- package/src/modules/customer_accounts/widgets/injection-table.ts +2 -0
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -11
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +7 -13
- package/src/modules/dashboards/api/roles/widgets/route.ts +3 -22
- package/src/modules/dashboards/api/users/widgets/route.ts +3 -22
- package/src/modules/dashboards/cli.ts +9 -4
- package/src/modules/dashboards/lib/widgetAssignmentScope.ts +0 -18
- package/src/modules/dictionaries/commands/entries.ts +16 -7
- package/src/modules/dictionaries/commands/entry-operations.ts +18 -8
- package/src/modules/dictionaries/commands/factory.ts +2 -8
- package/src/modules/dictionaries/fields/dictionary.tsx +32 -55
- package/src/modules/dictionaries/i18n/de.json +0 -2
- package/src/modules/dictionaries/i18n/en.json +0 -2
- package/src/modules/dictionaries/i18n/es.json +0 -2
- package/src/modules/dictionaries/i18n/pl.json +0 -2
- package/src/modules/directory/utils/organizationScope.ts +2 -36
- package/src/modules/entities/api/records.ts +7 -5
- package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +0 -1
- package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +0 -1
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +49 -51
- package/src/modules/entities/cli.ts +1 -2
- package/src/modules/entities/i18n/de.json +0 -34
- package/src/modules/entities/i18n/en.json +0 -34
- package/src/modules/entities/i18n/es.json +0 -34
- package/src/modules/entities/i18n/pl.json +0 -34
- package/src/modules/query_index/api/status.ts +8 -2
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/returns.ts +32 -2
- package/src/modules/sales/components/documents/AddressesSection.tsx +2 -6
- package/src/modules/sales/components/documents/ItemsSection.tsx +0 -5
- package/src/modules/sales/components/documents/LineItemDialog.tsx +0 -10
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +0 -46
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +40 -65
- package/src/modules/sales/i18n/de.json +0 -4
- package/src/modules/sales/i18n/en.json +0 -4
- package/src/modules/sales/i18n/es.json +0 -4
- package/src/modules/sales/i18n/pl.json +0 -4
- package/src/modules/sales/lib/shipments/snapshots.ts +0 -30
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +12 -1
- package/src/modules/workflows/lib/activity-executor.ts +22 -2
- package/src/modules/workflows/lib/find-definition.ts +53 -1
- package/src/modules/workflows/lib/signal-handler.ts +5 -4
- package/src/modules/workflows/lib/step-handler.ts +4 -8
- package/src/modules/workflows/lib/task-handler.ts +2 -4
- package/src/modules/workflows/lib/timer-handler.ts +3 -2
- package/src/modules/workflows/lib/transition-handler.ts +5 -13
- package/src/modules/workflows/lib/workflow-executor.ts +11 -8
- package/src/modules/workflows/migrations/Migration20260715120000.ts +114 -0
- package/src/modules/workflows/migrations/Migration20260716120000.ts +57 -0
- package/src/modules/workflows/workflows.ts +2 -0
- package/dist/modules/attachments/lib/reconcileOrganization.js +0 -110
- package/dist/modules/attachments/lib/reconcileOrganization.js.map +0 -7
- package/dist/modules/attachments/lib/requestScope.js +0 -10
- package/dist/modules/attachments/lib/requestScope.js.map +0 -7
- package/dist/modules/customers/components/detail/useDealsAccess.js +0 -16
- package/dist/modules/customers/components/detail/useDealsAccess.js.map +0 -7
- package/src/modules/attachments/lib/reconcileOrganization.ts +0 -188
- package/src/modules/attachments/lib/requestScope.ts +0 -27
- package/src/modules/customers/components/detail/useDealsAccess.ts +0 -19
|
@@ -93,7 +93,6 @@
|
|
|
93
93
|
"entities.customFields.editor.noFieldsets": "Nie zdefiniowano jeszcze zestawów pól. Zestawy pól pozwalają grupować pola niestandardowe dla różnych wariantów tej samej encji (np. produkty Moda vs Sport).",
|
|
94
94
|
"entities.customFields.editor.noGroup": "Bez grupy",
|
|
95
95
|
"entities.customFields.editor.noOptionsDefined": "Nie zdefiniowano opcji.",
|
|
96
|
-
"entities.customFields.editor.noParameterPlaceholder": "-",
|
|
97
96
|
"entities.customFields.editor.noValidationRules": "Nie zdefiniowano reguł walidacji.",
|
|
98
97
|
"entities.customFields.editor.optionLabelPlaceholder": "Etykieta widoczna dla użytkowników (opcjonalnie)",
|
|
99
98
|
"entities.customFields.editor.options": "Opcje",
|
|
@@ -119,17 +118,6 @@
|
|
|
119
118
|
"entities.customFields.editor.unassignedFields": "Pola nieprzypisane",
|
|
120
119
|
"entities.customFields.editor.unitsOptional": "Jednostki (opcjonalnie)",
|
|
121
120
|
"entities.customFields.editor.unitsPlaceholder": "kg, cm itp.",
|
|
122
|
-
"entities.customFields.editor.validation.date": "data",
|
|
123
|
-
"entities.customFields.editor.validation.eq": "równe",
|
|
124
|
-
"entities.customFields.editor.validation.float": "liczba zmiennoprzecinkowa",
|
|
125
|
-
"entities.customFields.editor.validation.gt": "większe niż",
|
|
126
|
-
"entities.customFields.editor.validation.gte": "większe lub równe",
|
|
127
|
-
"entities.customFields.editor.validation.integer": "liczba całkowita",
|
|
128
|
-
"entities.customFields.editor.validation.lt": "mniejsze niż",
|
|
129
|
-
"entities.customFields.editor.validation.lte": "mniejsze lub równe",
|
|
130
|
-
"entities.customFields.editor.validation.ne": "różne",
|
|
131
|
-
"entities.customFields.editor.validation.regex": "regex",
|
|
132
|
-
"entities.customFields.editor.validation.required": "wymagane",
|
|
133
121
|
"entities.customFields.editor.validationRules": "Reguły walidacji",
|
|
134
122
|
"entities.customFields.editor.value": "Wartość",
|
|
135
123
|
"entities.customFields.editor.valueRequired": "Wartość jest wymagana",
|
|
@@ -195,28 +183,6 @@
|
|
|
195
183
|
"entities.nav.systemEntities": "Encje systemowe",
|
|
196
184
|
"entities.nav.userEntities": "Encje użytkownika",
|
|
197
185
|
"entities.nav.userEntities.create": "Utwórz encję",
|
|
198
|
-
"entities.userEntities.edit.errors.deleteEntityFailed": "Nie udało się usunąć encji",
|
|
199
|
-
"entities.userEntities.edit.errors.invalidEntityDescription": "Brakuje identyfikatora encji albo jest on nieprawidłowy.",
|
|
200
|
-
"entities.userEntities.edit.errors.invalidEntityId": "Nieprawidłowy identyfikator encji",
|
|
201
|
-
"entities.userEntities.edit.errors.invalidEntityTitle": "Nieprawidłowa encja",
|
|
202
|
-
"entities.userEntities.edit.errors.loadDefinitionsFailed": "Nie udało się wczytać definicji encji",
|
|
203
|
-
"entities.userEntities.edit.errors.loadFailed": "Nie udało się wczytać",
|
|
204
|
-
"entities.userEntities.edit.errors.loadMetadataFailed": "Nie udało się wczytać metadanych encji",
|
|
205
|
-
"entities.userEntities.edit.errors.reloadDefinitionsFailed": "Nie udało się ponownie wczytać definicji pól",
|
|
206
|
-
"entities.userEntities.edit.errors.restoreFieldFailed": "Nie udało się przywrócić pola",
|
|
207
|
-
"entities.userEntities.edit.errors.saveEntityFailed": "Nie udało się zapisać encji",
|
|
208
|
-
"entities.userEntities.edit.errors.saveOrderFailed": "Nie udało się zapisać kolejności",
|
|
209
|
-
"entities.userEntities.edit.errors.validationFailed": "Walidacja nie powiodła się",
|
|
210
|
-
"entities.userEntities.edit.fieldsetTitle": "Edytuj zestaw pól: {{name}}",
|
|
211
|
-
"entities.userEntities.edit.flash.entityDeleted": "Encja została usunięta",
|
|
212
|
-
"entities.userEntities.edit.flash.orderSaved": "Kolejność została zapisana",
|
|
213
|
-
"entities.userEntities.edit.flash.restoredField": "Przywrócono {{key}}",
|
|
214
|
-
"entities.userEntities.edit.groups.definitions": "Definicje pól",
|
|
215
|
-
"entities.userEntities.edit.groups.settings": "Ustawienia encji",
|
|
216
|
-
"entities.userEntities.edit.orderNotice": "Zmieniono kolejność - zapisze się po opuszczeniu pola",
|
|
217
|
-
"entities.userEntities.edit.pageTitle": "Edytuj definicje",
|
|
218
|
-
"entities.userEntities.edit.showRecords": "Pokaż rekordy",
|
|
219
|
-
"entities.userEntities.edit.title": "Edytuj encję: {{entityId}}",
|
|
220
186
|
"entities.userEntities.errors.entityIdExists": "Identyfikator encji już istnieje",
|
|
221
187
|
"entities.userEntities.errors.entityIdRequired": "Identyfikator encji jest wymagany",
|
|
222
188
|
"entities.userEntities.errors.loadFailed": "Nie udało się wczytać encji",
|
|
@@ -415,7 +415,10 @@ export async function GET(req: Request) {
|
|
|
415
415
|
errorQuery = errorQuery.where('tenant_id' as any, 'is', null as any)
|
|
416
416
|
}
|
|
417
417
|
if (Array.isArray(organizationScopeIds) && organizationScopeIds.length) {
|
|
418
|
-
errorQuery = errorQuery.where(
|
|
418
|
+
errorQuery = errorQuery.where((eb: any) => eb.or([
|
|
419
|
+
eb('organization_id' as any, 'is', null),
|
|
420
|
+
eb('organization_id' as any, 'in', organizationScopeIds),
|
|
421
|
+
]))
|
|
419
422
|
} else {
|
|
420
423
|
errorQuery = errorQuery.where('organization_id' as any, 'is', null as any)
|
|
421
424
|
}
|
|
@@ -453,7 +456,10 @@ export async function GET(req: Request) {
|
|
|
453
456
|
logsQuery = logsQuery.where('tenant_id' as any, 'is', null as any)
|
|
454
457
|
}
|
|
455
458
|
if (Array.isArray(organizationScopeIds) && organizationScopeIds.length) {
|
|
456
|
-
logsQuery = logsQuery.where(
|
|
459
|
+
logsQuery = logsQuery.where((eb: any) => eb.or([
|
|
460
|
+
eb('organization_id' as any, 'is', null),
|
|
461
|
+
eb('organization_id' as any, 'in', organizationScopeIds),
|
|
462
|
+
]))
|
|
457
463
|
} else {
|
|
458
464
|
logsQuery = logsQuery.where('organization_id' as any, 'is', null as any)
|
|
459
465
|
}
|
|
@@ -125,7 +125,6 @@ import {
|
|
|
125
125
|
type SalesLineCalculationResult,
|
|
126
126
|
type SalesDocumentCalculationResult,
|
|
127
127
|
} from "../lib/types";
|
|
128
|
-
import { loadShippedQuantityByLine } from "../lib/shipments/snapshots";
|
|
129
128
|
import { resolveDictionaryEntryValue } from "../lib/dictionaries";
|
|
130
129
|
import { resolveStatusEntryIdByValue } from "../lib/statusHelpers";
|
|
131
130
|
import { SalesDocumentNumberGenerator } from "../services/salesDocumentNumberGenerator";
|
|
@@ -6522,69 +6521,6 @@ const quoteAdjustmentDeleteSchema = z.object({
|
|
|
6522
6521
|
quoteId: z.string().uuid(),
|
|
6523
6522
|
});
|
|
6524
6523
|
|
|
6525
|
-
const SHIPPED_QUANTITY_TOLERANCE = 1e-6;
|
|
6526
|
-
|
|
6527
|
-
const hasNumericChange = (
|
|
6528
|
-
next: number | null | undefined,
|
|
6529
|
-
previous: number | null | undefined,
|
|
6530
|
-
): boolean => {
|
|
6531
|
-
if (next === undefined || next === null) return false;
|
|
6532
|
-
if (previous === undefined || previous === null) return true;
|
|
6533
|
-
return Math.abs(next - previous) > SHIPPED_QUANTITY_TOLERANCE;
|
|
6534
|
-
};
|
|
6535
|
-
|
|
6536
|
-
const hasUnitChange = (
|
|
6537
|
-
next: string | null | undefined,
|
|
6538
|
-
previous: string | null | undefined,
|
|
6539
|
-
): boolean => {
|
|
6540
|
-
if (next === undefined || next === null) return false;
|
|
6541
|
-
const normalizedPrevious = (previous ?? "").trim().toLowerCase();
|
|
6542
|
-
if (!normalizedPrevious) return false;
|
|
6543
|
-
return next.trim().toLowerCase() !== normalizedPrevious;
|
|
6544
|
-
};
|
|
6545
|
-
|
|
6546
|
-
async function assertShippedOrderLineEditable(
|
|
6547
|
-
em: EntityManager,
|
|
6548
|
-
order: SalesOrder,
|
|
6549
|
-
existingSnapshot: SalesLineSnapshot | null,
|
|
6550
|
-
parsed: z.infer<typeof orderLineUpsertSchema>,
|
|
6551
|
-
): Promise<void> {
|
|
6552
|
-
const lineId = existingSnapshot?.id;
|
|
6553
|
-
if (!existingSnapshot || !lineId) return;
|
|
6554
|
-
const shippedByLine = await loadShippedQuantityByLine(em, order.id, {
|
|
6555
|
-
tenantId: order.tenantId,
|
|
6556
|
-
organizationId: order.organizationId,
|
|
6557
|
-
});
|
|
6558
|
-
const shippedQuantity = shippedByLine.get(lineId) ?? 0;
|
|
6559
|
-
if (shippedQuantity <= 0) return;
|
|
6560
|
-
|
|
6561
|
-
const { translate } = await resolveTranslations();
|
|
6562
|
-
const nextQuantity = parsed.quantity ?? existingSnapshot.quantity;
|
|
6563
|
-
if (nextQuantity < shippedQuantity - SHIPPED_QUANTITY_TOLERANCE) {
|
|
6564
|
-
throw new CrudHttpError(409, {
|
|
6565
|
-
error: translate(
|
|
6566
|
-
"sales.documents.items.errorQuantityBelowShipped",
|
|
6567
|
-
"You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
6568
|
-
{ shipped: shippedQuantity },
|
|
6569
|
-
),
|
|
6570
|
-
});
|
|
6571
|
-
}
|
|
6572
|
-
|
|
6573
|
-
const pricingChanged =
|
|
6574
|
-
hasNumericChange(parsed.unitPriceNet, existingSnapshot.unitPriceNet) ||
|
|
6575
|
-
hasNumericChange(parsed.unitPriceGross, existingSnapshot.unitPriceGross) ||
|
|
6576
|
-
hasNumericChange(parsed.taxRate, existingSnapshot.taxRate) ||
|
|
6577
|
-
hasUnitChange(parsed.quantityUnit, existingSnapshot.quantityUnit);
|
|
6578
|
-
if (pricingChanged) {
|
|
6579
|
-
throw new CrudHttpError(409, {
|
|
6580
|
-
error: translate(
|
|
6581
|
-
"sales.documents.items.errorPriceShipped",
|
|
6582
|
-
"You cannot change the price or unit of a line that has shipped items.",
|
|
6583
|
-
),
|
|
6584
|
-
});
|
|
6585
|
-
}
|
|
6586
|
-
}
|
|
6587
|
-
|
|
6588
6524
|
const orderLineUpsertCommand: CommandHandler<
|
|
6589
6525
|
{ body?: Record<string, unknown>; query?: Record<string, unknown> },
|
|
6590
6526
|
{ orderId: string; lineId: string }
|
|
@@ -6629,7 +6565,6 @@ const orderLineUpsertCommand: CommandHandler<
|
|
|
6629
6565
|
const existingSnapshot = parsed.id
|
|
6630
6566
|
? (lineSnapshots.find((line) => line.id === parsed.id) ?? null)
|
|
6631
6567
|
: null;
|
|
6632
|
-
await assertShippedOrderLineEditable(em, order, existingSnapshot, parsed);
|
|
6633
6568
|
const priceMode =
|
|
6634
6569
|
parsed.priceMode === "gross"
|
|
6635
6570
|
? "gross"
|
|
@@ -15,8 +15,8 @@ import type { SalesCalculationService } from '../services/salesCalculationServic
|
|
|
15
15
|
import type { SalesAdjustmentDraft, SalesLineSnapshot, SalesDocumentCalculationResult } from '../lib/types'
|
|
16
16
|
import { cloneJson, deriveLineNetFromGross, ensureOrganizationScope, ensureSameScope, ensureTenantScope, extractUndoPayload, toNumericString, enforceSalesDocumentOptimisticLock, SALES_RESOURCE_KIND_ORDER, SALES_RESOURCE_KIND_RETURN } from './shared'
|
|
17
17
|
import { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'
|
|
18
|
-
import { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine } from '../data/entities'
|
|
19
|
-
import {
|
|
18
|
+
import { SalesOrder, SalesOrderAdjustment, SalesOrderLine, SalesReturn, SalesReturnLine, SalesShipment, SalesShipmentItem } from '../data/entities'
|
|
19
|
+
import { coerceShipmentQuantity } from '../lib/shipments/snapshots'
|
|
20
20
|
import { computeAvailableReturnQuantity } from '../lib/returnQuantity'
|
|
21
21
|
import {
|
|
22
22
|
returnCreateSchema,
|
|
@@ -581,6 +581,36 @@ async function restoreReturnEffects(
|
|
|
581
581
|
return createdLines
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
+
async function loadShippedQuantityByLine(
|
|
585
|
+
em: EntityManager,
|
|
586
|
+
orderId: string,
|
|
587
|
+
scope: { tenantId: string; organizationId: string },
|
|
588
|
+
): Promise<Map<string, number>> {
|
|
589
|
+
const shipments = await findWithDecryption(
|
|
590
|
+
em,
|
|
591
|
+
SalesShipment,
|
|
592
|
+
{ order: orderId, deletedAt: null },
|
|
593
|
+
{},
|
|
594
|
+
scope,
|
|
595
|
+
)
|
|
596
|
+
const shippedByLine = new Map<string, number>()
|
|
597
|
+
if (!shipments.length) return shippedByLine
|
|
598
|
+
const items = await findWithDecryption(
|
|
599
|
+
em,
|
|
600
|
+
SalesShipmentItem,
|
|
601
|
+
{ shipment: { $in: shipments.map((shipment) => shipment.id) } },
|
|
602
|
+
{},
|
|
603
|
+
scope,
|
|
604
|
+
)
|
|
605
|
+
items.forEach((item) => {
|
|
606
|
+
const orderLineId = typeof item.orderLine === 'string' ? item.orderLine : item.orderLine?.id ?? null
|
|
607
|
+
if (!orderLineId) return
|
|
608
|
+
const next = (shippedByLine.get(orderLineId) ?? 0) + coerceShipmentQuantity(item.quantity)
|
|
609
|
+
shippedByLine.set(orderLineId, next)
|
|
610
|
+
})
|
|
611
|
+
return shippedByLine
|
|
612
|
+
}
|
|
613
|
+
|
|
584
614
|
function normalizeLinesInput(lines: ReturnCreateInput['lines']): ReturnLineInput[] {
|
|
585
615
|
const seen = new Set<string>()
|
|
586
616
|
const result: ReturnLineInput[] = []
|
|
@@ -890,12 +890,8 @@ export function SalesDocumentAddressesSection({
|
|
|
890
890
|
if (res?.result?.id) billingId = res.result.id
|
|
891
891
|
}
|
|
892
892
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
}
|
|
896
|
-
if (billingSnapshot || !billingId) {
|
|
897
|
-
payload.billingAddressSnapshot = billingSnapshot ?? null
|
|
898
|
-
}
|
|
893
|
+
payload.shippingAddressSnapshot = shippingSnapshot ?? null
|
|
894
|
+
payload.billingAddressSnapshot = billingSnapshot ?? null
|
|
899
895
|
payload.shippingAddressId = shippingSnapshot ? null : shippingId
|
|
900
896
|
payload.billingAddressId = billingSnapshot ? null : billingId
|
|
901
897
|
|
|
@@ -817,11 +817,6 @@ export function SalesDocumentItemsSection({
|
|
|
817
817
|
organizationId={resolvedOrganizationId}
|
|
818
818
|
tenantId={resolvedTenantId}
|
|
819
819
|
initialLine={lineForEdit}
|
|
820
|
-
shippedQuantity={
|
|
821
|
-
lineForEdit
|
|
822
|
-
? Math.max(0, shippedTotals.get(lineForEdit.id) ?? 0)
|
|
823
|
-
: 0
|
|
824
|
-
}
|
|
825
820
|
onSaved={async () => {
|
|
826
821
|
await loadItems();
|
|
827
822
|
emitSalesDocumentTotalsRefresh({ documentId, kind });
|
|
@@ -278,7 +278,6 @@ type SalesLineDialogProps = {
|
|
|
278
278
|
organizationId: string | null;
|
|
279
279
|
tenantId: string | null;
|
|
280
280
|
initialLine?: SalesLineRecord | null;
|
|
281
|
-
shippedQuantity?: number;
|
|
282
281
|
onOpenChange: (open: boolean) => void;
|
|
283
282
|
onSaved?: () => Promise<void> | void;
|
|
284
283
|
};
|
|
@@ -473,7 +472,6 @@ export function LineItemDialog({
|
|
|
473
472
|
organizationId,
|
|
474
473
|
tenantId,
|
|
475
474
|
initialLine,
|
|
476
|
-
shippedQuantity = 0,
|
|
477
475
|
onOpenChange,
|
|
478
476
|
onSaved,
|
|
479
477
|
}: SalesLineDialogProps) {
|
|
@@ -1328,14 +1326,6 @@ export function LineItemDialog({
|
|
|
1328
1326
|
},
|
|
1329
1327
|
);
|
|
1330
1328
|
}
|
|
1331
|
-
if (shippedQuantity > 0 && qtyNumber < shippedQuantity) {
|
|
1332
|
-
const message = t(
|
|
1333
|
-
"sales.documents.items.errorQuantityBelowShipped",
|
|
1334
|
-
"You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
1335
|
-
{ shipped: shippedQuantity },
|
|
1336
|
-
);
|
|
1337
|
-
throw createCrudFormError(message, { quantity: message });
|
|
1338
|
-
}
|
|
1339
1329
|
const resolvedQuantityUnit = (() => {
|
|
1340
1330
|
const entered = normalizeUnitCode(values.quantityUnit);
|
|
1341
1331
|
if (isCustomLine) return entered;
|
|
@@ -168,7 +168,6 @@ function CustomerQuickCreate({ t, onCreated }: CustomerQuickCreateProps) {
|
|
|
168
168
|
async (values: PersonFormValues) => {
|
|
169
169
|
setSaving(true)
|
|
170
170
|
try {
|
|
171
|
-
const addresses = Array.isArray(values.addresses) ? values.addresses : []
|
|
172
171
|
const payload = buildPersonPayload(values, organizationId)
|
|
173
172
|
const { result } = await createCrud<{ id?: string; entityId?: string }>('customers/people', payload, {
|
|
174
173
|
errorMessage: t('sales.documents.form.customer.quick.error', 'Failed to create customer.'),
|
|
@@ -178,51 +177,6 @@ function CustomerQuickCreate({ t, onCreated }: CustomerQuickCreateProps) {
|
|
|
178
177
|
(result && typeof result.id === 'string' && result.id) ||
|
|
179
178
|
null
|
|
180
179
|
if (!id) throw new Error('Missing customer id')
|
|
181
|
-
if (addresses.length) {
|
|
182
|
-
const normalize = (value?: string | null) => {
|
|
183
|
-
if (typeof value !== 'string') return undefined
|
|
184
|
-
const trimmed = value.trim()
|
|
185
|
-
return trimmed.length ? trimmed : undefined
|
|
186
|
-
}
|
|
187
|
-
for (const entry of addresses) {
|
|
188
|
-
const normalizedLine1 = normalize(entry.addressLine1)
|
|
189
|
-
if (!normalizedLine1) continue
|
|
190
|
-
const body: Record<string, unknown> = {
|
|
191
|
-
entityId: id,
|
|
192
|
-
...(organizationId ? { organizationId } : {}),
|
|
193
|
-
addressLine1: normalizedLine1,
|
|
194
|
-
isPrimary: entry.isPrimary ?? false,
|
|
195
|
-
}
|
|
196
|
-
const name = normalize(entry.name)
|
|
197
|
-
if (name !== undefined) body.name = name
|
|
198
|
-
const purpose = normalize(entry.purpose)
|
|
199
|
-
if (purpose !== undefined) body.purpose = purpose
|
|
200
|
-
const line2 = normalize(entry.addressLine2)
|
|
201
|
-
if (line2 !== undefined) body.addressLine2 = line2
|
|
202
|
-
const buildingNumber = normalize(entry.buildingNumber)
|
|
203
|
-
if (buildingNumber !== undefined) body.buildingNumber = buildingNumber
|
|
204
|
-
const flatNumber = normalize(entry.flatNumber)
|
|
205
|
-
if (flatNumber !== undefined) body.flatNumber = flatNumber
|
|
206
|
-
const city = normalize(entry.city)
|
|
207
|
-
if (city !== undefined) body.city = city
|
|
208
|
-
const region = normalize(entry.region)
|
|
209
|
-
if (region !== undefined) body.region = region
|
|
210
|
-
const postalCode = normalize(entry.postalCode)
|
|
211
|
-
if (postalCode !== undefined) body.postalCode = postalCode
|
|
212
|
-
const country = normalize(entry.country)
|
|
213
|
-
if (country !== undefined) body.country = country.toUpperCase()
|
|
214
|
-
if (typeof entry.latitude === 'number') body.latitude = entry.latitude
|
|
215
|
-
if (typeof entry.longitude === 'number') body.longitude = entry.longitude
|
|
216
|
-
try {
|
|
217
|
-
await createCrud('customers/addresses', body)
|
|
218
|
-
} catch (addressErr) {
|
|
219
|
-
const message =
|
|
220
|
-
(addressErr instanceof Error && addressErr.message ? addressErr.message : null) ||
|
|
221
|
-
t('customers.people.detail.addresses.error')
|
|
222
|
-
flash(message, 'error')
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
180
|
const displayName =
|
|
227
181
|
typeof values.displayName === 'string' && values.displayName.trim().length
|
|
228
182
|
? values.displayName.trim()
|
|
@@ -296,13 +296,6 @@ export function ShipmentDialog({
|
|
|
296
296
|
const [addressOptions, setAddressOptions] = React.useState<ShipmentAddressOption[]>([])
|
|
297
297
|
const [addressLoading, setAddressLoading] = React.useState(false)
|
|
298
298
|
const [addressError, setAddressError] = React.useState<string | null>(null)
|
|
299
|
-
const addressLoadPromiseRef = React.useRef<{
|
|
300
|
-
orderId: string
|
|
301
|
-
promise: Promise<ShipmentAddressOption[]>
|
|
302
|
-
} | null>(null)
|
|
303
|
-
const currentAddressOrderIdRef = React.useRef(orderId)
|
|
304
|
-
currentAddressOrderIdRef.current = orderId
|
|
305
|
-
const initializedDialogKeyRef = React.useRef<string | null>(null)
|
|
306
299
|
const [documentStatuses, setDocumentStatuses] = React.useState<StatusOption[]>([])
|
|
307
300
|
const [lineStatuses, setLineStatuses] = React.useState<StatusOption[]>([])
|
|
308
301
|
const [shipmentStatuses, setShipmentStatuses] = React.useState<StatusOption[]>([])
|
|
@@ -486,52 +479,37 @@ export function ShipmentDialog({
|
|
|
486
479
|
[],
|
|
487
480
|
)
|
|
488
481
|
|
|
489
|
-
const loadAddressOptions = React.useCallback(()
|
|
490
|
-
const activeRequest = addressLoadPromiseRef.current
|
|
491
|
-
if (activeRequest?.orderId === orderId) return activeRequest.promise
|
|
492
|
-
|
|
482
|
+
const loadAddressOptions = React.useCallback(async () => {
|
|
493
483
|
setAddressLoading(true)
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
return baseAddressOptions
|
|
524
|
-
}
|
|
525
|
-
})()
|
|
526
|
-
addressLoadPromiseRef.current = { orderId, promise: request }
|
|
527
|
-
void request.then(() => {
|
|
528
|
-
if (addressLoadPromiseRef.current?.promise === request) {
|
|
529
|
-
addressLoadPromiseRef.current = null
|
|
530
|
-
setAddressLoading(false)
|
|
531
|
-
}
|
|
532
|
-
})
|
|
533
|
-
return request
|
|
534
|
-
}, [baseAddressOptions, mapDocumentAddressOption, mergeAddressOptions, orderId, t])
|
|
484
|
+
try {
|
|
485
|
+
const params = new URLSearchParams({
|
|
486
|
+
page: '1',
|
|
487
|
+
pageSize: '100',
|
|
488
|
+
documentId: orderId,
|
|
489
|
+
documentKind: 'order',
|
|
490
|
+
})
|
|
491
|
+
const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(
|
|
492
|
+
`/api/sales/document-addresses?${params.toString()}`,
|
|
493
|
+
undefined,
|
|
494
|
+
{ fallback: { items: [] } },
|
|
495
|
+
)
|
|
496
|
+
const items = Array.isArray(response.result?.items) ? response.result.items : []
|
|
497
|
+
const mapped = items
|
|
498
|
+
.map((item) => mapDocumentAddressOption(item))
|
|
499
|
+
.filter((entry): entry is ShipmentAddressOption => Boolean(entry))
|
|
500
|
+
mergeAddressOptions(mapped)
|
|
501
|
+
setAddressError(null)
|
|
502
|
+
return mapped
|
|
503
|
+
} catch (err) {
|
|
504
|
+
logger.error('sales.shipments.addresses.load', { err })
|
|
505
|
+
setAddressError(
|
|
506
|
+
t('sales.documents.shipments.addressLoadError', 'Failed to load addresses.'),
|
|
507
|
+
)
|
|
508
|
+
return []
|
|
509
|
+
} finally {
|
|
510
|
+
setAddressLoading(false)
|
|
511
|
+
}
|
|
512
|
+
}, [mapDocumentAddressOption, mergeAddressOptions, orderId, t])
|
|
535
513
|
|
|
536
514
|
const buildPriceSubtitle = React.useCallback(
|
|
537
515
|
(option: ShippingMethodOption): string | undefined => {
|
|
@@ -873,20 +851,16 @@ export function ShipmentDialog({
|
|
|
873
851
|
)
|
|
874
852
|
|
|
875
853
|
React.useEffect(() => {
|
|
876
|
-
if (!open)
|
|
877
|
-
initializedDialogKeyRef.current = null
|
|
878
|
-
return
|
|
879
|
-
}
|
|
880
|
-
const dialogKey = `${orderId}:${mode}:${shipment?.id ?? 'new'}`
|
|
881
|
-
if (initializedDialogKeyRef.current === dialogKey) return
|
|
882
|
-
initializedDialogKeyRef.current = dialogKey
|
|
854
|
+
if (!open) return
|
|
883
855
|
setFormResetKey((prev) => prev + 1)
|
|
884
856
|
if (!shippingMethods.length) {
|
|
885
857
|
void loadShippingMethods()
|
|
886
858
|
}
|
|
887
859
|
setAddressOptions(baseAddressOptions)
|
|
888
860
|
setAddressError(null)
|
|
889
|
-
|
|
861
|
+
if (!addressOptions.length) {
|
|
862
|
+
void loadAddressOptions()
|
|
863
|
+
}
|
|
890
864
|
if (!shipmentStatuses.length) {
|
|
891
865
|
void loadShipmentStatuses()
|
|
892
866
|
}
|
|
@@ -897,6 +871,7 @@ export function ShipmentDialog({
|
|
|
897
871
|
void loadLineStatuses()
|
|
898
872
|
}
|
|
899
873
|
}, [
|
|
874
|
+
addressOptions.length,
|
|
900
875
|
baseAddressOptions,
|
|
901
876
|
documentStatuses.length,
|
|
902
877
|
loadAddressOptions,
|
|
@@ -906,8 +881,6 @@ export function ShipmentDialog({
|
|
|
906
881
|
loadShippingMethods,
|
|
907
882
|
mode,
|
|
908
883
|
open,
|
|
909
|
-
orderId,
|
|
910
|
-
shipment?.id,
|
|
911
884
|
lineStatuses.length,
|
|
912
885
|
shipmentStatuses.length,
|
|
913
886
|
shippingMethods.length,
|
|
@@ -966,9 +939,11 @@ export function ShipmentDialog({
|
|
|
966
939
|
|
|
967
940
|
const fetchAddressItems = React.useCallback(
|
|
968
941
|
async (query?: string): Promise<LookupSelectItem[]> => {
|
|
969
|
-
|
|
942
|
+
if (!addressOptions.length && !addressLoading) {
|
|
943
|
+
await loadAddressOptions()
|
|
944
|
+
}
|
|
970
945
|
const needle = query?.trim().toLowerCase() ?? ''
|
|
971
|
-
return
|
|
946
|
+
return addressOptions
|
|
972
947
|
.filter((option) => {
|
|
973
948
|
if (!needle) return true
|
|
974
949
|
return (
|
|
@@ -987,7 +962,7 @@ export function ShipmentDialog({
|
|
|
987
962
|
),
|
|
988
963
|
}))
|
|
989
964
|
},
|
|
990
|
-
[addressOptions, loadAddressOptions],
|
|
965
|
+
[addressLoading, addressOptions, loadAddressOptions],
|
|
991
966
|
)
|
|
992
967
|
|
|
993
968
|
const validateItems = React.useCallback(
|
|
@@ -638,10 +638,8 @@
|
|
|
638
638
|
"sales.documents.detail.items.errorDelete": "Position konnte nicht gelöscht werden.",
|
|
639
639
|
"sales.documents.detail.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
|
|
640
640
|
"sales.documents.detail.items.errorLoad": "Positionen konnten nicht geladen werden.",
|
|
641
|
-
"sales.documents.detail.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
|
|
642
641
|
"sales.documents.detail.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
|
|
643
642
|
"sales.documents.detail.items.errorQuantity": "Die Menge muss größer als 0 sein.",
|
|
644
|
-
"sales.documents.detail.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
|
|
645
643
|
"sales.documents.detail.items.errorSave": "Position konnte nicht gespeichert werden.",
|
|
646
644
|
"sales.documents.detail.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
|
|
647
645
|
"sales.documents.detail.items.errorVariantRequired": "Wähle eine Variante aus, um fortzufahren.",
|
|
@@ -952,10 +950,8 @@
|
|
|
952
950
|
"sales.documents.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
|
|
953
951
|
"sales.documents.items.errorLoad": "Positionen konnten nicht geladen werden.",
|
|
954
952
|
"sales.documents.items.errorNameRequired": "Name ist für benutzerdefinierte Positionen erforderlich.",
|
|
955
|
-
"sales.documents.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
|
|
956
953
|
"sales.documents.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
|
|
957
954
|
"sales.documents.items.errorQuantity": "Die Menge muss größer als 0 sein.",
|
|
958
|
-
"sales.documents.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
|
|
959
955
|
"sales.documents.items.errorSave": "Position konnte nicht gespeichert werden.",
|
|
960
956
|
"sales.documents.items.errorScope": "Organisation und Mandant sind erforderlich.",
|
|
961
957
|
"sales.documents.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
|
|
@@ -638,10 +638,8 @@
|
|
|
638
638
|
"sales.documents.detail.items.errorDelete": "Failed to delete line.",
|
|
639
639
|
"sales.documents.detail.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
|
|
640
640
|
"sales.documents.detail.items.errorLoad": "Failed to load items.",
|
|
641
|
-
"sales.documents.detail.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
|
|
642
641
|
"sales.documents.detail.items.errorProductRequired": "Select a product to continue.",
|
|
643
642
|
"sales.documents.detail.items.errorQuantity": "Quantity must be greater than 0.",
|
|
644
|
-
"sales.documents.detail.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
645
643
|
"sales.documents.detail.items.errorSave": "Failed to save line.",
|
|
646
644
|
"sales.documents.detail.items.errorUnitPrice": "Unit price must be greater than 0.",
|
|
647
645
|
"sales.documents.detail.items.errorVariantRequired": "Select a variant to continue.",
|
|
@@ -952,10 +950,8 @@
|
|
|
952
950
|
"sales.documents.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
|
|
953
951
|
"sales.documents.items.errorLoad": "Failed to load items.",
|
|
954
952
|
"sales.documents.items.errorNameRequired": "Name is required for custom lines.",
|
|
955
|
-
"sales.documents.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
|
|
956
953
|
"sales.documents.items.errorProductRequired": "Select a product to continue.",
|
|
957
954
|
"sales.documents.items.errorQuantity": "Quantity must be greater than 0.",
|
|
958
|
-
"sales.documents.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
959
955
|
"sales.documents.items.errorSave": "Failed to save line.",
|
|
960
956
|
"sales.documents.items.errorScope": "Organization and tenant are required.",
|
|
961
957
|
"sales.documents.items.errorUnitPrice": "Unit price must be greater than 0.",
|
|
@@ -638,10 +638,8 @@
|
|
|
638
638
|
"sales.documents.detail.items.errorDelete": "No se pudo eliminar la línea.",
|
|
639
639
|
"sales.documents.detail.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
|
|
640
640
|
"sales.documents.detail.items.errorLoad": "No se pudieron cargar los artículos.",
|
|
641
|
-
"sales.documents.detail.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
|
|
642
641
|
"sales.documents.detail.items.errorProductRequired": "Selecciona un producto para continuar.",
|
|
643
642
|
"sales.documents.detail.items.errorQuantity": "La cantidad debe ser mayor que 0.",
|
|
644
|
-
"sales.documents.detail.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
|
|
645
643
|
"sales.documents.detail.items.errorSave": "No se pudo guardar la línea.",
|
|
646
644
|
"sales.documents.detail.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
|
|
647
645
|
"sales.documents.detail.items.errorVariantRequired": "Selecciona una variante para continuar.",
|
|
@@ -952,10 +950,8 @@
|
|
|
952
950
|
"sales.documents.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
|
|
953
951
|
"sales.documents.items.errorLoad": "No se pudieron cargar los artículos.",
|
|
954
952
|
"sales.documents.items.errorNameRequired": "El nombre es obligatorio para líneas personalizadas.",
|
|
955
|
-
"sales.documents.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
|
|
956
953
|
"sales.documents.items.errorProductRequired": "Selecciona un producto para continuar.",
|
|
957
954
|
"sales.documents.items.errorQuantity": "La cantidad debe ser mayor que 0.",
|
|
958
|
-
"sales.documents.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
|
|
959
955
|
"sales.documents.items.errorSave": "No se pudo guardar la línea.",
|
|
960
956
|
"sales.documents.items.errorScope": "Se requieren organización e inquilino.",
|
|
961
957
|
"sales.documents.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
|
|
@@ -638,10 +638,8 @@
|
|
|
638
638
|
"sales.documents.detail.items.errorDelete": "Nie udało się usunąć pozycji.",
|
|
639
639
|
"sales.documents.detail.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
|
|
640
640
|
"sales.documents.detail.items.errorLoad": "Nie udało się wczytać pozycji.",
|
|
641
|
-
"sales.documents.detail.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
|
|
642
641
|
"sales.documents.detail.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
|
|
643
642
|
"sales.documents.detail.items.errorQuantity": "Ilość musi być większa niż 0.",
|
|
644
|
-
"sales.documents.detail.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
|
|
645
643
|
"sales.documents.detail.items.errorSave": "Nie udało się zapisać pozycji.",
|
|
646
644
|
"sales.documents.detail.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
|
|
647
645
|
"sales.documents.detail.items.errorVariantRequired": "Wybierz wariant, aby kontynuować.",
|
|
@@ -952,10 +950,8 @@
|
|
|
952
950
|
"sales.documents.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
|
|
953
951
|
"sales.documents.items.errorLoad": "Nie udało się załadować pozycji.",
|
|
954
952
|
"sales.documents.items.errorNameRequired": "Nazwa jest wymagana dla niestandardowych pozycji.",
|
|
955
|
-
"sales.documents.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
|
|
956
953
|
"sales.documents.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
|
|
957
954
|
"sales.documents.items.errorQuantity": "Ilość musi być większa niż 0.",
|
|
958
|
-
"sales.documents.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
|
|
959
955
|
"sales.documents.items.errorSave": "Nie udało się zapisać pozycji.",
|
|
960
956
|
"sales.documents.items.errorScope": "Wymagane są organizacja i najemca.",
|
|
961
957
|
"sales.documents.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
|
|
@@ -136,34 +136,4 @@ export const refreshShipmentItemsSnapshot = async (
|
|
|
136
136
|
return snapshot
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export const loadShippedQuantityByLine = async (
|
|
140
|
-
em: EntityManager,
|
|
141
|
-
orderId: string,
|
|
142
|
-
scope: { tenantId: string; organizationId: string },
|
|
143
|
-
): Promise<Map<string, number>> => {
|
|
144
|
-
const shipments = await findWithDecryption(
|
|
145
|
-
em,
|
|
146
|
-
SalesShipment,
|
|
147
|
-
{ order: orderId, deletedAt: null },
|
|
148
|
-
{},
|
|
149
|
-
scope,
|
|
150
|
-
)
|
|
151
|
-
const shippedByLine = new Map<string, number>()
|
|
152
|
-
if (!shipments.length) return shippedByLine
|
|
153
|
-
const items = await findWithDecryption(
|
|
154
|
-
em,
|
|
155
|
-
SalesShipmentItem,
|
|
156
|
-
{ shipment: { $in: shipments.map((shipment) => shipment.id) } },
|
|
157
|
-
{},
|
|
158
|
-
scope,
|
|
159
|
-
)
|
|
160
|
-
items.forEach((item) => {
|
|
161
|
-
const orderLineId = typeof item.orderLine === 'string' ? item.orderLine : (item.orderLine?.id ?? null)
|
|
162
|
-
if (!orderLineId) return
|
|
163
|
-
const next = (shippedByLine.get(orderLineId) ?? 0) + coerceShipmentQuantity(item.quantity)
|
|
164
|
-
shippedByLine.set(orderLineId, next)
|
|
165
|
-
})
|
|
166
|
-
return shippedByLine
|
|
167
|
-
}
|
|
168
|
-
|
|
169
139
|
export type { ShipmentItemSnapshot } from './types'
|
|
@@ -389,9 +389,20 @@ export default function CheckoutDemoPage() {
|
|
|
389
389
|
currencyCode: selectedCurrency || 'USD', // Ensure currency is always set
|
|
390
390
|
kind: 'product' as const,
|
|
391
391
|
productId: item.id,
|
|
392
|
-
|
|
392
|
+
name: item.name,
|
|
393
393
|
unitPriceGross: item.price,
|
|
394
394
|
})),
|
|
395
|
+
// Fold the demo's shipping and tax into order-level adjustments so the
|
|
396
|
+
// created order's grand total matches the cart total shown to the user
|
|
397
|
+
// (line items alone only cover the product subtotal).
|
|
398
|
+
orderAdjustments: [
|
|
399
|
+
...(shipping > 0
|
|
400
|
+
? [{ kind: 'shipping' as const, label: 'Shipping', currencyCode: selectedCurrency || 'USD', amountGross: shipping }]
|
|
401
|
+
: []),
|
|
402
|
+
...(tax > 0
|
|
403
|
+
? [{ kind: 'tax' as const, label: 'Tax', currencyCode: selectedCurrency || 'USD', amountGross: tax }]
|
|
404
|
+
: []),
|
|
405
|
+
],
|
|
395
406
|
itemCount: demoCart.reduce((sum, item) => sum + item.quantity, 0),
|
|
396
407
|
subtotal: subtotal,
|
|
397
408
|
tax: tax,
|