@apptimate/ui 6.3.0 → 6.5.0
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/package.json +1 -1
- package/src/base-components/Checkbox.tsx +10 -3
- package/src/base-components/SearchableSelect.tsx +2 -0
- package/src/base-components/Table.tsx +1 -1
- package/src/common-components/PaymentSection.tsx +6 -0
- package/src/common-components/item-wizard/ItemFormWizard.tsx +116 -107
- package/src/common-components/pickers/modals/SerialSelectionModal.tsx +20 -10
- package/src/common-components/transaction/MetadataPanel.tsx +2 -2
- package/src/common-components/transaction/ProductSelectionPanel.tsx +522 -515
- package/src/common-components/transaction/ProductTransactionScreen.tsx +50 -7
- package/src/common-components/transaction/types.ts +2 -0
|
@@ -172,7 +172,7 @@ export function ProductTransactionScreen({
|
|
|
172
172
|
(
|
|
173
173
|
item: TransactionItem,
|
|
174
174
|
variant?: any,
|
|
175
|
-
extra?: { quantity?: number; batches?: any[]; serial_numbers?: string[] }
|
|
175
|
+
extra?: { quantity?: number; batches?: any[]; serial_numbers?: string[]; serial_number_objects?: {id: number, serial_number: string}[] }
|
|
176
176
|
) => {
|
|
177
177
|
setLineItems((prevLineItems) => {
|
|
178
178
|
const actualVariant = variant || (item.variants && item.variants.length > 0 ? item.variants[0] : null);
|
|
@@ -222,6 +222,7 @@ export function ProductTransactionScreen({
|
|
|
222
222
|
variant_id: resolvedVariantId,
|
|
223
223
|
batches: extra?.batches || [],
|
|
224
224
|
serial_numbers: extra?.serial_numbers || [],
|
|
225
|
+
serial_number_objects: extra?.serial_number_objects || [],
|
|
225
226
|
quantity: qty,
|
|
226
227
|
unit_price: unitPrice,
|
|
227
228
|
discount_percent: discountPercent,
|
|
@@ -337,12 +338,34 @@ export function ProductTransactionScreen({
|
|
|
337
338
|
const handleSubmit = useCallback(async () => {
|
|
338
339
|
if (lineItems.length === 0) return;
|
|
339
340
|
|
|
341
|
+
let finalPayments = payments;
|
|
342
|
+
let actualAmountTendered = payments.reduce((sum, p) => sum + (Number(p.amount) || 0), 0);
|
|
343
|
+
|
|
340
344
|
if (config.requireFullPayment) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
toast.error('Total payments must equal the Grand Total (Use Credit mode to pay later).');
|
|
345
|
+
if (actualAmountTendered < grandTotal - 0.01) {
|
|
346
|
+
toast.error('Total payments must equal or exceed the Grand Total (Use Credit mode to pay later).');
|
|
344
347
|
return;
|
|
345
348
|
}
|
|
349
|
+
|
|
350
|
+
const excess = actualAmountTendered - grandTotal;
|
|
351
|
+
if (excess > 0.01) {
|
|
352
|
+
const hasNonCash = payments.some(p => p.mode_code !== 'cash' && Number(p.amount) > 0);
|
|
353
|
+
if (hasNonCash) {
|
|
354
|
+
toast.error('Overpayment (Change Due) is not supported when using multiple payment methods or non-cash modes.');
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
let remainingExcess = excess;
|
|
359
|
+
finalPayments = payments.map(p => {
|
|
360
|
+
if (p.mode_code === 'cash' && remainingExcess > 0) {
|
|
361
|
+
const amt = Number(p.amount) || 0;
|
|
362
|
+
const reduction = Math.min(amt, remainingExcess);
|
|
363
|
+
remainingExcess -= reduction;
|
|
364
|
+
return { ...p, amount: amt - reduction };
|
|
365
|
+
}
|
|
366
|
+
return p;
|
|
367
|
+
});
|
|
368
|
+
}
|
|
346
369
|
}
|
|
347
370
|
|
|
348
371
|
if (config.showWarehouse && !warehouseId) {
|
|
@@ -350,6 +373,17 @@ export function ProductTransactionScreen({
|
|
|
350
373
|
return;
|
|
351
374
|
}
|
|
352
375
|
|
|
376
|
+
if (config.type === 'pos') {
|
|
377
|
+
const isCredit = (p: any) => p.mode_code === "credit";
|
|
378
|
+
const totalPaid = payments.reduce((sum, p) => sum + (isCredit(p) ? 0 : (Number(p.amount) || 0)), 0);
|
|
379
|
+
const balance = grandTotal - totalPaid;
|
|
380
|
+
|
|
381
|
+
if (balance > 0.01 && !partyId) {
|
|
382
|
+
toast.error('Customer must be selected for outstanding balances or credit payments.');
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
353
387
|
for (const line of lineItems) {
|
|
354
388
|
if (line.item.tracking_type === 'batch') {
|
|
355
389
|
const requiresBatch = !config.disableTrackingSelection || ['sales', 'quotation'].includes(config.type);
|
|
@@ -429,7 +463,8 @@ export function ProductTransactionScreen({
|
|
|
429
463
|
line_total: l.line_total,
|
|
430
464
|
}];
|
|
431
465
|
}),
|
|
432
|
-
payments: config.showPayment ?
|
|
466
|
+
payments: config.showPayment ? finalPayments : undefined,
|
|
467
|
+
amount_tendered: config.showPayment ? actualAmountTendered : undefined,
|
|
433
468
|
subtotal,
|
|
434
469
|
discount_total: discountTotal,
|
|
435
470
|
grand_total: grandTotal,
|
|
@@ -456,7 +491,15 @@ export function ProductTransactionScreen({
|
|
|
456
491
|
}, [lineItems, config, partyId, warehouseId, transactionDate, expectedDeliveryDate, notes, payments, subtotal, discountTotal, grandTotal, onSubmit, defaultWarehouseId, initialData]);
|
|
457
492
|
|
|
458
493
|
return (
|
|
459
|
-
<
|
|
494
|
+
<form
|
|
495
|
+
onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}
|
|
496
|
+
onKeyDown={(e) => {
|
|
497
|
+
if (e.key === 'Enter' && (e.target as HTMLElement).tagName !== 'TEXTAREA' && (e.target as HTMLElement).tagName !== 'BUTTON') {
|
|
498
|
+
e.preventDefault();
|
|
499
|
+
}
|
|
500
|
+
}}
|
|
501
|
+
className="flex flex-col h-full"
|
|
502
|
+
>
|
|
460
503
|
{/* ── Two-Panel Layout ── */}
|
|
461
504
|
<div className="flex-1 flex gap-5 min-h-0">
|
|
462
505
|
{/* Left: Product Selection (75%) */}
|
|
@@ -627,6 +670,6 @@ export function ProductTransactionScreen({
|
|
|
627
670
|
</ModalFooter>
|
|
628
671
|
</Modal>
|
|
629
672
|
)}
|
|
630
|
-
</
|
|
673
|
+
</form>
|
|
631
674
|
);
|
|
632
675
|
}
|
|
@@ -262,6 +262,7 @@ export const TRANSACTION_PRESETS: Record<TransactionType, TransactionScreenConfi
|
|
|
262
262
|
allowCreateBatchAndSerial: false,
|
|
263
263
|
allowEditPrice: true,
|
|
264
264
|
showStock: true,
|
|
265
|
+
requireFullPayment: true,
|
|
265
266
|
},
|
|
266
267
|
opening_stock: {
|
|
267
268
|
type: 'opening_stock',
|
|
@@ -350,6 +351,7 @@ export interface TransactionPayload {
|
|
|
350
351
|
line_total: number;
|
|
351
352
|
}>;
|
|
352
353
|
payments?: PaymentEntry[];
|
|
354
|
+
amount_tendered?: number;
|
|
353
355
|
subtotal: number;
|
|
354
356
|
discount_total: number;
|
|
355
357
|
grand_total: number;
|