Skip to content

Commit

Permalink
feat: add revenues and expenses to sacem declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
sneko committed Jan 8, 2025
1 parent d5bfefc commit 64b5e38
Show file tree
Hide file tree
Showing 18 changed files with 1,479 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { BaseForm } from '@ad/src/components/BaseForm';
import { ErrorAlert } from '@ad/src/components/ErrorAlert';
import { EventSalesTable } from '@ad/src/components/EventSalesTable';
import { LoadingArea } from '@ad/src/components/LoadingArea';
import { SacemExpensesTable } from '@ad/src/components/SacemExpensesTable';
import { SacemRevenuesTable } from '@ad/src/components/SacemRevenuesTable';
import { useSingletonConfirmationDialog } from '@ad/src/components/modal/useModal';
import { FillSacemDeclarationSchema, FillSacemDeclarationSchemaType } from '@ad/src/models/actions/declaration';
import { currencyFormatter, currencyFormatterWithNoDecimals } from '@ad/src/utils/currency';
Expand Down Expand Up @@ -62,11 +64,8 @@ export function SacemDeclarationPage({ params: { eventSerieId } }: SacemDeclarat
const { showConfirmationDialog } = useSingletonConfirmationDialog();

const {
register,
handleSubmit,
formState: { errors, isDirty },
setValue,
watch,
formState: { isDirty },
control,
reset,
} = useForm<FillSacemDeclarationSchemaType>({
Expand All @@ -89,6 +88,8 @@ export function SacemDeclarationPage({ params: { eventSerieId } }: SacemDeclarat
placeCapacity: result.sacemDeclaration.placeCapacity,
managerName: result.sacemDeclaration.managerName,
managerTitle: result.sacemDeclaration.managerTitle,
revenues: result.sacemDeclaration.revenues,
expenses: result.sacemDeclaration.expenses,
});
},
[fillSacemDeclaration, reset, eventSerieId]
Expand All @@ -105,6 +106,8 @@ export function SacemDeclarationPage({ params: { eventSerieId } }: SacemDeclarat
placeCapacity: getSacemDeclaration.data.sacemDeclarationWrapper.declaration.placeCapacity,
managerName: getSacemDeclaration.data.sacemDeclarationWrapper.declaration.managerName,
managerTitle: getSacemDeclaration.data.sacemDeclarationWrapper.declaration.managerTitle,
revenues: getSacemDeclaration.data.sacemDeclarationWrapper.declaration.revenues,
expenses: getSacemDeclaration.data.sacemDeclarationWrapper.declaration.expenses,
}); // Update the form with fetched data
}
}, [getSacemDeclaration.data, formInitialized, setFormInitialized, reset, eventSerieId]);
Expand Down Expand Up @@ -664,63 +667,39 @@ export function SacemDeclarationPage({ params: { eventSerieId } }: SacemDeclarat
/>
</Tooltip>
</Grid>
<Grid item xs={12} sm={6}>
<Tooltip
title={
'Cette valeur provient initialement de votre billetterie mais peut être corrigée en ajustant les valeurs des représentations plus haut'
}
<Grid item xs={12}>
<Box
sx={{
bgcolor: fr.colors.decisions.background.alt.greenEmeraude.default,
borderRadius: '8px',
py: { xs: 2, md: 3 },
px: { xs: 1, md: 2 },
mt: 1,
}}
>
<TextField
disabled
label="Montant HT des recettes"
value={
sacemDeclarationWrapper.declaration
? currencyFormatter.format(sacemDeclarationWrapper.declaration.excludingTaxesAmount)
: currencyFormatter.format(sacemDeclarationWrapper.placeholder.excludingTaxesAmount)
}
fullWidth
/>
</Tooltip>
<SacemRevenuesTable control={control} />
</Box>
</Grid>
<Grid item xs={12} sm={6}>
<Tooltip
title={
'Cette valeur provient initialement de votre billetterie mais peut être corrigée en ajustant les valeurs des représentations plus haut'
}
>
<TextField
disabled
label="Montant de la TVA"
value={
sacemDeclarationWrapper.declaration
? currencyFormatter.format(
sacemDeclarationWrapper.declaration.includingTaxesAmount - sacemDeclarationWrapper.declaration.excludingTaxesAmount
)
: currencyFormatter.format(
sacemDeclarationWrapper.placeholder.includingTaxesAmount - sacemDeclarationWrapper.placeholder.excludingTaxesAmount
)
}
fullWidth
/>
</Tooltip>
</Grid>
<Grid item xs={12} sm={6}>
<Tooltip
title={
'Cette valeur provient initialement de votre billetterie mais peut être corrigée en ajustant les valeurs des représentations plus haut'
}
</Grid>
</Grid>
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography gutterBottom variant="h6" component="div">
Dépenses artistiques
</Typography>
<hr />
<Grid container spacing={2}>
<Grid item xs={12}>
<Box
sx={{
bgcolor: fr.colors.decisions.background.alt.redMarianne.default,
borderRadius: '8px',
py: { xs: 2, md: 3 },
px: { xs: 1, md: 2 },
mt: 1,
}}
>
<TextField
disabled
label="Montant TTC des recettes"
value={
sacemDeclarationWrapper.declaration
? currencyFormatter.format(sacemDeclarationWrapper.declaration.includingTaxesAmount)
: currencyFormatter.format(sacemDeclarationWrapper.placeholder.includingTaxesAmount)
}
fullWidth
/>
</Tooltip>
<SacemExpensesTable control={control} />
</Box>
</Grid>
</Grid>
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ErrorAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import z from 'zod';

import { formatMessageFromIssue } from '@ad/src/i18n';
import { CustomError, internalServerErrorError, unexpectedErrorError } from '@ad/src/models/entities/errors';
import { formatMessageFromCustomError } from '@ad/src/models/entities/helpers';
import { formatMessageFromCustomError } from '@ad/src/models/entities/errors/helpers';
import { AppRouter } from '@ad/src/server/app-router';
import { capitalizeFirstLetter } from '@ad/src/utils/format';

Expand Down
43 changes: 36 additions & 7 deletions src/components/EventSalesTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Alert, Snackbar, Tooltip } from '@mui/material';
import type { GridColDef, GridRowModel } from '@mui/x-data-grid';
import { GridAutosizeOptions, type GridColDef, type GridRowModel, useGridApiRef } from '@mui/x-data-grid';
import { DataGrid } from '@mui/x-data-grid/DataGrid';
import { useCallback, useState } from 'react';
import debounce from 'lodash.debounce';
import { useCallback, useEffect, useState } from 'react';

