@ngbplatform/ui 1.3.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/LICENSE +201 -0
- package/README.md +44 -0
- package/package.json +61 -0
- package/public/favicon.svg +6 -0
- package/public/silent-check-sso.html +8 -0
- package/src/assets/ngb_logo.svg +17 -0
- package/src/assets/ngb_logo_color.svg +17 -0
- package/src/index.ts +1023 -0
- package/src/ngb/README.md +27 -0
- package/src/ngb/accounting/NgbAccountingPeriodClosingPage.vue +1157 -0
- package/src/ngb/accounting/NgbChartOfAccountEditor.vue +590 -0
- package/src/ngb/accounting/NgbChartOfAccountsPage.vue +420 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryEditPage.vue +796 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryLinesEditor.vue +454 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryListPage.vue +186 -0
- package/src/ngb/accounting/api.ts +79 -0
- package/src/ngb/accounting/generalJournalEntry.ts +127 -0
- package/src/ngb/accounting/generalJournalEntryApi.ts +112 -0
- package/src/ngb/accounting/generalJournalEntryTypes.ts +155 -0
- package/src/ngb/accounting/navigation.ts +83 -0
- package/src/ngb/accounting/periodClosing.ts +75 -0
- package/src/ngb/accounting/periodClosingApi.ts +60 -0
- package/src/ngb/accounting/periodClosingTypes.ts +73 -0
- package/src/ngb/accounting/types.ts +57 -0
- package/src/ngb/api/audit.ts +23 -0
- package/src/ngb/api/catalogs.ts +50 -0
- package/src/ngb/api/contracts.ts +285 -0
- package/src/ngb/api/documents.ts +170 -0
- package/src/ngb/api/http.ts +446 -0
- package/src/ngb/api/lookups.ts +14 -0
- package/src/ngb/api/types.ts +6 -0
- package/src/ngb/auth/index.ts +13 -0
- package/src/ngb/auth/keycloak.ts +374 -0
- package/src/ngb/auth/router.ts +35 -0
- package/src/ngb/auth/types.ts +12 -0
- package/src/ngb/auth/useAuthStore.ts +209 -0
- package/src/ngb/command-palette/NgbCommandPaletteDialog.vue +342 -0
- package/src/ngb/command-palette/NgbCommandPaletteEmptyState.vue +55 -0
- package/src/ngb/command-palette/NgbCommandPaletteFooterHints.vue +29 -0
- package/src/ngb/command-palette/api.ts +10 -0
- package/src/ngb/command-palette/config.ts +16 -0
- package/src/ngb/command-palette/presentation.ts +85 -0
- package/src/ngb/command-palette/search.ts +130 -0
- package/src/ngb/command-palette/staticItems.ts +243 -0
- package/src/ngb/command-palette/storage.ts +45 -0
- package/src/ngb/command-palette/store.ts +716 -0
- package/src/ngb/command-palette/types.ts +120 -0
- package/src/ngb/command-palette/useCommandPaletteHotkeys.ts +27 -0
- package/src/ngb/command-palette/useCommandPalettePageContext.ts +18 -0
- package/src/ngb/components/NgbConfirmDialog.vue +63 -0
- package/src/ngb/components/NgbDialog.vue +44 -0
- package/src/ngb/components/NgbDrawer.vue +156 -0
- package/src/ngb/components/NgbHeaderActionCluster.vue +140 -0
- package/src/ngb/components/NgbModalShell.vue +99 -0
- package/src/ngb/components/NgbToolbar.vue +14 -0
- package/src/ngb/components/forms/NgbFormLayout.vue +13 -0
- package/src/ngb/components/forms/NgbFormRow.vue +21 -0
- package/src/ngb/components/forms/NgbFormSection.vue +16 -0
- package/src/ngb/components/forms/NgbValidationSummary.vue +18 -0
- package/src/ngb/components/navigation/NgbNavigationTree.vue +68 -0
- package/src/ngb/components/navigation/NgbTreeNode.vue +94 -0
- package/src/ngb/components/register/NgbColumnChooser.vue +101 -0
- package/src/ngb/components/register/NgbRegisterGrid.vue +473 -0
- package/src/ngb/components/register/registerTypes.ts +51 -0
- package/src/ngb/components/register/useRegisterColumnResize.ts +99 -0
- package/src/ngb/components/register/useRegisterColumnState.ts +220 -0
- package/src/ngb/components/register/useRegisterRows.ts +209 -0
- package/src/ngb/components/register/useRegisterViewport.ts +56 -0
- package/src/ngb/editor/NgbDocumentEffectsPage.vue +512 -0
- package/src/ngb/editor/NgbDocumentFlowPage.vue +409 -0
- package/src/ngb/editor/NgbDocumentPrintPage.vue +712 -0
- package/src/ngb/editor/NgbEditorDiscardDialog.vue +40 -0
- package/src/ngb/editor/NgbEntityAuditSidebar.vue +288 -0
- package/src/ngb/editor/NgbEntityEditor.vue +250 -0
- package/src/ngb/editor/NgbEntityEditorDrawerActions.vue +88 -0
- package/src/ngb/editor/NgbEntityEditorHeader.vue +114 -0
- package/src/ngb/editor/catalogNavigation.ts +13 -0
- package/src/ngb/editor/config.ts +252 -0
- package/src/ngb/editor/documentCopyDraft.ts +245 -0
- package/src/ngb/editor/documentEffects.ts +43 -0
- package/src/ngb/editor/documentEffectsDateFormatting.ts +18 -0
- package/src/ngb/editor/documentNavigation.ts +115 -0
- package/src/ngb/editor/documentStatus.ts +45 -0
- package/src/ngb/editor/entityEditorErrors.ts +162 -0
- package/src/ngb/editor/entityEditorPersistence.ts +241 -0
- package/src/ngb/editor/extensions.ts +40 -0
- package/src/ngb/editor/types.ts +295 -0
- package/src/ngb/editor/useConfiguredEntityEditorDocumentActions.ts +183 -0
- package/src/ngb/editor/useDocumentEditorDrawerState.ts +152 -0
- package/src/ngb/editor/useEditorDrawerState.ts +88 -0
- package/src/ngb/editor/useEntityEditorBusinessContext.ts +97 -0
- package/src/ngb/editor/useEntityEditorCapabilities.ts +190 -0
- package/src/ngb/editor/useEntityEditorCommandPalette.ts +154 -0
- package/src/ngb/editor/useEntityEditorCommitHandlers.ts +102 -0
- package/src/ngb/editor/useEntityEditorHeaderActions.ts +253 -0
- package/src/ngb/editor/useEntityEditorLeaveGuard.ts +66 -0
- package/src/ngb/editor/useEntityEditorNavigationActions.ts +235 -0
- package/src/ngb/editor/useEntityEditorOutputs.ts +59 -0
- package/src/ngb/editor/useEntityEditorPageActions.ts +57 -0
- package/src/ngb/editor/useRouteQueryEditorDrawer.ts +173 -0
- package/src/ngb/env/runtimeConfig.ts +25 -0
- package/src/ngb/lookup/config.ts +42 -0
- package/src/ngb/lookup/defaultConfig.ts +136 -0
- package/src/ngb/lookup/navigation.ts +76 -0
- package/src/ngb/lookup/prefetch.ts +40 -0
- package/src/ngb/lookup/store.ts +261 -0
- package/src/ngb/metadata/NgbDocumentListFiltersDrawer.vue +78 -0
- package/src/ngb/metadata/NgbDocumentPeriodFilter.vue +53 -0
- package/src/ngb/metadata/NgbEntityForm.vue +84 -0
- package/src/ngb/metadata/NgbEntityFormFieldsBlock.vue +110 -0
- package/src/ngb/metadata/NgbEntityListPageHeader.vue +80 -0
- package/src/ngb/metadata/NgbFilterFieldControl.vue +104 -0
- package/src/ngb/metadata/NgbMetadataCatalogEditPage.vue +42 -0
- package/src/ngb/metadata/NgbMetadataCatalogListPage.vue +269 -0
- package/src/ngb/metadata/NgbMetadataDocumentEditPage.vue +68 -0
- package/src/ngb/metadata/NgbMetadataDocumentListPage.vue +353 -0
- package/src/ngb/metadata/NgbMetadataFieldRenderer.vue +124 -0
- package/src/ngb/metadata/NgbMetadataLookupControl.vue +92 -0
- package/src/ngb/metadata/NgbRecycleBinFilter.vue +53 -0
- package/src/ngb/metadata/NgbRegisterPageLayout.vue +143 -0
- package/src/ngb/metadata/config.ts +28 -0
- package/src/ngb/metadata/dataTypes.ts +27 -0
- package/src/ngb/metadata/entityForm.ts +114 -0
- package/src/ngb/metadata/entityModel.ts +34 -0
- package/src/ngb/metadata/entityValueFormatting.ts +83 -0
- package/src/ngb/metadata/fieldRendererState.ts +84 -0
- package/src/ngb/metadata/filtering.ts +153 -0
- package/src/ngb/metadata/lookup.ts +25 -0
- package/src/ngb/metadata/monthPagedListQuery.ts +108 -0
- package/src/ngb/metadata/normalization.ts +100 -0
- package/src/ngb/metadata/referenceHydration.ts +99 -0
- package/src/ngb/metadata/register.ts +135 -0
- package/src/ngb/metadata/routePages.ts +86 -0
- package/src/ngb/metadata/store.ts +35 -0
- package/src/ngb/metadata/types.ts +276 -0
- package/src/ngb/metadata/useMetadataListFilters.ts +306 -0
- package/src/ngb/metadata/useMetadataRegisterPageData.ts +246 -0
- package/src/ngb/metadata/useValidationFocus.ts +49 -0
- package/src/ngb/primitives/NgbBadge.vue +31 -0
- package/src/ngb/primitives/NgbButton.vue +53 -0
- package/src/ngb/primitives/NgbCheckbox.vue +33 -0
- package/src/ngb/primitives/NgbDatePicker.vue +141 -0
- package/src/ngb/primitives/NgbIcon.vue +545 -0
- package/src/ngb/primitives/NgbInput.vue +57 -0
- package/src/ngb/primitives/NgbLookup.vue +264 -0
- package/src/ngb/primitives/NgbMonthPicker.vue +132 -0
- package/src/ngb/primitives/NgbMultiSelect.vue +179 -0
- package/src/ngb/primitives/NgbPeriodPicker.vue +125 -0
- package/src/ngb/primitives/NgbPickerNavButton.vue +31 -0
- package/src/ngb/primitives/NgbPickerPopover.vue +79 -0
- package/src/ngb/primitives/NgbRadioGroup.vue +53 -0
- package/src/ngb/primitives/NgbSelect.vue +108 -0
- package/src/ngb/primitives/NgbStatusIcon.vue +63 -0
- package/src/ngb/primitives/NgbSwitch.vue +42 -0
- package/src/ngb/primitives/NgbTabs.vue +116 -0
- package/src/ngb/primitives/NgbToastHost.vue +49 -0
- package/src/ngb/primitives/NgbTooltip.vue +27 -0
- package/src/ngb/primitives/iconNames.ts +83 -0
- package/src/ngb/primitives/toast.ts +66 -0
- package/src/ngb/primitives/useAsyncComboboxQuery.ts +85 -0
- package/src/ngb/primitives/useFloatingDropdownPosition.ts +129 -0
- package/src/ngb/reporting/NgbReportComposerCollectionSection.vue +106 -0
- package/src/ngb/reporting/NgbReportComposerPanel.vue +1187 -0
- package/src/ngb/reporting/NgbReportDateRangeFilter.vue +54 -0
- package/src/ngb/reporting/NgbReportPage.vue +1124 -0
- package/src/ngb/reporting/NgbReportSheet.vue +467 -0
- package/src/ngb/reporting/api.ts +35 -0
- package/src/ngb/reporting/composer.ts +904 -0
- package/src/ngb/reporting/config.ts +120 -0
- package/src/ngb/reporting/defaultConfig.ts +15 -0
- package/src/ngb/reporting/lookupFilters.ts +43 -0
- package/src/ngb/reporting/navigation.ts +181 -0
- package/src/ngb/reporting/pageHelpers.ts +73 -0
- package/src/ngb/reporting/pageSession.ts +92 -0
- package/src/ngb/reporting/paging.ts +66 -0
- package/src/ngb/reporting/types.ts +333 -0
- package/src/ngb/router/backNavigation.ts +122 -0
- package/src/ngb/router/queryParams.ts +129 -0
- package/src/ngb/router/queryState.ts +121 -0
- package/src/ngb/router/routeAliases.ts +66 -0
- package/src/ngb/router/routeParams.ts +15 -0
- package/src/ngb/router/shareLink.ts +39 -0
- package/src/ngb/security/NgbAccessAuditPanel.vue +32 -0
- package/src/ngb/security/NgbAccessDeniedState.vue +27 -0
- package/src/ngb/security/NgbEffectiveAccessPanel.vue +60 -0
- package/src/ngb/security/NgbPermissionMatrix.vue +160 -0
- package/src/ngb/security/NgbRoleEditorPage.vue +319 -0
- package/src/ngb/security/NgbRolesPage.vue +125 -0
- package/src/ngb/security/NgbUserEditorPage.vue +615 -0
- package/src/ngb/security/NgbUsersPage.vue +125 -0
- package/src/ngb/security/api.ts +91 -0
- package/src/ngb/security/audit.ts +21 -0
- package/src/ngb/security/permissions.ts +65 -0
- package/src/ngb/security/types.ts +157 -0
- package/src/ngb/security/useAccessStore.ts +69 -0
- package/src/ngb/site/NgbDashboardAsOfToolbar.vue +100 -0
- package/src/ngb/site/NgbDashboardStatusBanner.vue +91 -0
- package/src/ngb/site/NgbLogo.vue +44 -0
- package/src/ngb/site/NgbPageHeader.vue +49 -0
- package/src/ngb/site/NgbSiteShell.vue +286 -0
- package/src/ngb/site/NgbSiteSidebar.vue +270 -0
- package/src/ngb/site/NgbTopBar.vue +425 -0
- package/src/ngb/site/NgbTrendChart.vue +224 -0
- package/src/ngb/site/dashboardData.ts +324 -0
- package/src/ngb/site/mainMenuStore.ts +49 -0
- package/src/ngb/site/types.ts +31 -0
- package/src/ngb/site/useDashboardPageState.ts +98 -0
- package/src/ngb/site/useTheme.ts +95 -0
- package/src/ngb/utils/clone.ts +43 -0
- package/src/ngb/utils/dateValues.ts +107 -0
- package/src/ngb/utils/errorMessage.ts +14 -0
- package/src/ngb/utils/guid.ts +21 -0
- package/src/ngb/utils/stableValue.ts +21 -0
- package/src/ngb/utils/storage.ts +135 -0
- package/src/styles/tailwind.css +165 -0
- package/src/vite/publicAssets.ts +104 -0
- package/vite-public-assets.js +68 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { httpGet, httpPost, httpPut } from '../api/http';
|
|
2
|
+
import type { ByIdsRequestDto, LookupItemDto } from '../api/contracts';
|
|
3
|
+
import type {
|
|
4
|
+
ChartOfAccountsAccountDto,
|
|
5
|
+
ChartOfAccountsMetadataDto,
|
|
6
|
+
ChartOfAccountsPageDto,
|
|
7
|
+
ChartOfAccountsUpsertRequestDto,
|
|
8
|
+
} from './types';
|
|
9
|
+
|
|
10
|
+
export type GetChartOfAccountsPageArgs = {
|
|
11
|
+
offset?: number;
|
|
12
|
+
limit?: number;
|
|
13
|
+
search?: string | null;
|
|
14
|
+
onlyActive?: boolean | null;
|
|
15
|
+
includeDeleted?: boolean;
|
|
16
|
+
onlyDeleted?: boolean | null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function getChartOfAccountsPage(
|
|
20
|
+
args: GetChartOfAccountsPageArgs,
|
|
21
|
+
): Promise<ChartOfAccountsPageDto> {
|
|
22
|
+
const q = new URLSearchParams();
|
|
23
|
+
q.set('offset', String(args.offset ?? 0));
|
|
24
|
+
q.set('limit', String(args.limit ?? 20));
|
|
25
|
+
if (args.search) q.set('search', args.search);
|
|
26
|
+
|
|
27
|
+
if (args.includeDeleted != null) q.set('includeDeleted', String(args.includeDeleted));
|
|
28
|
+
if (args.onlyActive != null) q.set('onlyActive', String(args.onlyActive));
|
|
29
|
+
if (args.onlyDeleted != null) q.set('onlyDeleted', String(args.onlyDeleted));
|
|
30
|
+
|
|
31
|
+
const qs = q.toString();
|
|
32
|
+
return await httpGet<ChartOfAccountsPageDto>(`/api/chart-of-accounts${qs ? `?${qs}` : ''}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function getChartOfAccountsMetadata(): Promise<ChartOfAccountsMetadataDto> {
|
|
36
|
+
return await httpGet<ChartOfAccountsMetadataDto>('/api/chart-of-accounts/metadata');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function getChartOfAccountById(accountId: string): Promise<ChartOfAccountsAccountDto> {
|
|
40
|
+
return await httpGet<ChartOfAccountsAccountDto>(`/api/chart-of-accounts/${encodeURIComponent(accountId)}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function getChartOfAccountsByIds(ids: string[]): Promise<LookupItemDto[]> {
|
|
44
|
+
const request: ByIdsRequestDto = { ids }
|
|
45
|
+
return await httpPost<LookupItemDto[]>('/api/chart-of-accounts/by-ids', request);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function createChartOfAccount(
|
|
49
|
+
request: ChartOfAccountsUpsertRequestDto,
|
|
50
|
+
): Promise<ChartOfAccountsAccountDto> {
|
|
51
|
+
return await httpPost<ChartOfAccountsAccountDto>('/api/chart-of-accounts', request);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function updateChartOfAccount(
|
|
55
|
+
accountId: string,
|
|
56
|
+
request: ChartOfAccountsUpsertRequestDto,
|
|
57
|
+
): Promise<ChartOfAccountsAccountDto> {
|
|
58
|
+
return await httpPut<ChartOfAccountsAccountDto>(
|
|
59
|
+
`/api/chart-of-accounts/${encodeURIComponent(accountId)}`,
|
|
60
|
+
request,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function markChartOfAccountForDeletion(accountId: string): Promise<void> {
|
|
65
|
+
await httpPost<void>(`/api/chart-of-accounts/${encodeURIComponent(accountId)}/mark-for-deletion`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function unmarkChartOfAccountForDeletion(accountId: string): Promise<void> {
|
|
69
|
+
await httpPost<void>(`/api/chart-of-accounts/${encodeURIComponent(accountId)}/unmark-for-deletion`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function setChartOfAccountActive(
|
|
73
|
+
accountId: string,
|
|
74
|
+
isActive: boolean,
|
|
75
|
+
): Promise<void> {
|
|
76
|
+
await httpPost<void>(
|
|
77
|
+
`/api/chart-of-accounts/${encodeURIComponent(accountId)}/set-active?isActive=${encodeURIComponent(String(isActive))}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { normalizeDateOnlyValue, toDateOnlyValue } from '../utils/dateValues';
|
|
2
|
+
import type { GeneralJournalEntryEditorLineModel } from './generalJournalEntryTypes';
|
|
3
|
+
|
|
4
|
+
function randomToken(): string {
|
|
5
|
+
return Math.random().toString(36).slice(2, 8);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function createGeneralJournalEntryLineKey(prefix = 'line'): string {
|
|
9
|
+
return `${prefix}-${Date.now().toString(36)}-${randomToken()}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createGeneralJournalEntryLine(
|
|
13
|
+
clientKey = createGeneralJournalEntryLineKey(),
|
|
14
|
+
): GeneralJournalEntryEditorLineModel {
|
|
15
|
+
return {
|
|
16
|
+
clientKey,
|
|
17
|
+
side: 1,
|
|
18
|
+
account: null,
|
|
19
|
+
amount: '',
|
|
20
|
+
memo: '',
|
|
21
|
+
dimensions: {},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function parseGeneralJournalEntryAmount(value: string): number {
|
|
26
|
+
const normalized = String(value ?? '').trim().replace(/,/g, '');
|
|
27
|
+
const amount = Number(normalized);
|
|
28
|
+
return Number.isFinite(amount) ? amount : Number.NaN;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function formatGeneralJournalEntryMoney(value: number): string {
|
|
32
|
+
const amount = Number.isFinite(value) ? value : 0;
|
|
33
|
+
return amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function todayDateOnly(now = new Date()): string {
|
|
37
|
+
return toDateOnlyValue(now);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function normalizeDateOnly(value: string | null | undefined): string | null {
|
|
41
|
+
const normalized = normalizeDateOnlyValue(value);
|
|
42
|
+
if (normalized) return normalized;
|
|
43
|
+
|
|
44
|
+
const raw = String(value ?? '').trim();
|
|
45
|
+
if (!raw) return null;
|
|
46
|
+
|
|
47
|
+
const date = new Date(raw);
|
|
48
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
49
|
+
return date.toISOString().slice(0, 10);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function toUtcMidday(dateOnly: string | null | undefined): string {
|
|
53
|
+
const normalized = normalizeDateOnly(dateOnly);
|
|
54
|
+
if (!normalized) throw new Error('Date is required.');
|
|
55
|
+
return `${normalized}T12:00:00Z`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function normalizeGeneralJournalEntryApprovalState(value: unknown): number {
|
|
59
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
60
|
+
|
|
61
|
+
const raw = String(value ?? '').trim().toLowerCase();
|
|
62
|
+
switch (raw) {
|
|
63
|
+
case '1':
|
|
64
|
+
case 'draft':
|
|
65
|
+
return 1;
|
|
66
|
+
case '2':
|
|
67
|
+
case 'submitted':
|
|
68
|
+
return 2;
|
|
69
|
+
case '3':
|
|
70
|
+
case 'approved':
|
|
71
|
+
return 3;
|
|
72
|
+
case '4':
|
|
73
|
+
case 'rejected':
|
|
74
|
+
return 4;
|
|
75
|
+
default:
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function normalizeGeneralJournalEntrySource(value: unknown): number {
|
|
81
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
82
|
+
|
|
83
|
+
const raw = String(value ?? '').trim().toLowerCase();
|
|
84
|
+
switch (raw) {
|
|
85
|
+
case '2':
|
|
86
|
+
case 'system':
|
|
87
|
+
return 2;
|
|
88
|
+
case '1':
|
|
89
|
+
case 'manual':
|
|
90
|
+
default:
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function generalJournalEntryApprovalStateLabel(value: unknown): string {
|
|
96
|
+
switch (normalizeGeneralJournalEntryApprovalState(value)) {
|
|
97
|
+
case 2:
|
|
98
|
+
return 'Submitted';
|
|
99
|
+
case 3:
|
|
100
|
+
return 'Approved';
|
|
101
|
+
case 4:
|
|
102
|
+
return 'Rejected';
|
|
103
|
+
default:
|
|
104
|
+
return 'Draft';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function generalJournalEntrySourceLabel(value: unknown): string {
|
|
109
|
+
return normalizeGeneralJournalEntrySource(value) === 2 ? 'System' : 'Manual';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function generalJournalEntryJournalTypeLabel(value: unknown): string {
|
|
113
|
+
switch (Number(value)) {
|
|
114
|
+
case 1:
|
|
115
|
+
return 'Standard';
|
|
116
|
+
case 2:
|
|
117
|
+
return 'Reversing';
|
|
118
|
+
case 3:
|
|
119
|
+
return 'Adjusting';
|
|
120
|
+
case 4:
|
|
121
|
+
return 'Opening';
|
|
122
|
+
case 5:
|
|
123
|
+
return 'Closing';
|
|
124
|
+
default:
|
|
125
|
+
return '—';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { httpGet, httpPost, httpPut } from '../api/http';
|
|
2
|
+
import type {
|
|
3
|
+
CreateGeneralJournalEntryDraftRequestDto,
|
|
4
|
+
GeneralJournalEntryAccountContextDto,
|
|
5
|
+
GeneralJournalEntryApproveRequestDto,
|
|
6
|
+
GeneralJournalEntryDetailsDto,
|
|
7
|
+
GeneralJournalEntryPageDto,
|
|
8
|
+
GeneralJournalEntryPostRequestDto,
|
|
9
|
+
GeneralJournalEntryRejectRequestDto,
|
|
10
|
+
GeneralJournalEntryReverseRequestDto,
|
|
11
|
+
GeneralJournalEntrySubmitRequestDto,
|
|
12
|
+
ReplaceGeneralJournalEntryLinesRequestDto,
|
|
13
|
+
UpdateGeneralJournalEntryHeaderRequestDto,
|
|
14
|
+
} from './generalJournalEntryTypes';
|
|
15
|
+
|
|
16
|
+
const base = '/api/accounting/general-journal-entries';
|
|
17
|
+
|
|
18
|
+
export type GetGeneralJournalEntryPageArgs = {
|
|
19
|
+
offset?: number;
|
|
20
|
+
limit?: number;
|
|
21
|
+
search?: string | null;
|
|
22
|
+
dateFrom?: string | null;
|
|
23
|
+
dateTo?: string | null;
|
|
24
|
+
trash?: 'active' | 'deleted' | 'all' | null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export async function getGeneralJournalEntryPage(
|
|
28
|
+
args: GetGeneralJournalEntryPageArgs,
|
|
29
|
+
): Promise<GeneralJournalEntryPageDto> {
|
|
30
|
+
const q = new URLSearchParams();
|
|
31
|
+
q.set('offset', String(args.offset ?? 0));
|
|
32
|
+
q.set('limit', String(args.limit ?? 50));
|
|
33
|
+
if (args.search) q.set('search', args.search);
|
|
34
|
+
if (args.dateFrom) q.set('dateFrom', args.dateFrom);
|
|
35
|
+
if (args.dateTo) q.set('dateTo', args.dateTo);
|
|
36
|
+
if (args.trash) q.set('trash', args.trash);
|
|
37
|
+
const qs = q.toString();
|
|
38
|
+
return await httpGet<GeneralJournalEntryPageDto>(`${base}${qs ? `?${qs}` : ''}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function getGeneralJournalEntry(id: string): Promise<GeneralJournalEntryDetailsDto> {
|
|
42
|
+
return await httpGet<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function createGeneralJournalEntryDraft(
|
|
46
|
+
request: CreateGeneralJournalEntryDraftRequestDto,
|
|
47
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
48
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(base, request);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function updateGeneralJournalEntryHeader(
|
|
52
|
+
id: string,
|
|
53
|
+
request: UpdateGeneralJournalEntryHeaderRequestDto,
|
|
54
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
55
|
+
return await httpPut<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/header`, request);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function replaceGeneralJournalEntryLines(
|
|
59
|
+
id: string,
|
|
60
|
+
request: ReplaceGeneralJournalEntryLinesRequestDto,
|
|
61
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
62
|
+
return await httpPut<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/lines`, request);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function submitGeneralJournalEntry(
|
|
66
|
+
id: string,
|
|
67
|
+
request: GeneralJournalEntrySubmitRequestDto,
|
|
68
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
69
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/submit`, request);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function approveGeneralJournalEntry(
|
|
73
|
+
id: string,
|
|
74
|
+
request: GeneralJournalEntryApproveRequestDto,
|
|
75
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
76
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/approve`, request);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function rejectGeneralJournalEntry(
|
|
80
|
+
id: string,
|
|
81
|
+
request: GeneralJournalEntryRejectRequestDto,
|
|
82
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
83
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/reject`, request);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function postGeneralJournalEntry(
|
|
87
|
+
id: string,
|
|
88
|
+
request: GeneralJournalEntryPostRequestDto,
|
|
89
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
90
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/post`, request);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function reverseGeneralJournalEntry(
|
|
94
|
+
id: string,
|
|
95
|
+
request: GeneralJournalEntryReverseRequestDto,
|
|
96
|
+
): Promise<GeneralJournalEntryDetailsDto> {
|
|
97
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/reverse`, request);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function getGeneralJournalEntryAccountContext(
|
|
101
|
+
accountId: string,
|
|
102
|
+
): Promise<GeneralJournalEntryAccountContextDto> {
|
|
103
|
+
return await httpGet<GeneralJournalEntryAccountContextDto>(`${base}/accounts/${encodeURIComponent(accountId)}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function markGeneralJournalEntryForDeletion(id: string): Promise<GeneralJournalEntryDetailsDto> {
|
|
107
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/mark-for-deletion`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function unmarkGeneralJournalEntryForDeletion(id: string): Promise<GeneralJournalEntryDetailsDto> {
|
|
111
|
+
return await httpPost<GeneralJournalEntryDetailsDto>(`${base}/${encodeURIComponent(id)}/unmark-for-deletion`);
|
|
112
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { LookupItem, LookupSource } from '../metadata/types';
|
|
2
|
+
|
|
3
|
+
export type GeneralJournalEntryDimensionValueDto = {
|
|
4
|
+
dimensionId: string;
|
|
5
|
+
valueId: string;
|
|
6
|
+
display?: string | null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type GeneralJournalEntryLineDto = {
|
|
10
|
+
lineNo: number;
|
|
11
|
+
side: number;
|
|
12
|
+
accountId: string;
|
|
13
|
+
accountDisplay?: string | null;
|
|
14
|
+
amount: number;
|
|
15
|
+
memo?: string | null;
|
|
16
|
+
dimensionSetId: string;
|
|
17
|
+
dimensions: GeneralJournalEntryDimensionValueDto[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type GeneralJournalEntryAllocationDto = {
|
|
21
|
+
entryNo: number;
|
|
22
|
+
debitLineNo: number;
|
|
23
|
+
creditLineNo: number;
|
|
24
|
+
amount: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type GeneralJournalEntryHeaderDto = {
|
|
28
|
+
journalType: number;
|
|
29
|
+
source: number;
|
|
30
|
+
approvalState: number;
|
|
31
|
+
reasonCode?: string | null;
|
|
32
|
+
memo?: string | null;
|
|
33
|
+
externalReference?: string | null;
|
|
34
|
+
autoReverse: boolean;
|
|
35
|
+
autoReverseOnUtc?: string | null;
|
|
36
|
+
reversalOfDocumentId?: string | null;
|
|
37
|
+
reversalOfDocumentDisplay?: string | null;
|
|
38
|
+
initiatedBy?: string | null;
|
|
39
|
+
initiatedAtUtc?: string | null;
|
|
40
|
+
submittedBy?: string | null;
|
|
41
|
+
submittedAtUtc?: string | null;
|
|
42
|
+
approvedBy?: string | null;
|
|
43
|
+
approvedAtUtc?: string | null;
|
|
44
|
+
rejectedBy?: string | null;
|
|
45
|
+
rejectedAtUtc?: string | null;
|
|
46
|
+
rejectReason?: string | null;
|
|
47
|
+
postedBy?: string | null;
|
|
48
|
+
postedAtUtc?: string | null;
|
|
49
|
+
createdAtUtc: string;
|
|
50
|
+
updatedAtUtc: string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type GeneralJournalEntryListItemDto = {
|
|
54
|
+
id: string;
|
|
55
|
+
dateUtc: string;
|
|
56
|
+
number?: string | null;
|
|
57
|
+
display?: string | null;
|
|
58
|
+
documentStatus: number | string;
|
|
59
|
+
isMarkedForDeletion: boolean;
|
|
60
|
+
journalType: number;
|
|
61
|
+
source: number;
|
|
62
|
+
approvalState: number;
|
|
63
|
+
reasonCode?: string | null;
|
|
64
|
+
memo?: string | null;
|
|
65
|
+
externalReference?: string | null;
|
|
66
|
+
autoReverse: boolean;
|
|
67
|
+
autoReverseOnUtc?: string | null;
|
|
68
|
+
reversalOfDocumentId?: string | null;
|
|
69
|
+
postedBy?: string | null;
|
|
70
|
+
postedAtUtc?: string | null;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type GeneralJournalEntryPageDto = {
|
|
74
|
+
items: GeneralJournalEntryListItemDto[];
|
|
75
|
+
offset: number;
|
|
76
|
+
limit: number;
|
|
77
|
+
total?: number | null;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export type GeneralJournalEntryDocumentDto = {
|
|
81
|
+
id: string;
|
|
82
|
+
display?: string | null;
|
|
83
|
+
status: number | string;
|
|
84
|
+
isMarkedForDeletion: boolean;
|
|
85
|
+
number?: string | null;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type GeneralJournalEntryDetailsDto = {
|
|
89
|
+
document: GeneralJournalEntryDocumentDto;
|
|
90
|
+
dateUtc: string;
|
|
91
|
+
header: GeneralJournalEntryHeaderDto;
|
|
92
|
+
lines: GeneralJournalEntryLineDto[];
|
|
93
|
+
allocations: GeneralJournalEntryAllocationDto[];
|
|
94
|
+
accountContexts?: GeneralJournalEntryAccountContextDto[];
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type GeneralJournalEntryDimensionRuleDto = {
|
|
98
|
+
dimensionId: string;
|
|
99
|
+
dimensionCode: string;
|
|
100
|
+
ordinal: number;
|
|
101
|
+
isRequired: boolean;
|
|
102
|
+
lookup?: LookupSource | null;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type GeneralJournalEntryAccountContextDto = {
|
|
106
|
+
accountId: string;
|
|
107
|
+
code: string;
|
|
108
|
+
name: string;
|
|
109
|
+
dimensionRules: GeneralJournalEntryDimensionRuleDto[];
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export type CreateGeneralJournalEntryDraftRequestDto = {
|
|
113
|
+
dateUtc: string;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type UpdateGeneralJournalEntryHeaderRequestDto = {
|
|
117
|
+
updatedBy: string;
|
|
118
|
+
journalType?: number | null;
|
|
119
|
+
reasonCode?: string | null;
|
|
120
|
+
memo?: string | null;
|
|
121
|
+
externalReference?: string | null;
|
|
122
|
+
autoReverse?: boolean | null;
|
|
123
|
+
autoReverseOnUtc?: string | null;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export type GeneralJournalEntryLineInputDto = {
|
|
127
|
+
side: number;
|
|
128
|
+
accountId: string;
|
|
129
|
+
amount: number;
|
|
130
|
+
memo?: string | null;
|
|
131
|
+
dimensions?: GeneralJournalEntryDimensionValueDto[] | null;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export type ReplaceGeneralJournalEntryLinesRequestDto = {
|
|
135
|
+
updatedBy: string;
|
|
136
|
+
lines: GeneralJournalEntryLineInputDto[];
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type GeneralJournalEntrySubmitRequestDto = Record<string, never>;
|
|
140
|
+
export type GeneralJournalEntryApproveRequestDto = Record<string, never>;
|
|
141
|
+
export type GeneralJournalEntryPostRequestDto = Record<string, never>;
|
|
142
|
+
export type GeneralJournalEntryRejectRequestDto = { rejectReason: string };
|
|
143
|
+
export type GeneralJournalEntryReverseRequestDto = {
|
|
144
|
+
reversalDateUtc: string;
|
|
145
|
+
postImmediately?: boolean;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export type GeneralJournalEntryEditorLineModel = {
|
|
149
|
+
clientKey: string;
|
|
150
|
+
side: number;
|
|
151
|
+
account: LookupItem | null;
|
|
152
|
+
amount: string;
|
|
153
|
+
memo: string;
|
|
154
|
+
dimensions: Record<string, LookupItem | null>;
|
|
155
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export const DEFAULT_CHART_OF_ACCOUNTS_BASE_PATH = '/admin/chart-of-accounts';
|
|
2
|
+
export const DEFAULT_GENERAL_JOURNAL_ENTRIES_BASE_PATH = '/accounting/general-journal-entries';
|
|
3
|
+
export const DEFAULT_ACCOUNTING_PERIOD_CLOSING_BASE_PATH = '/admin/accounting/period-closing';
|
|
4
|
+
|
|
5
|
+
export type ChartOfAccountsRouteOptions = {
|
|
6
|
+
panel?: 'new' | 'edit' | null;
|
|
7
|
+
id?: string | null;
|
|
8
|
+
basePath?: string | null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type GeneralJournalEntriesRouteOptions = {
|
|
12
|
+
basePath?: string | null;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type AccountingPeriodClosingRouteOptions = {
|
|
16
|
+
year?: string | number | null;
|
|
17
|
+
month?: string | null;
|
|
18
|
+
fy?: string | null;
|
|
19
|
+
basePath?: string | null;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const GENERAL_JOURNAL_ENTRY_DOCUMENT_TYPES = new Set([
|
|
23
|
+
'accounting.general_journal_entry',
|
|
24
|
+
'general_journal_entry',
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
function normalizePathSegment(value: string | null | undefined): string {
|
|
28
|
+
return String(value ?? '').trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function appendQuery(path: string, query: Record<string, string | null | undefined>): string {
|
|
32
|
+
const params = new URLSearchParams();
|
|
33
|
+
|
|
34
|
+
for (const [key, value] of Object.entries(query)) {
|
|
35
|
+
const normalized = normalizePathSegment(value);
|
|
36
|
+
if (!normalized) continue;
|
|
37
|
+
params.set(key, normalized);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const serialized = params.toString();
|
|
41
|
+
return serialized ? `${path}?${serialized}` : path;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function buildChartOfAccountsPath(options: ChartOfAccountsRouteOptions = {}): string {
|
|
45
|
+
return appendQuery(
|
|
46
|
+
normalizePathSegment(options.basePath) || DEFAULT_CHART_OF_ACCOUNTS_BASE_PATH,
|
|
47
|
+
{
|
|
48
|
+
panel: options.panel ?? undefined,
|
|
49
|
+
id: options.id ?? undefined,
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isGeneralJournalEntryDocumentType(documentType: string | null | undefined): boolean {
|
|
55
|
+
return GENERAL_JOURNAL_ENTRY_DOCUMENT_TYPES.has(normalizePathSegment(documentType));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function buildGeneralJournalEntriesListPath(options: GeneralJournalEntriesRouteOptions = {}): string {
|
|
59
|
+
return normalizePathSegment(options.basePath) || DEFAULT_GENERAL_JOURNAL_ENTRIES_BASE_PATH;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function buildGeneralJournalEntriesPath(
|
|
63
|
+
id?: string | null,
|
|
64
|
+
options: GeneralJournalEntriesRouteOptions = {},
|
|
65
|
+
): string {
|
|
66
|
+
const basePath = buildGeneralJournalEntriesListPath(options);
|
|
67
|
+
const normalizedId = normalizePathSegment(id);
|
|
68
|
+
if (!normalizedId) return `${basePath}/new`;
|
|
69
|
+
return `${basePath}/${encodeURIComponent(normalizedId)}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function buildAccountingPeriodClosingPath(
|
|
73
|
+
options: AccountingPeriodClosingRouteOptions = {},
|
|
74
|
+
): string {
|
|
75
|
+
return appendQuery(
|
|
76
|
+
normalizePathSegment(options.basePath) || DEFAULT_ACCOUNTING_PERIOD_CLOSING_BASE_PATH,
|
|
77
|
+
{
|
|
78
|
+
year: options.year == null ? undefined : String(options.year),
|
|
79
|
+
month: options.month ?? undefined,
|
|
80
|
+
fy: options.fy ?? undefined,
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
currentMonthValue,
|
|
3
|
+
dateOnlyToMonthValue,
|
|
4
|
+
formatMonthValue,
|
|
5
|
+
monthValueToDateOnly,
|
|
6
|
+
monthValueYear,
|
|
7
|
+
normalizeMonthValue,
|
|
8
|
+
} from '../utils/dateValues';
|
|
9
|
+
import {
|
|
10
|
+
normalizeMonthQueryValue,
|
|
11
|
+
normalizeYearQueryValue,
|
|
12
|
+
} from '../router/queryParams';
|
|
13
|
+
|
|
14
|
+
type PeriodClosingQueryLike = {
|
|
15
|
+
year?: unknown;
|
|
16
|
+
month?: unknown;
|
|
17
|
+
fy?: unknown;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function currentCalendarYear(now = new Date()): number {
|
|
21
|
+
return now.getFullYear();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function defaultMonthValueForYear(year: number, now = new Date()): string {
|
|
25
|
+
const current = currentMonthValue(now);
|
|
26
|
+
return monthValueYear(current) === year ? current : `${year}-01`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function alignMonthValueToYear(
|
|
30
|
+
monthValue: string | null | undefined,
|
|
31
|
+
year: number,
|
|
32
|
+
now = new Date(),
|
|
33
|
+
): string {
|
|
34
|
+
const normalized = normalizeMonthValue(monthValue) ?? defaultMonthValueForYear(year, now);
|
|
35
|
+
return `${year}-${normalized.slice(5, 7)}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function resolveSelectedYear(query: PeriodClosingQueryLike, now = new Date()): number {
|
|
39
|
+
const explicitYear = normalizeYearQueryValue(query.year);
|
|
40
|
+
if (explicitYear) return explicitYear;
|
|
41
|
+
|
|
42
|
+
const monthYear = monthValueYear(normalizeMonthQueryValue(query.month));
|
|
43
|
+
if (monthYear) return monthYear;
|
|
44
|
+
|
|
45
|
+
const fiscalYear = monthValueYear(normalizeMonthQueryValue(query.fy));
|
|
46
|
+
if (fiscalYear) return fiscalYear;
|
|
47
|
+
|
|
48
|
+
return currentCalendarYear(now);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function resolveSelectedMonthValue(
|
|
52
|
+
queryValue: unknown,
|
|
53
|
+
selectedYear: number,
|
|
54
|
+
now = new Date(),
|
|
55
|
+
): string {
|
|
56
|
+
const fromQuery = normalizeMonthQueryValue(queryValue);
|
|
57
|
+
if (fromQuery && monthValueYear(fromQuery) === selectedYear) return fromQuery;
|
|
58
|
+
return defaultMonthValueForYear(selectedYear, now);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function selectMonthValue(value: string | null | undefined): string | null {
|
|
62
|
+
return normalizeMonthValue(value) ?? dateOnlyToMonthValue(value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function toPeriodDateOnly(monthValue: string): string {
|
|
66
|
+
return monthValueToDateOnly(monthValue) ?? `${monthValue}-01`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function formatPeriodMonthValue(value: string | null | undefined): string {
|
|
70
|
+
return formatMonthValue(value) ?? '—';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function formatPeriodDateOnly(value: string | null | undefined): string {
|
|
74
|
+
return formatPeriodMonthValue(dateOnlyToMonthValue(value));
|
|
75
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { httpGet, httpPost } from '../api/http';
|
|
2
|
+
import type {
|
|
3
|
+
CloseFiscalYearRequestDto,
|
|
4
|
+
CloseMonthRequestDto,
|
|
5
|
+
FiscalYearCloseStatusDto,
|
|
6
|
+
PeriodClosingCalendarDto,
|
|
7
|
+
PeriodCloseStatusDto,
|
|
8
|
+
ReopenFiscalYearRequestDto,
|
|
9
|
+
ReopenMonthRequestDto,
|
|
10
|
+
RetainedEarningsAccountOptionDto,
|
|
11
|
+
} from './periodClosingTypes';
|
|
12
|
+
|
|
13
|
+
export async function getMonthCloseStatus(period: string): Promise<PeriodCloseStatusDto> {
|
|
14
|
+
return await httpGet<PeriodCloseStatusDto>('/api/accounting/period-closing/month', { period });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function closeMonth(request: CloseMonthRequestDto): Promise<PeriodCloseStatusDto> {
|
|
18
|
+
return await httpPost<PeriodCloseStatusDto>('/api/accounting/period-closing/month/close', request);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function reopenMonth(request: ReopenMonthRequestDto): Promise<PeriodCloseStatusDto> {
|
|
22
|
+
return await httpPost<PeriodCloseStatusDto>('/api/accounting/period-closing/month/reopen', request);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function getPeriodClosingCalendar(year: number): Promise<PeriodClosingCalendarDto> {
|
|
26
|
+
return await httpGet<PeriodClosingCalendarDto>('/api/accounting/period-closing/calendar', { year });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function getFiscalYearCloseStatus(
|
|
30
|
+
fiscalYearEndPeriod: string,
|
|
31
|
+
): Promise<FiscalYearCloseStatusDto> {
|
|
32
|
+
return await httpGet<FiscalYearCloseStatusDto>('/api/accounting/period-closing/fiscal-year', {
|
|
33
|
+
fiscalYearEndPeriod,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function closeFiscalYear(
|
|
38
|
+
request: CloseFiscalYearRequestDto,
|
|
39
|
+
): Promise<FiscalYearCloseStatusDto> {
|
|
40
|
+
return await httpPost<FiscalYearCloseStatusDto>('/api/accounting/period-closing/fiscal-year/close', request);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function reopenFiscalYear(
|
|
44
|
+
request: ReopenFiscalYearRequestDto,
|
|
45
|
+
): Promise<FiscalYearCloseStatusDto> {
|
|
46
|
+
return await httpPost<FiscalYearCloseStatusDto>('/api/accounting/period-closing/fiscal-year/reopen', request);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function searchRetainedEarningsAccounts(args?: {
|
|
50
|
+
query?: string | null;
|
|
51
|
+
limit?: number;
|
|
52
|
+
}): Promise<RetainedEarningsAccountOptionDto[]> {
|
|
53
|
+
return await httpGet<RetainedEarningsAccountOptionDto[]>(
|
|
54
|
+
'/api/accounting/period-closing/retained-earnings-accounts',
|
|
55
|
+
{
|
|
56
|
+
q: args?.query?.trim() || undefined,
|
|
57
|
+
limit: args?.limit ?? 20,
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
}
|