@accounter/client 0.0.8-alpha-20251028124234-328844c99a42b68aa9e2f32fd86da80b4832f631 → 0.0.8-alpha-20251028124537-8b0946b10a6e597c997017c33fb80fbf674e2feb
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/CHANGELOG.md +84 -13
- package/dist/assets/{Checkbox-BR6kGuhg.js → Checkbox-DBiOK2wr.js} +3 -3
- package/dist/assets/{Progress-7xtiFwK3.js → Progress-3b9RPwUr.js} +1 -1
- package/dist/assets/Typography-BjOvYDtJ.js +1 -0
- package/dist/assets/accordion-gDGB9JKa.js +1 -0
- package/dist/assets/accountant-approvals-aQMSAP78.js +1 -0
- package/dist/assets/all-charges-X9R8PfNk.js +1 -0
- package/dist/assets/{arrow-up-down-DPG1l9S1.js → arrow-up-down-B3nz1j1G.js} +2 -2
- package/dist/assets/{building-2-BgvPBt2Z.js → building-2-DyCA1u9z.js} +2 -2
- package/dist/assets/business-BOAeYn9N.js +27 -0
- package/dist/assets/{business-header-u2sfE_d8.js → business-header-Ck0v04Iw.js} +1 -1
- package/dist/assets/business-transactions-single-_OIHJEfY.js +1 -0
- package/dist/assets/business-trip-CYZP6qrZ.js +1 -0
- package/dist/assets/charges-filters-Dc9JkkaM.js +1 -0
- package/dist/assets/charges-ledger-validation-BiBZ2pEf.js +1 -0
- package/dist/assets/{chart-ByngRufj.js → chart-xV-krckX.js} +6 -6
- package/dist/assets/{data-table-pagination-D4OEFmX_.js → data-table-pagination-BtKmZaSS.js} +3 -3
- package/dist/assets/editable-business-trip-BIRxgXHu.js +16 -0
- package/dist/assets/index-2x_26B9B.js +1 -0
- package/dist/assets/index-4yVbIKWS.js +1 -0
- package/dist/assets/index-B-uojS_H.js +1 -0
- package/dist/assets/index-BFRBCjVk.css +1 -0
- package/dist/assets/index-BVffhJ_X.js +2 -0
- package/dist/assets/index-BZFydPbo.js +1 -0
- package/dist/assets/index-BazMRdI3.js +6 -0
- package/dist/assets/index-BsTpXlvi.js +891 -0
- package/dist/assets/{index-CLUhAJ3t.js → index-C3BnUF_U.js} +3 -3
- package/dist/assets/index-CD_kl3oZ.js +1 -0
- package/dist/assets/{index-UMFH47hN.js → index-CWM7AEkA.js} +4 -4
- package/dist/assets/index-CaXjK2fb.js +2 -0
- package/dist/assets/index-CbJd62Hp.js +1 -0
- package/dist/assets/index-CdKoH7Cz.js +9 -0
- package/dist/assets/index-Crc98w5p.js +1 -0
- package/dist/assets/index-Cs-QBGd0.js +1 -0
- package/dist/assets/index-D2ada9K2.js +1 -0
- package/dist/assets/index-DAkukoD_.js +1 -0
- package/dist/assets/index-DML4EmHc.js +1 -0
- package/dist/assets/{index-Bsl7tJp_.js → index-DuBbCD-l.js} +22 -22
- package/dist/assets/{index-BetG0HVN.js → index-DypFylYK.js} +3 -3
- package/dist/assets/{index-vChLJwSt.js → index-KFd7K_WR.js} +3 -3
- package/dist/assets/index-rwlm4BcW.js +1 -0
- package/dist/assets/index-xA-DiOzv.js +1 -0
- package/dist/assets/{index.es-NphQjU3m.js → index.es-C6nk1zNp.js} +1 -1
- package/dist/assets/issue-document-BezTjH4r.js +1 -0
- package/dist/assets/login-page-I-7tCrbB.js +1 -0
- package/dist/assets/missing-info-charges-BDgEJ4mj.js +1 -0
- package/dist/assets/page-not-found-CIT5vwb-.js +1 -0
- package/dist/assets/{pencil-tV0FsM6V.js → pencil-BHXyXIP9.js} +2 -2
- package/dist/assets/report-commentary-row-DHfnYhMN.js +1 -0
- package/dist/assets/{save-Czmh3tvC.js → save-NUZuyPEH.js} +2 -2
- package/dist/assets/sub-3UcXQDsZ.js +1 -0
- package/dist/assets/subMonths-BbuiFsxa.js +1 -0
- package/dist/index.html +2 -2
- package/package.json +5 -5
- package/src/components/business/admin-business-section.tsx +74 -36
- package/src/components/business/contracts-section.tsx +25 -4
- package/src/components/business-transactions/business-extended-info.tsx +5 -5
- package/src/components/business-transactions/index.tsx +28 -1
- package/src/components/businesses/index.tsx +2 -6
- package/src/components/charges/cells/business-trip.tsx +1 -6
- package/src/components/charges/cells/counterparty.tsx +28 -4
- package/src/components/charges/helpers.ts +15 -0
- package/src/components/clients/contracts/modify-contract-dialog.tsx +70 -14
- package/src/components/clients/modify-client-dialog.tsx +27 -9
- package/src/components/common/business-trip-report/parts/core-expense-row.tsx +2 -2
- package/src/components/common/business-trip-report/parts/report-header.tsx +1 -2
- package/src/components/common/business-trip-report/parts/uncategorized-transactions.tsx +2 -2
- package/src/components/common/buttons/charge-navigate-button.tsx +11 -12
- package/src/components/common/modals/edit-charge-modal.tsx +2 -2
- package/src/components/common/modals/insert-business.tsx +88 -36
- package/src/components/common/modals/insert-document-modal.tsx +2 -2
- package/src/components/common/modals/match-document-modal.tsx +2 -2
- package/src/components/common/new-documents-list.tsx +2 -2
- package/src/components/documents-table/cells/creditor.tsx +11 -2
- package/src/components/documents-table/cells/debtor.tsx +11 -2
- package/src/components/layout/user-nav.tsx +22 -3
- package/src/components/ledger-table/counterparty-cell.tsx +33 -4
- package/src/components/reports/conto/index.tsx +18 -1
- package/src/components/reports/trial-balance-report/index.tsx +17 -1
- package/src/components/screens/businesses/business.tsx +4 -0
- package/src/components/screens/charges/all-charges.tsx +17 -1
- package/src/components/screens/charges/charge.tsx +4 -0
- package/src/components/screens/reports/balance-report/index.tsx +14 -0
- package/src/components/screens/reports/depreciation-report/index.tsx +14 -0
- package/src/components/transactions-table/cells/counterparty.tsx +23 -2
- package/src/components/transactions-table/cells-legacy/counterparty.tsx +26 -3
- package/src/gql/gql.ts +9 -9
- package/src/gql/graphql.ts +29 -23
- package/src/hooks/use-get-all-contracts.ts +1 -1
- package/src/providers/urql.tsx +2 -2
- package/dist/assets/MultiSelect-BqcJrWnD.js +0 -1
- package/dist/assets/Pagination-6Sv5LXxl.js +0 -1
- package/dist/assets/Table-C5zxD95i.js +0 -1
- package/dist/assets/Typography-CMzSQZKD.js +0 -1
- package/dist/assets/YearPickerInput-CllwSjcn.js +0 -1
- package/dist/assets/accordion-CMR2fANH.js +0 -1
- package/dist/assets/accountant-approvals-BHFXpHHc.js +0 -1
- package/dist/assets/accounter-table-CpeQD4PG.js +0 -1
- package/dist/assets/addDays-DvwuJbUs.js +0 -1
- package/dist/assets/all-charges-At7WJXuW.js +0 -1
- package/dist/assets/business-DKvbSnga.js +0 -32
- package/dist/assets/business-extended-info-7CM8px2e.js +0 -13
- package/dist/assets/business-transactions-filters-DmpO9Bwo.js +0 -1
- package/dist/assets/business-transactions-single-rF6JbAL7.js +0 -1
- package/dist/assets/business-trip-BGrp09N7.js +0 -1
- package/dist/assets/charge-C-EaA1Xc.js +0 -1
- package/dist/assets/charges-filters-Dq-8QHH-.js +0 -1
- package/dist/assets/charges-ledger-validation-DlkzVow7.js +0 -1
- package/dist/assets/charges-table-Cncs1HLi.js +0 -62
- package/dist/assets/create-event-handler-BiA-1lGu.js +0 -1
- package/dist/assets/download-csv-button-Df5rDeDc.js +0 -1
- package/dist/assets/editable-business-trip-Bav24z0u.js +0 -16
- package/dist/assets/funnel-BJ71hzoq.js +0 -6
- package/dist/assets/index-BRv0JZw4.js +0 -1
- package/dist/assets/index-BXlS8oD_.js +0 -1
- package/dist/assets/index-BplSRMAq.css +0 -1
- package/dist/assets/index-Cix5qjA-.js +0 -2
- package/dist/assets/index-CizLtiES.js +0 -1
- package/dist/assets/index-DKBzv0gc.js +0 -1
- package/dist/assets/index-DR_5jpS4.js +0 -6
- package/dist/assets/index-DTmtILfq.js +0 -1
- package/dist/assets/index-DU0G7FZm.js +0 -1
- package/dist/assets/index-DUWRgLfu.js +0 -9
- package/dist/assets/index-DYZPWG4k.js +0 -2
- package/dist/assets/index-DdUE2_44.js +0 -1
- package/dist/assets/index-De5dvO0S.js +0 -1
- package/dist/assets/index-Des3eR4f.js +0 -1
- package/dist/assets/index-DpYwi5kf.js +0 -6
- package/dist/assets/index-GzyQZkbY.js +0 -1
- package/dist/assets/index-HzLXi-qB.js +0 -1
- package/dist/assets/index-Ji28AZwq.js +0 -1
- package/dist/assets/index-fuT9duEO.js +0 -1
- package/dist/assets/index-wck8Xuay.js +0 -1
- package/dist/assets/index-wyU9I4Kz.js +0 -768
- package/dist/assets/insert-business-trip-modal-vS1QrUJz.js +0 -6
- package/dist/assets/issue-document-pIswc_8i.js +0 -1
- package/dist/assets/list-plus-Dy3vzJVy.js +0 -6
- package/dist/assets/login-page-YXRfklK1.js +0 -1
- package/dist/assets/match-document-modal-BPG_hljb.js +0 -16
- package/dist/assets/missing-info-charges-D8dUfChs.js +0 -1
- package/dist/assets/modal-D47umnak.js +0 -1
- package/dist/assets/page-layout-BG0XvWfD.js +0 -1
- package/dist/assets/page-not-found-Cy6oIIb1.js +0 -1
- package/dist/assets/panel-top-open-B1rhJYjQ.js +0 -11
- package/dist/assets/report-commentary-row-BL2RkIHq.js +0 -1
- package/dist/assets/similar-transactions-modal-MQeC2gtu.js +0 -1
- package/dist/assets/sub-B4_VmmF9.js +0 -1
- package/dist/assets/subMonths-DG7w6bCY.js +0 -1
- package/dist/assets/summary-DvHtnArZ.js +0 -1
- package/dist/assets/switch-GSloW_Ey.js +0 -1
- package/dist/assets/toggle-expansion-button-lwJYTklN.js +0 -1
- package/dist/assets/tooltip-BbKSwLCX.js +0 -1
- package/dist/assets/use-url-query-CUVSXgm0.js +0 -1
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
} from '@/helpers/index.js';
|
|
39
39
|
import { useUpdateAdminBusiness } from '@/hooks/use-update-admin-business.js';
|
|
40
40
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
41
|
+
import { Separator } from '../ui/separator';
|
|
41
42
|
|
|
42
43
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
43
44
|
/* GraphQL */ `
|
|
@@ -46,10 +47,11 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
46
47
|
... on LtdFinancialEntity {
|
|
47
48
|
adminInfo {
|
|
48
49
|
id
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
withholdingTaxBookNumber
|
|
51
|
+
withholdingTaxFileNumber
|
|
52
|
+
socialSecurityEmployerId
|
|
53
|
+
taxAdvancesRate
|
|
54
|
+
taxAdvancesId
|
|
53
55
|
registrationDate
|
|
54
56
|
}
|
|
55
57
|
}
|
|
@@ -57,16 +59,16 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
57
59
|
`;
|
|
58
60
|
|
|
59
61
|
const adminBusinessFormSchema = z.object({
|
|
60
|
-
|
|
61
|
-
message: '
|
|
62
|
+
withholdingTaxBookNumber: z.string().min(1, {
|
|
63
|
+
message: 'Withholding Tax Book Number is required',
|
|
62
64
|
}),
|
|
63
|
-
|
|
64
|
-
message: 'Tax
|
|
65
|
+
withholdingTaxFileNumber: z.string().min(1, {
|
|
66
|
+
message: 'Withholding Tax File Number is required',
|
|
65
67
|
}),
|
|
66
|
-
|
|
68
|
+
socialSecurityEmployerId: z.string().min(1, {
|
|
67
69
|
message: 'National Insurance Employer ID is required',
|
|
68
70
|
}),
|
|
69
|
-
|
|
71
|
+
taxAdvancesRate: z
|
|
70
72
|
.number()
|
|
71
73
|
.min(0, {
|
|
72
74
|
message: 'Advance Tax Rate must be at least 0',
|
|
@@ -74,8 +76,11 @@ const adminBusinessFormSchema = z.object({
|
|
|
74
76
|
.max(100, {
|
|
75
77
|
message: 'Advance Tax Rate must be at most 100',
|
|
76
78
|
}),
|
|
79
|
+
taxAdvancesId: z.string().min(1, {
|
|
80
|
+
message: 'Tax Advances ID is required',
|
|
81
|
+
}),
|
|
77
82
|
registrationDate: z.string().min(1, {
|
|
78
|
-
message: 'Registration Date is required',
|
|
83
|
+
message: 'Business Registration Start Date is required',
|
|
79
84
|
}),
|
|
80
85
|
});
|
|
81
86
|
|
|
@@ -89,10 +94,11 @@ function BusinessAdminSectionFragmentToFormValues(
|
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
return {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
withholdingTaxBookNumber: admin.adminInfo.withholdingTaxBookNumber ?? '',
|
|
98
|
+
withholdingTaxFileNumber: admin.adminInfo.withholdingTaxFileNumber ?? '',
|
|
99
|
+
socialSecurityEmployerId: admin.adminInfo.socialSecurityEmployerId ?? '',
|
|
100
|
+
taxAdvancesRate: admin.adminInfo.taxAdvancesRate ?? 0,
|
|
101
|
+
taxAdvancesId: admin.adminInfo.taxAdvancesId ?? '',
|
|
96
102
|
registrationDate: admin.adminInfo.registrationDate ?? '',
|
|
97
103
|
};
|
|
98
104
|
}
|
|
@@ -101,10 +107,11 @@ function convertFormDataToUpdateAdminBusinessInput(
|
|
|
101
107
|
formData: Partial<AdminBusinessFormValues>,
|
|
102
108
|
): UpdateAdminBusinessInput {
|
|
103
109
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
withholdingTaxBookNumber: formData.withholdingTaxBookNumber,
|
|
111
|
+
withholdingTaxFileNumber: formData.withholdingTaxFileNumber,
|
|
112
|
+
socialSecurityEmployerId: formData.socialSecurityEmployerId,
|
|
113
|
+
taxAdvancesRate: formData.taxAdvancesRate,
|
|
114
|
+
taxAdvancesId: formData.taxAdvancesId,
|
|
108
115
|
registrationDate: formData.registrationDate
|
|
109
116
|
? (formatTimelessDateString(new Date(formData.registrationDate)) as TimelessDateString)
|
|
110
117
|
: undefined,
|
|
@@ -174,16 +181,19 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
174
181
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
|
175
182
|
<CardContent>
|
|
176
183
|
<div className="grid gap-6 md:grid-cols-2">
|
|
177
|
-
|
|
184
|
+
<h3 className="text-sm font-semibold text-foreground md:col-span-2">
|
|
185
|
+
Withholding Tax
|
|
186
|
+
</h3>
|
|
187
|
+
|
|
178
188
|
<FormField
|
|
179
189
|
control={form.control}
|
|
180
|
-
name="
|
|
190
|
+
name="withholdingTaxBookNumber"
|
|
181
191
|
render={({ field, fieldState }) => (
|
|
182
192
|
<FormItem>
|
|
183
|
-
<FormLabel>
|
|
193
|
+
<FormLabel>Book Number</FormLabel>
|
|
184
194
|
<FormControl>
|
|
185
195
|
<Input
|
|
186
|
-
placeholder="Enter
|
|
196
|
+
placeholder="Enter book number"
|
|
187
197
|
{...field}
|
|
188
198
|
className={dirtyFieldMarker(fieldState)}
|
|
189
199
|
/>
|
|
@@ -193,16 +203,15 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
193
203
|
)}
|
|
194
204
|
/>
|
|
195
205
|
|
|
196
|
-
{/* Tax Prepayment ID */}
|
|
197
206
|
<FormField
|
|
198
207
|
control={form.control}
|
|
199
|
-
name="
|
|
208
|
+
name="withholdingTaxFileNumber"
|
|
200
209
|
render={({ field, fieldState }) => (
|
|
201
210
|
<FormItem>
|
|
202
|
-
<FormLabel>
|
|
211
|
+
<FormLabel>File Number</FormLabel>
|
|
203
212
|
<FormControl>
|
|
204
213
|
<Input
|
|
205
|
-
placeholder="Enter
|
|
214
|
+
placeholder="Enter file number"
|
|
206
215
|
{...field}
|
|
207
216
|
className={dirtyFieldMarker(fieldState)}
|
|
208
217
|
/>
|
|
@@ -212,16 +221,19 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
212
221
|
)}
|
|
213
222
|
/>
|
|
214
223
|
|
|
215
|
-
|
|
224
|
+
<Separator className="md:col-span-2" />
|
|
225
|
+
|
|
226
|
+
<h3 className="text-sm font-semibold text-foreground md:col-span-2">Tax Advances</h3>
|
|
227
|
+
|
|
216
228
|
<FormField
|
|
217
229
|
control={form.control}
|
|
218
|
-
name="
|
|
230
|
+
name="taxAdvancesId"
|
|
219
231
|
render={({ field, fieldState }) => (
|
|
220
232
|
<FormItem>
|
|
221
|
-
<FormLabel>
|
|
233
|
+
<FormLabel>Identification number</FormLabel>
|
|
222
234
|
<FormControl>
|
|
223
235
|
<Input
|
|
224
|
-
placeholder="Enter
|
|
236
|
+
placeholder="Enter tax advances ID"
|
|
225
237
|
{...field}
|
|
226
238
|
className={dirtyFieldMarker(fieldState)}
|
|
227
239
|
/>
|
|
@@ -231,13 +243,12 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
231
243
|
)}
|
|
232
244
|
/>
|
|
233
245
|
|
|
234
|
-
{/* Advance Tax Rate */}
|
|
235
246
|
<FormField
|
|
236
247
|
control={form.control}
|
|
237
|
-
name="
|
|
248
|
+
name="taxAdvancesRate"
|
|
238
249
|
render={({ field, fieldState }) => (
|
|
239
250
|
<FormItem>
|
|
240
|
-
<FormLabel>
|
|
251
|
+
<FormLabel>Tax Rate (%)</FormLabel>
|
|
241
252
|
<FormControl>
|
|
242
253
|
<Input
|
|
243
254
|
type="number"
|
|
@@ -254,13 +265,40 @@ export function AdminBusinessSection({ data, refetchBusiness }: Props): React.Re
|
|
|
254
265
|
)}
|
|
255
266
|
/>
|
|
256
267
|
|
|
257
|
-
|
|
268
|
+
<Separator className="md:col-span-2" />
|
|
269
|
+
|
|
270
|
+
<h3 className="text-sm font-semibold text-foreground md:col-span-2">
|
|
271
|
+
Social Security
|
|
272
|
+
</h3>
|
|
273
|
+
|
|
274
|
+
{/* Social Security Employer ID */}
|
|
275
|
+
<FormField
|
|
276
|
+
control={form.control}
|
|
277
|
+
name="socialSecurityEmployerId"
|
|
278
|
+
render={({ field, fieldState }) => (
|
|
279
|
+
<FormItem>
|
|
280
|
+
<FormLabel>Employer Identifier</FormLabel>
|
|
281
|
+
<FormControl>
|
|
282
|
+
<Input
|
|
283
|
+
placeholder="Enter employer ID"
|
|
284
|
+
{...field}
|
|
285
|
+
className={dirtyFieldMarker(fieldState)}
|
|
286
|
+
/>
|
|
287
|
+
</FormControl>
|
|
288
|
+
<FormMessage />
|
|
289
|
+
</FormItem>
|
|
290
|
+
)}
|
|
291
|
+
/>
|
|
292
|
+
|
|
293
|
+
<Separator className="md:col-span-2" />
|
|
294
|
+
|
|
295
|
+
{/* Business Registration Start Date */}
|
|
258
296
|
<FormField
|
|
259
297
|
control={form.control}
|
|
260
298
|
name="registrationDate"
|
|
261
299
|
render={({ field, fieldState }) => (
|
|
262
300
|
<FormItem>
|
|
263
|
-
<FormLabel>Registration Date</FormLabel>
|
|
301
|
+
<FormLabel>Business Registration Start Date</FormLabel>
|
|
264
302
|
<FormControl>
|
|
265
303
|
<Input type="date" {...field} className={dirtyFieldMarker(fieldState)} />
|
|
266
304
|
</FormControl>
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
query ClientContractsSection($clientId: UUID!) {
|
|
22
22
|
contractsByClient(clientId: $clientId) {
|
|
23
23
|
id
|
|
24
|
-
|
|
24
|
+
purchaseOrders
|
|
25
25
|
startDate
|
|
26
26
|
endDate
|
|
27
27
|
amount {
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
remarks
|
|
36
36
|
plan
|
|
37
37
|
msCloud
|
|
38
|
+
operationsLimit
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
`;
|
|
@@ -46,7 +47,7 @@ function convertContractDataToFormValues(
|
|
|
46
47
|
id: contract.id,
|
|
47
48
|
// TODO: activate this field later. requires additional backend support
|
|
48
49
|
// operationsLimit: 0, // Placeholder, as this field is not in the query
|
|
49
|
-
|
|
50
|
+
pos: contract.purchaseOrders ?? undefined,
|
|
50
51
|
startDate: contract.startDate,
|
|
51
52
|
endDate: contract.endDate,
|
|
52
53
|
paymentAmount: contract.amount.raw,
|
|
@@ -58,6 +59,7 @@ function convertContractDataToFormValues(
|
|
|
58
59
|
subscriptionPlan: contract.plan ?? undefined,
|
|
59
60
|
defaultRemark: contract.remarks ?? undefined,
|
|
60
61
|
defaultDocumentType: contract.documentType ?? undefined,
|
|
62
|
+
operationsLimit: contract.operationsLimit,
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -130,8 +132,22 @@ export function ContractsSection({ clientId }: Props) {
|
|
|
130
132
|
</div>
|
|
131
133
|
|
|
132
134
|
<div className="space-y-0">
|
|
133
|
-
<p className="text-sm text-muted-foreground">PO
|
|
134
|
-
<p className="text-sm font-medium font-mono">
|
|
135
|
+
<p className="text-sm text-muted-foreground">PO Numbers</p>
|
|
136
|
+
<p className="text-sm font-medium font-mono">
|
|
137
|
+
{contract.purchaseOrders.toReversed()[0] ?? ''}
|
|
138
|
+
</p>
|
|
139
|
+
{contract.purchaseOrders.length > 1 && (
|
|
140
|
+
<div className="space-x-1">
|
|
141
|
+
{contract.purchaseOrders
|
|
142
|
+
.toReversed()
|
|
143
|
+
.slice(1)
|
|
144
|
+
.map(po => (
|
|
145
|
+
<span key={po} className="text-xs font-thin font-mono">
|
|
146
|
+
{po}
|
|
147
|
+
</span>
|
|
148
|
+
))}
|
|
149
|
+
</div>
|
|
150
|
+
)}
|
|
135
151
|
</div>
|
|
136
152
|
|
|
137
153
|
{/* TODO: activate this field later. requires additional backend support */}
|
|
@@ -161,6 +177,11 @@ export function ContractsSection({ clientId }: Props) {
|
|
|
161
177
|
</p>
|
|
162
178
|
</div>
|
|
163
179
|
|
|
180
|
+
<div className="space-y-0">
|
|
181
|
+
<p className="text-sm text-muted-foreground">Operations Limit</p>
|
|
182
|
+
<p className="text-sm font-medium">{contract.operationsLimit.toLocaleString()}</p>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
164
185
|
<div className="space-y-0">
|
|
165
186
|
<p className="text-sm text-muted-foreground">Document Type</p>
|
|
166
187
|
<p className="text-sm font-medium">
|
|
@@ -3,7 +3,6 @@ import { format } from 'date-fns';
|
|
|
3
3
|
import { ChevronsLeftRightEllipsis, ChevronsRightLeft } from 'lucide-react';
|
|
4
4
|
import { Link } from 'react-router-dom';
|
|
5
5
|
import { useQuery } from 'urql';
|
|
6
|
-
import { ROUTES } from '@/router/routes.js';
|
|
7
6
|
import { Mark, Table, Tooltip } from '@mantine/core';
|
|
8
7
|
import {
|
|
9
8
|
BusinessTransactionsInfoDocument,
|
|
@@ -13,8 +12,10 @@ import {
|
|
|
13
12
|
} from '../../gql/graphql.js';
|
|
14
13
|
import { FIAT_CURRENCIES, formatAmountWithCurrency } from '../../helpers/index.js';
|
|
15
14
|
import { AccounterLoader } from '../common/index.js';
|
|
15
|
+
import { getChargeHref } from '../screens/charges/charge.js';
|
|
16
16
|
import { Button } from '../ui/button.js';
|
|
17
17
|
import { DownloadCSV } from './download-csv.js';
|
|
18
|
+
import { getBusinessTransactionsHref } from './index.js';
|
|
18
19
|
|
|
19
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
20
21
|
/* GraphQL */ `
|
|
@@ -228,15 +229,14 @@ export function BusinessExtendedInfo({ businessID, filter }: Props): ReactElemen
|
|
|
228
229
|
{extendedTransactions.map((row, index) => (
|
|
229
230
|
<tr
|
|
230
231
|
key={index}
|
|
231
|
-
className="cursor-pointer"
|
|
232
232
|
onClick={event => {
|
|
233
233
|
event.stopPropagation();
|
|
234
|
-
window.open(
|
|
234
|
+
window.open(getChargeHref(row.chargeId), '_blank', 'noreferrer');
|
|
235
235
|
}}
|
|
236
236
|
>
|
|
237
237
|
<td>
|
|
238
238
|
<Link
|
|
239
|
-
to={
|
|
239
|
+
to={getBusinessTransactionsHref({ businessIDs: [row.business.id] })}
|
|
240
240
|
target="_blank"
|
|
241
241
|
rel="noreferrer"
|
|
242
242
|
onClick={event => event.stopPropagation()}
|
|
@@ -274,7 +274,7 @@ export function BusinessExtendedInfo({ businessID, filter }: Props): ReactElemen
|
|
|
274
274
|
<td>
|
|
275
275
|
{row.counterAccount && (
|
|
276
276
|
<Link
|
|
277
|
-
to={
|
|
277
|
+
to={getBusinessTransactionsHref({ businessIDs: [row.counterAccount.id] })}
|
|
278
278
|
target="_blank"
|
|
279
279
|
rel="noreferrer"
|
|
280
280
|
onClick={event => event.stopPropagation()}
|
|
@@ -21,7 +21,10 @@ import { AccounterTableRow } from '../common/index.js';
|
|
|
21
21
|
import { PageLayout } from '../layout/page-layout.js';
|
|
22
22
|
import { Button } from '../ui/button.js';
|
|
23
23
|
import { BusinessExtendedInfo } from './business-extended-info.js';
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
BusinessTransactionsFilters,
|
|
26
|
+
encodeTransactionsFilters,
|
|
27
|
+
} from './business-transactions-filters.js';
|
|
25
28
|
|
|
26
29
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
27
30
|
/* GraphQL */ `
|
|
@@ -66,6 +69,30 @@ import { BusinessTransactionsFilters } from './business-transactions-filters.js'
|
|
|
66
69
|
}
|
|
67
70
|
`;
|
|
68
71
|
|
|
72
|
+
export function getBusinessTransactionsHref(filter?: BusinessTransactionsFilter | null): string {
|
|
73
|
+
const params = new URLSearchParams();
|
|
74
|
+
|
|
75
|
+
let businessId: string | undefined = undefined;
|
|
76
|
+
let adjustedFilter = filter;
|
|
77
|
+
if (filter?.businessIDs && filter.businessIDs.length === 1) {
|
|
78
|
+
const { businessIDs, ...rest } = filter;
|
|
79
|
+
businessId = businessIDs[0];
|
|
80
|
+
adjustedFilter = rest;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const transactionsFilters = encodeTransactionsFilters(adjustedFilter);
|
|
84
|
+
if (transactionsFilters) {
|
|
85
|
+
// Add it as a single encoded parameter
|
|
86
|
+
params.append('transactionsFilters', transactionsFilters);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const queryParams = params.size > 0 ? `?${params}` : '';
|
|
90
|
+
if (businessId) {
|
|
91
|
+
return `/businesses/${businessId}/transactions${queryParams}`;
|
|
92
|
+
}
|
|
93
|
+
return `/businesses/transactions${queryParams}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
69
96
|
type BusinessTransactionsSum = Extract<
|
|
70
97
|
BusinessTransactionsSummeryQuery['businessTransactionsSumFromLedgerRecords'],
|
|
71
98
|
{ businessTransactionsSum: unknown }
|
|
@@ -159,16 +159,12 @@ export const Businesses = (): ReactElement => {
|
|
|
159
159
|
tabIndex={0}
|
|
160
160
|
className="flex-1 cursor-pointer"
|
|
161
161
|
onClick={(): void => {
|
|
162
|
-
navigate(ROUTES.BUSINESSES.DETAIL(business.id)
|
|
163
|
-
state: { from: ROUTES.BUSINESSES.ALL },
|
|
164
|
-
});
|
|
162
|
+
navigate(ROUTES.BUSINESSES.DETAIL(business.id));
|
|
165
163
|
}}
|
|
166
164
|
onKeyDown={(e): void => {
|
|
167
165
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
168
166
|
e.preventDefault();
|
|
169
|
-
navigate(ROUTES.BUSINESSES.DETAIL(business.id)
|
|
170
|
-
state: { from: ROUTES.BUSINESSES.ALL },
|
|
171
|
-
});
|
|
167
|
+
navigate(ROUTES.BUSINESSES.DETAIL(business.id));
|
|
172
168
|
}
|
|
173
169
|
}}
|
|
174
170
|
>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ReactElement } from 'react';
|
|
2
2
|
import { Link } from 'react-router-dom';
|
|
3
|
-
import { ROUTES } from '@/router/routes.js';
|
|
4
3
|
import { ChargesTableBusinessTripFieldsFragmentDoc } from '../../../gql/graphql.js';
|
|
5
4
|
import { getFragmentData, type FragmentType } from '../../../gql/index.js';
|
|
6
5
|
|
|
@@ -31,11 +30,7 @@ export const BusinessTrip = ({ data }: Props): ReactElement => {
|
|
|
31
30
|
return (
|
|
32
31
|
<td>
|
|
33
32
|
<Link
|
|
34
|
-
to={
|
|
35
|
-
charge.businessTrip?.id
|
|
36
|
-
? ROUTES.BUSINESS_TRIPS.DETAIL(charge.businessTrip?.id)
|
|
37
|
-
: ROUTES.BUSINESS_TRIPS.ROOT
|
|
38
|
-
}
|
|
33
|
+
to={`/business-trips/${charge.businessTrip?.id}`}
|
|
39
34
|
target="_blank"
|
|
40
35
|
rel="noreferrer"
|
|
41
36
|
onClick={event => event.stopPropagation()}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { useMemo, type ReactElement } from 'react';
|
|
1
|
+
import { useCallback, useMemo, type ReactElement } from 'react';
|
|
2
2
|
import { Link } from 'react-router-dom';
|
|
3
|
-
import { ROUTES } from '@/router/routes.js';
|
|
4
3
|
import { Indicator } from '@mantine/core';
|
|
5
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ChargesTableEntityFieldsFragmentDoc,
|
|
6
|
+
MissingChargeInfo,
|
|
7
|
+
type ChargeFilter,
|
|
8
|
+
} from '../../../gql/graphql.js';
|
|
6
9
|
import { getFragmentData, type FragmentType } from '../../../gql/index.js';
|
|
10
|
+
import { useUrlQuery } from '../../../hooks/use-url-query.js';
|
|
11
|
+
import { getBusinessTransactionsHref } from '../../business-transactions/index.js';
|
|
7
12
|
|
|
8
13
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
9
14
|
/* GraphQL */ `
|
|
@@ -27,6 +32,7 @@ type Props = {
|
|
|
27
32
|
};
|
|
28
33
|
|
|
29
34
|
export const Counterparty = ({ data }: Props): ReactElement => {
|
|
35
|
+
const { get } = useUrlQuery();
|
|
30
36
|
const { counterparty, validationData, __typename } = getFragmentData(
|
|
31
37
|
ChargesTableEntityFieldsFragmentDoc,
|
|
32
38
|
data,
|
|
@@ -53,13 +59,31 @@ export const Counterparty = ({ data }: Props): ReactElement => {
|
|
|
53
59
|
);
|
|
54
60
|
const { name, id } = counterparty ?? { name: 'Missing', id: undefined };
|
|
55
61
|
|
|
62
|
+
const encodedFilters = get('chargesFilters');
|
|
63
|
+
|
|
64
|
+
const getHref = useCallback(
|
|
65
|
+
(businessID: string) => {
|
|
66
|
+
const currentFilters = encodedFilters
|
|
67
|
+
? (JSON.parse(decodeURIComponent(encodedFilters as string)) as ChargeFilter)
|
|
68
|
+
: {};
|
|
69
|
+
|
|
70
|
+
return getBusinessTransactionsHref({
|
|
71
|
+
fromDate: currentFilters.fromDate,
|
|
72
|
+
toDate: currentFilters.toDate,
|
|
73
|
+
ownerIds: currentFilters.byOwners,
|
|
74
|
+
businessIDs: [businessID],
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
[encodedFilters],
|
|
78
|
+
);
|
|
79
|
+
|
|
56
80
|
return (
|
|
57
81
|
<td>
|
|
58
82
|
<div className="flex flex-wrap">
|
|
59
83
|
<Indicator inline size={12} disabled={!isError} color="red" zIndex="auto">
|
|
60
84
|
{!isError && id && (
|
|
61
85
|
<Link
|
|
62
|
-
to={
|
|
86
|
+
to={getHref(id)}
|
|
63
87
|
target="_blank"
|
|
64
88
|
rel="noreferrer"
|
|
65
89
|
onClick={event => event.stopPropagation()}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChargeFilter } from '../../gql/graphql.js';
|
|
2
|
+
import { getBusinessTransactionsHref } from '../business-transactions/index.js';
|
|
3
|
+
|
|
4
|
+
export const getBusinessHref = (businessID: string, encodedFilters: string): string => {
|
|
5
|
+
const currentFilters = encodedFilters
|
|
6
|
+
? (JSON.parse(decodeURIComponent(encodedFilters)) as ChargeFilter)
|
|
7
|
+
: {};
|
|
8
|
+
|
|
9
|
+
return getBusinessTransactionsHref({
|
|
10
|
+
fromDate: currentFilters.fromDate,
|
|
11
|
+
toDate: currentFilters.toDate,
|
|
12
|
+
ownerIds: currentFilters.byOwners,
|
|
13
|
+
businessIDs: [businessID],
|
|
14
|
+
});
|
|
15
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { format } from 'date-fns';
|
|
3
|
-
import { Plus } from 'lucide-react';
|
|
3
|
+
import { Plus, X } from 'lucide-react';
|
|
4
4
|
import { useForm } from 'react-hook-form';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { Badge } from '@/components/ui/badge.js';
|
|
6
7
|
import { Button } from '@/components/ui/button.js';
|
|
7
8
|
import {
|
|
8
9
|
Dialog,
|
|
@@ -48,7 +49,7 @@ const contractFormSchema = z.object({
|
|
|
48
49
|
// operationsLimit: z.number().optional(),
|
|
49
50
|
startDate: z.iso.date('Start date is required'),
|
|
50
51
|
endDate: z.iso.date('End date is required'),
|
|
51
|
-
|
|
52
|
+
pos: z.array(z.string()),
|
|
52
53
|
paymentAmount: z.number().min(0, 'Payment amount must be non-negative'),
|
|
53
54
|
paymentCurrency: z.enum(Object.values(Currency), 'Currency is required'),
|
|
54
55
|
productType: z.enum(Object.values(Product)).optional(),
|
|
@@ -58,6 +59,7 @@ const contractFormSchema = z.object({
|
|
|
58
59
|
isActive: z.boolean(),
|
|
59
60
|
defaultRemark: z.string().optional(),
|
|
60
61
|
defaultDocumentType: z.enum(Object.values(DocumentType)),
|
|
62
|
+
operationsLimit: z.int().min(0, 'Operations limit must be non-negative'),
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
export type ContractFormValues = z.infer<typeof contractFormSchema>;
|
|
@@ -67,7 +69,7 @@ const newContractDefaultValues: ContractFormValues = {
|
|
|
67
69
|
// operationsLimit: 0,
|
|
68
70
|
startDate: '',
|
|
69
71
|
endDate: '',
|
|
70
|
-
|
|
72
|
+
pos: [],
|
|
71
73
|
paymentAmount: 0,
|
|
72
74
|
paymentCurrency: Currency.Usd,
|
|
73
75
|
productType: Product.Hive,
|
|
@@ -77,6 +79,7 @@ const newContractDefaultValues: ContractFormValues = {
|
|
|
77
79
|
isActive: true,
|
|
78
80
|
defaultRemark: undefined,
|
|
79
81
|
defaultDocumentType: DocumentType.Proforma,
|
|
82
|
+
operationsLimit: 0,
|
|
80
83
|
};
|
|
81
84
|
|
|
82
85
|
interface Props {
|
|
@@ -88,6 +91,7 @@ interface Props {
|
|
|
88
91
|
export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
89
92
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
90
93
|
const [editingContract, setEditingContract] = useState<ContractFormValues | null>(null);
|
|
94
|
+
const [newPO, setNewPO] = useState('');
|
|
91
95
|
|
|
92
96
|
const { updateContract, updating } = useUpdateContract();
|
|
93
97
|
const { createContract, creating } = useCreateContract();
|
|
@@ -97,6 +101,26 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
97
101
|
defaultValues: contract || newContractDefaultValues,
|
|
98
102
|
});
|
|
99
103
|
|
|
104
|
+
const addPO = () => {
|
|
105
|
+
const trimmedPO = newPO.trim();
|
|
106
|
+
if (trimmedPO) {
|
|
107
|
+
const currentLinks = form.getValues('pos');
|
|
108
|
+
if (!currentLinks.includes(trimmedPO)) {
|
|
109
|
+
form.setValue('pos', [...currentLinks, trimmedPO], { shouldDirty: true });
|
|
110
|
+
}
|
|
111
|
+
setNewPO('');
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const removePO = (index: number) => {
|
|
116
|
+
const currentLinks = form.getValues('pos');
|
|
117
|
+
form.setValue(
|
|
118
|
+
'pos',
|
|
119
|
+
currentLinks.filter((_, i) => i !== index),
|
|
120
|
+
{ shouldDirty: true },
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
100
124
|
useEffect(() => {
|
|
101
125
|
if (contract) {
|
|
102
126
|
setEditingContract(contract);
|
|
@@ -105,7 +129,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
105
129
|
// operationsLimit: contract.operationsLimit,
|
|
106
130
|
startDate: contract.startDate,
|
|
107
131
|
endDate: contract.endDate,
|
|
108
|
-
|
|
132
|
+
pos: contract.pos,
|
|
109
133
|
paymentAmount: contract.paymentAmount,
|
|
110
134
|
paymentCurrency: contract.paymentCurrency,
|
|
111
135
|
productType: contract.productType,
|
|
@@ -115,6 +139,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
115
139
|
isActive: contract.isActive,
|
|
116
140
|
defaultRemark: contract.defaultRemark,
|
|
117
141
|
defaultDocumentType: contract.defaultDocumentType,
|
|
142
|
+
operationsLimit: contract.operationsLimit,
|
|
118
143
|
});
|
|
119
144
|
setIsDialogOpen(true);
|
|
120
145
|
}
|
|
@@ -141,9 +166,10 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
141
166
|
msCloud: values.msCloudLink,
|
|
142
167
|
plan: values.subscriptionPlan,
|
|
143
168
|
product: values.productType,
|
|
144
|
-
|
|
169
|
+
purchaseOrders: values.pos,
|
|
145
170
|
remarks: values.defaultRemark,
|
|
146
171
|
startDate: format(new Date(values.startDate), 'yyyy-MM-dd') as TimelessDateString,
|
|
172
|
+
operationsLimit: values.operationsLimit,
|
|
147
173
|
},
|
|
148
174
|
});
|
|
149
175
|
} else {
|
|
@@ -163,9 +189,10 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
163
189
|
msCloud: values.msCloudLink,
|
|
164
190
|
plan: values.subscriptionPlan,
|
|
165
191
|
product: values.productType,
|
|
166
|
-
|
|
192
|
+
purchaseOrders: values.pos,
|
|
167
193
|
remarks: values.defaultRemark,
|
|
168
194
|
startDate: format(new Date(values.startDate), 'yyyy-MM-dd') as TimelessDateString,
|
|
195
|
+
operationsLimit: values.operationsLimit,
|
|
169
196
|
},
|
|
170
197
|
});
|
|
171
198
|
}
|
|
@@ -197,8 +224,7 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
197
224
|
<form onSubmit={form.handleSubmit(onSubmit)}>
|
|
198
225
|
<div className="grid gap-4 py-4">
|
|
199
226
|
<div className="grid gap-4 md:grid-cols-2">
|
|
200
|
-
|
|
201
|
-
{/* <FormField
|
|
227
|
+
<FormField
|
|
202
228
|
control={form.control}
|
|
203
229
|
name="operationsLimit"
|
|
204
230
|
render={({ field }) => (
|
|
@@ -210,16 +236,46 @@ export function ModifyContractDialog({ clientId, contract, onDone }: Props) {
|
|
|
210
236
|
<FormMessage />
|
|
211
237
|
</FormItem>
|
|
212
238
|
)}
|
|
213
|
-
/>
|
|
239
|
+
/>
|
|
214
240
|
<FormField
|
|
215
241
|
control={form.control}
|
|
216
|
-
name="
|
|
242
|
+
name="pos"
|
|
217
243
|
render={({ field }) => (
|
|
218
244
|
<FormItem>
|
|
219
|
-
<FormLabel>
|
|
220
|
-
<
|
|
221
|
-
<Input
|
|
222
|
-
|
|
245
|
+
<FormLabel>Purchase Orders</FormLabel>
|
|
246
|
+
<div className="flex gap-2">
|
|
247
|
+
<Input
|
|
248
|
+
placeholder="Add PO..."
|
|
249
|
+
value={newPO}
|
|
250
|
+
onChange={e => setNewPO(e.target.value)}
|
|
251
|
+
onKeyDown={e => {
|
|
252
|
+
if (e.key === 'Enter') {
|
|
253
|
+
e.preventDefault();
|
|
254
|
+
addPO();
|
|
255
|
+
}
|
|
256
|
+
}}
|
|
257
|
+
/>
|
|
258
|
+
<Button type="button" size="sm" onClick={addPO}>
|
|
259
|
+
<Plus className="h-4 w-4" />
|
|
260
|
+
</Button>
|
|
261
|
+
</div>
|
|
262
|
+
<div className="flex flex-wrap gap-2 mt-2">
|
|
263
|
+
{field.value?.map((link, index) => (
|
|
264
|
+
<Badge key={link} variant="secondary" className="gap-1 max-w-xs truncate">
|
|
265
|
+
{link}
|
|
266
|
+
{index === field.value.length - 1 && (
|
|
267
|
+
<Button
|
|
268
|
+
variant="ghost"
|
|
269
|
+
size="icon"
|
|
270
|
+
className="p-0 size-3"
|
|
271
|
+
onClick={() => removePO(index)}
|
|
272
|
+
>
|
|
273
|
+
<X className="size-3 cursor-pointer flex-shrink-0" />
|
|
274
|
+
</Button>
|
|
275
|
+
)}
|
|
276
|
+
</Badge>
|
|
277
|
+
))}
|
|
278
|
+
</div>
|
|
223
279
|
<FormMessage />
|
|
224
280
|
</FormItem>
|
|
225
281
|
)}
|