umwd-components 0.1.640 → 0.1.641
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/dist/node_modules/base64-js/index.js +1 -1
- package/dist/node_modules/ieee754/index.js +1 -1
- package/dist/src/components/e-commerce/iro/TextualManageIROForm.js +1 -1
- package/dist/src/data/services/common/confirmation-service.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/data/services/common/confirmation-service.d.ts +2 -1
- package/dist/types/types/e-commerce/invoice/types.d.ts +12 -0
- package/package.json +1 -1
- package/src/components/e-commerce/iro/TextualManageIROForm.tsx +324 -3
- package/src/data/services/common/confirmation-service.ts +9 -2
- package/src/types/e-commerce/invoice/types.ts +16 -0
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { InvoiceOverwrites } from "../../../types/e-commerce/invoice/types";
|
|
2
|
+
export declare function confirmationService(path: string, ids: number[], overwrites?: object | InvoiceOverwrites): Promise<any>;
|
|
@@ -65,3 +65,15 @@ export interface Invoice {
|
|
|
65
65
|
customer?: number;
|
|
66
66
|
comments?: string;
|
|
67
67
|
}
|
|
68
|
+
export interface InvoiceOverwrites {
|
|
69
|
+
lines?: {
|
|
70
|
+
quantity?: number;
|
|
71
|
+
vat_rate?: number;
|
|
72
|
+
price_excl_vat?: number;
|
|
73
|
+
price_incl_vat?: number;
|
|
74
|
+
}[];
|
|
75
|
+
customer_internal_reference?: string;
|
|
76
|
+
total_excl_vat?: number;
|
|
77
|
+
VAT_total?: number;
|
|
78
|
+
total_incl_vat?: number;
|
|
79
|
+
}
|
package/package.json
CHANGED
|
@@ -37,6 +37,8 @@ import {
|
|
|
37
37
|
List,
|
|
38
38
|
ListItem,
|
|
39
39
|
TextField,
|
|
40
|
+
DialogContentText,
|
|
41
|
+
CircularProgress,
|
|
40
42
|
} from "@mui/material";
|
|
41
43
|
import NumbersIcon from "@mui/icons-material/Numbers";
|
|
42
44
|
import AssignmentReturnIcon from "@mui/icons-material/AssignmentReturn";
|
|
@@ -45,6 +47,11 @@ import BusinessIcon from "@mui/icons-material/Business";
|
|
|
45
47
|
import DescriptionIcon from "@mui/icons-material/Description";
|
|
46
48
|
import UpdateIcon from "@mui/icons-material/Update";
|
|
47
49
|
import { IroStatusIndicator } from "./IroStatusIndicator";
|
|
50
|
+
import { InvoiceOverwrites } from "../../../types/e-commerce/invoice/types";
|
|
51
|
+
import { Iro } from "../../../types/e-commerce/iro/types";
|
|
52
|
+
import { queryAllProducts } from "../../../data/loaders/e-commerce/queryAllProducts";
|
|
53
|
+
import qs from "qs";
|
|
54
|
+
import { Product } from "../../../types/e-commerce/product/types";
|
|
48
55
|
|
|
49
56
|
const INITIAL_STATE = {
|
|
50
57
|
zodErrors: null,
|
|
@@ -53,18 +60,305 @@ const INITIAL_STATE = {
|
|
|
53
60
|
message: null,
|
|
54
61
|
};
|
|
55
62
|
|
|
63
|
+
function OverwritesDialog({
|
|
64
|
+
open,
|
|
65
|
+
handleClose,
|
|
66
|
+
overwrites,
|
|
67
|
+
setOverwrites,
|
|
68
|
+
iro,
|
|
69
|
+
}: {
|
|
70
|
+
open: boolean;
|
|
71
|
+
handleClose: () => void;
|
|
72
|
+
overwrites: InvoiceOverwrites;
|
|
73
|
+
setOverwrites: (overwrites: InvoiceOverwrites) => void;
|
|
74
|
+
iro: Iro;
|
|
75
|
+
}) {
|
|
76
|
+
const [loading, setLoading] = useState(false);
|
|
77
|
+
|
|
78
|
+
// Initialize overwrites values when dialog opens
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const fetchProducts = async () => {
|
|
81
|
+
setLoading(true);
|
|
82
|
+
const query = qs.stringify(
|
|
83
|
+
{
|
|
84
|
+
filters: {
|
|
85
|
+
product_number: {
|
|
86
|
+
$in: iro.iro_items.data.map(
|
|
87
|
+
(item) => item.product?.product_number?.replace(/^r-/, "") || ""
|
|
88
|
+
),
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
populate: {
|
|
92
|
+
price: true,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{ encodeValuesOnly: true }
|
|
96
|
+
);
|
|
97
|
+
const correspondingProductsData = await queryAllProducts(query);
|
|
98
|
+
const correspondingProducts = correspondingProductsData.data.map(
|
|
99
|
+
(product: Product) => {
|
|
100
|
+
return {
|
|
101
|
+
id: product.id,
|
|
102
|
+
product_number: product.product_number,
|
|
103
|
+
price: product.price,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
console.log("correspondingProducts", correspondingProducts);
|
|
109
|
+
setLoading(false);
|
|
110
|
+
|
|
111
|
+
// Calculate totals from the IRO items
|
|
112
|
+
let totalExclVat = 0;
|
|
113
|
+
let totalInclVat = 0;
|
|
114
|
+
|
|
115
|
+
// Create line overwrites for each item
|
|
116
|
+
const lineOverwrites = iro.iro_items.data.map((item, index) => {
|
|
117
|
+
const product = item.product;
|
|
118
|
+
const correspondingProduct = correspondingProducts.find(
|
|
119
|
+
(p: Product) =>
|
|
120
|
+
p.product_number === product?.product_number?.replace(/^r-/, "") ||
|
|
121
|
+
""
|
|
122
|
+
);
|
|
123
|
+
// For return products, typically the product_number starts with r-
|
|
124
|
+
// The original product should have the same number without the r-
|
|
125
|
+
let price_excl_vat = 0;
|
|
126
|
+
let price_incl_vat = 0;
|
|
127
|
+
let vat_rate = 0;
|
|
128
|
+
|
|
129
|
+
if (correspondingProduct && correspondingProduct.price) {
|
|
130
|
+
price_excl_vat = correspondingProduct.price.price || 0;
|
|
131
|
+
price_incl_vat = correspondingProduct.price.price_incl_vat || 0;
|
|
132
|
+
vat_rate = correspondingProduct.price.vat_rate || 0;
|
|
133
|
+
|
|
134
|
+
// Add to totals
|
|
135
|
+
const itemTotalExclVat = price_excl_vat * item.returned_quantity;
|
|
136
|
+
const itemTotalInclVat = price_incl_vat * item.returned_quantity;
|
|
137
|
+
|
|
138
|
+
totalExclVat += itemTotalExclVat;
|
|
139
|
+
totalInclVat += itemTotalInclVat;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
vat_rate,
|
|
144
|
+
price_excl_vat,
|
|
145
|
+
price_incl_vat,
|
|
146
|
+
quantity: item.returned_quantity,
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Set the calculated values to the overwrites
|
|
151
|
+
setOverwrites({
|
|
152
|
+
customer_internal_reference: iro.customer_reference || "",
|
|
153
|
+
total_excl_vat: parseFloat(totalExclVat.toFixed(2)),
|
|
154
|
+
total_incl_vat: parseFloat(totalInclVat.toFixed(2)),
|
|
155
|
+
lines: lineOverwrites,
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if (open && iro?.iro_items?.data?.length > 0) {
|
|
160
|
+
fetchProducts();
|
|
161
|
+
}
|
|
162
|
+
}, [open, iro]);
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<Dialog open={open} fullWidth maxWidth="lg">
|
|
166
|
+
<DialogTitle>Check or overwrite value for the return payment</DialogTitle>
|
|
167
|
+
<DialogContent>
|
|
168
|
+
<Stack spacing={2} alignItems="left" sx={{ px: 0 }}>
|
|
169
|
+
<DialogContentText>
|
|
170
|
+
This is very important because these values will be used for
|
|
171
|
+
automated invoice generation
|
|
172
|
+
</DialogContentText>
|
|
173
|
+
<DialogContentText variant="h5">Overwrites</DialogContentText>
|
|
174
|
+
{loading ? (
|
|
175
|
+
<CircularProgress />
|
|
176
|
+
) : (
|
|
177
|
+
<Stack spacing={2}>
|
|
178
|
+
<TextField
|
|
179
|
+
label="Customer internal reference"
|
|
180
|
+
name="customer_internal_reference"
|
|
181
|
+
fullWidth
|
|
182
|
+
variant="outlined"
|
|
183
|
+
value={overwrites.customer_internal_reference}
|
|
184
|
+
onChange={(e) =>
|
|
185
|
+
setOverwrites({
|
|
186
|
+
...overwrites,
|
|
187
|
+
customer_internal_reference: e.target.value,
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
/>
|
|
191
|
+
<TextField
|
|
192
|
+
label="Total excl. VAT"
|
|
193
|
+
name="total_excl_vat"
|
|
194
|
+
type="number"
|
|
195
|
+
fullWidth
|
|
196
|
+
variant="outlined"
|
|
197
|
+
value={overwrites.total_excl_vat}
|
|
198
|
+
onChange={(e) =>
|
|
199
|
+
setOverwrites({
|
|
200
|
+
...overwrites,
|
|
201
|
+
total_excl_vat: parseFloat(e.target.value),
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
/>
|
|
205
|
+
<TextField
|
|
206
|
+
label="Total incl. VAT"
|
|
207
|
+
name="total_incl_vat"
|
|
208
|
+
type="number"
|
|
209
|
+
fullWidth
|
|
210
|
+
variant="outlined"
|
|
211
|
+
value={overwrites.total_incl_vat}
|
|
212
|
+
onChange={(e) =>
|
|
213
|
+
setOverwrites({
|
|
214
|
+
...overwrites,
|
|
215
|
+
total_incl_vat: parseFloat(e.target.value),
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
/>
|
|
219
|
+
</Stack>
|
|
220
|
+
)}
|
|
221
|
+
{iro?.iro_items?.data?.length > 0 && (
|
|
222
|
+
<>
|
|
223
|
+
<DialogContentText variant="h5">Items</DialogContentText>
|
|
224
|
+
|
|
225
|
+
{iro.iro_items.data.map((item, index) => {
|
|
226
|
+
return (
|
|
227
|
+
<Stack
|
|
228
|
+
spacing={2}
|
|
229
|
+
direction="row"
|
|
230
|
+
alignItems="center"
|
|
231
|
+
sx={{ px: 2 }}
|
|
232
|
+
key={item.id}
|
|
233
|
+
>
|
|
234
|
+
<Typography sx={{ minWidth: 100 }}>
|
|
235
|
+
{item.line_item_number}
|
|
236
|
+
</Typography>
|
|
237
|
+
<Typography sx={{ minWidth: 150 }}>
|
|
238
|
+
{item.product?.product_number}
|
|
239
|
+
</Typography>
|
|
240
|
+
<Typography sx={{ minWidth: 200 }}>
|
|
241
|
+
{item.product?.title}
|
|
242
|
+
</Typography>
|
|
243
|
+
|
|
244
|
+
<TextField
|
|
245
|
+
size="small"
|
|
246
|
+
label="VAT %"
|
|
247
|
+
name="vat_rate"
|
|
248
|
+
type="number"
|
|
249
|
+
sx={{ width: 100 }}
|
|
250
|
+
value={overwrites?.lines?.[index]?.vat_rate ?? ""}
|
|
251
|
+
onChange={(e) => {
|
|
252
|
+
const newLines = [...(overwrites.lines || [])];
|
|
253
|
+
newLines[index] = {
|
|
254
|
+
...newLines[index],
|
|
255
|
+
vat_rate: parseFloat(e.target.value),
|
|
256
|
+
};
|
|
257
|
+
setOverwrites({
|
|
258
|
+
...overwrites,
|
|
259
|
+
lines: newLines,
|
|
260
|
+
});
|
|
261
|
+
}}
|
|
262
|
+
/>
|
|
263
|
+
|
|
264
|
+
<TextField
|
|
265
|
+
size="small"
|
|
266
|
+
label="Price excl."
|
|
267
|
+
name="price_excl_vat"
|
|
268
|
+
type="number"
|
|
269
|
+
sx={{ width: 120 }}
|
|
270
|
+
value={overwrites?.lines?.[index]?.price_excl_vat ?? ""}
|
|
271
|
+
onChange={(e) => {
|
|
272
|
+
const newLines = [...(overwrites.lines || [])];
|
|
273
|
+
newLines[index] = {
|
|
274
|
+
...newLines[index],
|
|
275
|
+
price_excl_vat: parseFloat(e.target.value),
|
|
276
|
+
};
|
|
277
|
+
setOverwrites({
|
|
278
|
+
...overwrites,
|
|
279
|
+
lines: newLines,
|
|
280
|
+
});
|
|
281
|
+
}}
|
|
282
|
+
/>
|
|
283
|
+
|
|
284
|
+
<TextField
|
|
285
|
+
size="small"
|
|
286
|
+
label="Price incl."
|
|
287
|
+
name="price_incl_vat"
|
|
288
|
+
type="number"
|
|
289
|
+
sx={{ width: 120 }}
|
|
290
|
+
value={overwrites?.lines?.[index]?.price_incl_vat ?? ""}
|
|
291
|
+
onChange={(e) => {
|
|
292
|
+
const newLines = [...(overwrites.lines || [])];
|
|
293
|
+
newLines[index] = {
|
|
294
|
+
...newLines[index],
|
|
295
|
+
price_incl_vat: parseFloat(e.target.value),
|
|
296
|
+
};
|
|
297
|
+
setOverwrites({
|
|
298
|
+
...overwrites,
|
|
299
|
+
lines: newLines,
|
|
300
|
+
});
|
|
301
|
+
}}
|
|
302
|
+
/>
|
|
303
|
+
|
|
304
|
+
<TextField
|
|
305
|
+
size="small"
|
|
306
|
+
label="Qty"
|
|
307
|
+
name="quantity"
|
|
308
|
+
type="number"
|
|
309
|
+
sx={{ width: 80 }}
|
|
310
|
+
value={overwrites?.lines?.[index]?.quantity ?? ""}
|
|
311
|
+
onChange={(e) => {
|
|
312
|
+
const newLines = [...(overwrites.lines || [])];
|
|
313
|
+
newLines[index] = {
|
|
314
|
+
...newLines[index],
|
|
315
|
+
quantity: parseFloat(e.target.value),
|
|
316
|
+
};
|
|
317
|
+
setOverwrites({
|
|
318
|
+
...overwrites,
|
|
319
|
+
lines: newLines,
|
|
320
|
+
});
|
|
321
|
+
}}
|
|
322
|
+
/>
|
|
323
|
+
</Stack>
|
|
324
|
+
);
|
|
325
|
+
})}
|
|
326
|
+
</>
|
|
327
|
+
)}
|
|
328
|
+
</Stack>
|
|
329
|
+
</DialogContent>
|
|
330
|
+
<DialogActions>
|
|
331
|
+
<Button
|
|
332
|
+
variant="contained"
|
|
333
|
+
onClick={(e) => {
|
|
334
|
+
confirmationService("iros", [iro.id], overwrites);
|
|
335
|
+
handleClose();
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
Confirm
|
|
339
|
+
</Button>
|
|
340
|
+
<Button variant="contained" onClick={handleClose}>
|
|
341
|
+
Cancel
|
|
342
|
+
</Button>
|
|
343
|
+
</DialogActions>
|
|
344
|
+
</Dialog>
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
56
348
|
function ConfirmFormDialog({
|
|
57
349
|
open,
|
|
58
350
|
handleClose,
|
|
59
351
|
orderID,
|
|
60
352
|
currentStatus,
|
|
61
353
|
revalidateCallback,
|
|
354
|
+
openOverwritesDialog,
|
|
62
355
|
}: {
|
|
63
356
|
open: boolean;
|
|
64
357
|
handleClose: () => void;
|
|
65
358
|
orderID: number;
|
|
66
359
|
currentStatus: "requested" | "finalising_process";
|
|
67
360
|
revalidateCallback?: () => void;
|
|
361
|
+
openOverwritesDialog?: () => void;
|
|
68
362
|
}) {
|
|
69
363
|
return (
|
|
70
364
|
<Dialog open={open}>
|
|
@@ -83,6 +377,11 @@ function ConfirmFormDialog({
|
|
|
83
377
|
? "By confirming the return you will update it's status from requested to returning"
|
|
84
378
|
: "By confirming the return you will update it's status from finalising_process to done"}
|
|
85
379
|
</ListItem>
|
|
380
|
+
{currentStatus === "finalising_process" && (
|
|
381
|
+
<ListItem>
|
|
382
|
+
Confirming this order will automatically create an invoice
|
|
383
|
+
</ListItem>
|
|
384
|
+
)}
|
|
86
385
|
</List>
|
|
87
386
|
<Typography>Current status: {currentStatus}</Typography>
|
|
88
387
|
</Stack>
|
|
@@ -91,9 +390,14 @@ function ConfirmFormDialog({
|
|
|
91
390
|
<Button
|
|
92
391
|
variant="contained"
|
|
93
392
|
onClick={(e) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
393
|
+
if (currentStatus === "finalising_process") {
|
|
394
|
+
openOverwritesDialog && openOverwritesDialog();
|
|
395
|
+
handleClose();
|
|
396
|
+
} else if (currentStatus === "requested") {
|
|
397
|
+
confirmationService("iros", [orderID]);
|
|
398
|
+
revalidateCallback && revalidateCallback();
|
|
399
|
+
handleClose();
|
|
400
|
+
}
|
|
97
401
|
}}
|
|
98
402
|
>
|
|
99
403
|
Yes
|
|
@@ -196,6 +500,14 @@ export default function TextualManageIROForm({
|
|
|
196
500
|
|
|
197
501
|
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
|
198
502
|
const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
|
|
503
|
+
const [overwritesDialogOpen, setOverwritesDialogOpen] = useState(false);
|
|
504
|
+
|
|
505
|
+
const [overwrites, setOverwrites] = useState<InvoiceOverwrites>({
|
|
506
|
+
customer_internal_reference: "",
|
|
507
|
+
total_excl_vat: 0,
|
|
508
|
+
total_incl_vat: 0,
|
|
509
|
+
lines: [],
|
|
510
|
+
});
|
|
199
511
|
|
|
200
512
|
const [showing, setShowing] = useState<
|
|
201
513
|
("received" | "registered" | "released" | "reports")[]
|
|
@@ -278,6 +590,7 @@ export default function TextualManageIROForm({
|
|
|
278
590
|
}, [formState]);
|
|
279
591
|
|
|
280
592
|
useEffect(() => {
|
|
593
|
+
console.log("data", data);
|
|
281
594
|
if (data.iro_items?.data) {
|
|
282
595
|
setItems(data.iro_items.data ? data.iro_items.data : []);
|
|
283
596
|
}
|
|
@@ -455,6 +768,14 @@ export default function TextualManageIROForm({
|
|
|
455
768
|
orderID={data.id}
|
|
456
769
|
currentStatus={data.status}
|
|
457
770
|
revalidateCallback={revalidateCallback}
|
|
771
|
+
openOverwritesDialog={() => setOverwritesDialogOpen(true)}
|
|
772
|
+
/>
|
|
773
|
+
<OverwritesDialog
|
|
774
|
+
open={overwritesDialogOpen}
|
|
775
|
+
handleClose={() => setOverwritesDialogOpen(false)}
|
|
776
|
+
overwrites={overwrites}
|
|
777
|
+
setOverwrites={setOverwrites}
|
|
778
|
+
iro={data}
|
|
458
779
|
/>
|
|
459
780
|
<CancelIroDialog
|
|
460
781
|
open={cancelDialogOpen}
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import { getAuthToken } from "../get-token";
|
|
4
4
|
import { getStrapiURL } from "../../../lib/utils"; //"@/lib/utils";
|
|
5
|
+
import { InvoiceOverwrites } from "../../../types/e-commerce/invoice/types";
|
|
5
6
|
|
|
6
7
|
// TODO move to common services
|
|
7
|
-
export async function confirmationService(
|
|
8
|
+
export async function confirmationService(
|
|
9
|
+
path: string,
|
|
10
|
+
ids: number[],
|
|
11
|
+
overwrites: object | InvoiceOverwrites = {}
|
|
12
|
+
) {
|
|
8
13
|
const authToken = await getAuthToken();
|
|
9
14
|
|
|
10
15
|
const baseUrl = getStrapiURL();
|
|
@@ -13,7 +18,9 @@ export async function confirmationService(path: string, ids: number[]) {
|
|
|
13
18
|
|
|
14
19
|
if (!authToken) throw new Error("No auth token found");
|
|
15
20
|
|
|
16
|
-
const payload = JSON.stringify({
|
|
21
|
+
const payload = JSON.stringify({
|
|
22
|
+
data: { selectedIds: [...ids], overwrites },
|
|
23
|
+
});
|
|
17
24
|
|
|
18
25
|
console.log("payload", payload);
|
|
19
26
|
console.log("url", url);
|
|
@@ -69,3 +69,19 @@ export interface Invoice {
|
|
|
69
69
|
customer?: number;
|
|
70
70
|
comments?: string;
|
|
71
71
|
}
|
|
72
|
+
|
|
73
|
+
// TODO a copy of this exists in the umwd project, consider moving to a common place
|
|
74
|
+
// TODO consider moving to a common place, this is used in the umwd project as well
|
|
75
|
+
// /cms/api/e-commerce/services/invoice/confirm
|
|
76
|
+
export interface InvoiceOverwrites {
|
|
77
|
+
lines?: {
|
|
78
|
+
quantity?: number;
|
|
79
|
+
vat_rate?: number;
|
|
80
|
+
price_excl_vat?: number;
|
|
81
|
+
price_incl_vat?: number;
|
|
82
|
+
}[];
|
|
83
|
+
customer_internal_reference?: string;
|
|
84
|
+
total_excl_vat?: number;
|
|
85
|
+
VAT_total?: number;
|
|
86
|
+
total_incl_vat?: number;
|
|
87
|
+
}
|