import { ErrorAlert } from '@ad/src/components/ErrorAlert';
import styles from '@ad/src/components/EventSalesTable.module.scss';
Expand All @@ -24,20 +25,45 @@ export interface EventSalesTableProps {
}

export function EventSalesTable({ wrapper, onRowUpdate }: EventSalesTableProps) {
const apiRef = useGridApiRef();

const [autosizeOption] = useState<GridAutosizeOptions>({
includeOutliers: true,
includeHeaders: true,
outliersFactor: 1.5,
expand: true,
});

useEffect(() => {
apiRef.current.autosizeColumns(autosizeOption);
}, [apiRef, wrapper.sales, autosizeOption]);

useEffect(() => {
// We also autosize when the frame is changing
// Note: using `onResize` is triggered sometimes for internal DataGrid things so it's not relevent for us
const update = debounce(() => {
apiRef.current.autosizeColumns(autosizeOption);
}, 50);

window.addEventListener('resize', update);

return () => {
window.removeEventListener('resize', update);
};
}, [apiRef, autosizeOption]);

// To type options functions have a look at https://github.com/mui/mui-x/pull/4064
const columns: GridColDef<SalesWrapperSchemaType>[] = [
const [columns] = useState<GridColDef<SalesWrapperSchemaType>[]>([
{
field: `${salesTypedNameof('ticketCategory')}.${ticketCategoryTypedNameof('name')}`,
headerName: 'Catégorie des tickets',
flex: 1.5,
renderCell: (params) => {
return <span data-sentry-mask>{params.row.ticketCategory.name}</span>;
},
},
{
field: `${salesTypedNameof('eventCategoryTickets')}.${ticketCategoryTypedNameof('price')}`,
headerName: 'Prix unitaire TTC',
flex: 1,
editable: true,
type: 'number',
valueGetter: (_, row) => {
Expand Down Expand Up @@ -77,7 +103,6 @@ export function EventSalesTable({ wrapper, onRowUpdate }: EventSalesTableProps)
{
field: `${salesTypedNameof('eventCategoryTickets')}.${eventCategoryTicketsTypedNameof('total')}`,
headerName: 'Nombre de billets vendus',
flex: 1,
editable: true,
type: 'number',
valueGetter: (_, row) => {
Expand Down Expand Up @@ -111,7 +136,7 @@ export function EventSalesTable({ wrapper, onRowUpdate }: EventSalesTableProps)
return params.row.eventCategoryTickets.totalOverride !== null ? styles.overridenCell : '';
},
},
];
]);

const [snackbarAlert, setSnackbarAlert] = useState<JSX.Element | null>(null);
const handleCloseSnackbar = useCallback(() => setSnackbarAlert(null), []);
Expand Down Expand Up @@ -159,6 +184,7 @@ export function EventSalesTable({ wrapper, onRowUpdate }: EventSalesTableProps)
return (
<>
<DataGrid
apiRef={apiRef}
rows={wrapper.sales}
getRowId={(row) => row.ticketCategory.id}
columns={columns}
Expand Down Expand Up @@ -192,6 +218,9 @@ export function EventSalesTable({ wrapper, onRowUpdate }: EventSalesTableProps)
// Start observing the cell element for child additions
observer.observe(editCellElement, { childList: true, subtree: true });
}}
autosizeOnMount={true}
autosizeOptions={autosizeOption}
disableVirtualization={true}
aria-label="tableau des ventes d'une représentation"
data-sentry-mask
/>
Expand Down
38 changes: 38 additions & 0 deletions src/components/SacemExpensesTable.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Meta, StoryFn } from '@storybook/react';
import { within } from '@storybook/test';
import { useForm } from 'react-hook-form';

import { StoryHelperFactory } from '@ad/.storybook/helpers';
import { SacemExpensesTable } from '@ad/src/components/SacemExpensesTable';
import { sacemDeclarations } from '@ad/src/fixtures/declaration';
import { FillSacemDeclarationSchemaType } from '@ad/src/models/actions/declaration';

type ComponentType = typeof SacemExpensesTable;
const { generateMetaDefault, prepareStory } = StoryHelperFactory<ComponentType>();

export default {
title: 'Components/SacemExpensesTable',
component: SacemExpensesTable,
...generateMetaDefault({
parameters: {},
}),
} as Meta<ComponentType>;

const Template: StoryFn<ComponentType> = (args) => {
const { control } = useForm<FillSacemDeclarationSchemaType>({
defaultValues: {
expenses: sacemDeclarations[0].expenses,
},
});

return <SacemExpensesTable {...args} control={control} />;
};

const NormalStory = Template.bind({});
NormalStory.args = {};
NormalStory.parameters = {};
NormalStory.play = async ({ canvasElement }) => {
await within(canvasElement).findByRole('grid');
};

export const Normal = prepareStory(NormalStory);
Loading

0 comments on commit 64b5e38

Please sign in to comment.