Skip to content

Commit

Permalink
[SELC-5699] Feat: Instituions of type EA can hadle delegation
Browse files Browse the repository at this point in the history
  • Loading branch information
OraldoDoci authored Oct 9, 2024
1 parent 0ebfe42 commit c1e4c9d
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 198 deletions.
6 changes: 6 additions & 0 deletions openApi/dashboard-api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -3766,6 +3766,9 @@
"billing" : {
"$ref" : "#/components/schemas/Billing"
},
"isAggregator" : {
"type" : "boolean"
},
"productId" : {
"type" : "string"
},
Expand Down Expand Up @@ -3794,6 +3797,9 @@
"billing" : {
"$ref" : "#/components/schemas/Billing"
},
"isAggregator" : {
"type" : "boolean"
},
"productId" : {
"type" : "string"
},
Expand Down
6 changes: 6 additions & 0 deletions openApi/generated-dashboard/dashboard-swagger20.json
Original file line number Diff line number Diff line change
Expand Up @@ -3354,6 +3354,9 @@
"billing": {
"$ref": "#/definitions/Billing"
},
"isAggregator": {
"type": "boolean"
},
"productId": {
"type": "string"
},
Expand Down Expand Up @@ -3389,6 +3392,9 @@
"billing": {
"$ref": "#/definitions/Billing"
},
"isAggregator": {
"type": "boolean"
},
"productId": {
"type": "string"
},
Expand Down
1 change: 1 addition & 0 deletions src/locale/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export default {
PG: 'Azienda',
REC: 'Recapitista',
CON: 'Consolidatore',
PRV: 'Privato',
},
delegationBanner: {
title: 'Delega la gestione dei prodotti a un Partner o a un Intermediario',
Expand Down
225 changes: 113 additions & 112 deletions src/model/Party.tsx
Original file line number Diff line number Diff line change
@@ -1,112 +1,113 @@
import { GeographicTaxonomyResource } from '../api/generated/b4f-dashboard/GeographicTaxonomyResource';
import { InstitutionBaseResource } from '../api/generated/b4f-dashboard/InstitutionBaseResource';
import { InstitutionResource } from '../api/generated/b4f-dashboard/InstitutionResource';
import { ProductOnBoardingStatusEnum } from '../api/generated/b4f-dashboard/OnboardedProductResource';
import { ENV } from '../utils/env';

export type UserRole = 'ADMIN' | 'LIMITED';
export type PartyRole = 'DELEGATE' | 'MANAGER' | 'OPERATOR' | 'SUB_DELEGATE';
export type UserStatus = 'PENDING' | 'ACTIVE' | 'SUSPENDED' | 'TOBEVALIDATED';

type OnboardedProduct = {
authorized?: boolean;
billing?: {
publicServices?: boolean;
recipientCode?: string;
vatNumber?: string;
};
productId?: string;
productOnBoardingStatus?: ProductOnBoardingStatusEnum;
userProductActions?: Array<string>;
userRole?: string;
};

export type Party = {
partyId: string;
products: Array<OnboardedProduct>;
externalId?: string;
originId?: string;
origin?: string;
description: string;
digitalAddress?: string;
category?: string;
urlLogo?: string;
fiscalCode?: string;
registeredOffice: string;
zipCode?: string;
typology: string;
institutionType?: string;
recipientCode?: string;
geographicTaxonomies?: Array<GeographicTaxonomyResource>;
delegation?: boolean;
vatNumberGroup?: boolean;
supportEmail?: string;
vatNumber?: string;
subunitCode?: string;
subunitType?: string;
aooParentCode?: string;
parentDescription?: string;
userRole?: UserRole;
status?: UserStatus;
city?: string;
country?: string;
};

export type BaseParty = {
partyId: string;
description: string;
status: UserStatus;
userRole: UserRole;
urlLogo?: string;
parentDescription?: string;
};

const buildUrlLog = (partyId: string) =>
`${ENV.URL_INSTITUTION_LOGO.PREFIX}${partyId}${ENV.URL_INSTITUTION_LOGO.SUFFIX}`;

export const institutionResource2Party = (institutionResource: InstitutionResource): Party => {
const urlLogo = institutionResource.id && buildUrlLog(institutionResource.id);
return {
partyId: institutionResource.id ?? '',
externalId: institutionResource.externalId ?? '',
originId: institutionResource?.originId,
origin: institutionResource?.origin,
description: institutionResource.name ?? '',
digitalAddress: institutionResource.mailAddress,
category: institutionResource.category,
urlLogo,
fiscalCode: institutionResource.fiscalCode,
registeredOffice: institutionResource.address ?? '',
zipCode: institutionResource.zipCode ?? '',
city: institutionResource.city ?? '',
country: institutionResource.country ?? '',
typology: 'TODO', // it will represent the taxonomy of the party
institutionType: institutionResource.institutionType,
recipientCode: institutionResource.recipientCode,
geographicTaxonomies:
institutionResource.geographicTaxonomies as Array<GeographicTaxonomyResource>,
delegation: institutionResource.delegation,
vatNumberGroup: institutionResource.vatNumberGroup,
supportEmail: institutionResource.supportContact?.supportEmail,
vatNumber: institutionResource.vatNumber,
subunitCode: institutionResource.subunitCode,
subunitType: institutionResource.subunitType,
aooParentCode: institutionResource.aooParentCode,
parentDescription: institutionResource.parentDescription,
products: institutionResource.products as Array<OnboardedProduct>,
};
};

export const institutionBaseResource2BaseParty = (
institutionResource: InstitutionBaseResource
): BaseParty => {
const urlLogo = institutionResource.id && buildUrlLog(institutionResource.id);
return {
partyId: institutionResource.id ?? '',
description: institutionResource.name ?? '',
status: institutionResource.status as UserStatus,
userRole: institutionResource.userRole as UserRole,
parentDescription: institutionResource.parentDescription,
urlLogo,
};
};
import { GeographicTaxonomyResource } from '../api/generated/b4f-dashboard/GeographicTaxonomyResource';
import { InstitutionBaseResource } from '../api/generated/b4f-dashboard/InstitutionBaseResource';
import { InstitutionResource } from '../api/generated/b4f-dashboard/InstitutionResource';
import { ProductOnBoardingStatusEnum } from '../api/generated/b4f-dashboard/OnboardedProductResource';
import { ENV } from '../utils/env';

export type UserRole = 'ADMIN' | 'LIMITED';
export type PartyRole = 'DELEGATE' | 'MANAGER' | 'OPERATOR' | 'SUB_DELEGATE';
export type UserStatus = 'PENDING' | 'ACTIVE' | 'SUSPENDED' | 'TOBEVALIDATED';

type OnboardedProduct = {
authorized?: boolean;
billing?: {
publicServices?: boolean;
recipientCode?: string;
vatNumber?: string;
};
productId?: string;
productOnBoardingStatus?: ProductOnBoardingStatusEnum;
userProductActions?: Array<string>;
userRole?: string;
isAggregator?: boolean;
};

export type Party = {
partyId: string;
products: Array<OnboardedProduct>;
externalId?: string;
originId?: string;
origin?: string;
description: string;
digitalAddress?: string;
category?: string;
urlLogo?: string;
fiscalCode?: string;
registeredOffice: string;
zipCode?: string;
typology: string;
institutionType?: string;
recipientCode?: string;
geographicTaxonomies?: Array<GeographicTaxonomyResource>;
delegation?: boolean;
vatNumberGroup?: boolean;
supportEmail?: string;
vatNumber?: string;
subunitCode?: string;
subunitType?: string;
aooParentCode?: string;
parentDescription?: string;
userRole?: UserRole;
status?: UserStatus;
city?: string;
country?: string;
};

export type BaseParty = {
partyId: string;
description: string;
status: UserStatus;
userRole: UserRole;
urlLogo?: string;
parentDescription?: string;
};

const buildUrlLog = (partyId: string) =>
`${ENV.URL_INSTITUTION_LOGO.PREFIX}${partyId}${ENV.URL_INSTITUTION_LOGO.SUFFIX}`;

export const institutionResource2Party = (institutionResource: InstitutionResource): Party => {
const urlLogo = institutionResource.id && buildUrlLog(institutionResource.id);
return {
partyId: institutionResource.id ?? '',
externalId: institutionResource.externalId ?? '',
originId: institutionResource?.originId,
origin: institutionResource?.origin,
description: institutionResource.name ?? '',
digitalAddress: institutionResource.mailAddress,
category: institutionResource.category,
urlLogo,
fiscalCode: institutionResource.fiscalCode,
registeredOffice: institutionResource.address ?? '',
zipCode: institutionResource.zipCode ?? '',
city: institutionResource.city ?? '',
country: institutionResource.country ?? '',
typology: 'TODO', // it will represent the taxonomy of the party
institutionType: institutionResource.institutionType,
recipientCode: institutionResource.recipientCode,
geographicTaxonomies:
institutionResource.geographicTaxonomies as Array<GeographicTaxonomyResource>,
delegation: institutionResource.delegation,
vatNumberGroup: institutionResource.vatNumberGroup,
supportEmail: institutionResource.supportContact?.supportEmail,
vatNumber: institutionResource.vatNumber,
subunitCode: institutionResource.subunitCode,
subunitType: institutionResource.subunitType,
aooParentCode: institutionResource.aooParentCode,
parentDescription: institutionResource.parentDescription,
products: institutionResource.products as Array<OnboardedProduct>,
};
};

export const institutionBaseResource2BaseParty = (
institutionResource: InstitutionBaseResource
): BaseParty => {
const urlLogo = institutionResource.id && buildUrlLog(institutionResource.id);
return {
partyId: institutionResource.id ?? '',
description: institutionResource.name ?? '',
status: institutionResource.status as UserStatus,
userRole: institutionResource.userRole as UserRole,
parentDescription: institutionResource.parentDescription,
urlLogo,
};
};
60 changes: 40 additions & 20 deletions src/pages/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,28 @@ export const buildRoutes = (

// eslint-disable-next-line sonarjs/cognitive-complexity
const Dashboard = () => {
const history = useHistory();
const party = useAppSelector(partiesSelectors.selectPartySelected);
const products = useAppSelector(partiesSelectors.selectPartySelectedProducts);
const store = useStore();
const theme = useTheme();
const { getAllProductsWithPermission, hasPermission } = usePermissions();
const { i18n, t } = useTranslation();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('lg'));

const [drawerOpen, setDrawerOpen] = useState(false);
const [hideLabels, setHideLabels] = useState(false);

const { getAllProductsWithPermission, hasPermission } = usePermissions();
const history = useHistory();
const location = useLocation();

const store = useStore();
const party = useAppSelector(partiesSelectors.selectPartySelected);
const products = useAppSelector(partiesSelectors.selectPartySelectedProducts);

const canSeeAddDelegation = getAllProductsWithPermission(Actions.ViewDelegations).length > 0;
const isPT = party?.institutionType === 'PT';
const hasDelegation = !!party?.delegation;
const hasDelegation = Boolean(party?.delegation);

const productsMap: ProductsMap =
useMemo(() => buildProductsMap(products ?? []), [products]) ?? [];

const decorators = { withProductRolesMap, withSelectedProduct, withSelectedProductRoles };

const activeProducts: Array<Product> =
useMemo(
Expand All @@ -117,6 +124,12 @@ const Dashboard = () => {
[products, party]
) ?? [];

const delegableProducts: Array<Product> = activeProducts.filter((product) =>
party?.products.some(
(partyProduct) => partyProduct.productId === product.id && product.delegable
)
);

const authorizedDelegableProducts: Array<Product> = activeProducts.filter((ap) =>
party?.products.some(
(p) =>
Expand All @@ -125,7 +138,15 @@ const Dashboard = () => {
ap.delegable
)
);
const hasAuthorizedProducts = authorizedDelegableProducts.length > 0;

const canAggregatorSeeHandleDelegations = useMemo(() => {
const aggregatorProduct = party?.products?.find(
(product) =>
product.isAggregator &&
hasPermission(product.productId ?? '', Actions.ViewManagedInstitutions)
);
return Boolean(aggregatorProduct && hasDelegation);
}, [party, hasDelegation]);

const isInvoiceSectionVisible = !!products?.some(
(prod) =>
Expand All @@ -136,23 +157,22 @@ const Dashboard = () => {
)
);

const productsMap: ProductsMap =
useMemo(() => buildProductsMap(products ?? []), [products]) ?? [];

const decorators = { withProductRolesMap, withSelectedProduct, withSelectedProductRoles };

const isAddDelegateSectionVisible =
ENV.DELEGATIONS.ENABLE &&
authorizedDelegableProducts.length > 0 &&
!isPT &&
canSeeAddDelegation;
getAllProductsWithPermission(Actions.ViewDelegations).length > 0;

const isHandleDelegationsVisible =
getAllProductsWithPermission(Actions.ViewManagedInstitutions).length > 0 &&
hasAuthorizedProducts &&
(isPT || hasDelegation);
const isHandleDelegationsVisible = useMemo(() => {
const hasPermissionForManagedInstitutions =
getAllProductsWithPermission(Actions.ViewManagedInstitutions).length > 0;
const canShowDelegations = delegableProducts.length > 0 && (isPT || hasDelegation);

const location = useLocation();
return (
(hasPermissionForManagedInstitutions && canShowDelegations) ||
canAggregatorSeeHandleDelegations
);
}, [authorizedDelegableProducts, isPT, hasDelegation, canAggregatorSeeHandleDelegations]);

// Check if the current route matches any path in the array
const paths = [DASHBOARD_ROUTES.ADD_DELEGATE.path, `${ENV.ROUTES.USERS}/add`];
Expand Down
Loading

0 comments on commit c1e4c9d

Please sign in to comment.