diff --git a/projects/organization-management/src/app/components/budget-widget/budget-widget.component.ts b/projects/organization-management/src/app/components/budget-widget/budget-widget.component.ts index aacaede51c..1f5c9b9ece 100644 --- a/projects/organization-management/src/app/components/budget-widget/budget-widget.component.ts +++ b/projects/organization-management/src/app/components/budget-widget/budget-widget.component.ts @@ -2,10 +2,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { GenerateLazyComponent } from 'ish-core/utils/module-loader/generate-lazy-component.decorator'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; @Component({ selector: 'ish-budget-widget', diff --git a/projects/organization-management/src/app/components/user-budget-form/user-budget-form.component.ts b/projects/organization-management/src/app/components/user-budget-form/user-budget-form.component.ts index 9fb26ccb7e..ac41dd2f30 100644 --- a/projects/organization-management/src/app/components/user-budget-form/user-budget-form.component.ts +++ b/projects/organization-management/src/app/components/user-budget-form/user-budget-form.component.ts @@ -4,9 +4,10 @@ import { FormGroup } from '@angular/forms'; import { FormlyFieldConfig } from '@ngx-formly/core'; import { AppFacade } from 'ish-core/facades/app.facade'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { whenTruthy } from 'ish-core/utils/operators'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + interface UserBudgetModel { orderSpentLimitValue?: number; budgetValue?: number; diff --git a/projects/organization-management/src/app/components/user-budget/user-budget.component.ts b/projects/organization-management/src/app/components/user-budget/user-budget.component.ts index c0931f30b6..c98410527f 100644 --- a/projects/organization-management/src/app/components/user-budget/user-budget.component.ts +++ b/projects/organization-management/src/app/components/user-budget/user-budget.component.ts @@ -1,7 +1,8 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { Price } from 'ish-core/models/price/price.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; + +import { UserBudget } from '../../models/user-budget/user-budget.model'; /** * displays the user budget and the appropriate budget bar diff --git a/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.spec.ts b/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.spec.ts index 7e10f4dfc7..32642c98ad 100644 --- a/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.spec.ts +++ b/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.spec.ts @@ -3,10 +3,11 @@ import { FormGroup } from '@angular/forms'; import { TranslateModule } from '@ngx-translate/core'; import { MockComponent } from 'ng-mocks'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; import { FormlyTestingModule } from 'ish-shared/formly/dev/testing/formly-testing.module'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; + import { UserProfileFormComponent } from './user-profile-form.component'; describe('User Profile Form Component', () => { diff --git a/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.ts b/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.ts index 905961a458..caa3648843 100644 --- a/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.ts +++ b/projects/organization-management/src/app/components/user-profile-form/user-profile-form.component.ts @@ -3,9 +3,10 @@ import { FormGroup } from '@angular/forms'; import { FormlyFieldConfig } from '@ngx-formly/core'; import { pick } from 'lodash-es'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; + @Component({ selector: 'ish-user-profile-form', templateUrl: './user-profile-form.component.html', diff --git a/projects/organization-management/src/app/exports/index.ts b/projects/organization-management/src/app/exports/index.ts index aad4cf01a0..52b4141b9f 100644 --- a/projects/organization-management/src/app/exports/index.ts +++ b/projects/organization-management/src/app/exports/index.ts @@ -2,5 +2,6 @@ export { OrganizationManagementRoutingModule } from '../pages/organization-manag export { OrganizationManagementExportsModule } from './organization-management-exports.module'; export { OrganizationManagementBreadcrumbService } from '../services/organization-management-breadcrumb/organization-management-breadcrumb.service'; +export { UserBudget } from '../models/user-budget/user-budget.model'; export { LazyBudgetWidgetComponent } from './lazy-budget-widget/lazy-budget-widget.component'; export { LazyCostCenterWidgetComponent } from './lazy-cost-center-widget/lazy-cost-center-widget.component'; diff --git a/projects/organization-management/src/app/facades/organization-management.facade.ts b/projects/organization-management/src/app/facades/organization-management.facade.ts index d740d6bc57..c31b98b504 100644 --- a/projects/organization-management/src/app/facades/organization-management.facade.ts +++ b/projects/organization-management/src/app/facades/organization-management.facade.ts @@ -4,17 +4,20 @@ import { differenceBy } from 'lodash-es'; import { Observable, combineLatest } from 'rxjs'; import { distinctUntilChanged, filter, map, switchMap, take, withLatestFrom } from 'rxjs/operators'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { CostCenter, CostCenterBase, CostCenterBuyer } from 'ish-core/models/cost-center/cost-center.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { getUserPermissions, getUserRoles } from 'ish-core/store/customer/authorization'; import { getLoggedInUser } from 'ish-core/store/customer/user'; +import { toObservable } from 'ish-core/utils/functions'; +import { mapToProperty, whenTruthy } from 'ish-core/utils/operators'; + +import { B2bUser } from '../models/b2b-user/b2b-user.model'; +import { UserBudget } from '../models/user-budget/user-budget.model'; import { getCurrentUserBudget, getCurrentUserBudgetError, getCurrentUserBudgetLoading, loadBudget, -} from 'ish-core/store/organization-management/budget'; +} from '../store/budget'; import { addCostCenter, addCostCenterBuyers, @@ -27,7 +30,7 @@ import { loadCostCenters, updateCostCenter, updateCostCenterBuyer, -} from 'ish-core/store/organization-management/cost-centers'; +} from '../store/cost-centers'; import { addUser, deleteUser, @@ -43,9 +46,7 @@ import { setUserBudget, setUserRoles, updateUser, -} from 'ish-core/store/organization-management/users'; -import { toObservable } from 'ish-core/utils/functions'; -import { mapToProperty, whenTruthy } from 'ish-core/utils/operators'; +} from '../store/users'; /* eslint-disable @typescript-eslint/member-ordering */ @Injectable({ providedIn: 'root' }) diff --git a/projects/organization-management/src/app/guards/fetch-cost-centers.guard.ts b/projects/organization-management/src/app/guards/fetch-cost-centers.guard.ts index d7716b58f4..10d8e945bf 100644 --- a/projects/organization-management/src/app/guards/fetch-cost-centers.guard.ts +++ b/projects/organization-management/src/app/guards/fetch-cost-centers.guard.ts @@ -2,7 +2,7 @@ import { inject } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable, of } from 'rxjs'; -import { loadCostCenters } from 'ish-core/store/organization-management/cost-centers'; +import { loadCostCenters } from '../store/cost-centers'; /** * Fetch cost centers for cost center management page diff --git a/projects/organization-management/src/app/guards/fetch-users.guard.ts b/projects/organization-management/src/app/guards/fetch-users.guard.ts index b8007c2ac7..8c61263920 100644 --- a/projects/organization-management/src/app/guards/fetch-users.guard.ts +++ b/projects/organization-management/src/app/guards/fetch-users.guard.ts @@ -4,7 +4,7 @@ import { Store, select } from '@ngrx/store'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; -import { getUserCount, loadUsers } from 'ish-core/store/organization-management/users'; +import { getUserCount, loadUsers } from '../store/users'; /** * Fetch users for user management page diff --git a/src/app/core/models/b2b-role/b2b-role.interface.ts b/projects/organization-management/src/app/models/b2b-role/b2b-role.interface.ts similarity index 100% rename from src/app/core/models/b2b-role/b2b-role.interface.ts rename to projects/organization-management/src/app/models/b2b-role/b2b-role.interface.ts diff --git a/src/app/core/models/b2b-role/b2b-role.mapper.spec.ts b/projects/organization-management/src/app/models/b2b-role/b2b-role.mapper.spec.ts similarity index 100% rename from src/app/core/models/b2b-role/b2b-role.mapper.spec.ts rename to projects/organization-management/src/app/models/b2b-role/b2b-role.mapper.spec.ts diff --git a/src/app/core/models/b2b-role/b2b-role.mapper.ts b/projects/organization-management/src/app/models/b2b-role/b2b-role.mapper.ts similarity index 100% rename from src/app/core/models/b2b-role/b2b-role.mapper.ts rename to projects/organization-management/src/app/models/b2b-role/b2b-role.mapper.ts diff --git a/src/app/core/models/b2b-role/b2b-role.model.ts b/projects/organization-management/src/app/models/b2b-role/b2b-role.model.ts similarity index 100% rename from src/app/core/models/b2b-role/b2b-role.model.ts rename to projects/organization-management/src/app/models/b2b-role/b2b-role.model.ts diff --git a/projects/organization-management/src/app/models/b2b-user/b2b-user.interface.ts b/projects/organization-management/src/app/models/b2b-user/b2b-user.interface.ts new file mode 100644 index 0000000000..3be3d2efcd --- /dev/null +++ b/projects/organization-management/src/app/models/b2b-user/b2b-user.interface.ts @@ -0,0 +1,6 @@ +import { Link } from 'ish-core/models/link/link.model'; +import { UserData } from 'ish-core/models/user/user.interface'; + +export type B2bUserData = UserData & { active: boolean }; + +export type B2bUserDataLink = Link & { login: string }; diff --git a/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.spec.ts b/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.spec.ts new file mode 100644 index 0000000000..2d8a5e9558 --- /dev/null +++ b/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.spec.ts @@ -0,0 +1,104 @@ +import { Address } from 'ish-core/models/address/address.model'; +import { PaymentInstrument } from 'ish-core/models/payment-instrument/payment-instrument.model'; +import { BasketMockData } from 'ish-core/utils/dev/basket-mock-data'; + +import { B2bUserData, B2bUserDataLink } from './b2b-user.interface'; +import { B2bUserMapper } from './b2b-user.mapper'; + +describe('B2b User Mapper', () => { + describe('fromData', () => { + it(`should return User when getting UserData`, () => { + const userData = { + firstName: 'Patricia', + lastName: 'Miller', + preferredInvoiceToAddress: BasketMockData.getAddress(), + preferredShipToAddress: { urn: 'urn:1234' } as Address, + preferredPaymentInstrument: { id: '1234' } as PaymentInstrument, + preferredLanguage: 'en_US', + active: true, + } as B2bUserData; + const user = B2bUserMapper.fromData(userData); + + expect(user).toMatchInlineSnapshot(` + { + "active": true, + "birthday": undefined, + "businessPartnerNo": undefined, + "department": undefined, + "email": undefined, + "fax": undefined, + "firstName": "Patricia", + "lastName": "Miller", + "login": undefined, + "phoneBusiness": undefined, + "phoneHome": undefined, + "phoneMobile": undefined, + "preferredInvoiceToAddressUrn": "urn:address:customer:JgEKAE8BA50AAAFgDtAd1LZU:ilMKAE8BlIUAAAFgEdAd1LZU", + "preferredLanguage": "en_US", + "preferredPaymentInstrumentId": "1234", + "preferredShipToAddressUrn": "urn:1234", + "title": undefined, + } + `); + }); + }); + + describe('fromListData', () => { + it(`should return User when getting UserListData`, () => { + const userListData = [ + { + login: 'pmiller@test.intershop.de', + attributes: [ + { + name: 'roleIDs', + value: ['APP_B2B_COSTCENTER_OWNER', 'APP_B2B_BUYER'], + }, + { name: 'firstName', value: 'Patricia' }, + { name: 'lastName', value: 'Miller' }, + { name: 'active', value: true }, + { name: 'budgetPeriod', type: 'String', value: 'monthly' }, + { name: 'orderSpentLimit', type: 'MoneyRO', value: { currency: 'USD', value: 500 } }, + { name: 'budget', type: 'MoneyRO', value: { currency: 'USD', value: 10000 } }, + { name: 'remainingBudget', type: 'MoneyRO', value: { currency: 'USD', value: 8000 } }, + { name: 'spentBudget', type: 'MoneyRO', value: { currency: 'USD', value: 2000 } }, + ], + } as B2bUserDataLink, + ]; + const users = B2bUserMapper.fromListData(userListData); + + expect(users).toMatchInlineSnapshot(` + [ + { + "active": true, + "firstName": "Patricia", + "lastName": "Miller", + "login": "pmiller@test.intershop.de", + "roleIDs": [ + "APP_B2B_COSTCENTER_OWNER", + "APP_B2B_BUYER", + ], + "userBudget": { + "budget": { + "currency": "USD", + "value": 10000, + }, + "budgetPeriod": "monthly", + "orderSpentLimit": { + "currency": "USD", + "value": 500, + }, + "remainingBudget": { + "currency": "USD", + "value": 8000, + }, + "spentBudget": { + "currency": "USD", + "value": 2000, + }, + }, + }, + ] + `); + }); + }); +}); diff --git a/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.ts b/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.ts new file mode 100644 index 0000000000..b116919544 --- /dev/null +++ b/projects/organization-management/src/app/models/b2b-user/b2b-user.mapper.ts @@ -0,0 +1,35 @@ +import { AttributeHelper } from 'ish-core/models/attribute/attribute.helper'; +import { UserMapper } from 'ish-core/models/user/user.mapper'; + +import { B2bUserData, B2bUserDataLink } from './b2b-user.interface'; +import { B2bUser } from './b2b-user.model'; + +export class B2bUserMapper { + static fromData(user: B2bUserData): B2bUser { + return { ...UserMapper.fromData(user), active: user.active }; + } + + static fromListData(data: B2bUserDataLink[]): B2bUser[] { + if (data) { + return data.map(e => ({ + login: e.login, + firstName: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'firstName'), + lastName: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'lastName'), + roleIDs: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'roleIDs'), + active: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'active'), + userBudget: { + orderSpentLimit: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'orderSpentLimit'), + budget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budget'), + remainingBudget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'remainingBudget'), + budgetPeriod: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budgetPeriod'), + spentBudget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'spentBudget') || { + ...AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budget'), + value: 0, + }, + }, + })); + } else { + throw new Error('data is required'); + } + } +} diff --git a/projects/organization-management/src/app/models/b2b-user/b2b-user.model.ts b/projects/organization-management/src/app/models/b2b-user/b2b-user.model.ts new file mode 100644 index 0000000000..e994c2f496 --- /dev/null +++ b/projects/organization-management/src/app/models/b2b-user/b2b-user.model.ts @@ -0,0 +1,9 @@ +import { User } from 'ish-core/models/user/user.model'; + +import { UserBudget } from '../user-budget/user-budget.model'; + +export interface B2bUser extends Partial { + roleIDs?: string[]; + active?: boolean; + userBudget?: UserBudget; +} diff --git a/src/app/core/models/user-budget/user-budget.model.ts b/projects/organization-management/src/app/models/user-budget/user-budget.model.ts similarity index 100% rename from src/app/core/models/user-budget/user-budget.model.ts rename to projects/organization-management/src/app/models/user-budget/user-budget.model.ts diff --git a/projects/organization-management/src/app/organization-management.module.ts b/projects/organization-management/src/app/organization-management.module.ts index 782a26fbaf..54f2442070 100644 --- a/projects/organization-management/src/app/organization-management.module.ts +++ b/projects/organization-management/src/app/organization-management.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; import { SharedModule } from 'ish-shared/shared.module'; import { BudgetWidgetComponent } from './components/budget-widget/budget-widget.component'; @@ -13,6 +12,7 @@ import { UserBudgetFormComponent } from './components/user-budget-form/user-budg import { UserBudgetComponent } from './components/user-budget/user-budget.component'; import { UserProfileFormComponent } from './components/user-profile-form/user-profile-form.component'; import { UserRolesSelectionComponent } from './components/user-roles-selection/user-roles-selection.component'; +import { OrganizationManagementStoreModule } from './store/organization-management-store.module'; const exportedComponents = [ CostCenterBudgetComponent, diff --git a/projects/organization-management/src/app/pages/cost-center-buyers/cost-center-buyers-page.component.ts b/projects/organization-management/src/app/pages/cost-center-buyers/cost-center-buyers-page.component.ts index 557cedfaf1..a6e778c634 100644 --- a/projects/organization-management/src/app/pages/cost-center-buyers/cost-center-buyers-page.component.ts +++ b/projects/organization-management/src/app/pages/cost-center-buyers/cost-center-buyers-page.component.ts @@ -7,7 +7,6 @@ import { Observable, merge } from 'rxjs'; import { take, withLatestFrom } from 'rxjs/operators'; import { AppFacade } from 'ish-core/facades/app.facade'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { CostCenterBuyer } from 'ish-core/models/cost-center/cost-center.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { PriceHelper } from 'ish-core/models/price/price.model'; @@ -15,6 +14,7 @@ import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils'; import { FormsService } from 'ish-shared/forms/utils/forms.service'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; /** * The Cost Center Buyers Page Component displays all the users that are not yet assigned to this cost center. The user can enter user budgets and add these users to the cost center. diff --git a/projects/organization-management/src/app/pages/user-create/user-create-page.component.ts b/projects/organization-management/src/app/pages/user-create/user-create-page.component.ts index bf789885b7..c3311a23f3 100644 --- a/projects/organization-management/src/app/pages/user-create/user-create-page.component.ts +++ b/projects/organization-management/src/app/pages/user-create/user-create-page.component.ts @@ -3,11 +3,11 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { v4 as uuid } from 'uuid'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; @Component({ selector: 'ish-user-create-page', diff --git a/projects/organization-management/src/app/pages/user-detail/user-detail-budget/user-detail-budget.component.ts b/projects/organization-management/src/app/pages/user-detail/user-detail-budget/user-detail-budget.component.ts index 484ad981ba..2e9a2a4b73 100644 --- a/projects/organization-management/src/app/pages/user-detail/user-detail-budget/user-detail-budget.component.ts +++ b/projects/organization-management/src/app/pages/user-detail/user-detail-budget/user-detail-budget.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; +import { UserBudget } from '../../../models/user-budget/user-budget.model'; /** * displays the user budget and the appropriate budget bar diff --git a/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.spec.ts b/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.spec.ts index 35cdbdc7c5..ab5f39fbb3 100644 --- a/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.spec.ts +++ b/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.spec.ts @@ -5,11 +5,11 @@ import { MockComponent, MockPipe } from 'ng-mocks'; import { of } from 'rxjs'; import { anything, instance, mock, when } from 'ts-mockito'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { ServerSettingPipe } from 'ish-core/pipes/server-setting.pipe'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bRole } from '../../models/b2b-role/b2b-role.model'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { UserDetailPageComponent } from './user-detail-page.component'; diff --git a/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.ts b/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.ts index 02022178ca..33c7a52dee 100644 --- a/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.ts +++ b/projects/organization-management/src/app/pages/user-detail/user-detail-page.component.ts @@ -1,11 +1,11 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { mapToProperty, whenTruthy } from 'ish-core/utils/operators'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bRole } from '../../models/b2b-role/b2b-role.model'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; @Component({ selector: 'ish-user-detail-page', diff --git a/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.spec.ts b/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.spec.ts index 66f8943a23..cd2487f5f2 100644 --- a/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.spec.ts +++ b/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.spec.ts @@ -4,11 +4,11 @@ import { MockComponent, MockPipe } from 'ng-mocks'; import { of } from 'rxjs'; import { anything, instance, mock, when } from 'ts-mockito'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { ServerSettingPipe } from 'ish-core/pipes/server-setting.pipe'; import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { UserEditBudgetPageComponent } from './user-edit-budget-page.component'; diff --git a/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.ts b/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.ts index 287e3b1b2f..2ef7e241a1 100644 --- a/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.ts +++ b/projects/organization-management/src/app/pages/user-edit-budget/user-edit-budget-page.component.ts @@ -2,12 +2,12 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; @Component({ selector: 'ish-user-edit-budget-page', diff --git a/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.spec.ts b/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.spec.ts index 7961e3a642..6566e83fe2 100644 --- a/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.spec.ts +++ b/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.spec.ts @@ -5,10 +5,9 @@ import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { instance, mock, when } from 'ts-mockito'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; - import { UserProfileFormComponent } from '../../components/user-profile-form/user-profile-form.component'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { UserEditProfilePageComponent } from './user-edit-profile-page.component'; diff --git a/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.ts b/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.ts index 073c21ab1a..d6e1a1e564 100644 --- a/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.ts +++ b/projects/organization-management/src/app/pages/user-edit-profile/user-edit-profile-page.component.ts @@ -2,11 +2,11 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { markAsDirtyRecursive } from 'ish-shared/forms/utils/form-utils'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; @Component({ selector: 'ish-user-edit-profile-page', diff --git a/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.spec.ts b/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.spec.ts index 9eacc6ec7b..680d68d301 100644 --- a/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.spec.ts +++ b/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.spec.ts @@ -6,12 +6,12 @@ import { of } from 'rxjs'; import { instance, mock, when } from 'ts-mockito'; import { AccountFacade } from 'ish-core/facades/account.facade'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { User } from 'ish-core/models/user/user.model'; import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; import { UserRolesSelectionComponent } from '../../components/user-roles-selection/user-roles-selection.component'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { UserEditRolesPageComponent } from './user-edit-roles-page.component'; diff --git a/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.ts b/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.ts index 6d4d315101..2a4fd40055 100644 --- a/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.ts +++ b/projects/organization-management/src/app/pages/user-edit-roles/user-edit-roles-page.component.ts @@ -5,11 +5,11 @@ import { Observable, combineLatest, of } from 'rxjs'; import { map, shareReplay, switchMap, take } from 'rxjs/operators'; import { AccountFacade } from 'ish-core/facades/account.facade'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { whenTruthy } from 'ish-core/utils/operators'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; @Component({ selector: 'ish-user-edit-roles-page', diff --git a/projects/organization-management/src/app/pages/users/user-roles-badges/user-roles-badges.component.ts b/projects/organization-management/src/app/pages/users/user-roles-badges/user-roles-badges.component.ts index 5a4c651d7e..543903e424 100644 --- a/projects/organization-management/src/app/pages/users/user-roles-badges/user-roles-badges.component.ts +++ b/projects/organization-management/src/app/pages/users/user-roles-badges/user-roles-badges.component.ts @@ -1,9 +1,8 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { Observable } from 'rxjs'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; - import { OrganizationManagementFacade } from '../../../facades/organization-management.facade'; +import { B2bRole } from '../../../models/b2b-role/b2b-role.model'; @Component({ selector: 'ish-user-roles-badges', diff --git a/projects/organization-management/src/app/pages/users/users-page.component.spec.ts b/projects/organization-management/src/app/pages/users/users-page.component.spec.ts index 671653aa52..9e6a4c6dd0 100644 --- a/projects/organization-management/src/app/pages/users/users-page.component.spec.ts +++ b/projects/organization-management/src/app/pages/users/users-page.component.spec.ts @@ -7,13 +7,13 @@ import { of } from 'rxjs'; import { instance, mock, when } from 'ts-mockito'; import { AccountFacade } from 'ish-core/facades/account.facade'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { ServerSettingPipe } from 'ish-core/pipes/server-setting.pipe'; import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; import { LoadingComponent } from 'ish-shared/components/common/loading/loading.component'; import { ModalDialogComponent } from 'ish-shared/components/common/modal-dialog/modal-dialog.component'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { UserRolesBadgesComponent } from './user-roles-badges/user-roles-badges.component'; import { UsersPageComponent } from './users-page.component'; diff --git a/projects/organization-management/src/app/pages/users/users-page.component.ts b/projects/organization-management/src/app/pages/users/users-page.component.ts index c50ce1cfa0..a0e0fc17ae 100644 --- a/projects/organization-management/src/app/pages/users/users-page.component.ts +++ b/projects/organization-management/src/app/pages/users/users-page.component.ts @@ -2,11 +2,11 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { AccountFacade } from 'ish-core/facades/account.facade'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { User } from 'ish-core/models/user/user.model'; import { OrganizationManagementFacade } from '../../facades/organization-management.facade'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; @Component({ selector: 'ish-users-page', diff --git a/src/app/core/services/cost-centers/cost-centers.service.spec.ts b/projects/organization-management/src/app/services/cost-centers/cost-centers.service.spec.ts similarity index 100% rename from src/app/core/services/cost-centers/cost-centers.service.spec.ts rename to projects/organization-management/src/app/services/cost-centers/cost-centers.service.spec.ts diff --git a/src/app/core/services/cost-centers/cost-centers.service.ts b/projects/organization-management/src/app/services/cost-centers/cost-centers.service.ts similarity index 100% rename from src/app/core/services/cost-centers/cost-centers.service.ts rename to projects/organization-management/src/app/services/cost-centers/cost-centers.service.ts diff --git a/projects/organization-management/src/app/services/organization-management-breadcrumb/organization-management-breadcrumb.service.spec.ts b/projects/organization-management/src/app/services/organization-management-breadcrumb/organization-management-breadcrumb.service.spec.ts index feb8103c39..bdd328c2b6 100644 --- a/projects/organization-management/src/app/services/organization-management-breadcrumb/organization-management-breadcrumb.service.spec.ts +++ b/projects/organization-management/src/app/services/organization-management-breadcrumb/organization-management-breadcrumb.service.spec.ts @@ -7,14 +7,14 @@ import { TranslateModule } from '@ngx-translate/core'; import { AuthorizationToggleModule } from 'ish-core/authorization-toggle.module'; import { FeatureToggleModule } from 'ish-core/feature-toggle.module'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { CostCenter } from 'ish-core/models/cost-center/cost-center.model'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { loadCostCenterSuccess } from 'ish-core/store/organization-management/cost-centers/cost-centers.actions'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; -import { loadUserSuccess } from 'ish-core/store/organization-management/users/users.actions'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; import { routes } from '../../pages/organization-management-routing.module'; +import { loadCostCenterSuccess } from '../../store/cost-centers'; +import { OrganizationManagementStoreModule } from '../../store/organization-management-store.module'; +import { loadUserSuccess } from '../../store/users'; import { OrganizationManagementBreadcrumbService } from './organization-management-breadcrumb.service'; diff --git a/src/app/core/services/users/users.service.spec.ts b/projects/organization-management/src/app/services/users/users.service.spec.ts similarity index 96% rename from src/app/core/services/users/users.service.spec.ts rename to projects/organization-management/src/app/services/users/users.service.spec.ts index d66aa3b3b7..71f40f7636 100644 --- a/src/app/core/services/users/users.service.spec.ts +++ b/projects/organization-management/src/app/services/users/users.service.spec.ts @@ -4,14 +4,15 @@ import { of } from 'rxjs'; import { anyString, anything, capture, instance, mock, verify, when } from 'ts-mockito'; import { AppFacade } from 'ish-core/facades/app.facade'; -import { B2bRoleData } from 'ish-core/models/b2b-role/b2b-role.interface'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { Customer } from 'ish-core/models/customer/customer.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { ApiService } from 'ish-core/services/api/api.service'; import { getLoggedInCustomer } from 'ish-core/store/customer/user'; import { encodeResourceID } from 'ish-core/utils/url-resource-ids'; +import { B2bRoleData } from '../../models/b2b-role/b2b-role.interface'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + import { UsersService } from './users.service'; describe('Users Service', () => { diff --git a/src/app/core/services/users/users.service.ts b/projects/organization-management/src/app/services/users/users.service.ts similarity index 94% rename from src/app/core/services/users/users.service.ts rename to projects/organization-management/src/app/services/users/users.service.ts index 64e079af72..43af746051 100644 --- a/src/app/core/services/users/users.service.ts +++ b/projects/organization-management/src/app/services/users/users.service.ts @@ -4,18 +4,19 @@ import { Observable, forkJoin, of, throwError } from 'rxjs'; import { concatMap, map, switchMap, take, withLatestFrom } from 'rxjs/operators'; import { AppFacade } from 'ish-core/facades/app.facade'; -import { B2bRoleData } from 'ish-core/models/b2b-role/b2b-role.interface'; -import { B2bRoleMapper } from 'ish-core/models/b2b-role/b2b-role.mapper'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; -import { B2bUserMapper } from 'ish-core/models/b2b-user/b2b-user.mapper'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { PriceHelper } from 'ish-core/models/price/price.helper'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { ApiService, unpackEnvelope } from 'ish-core/services/api/api.service'; import { getLoggedInCustomer } from 'ish-core/store/customer/user'; import { whenTruthy } from 'ish-core/utils/operators'; import { encodeResourceID } from 'ish-core/utils/url-resource-ids'; +import { B2bRoleData } from '../../models/b2b-role/b2b-role.interface'; +import { B2bRoleMapper } from '../../models/b2b-role/b2b-role.mapper'; +import { B2bRole } from '../../models/b2b-role/b2b-role.model'; +import { B2bUserMapper } from '../../models/b2b-user/b2b-user.mapper'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + @Injectable({ providedIn: 'root' }) export class UsersService { constructor( diff --git a/src/app/core/store/organization-management/budget/budget.actions.ts b/projects/organization-management/src/app/store/budget/budget.actions.ts similarity index 83% rename from src/app/core/store/organization-management/budget/budget.actions.ts rename to projects/organization-management/src/app/store/budget/budget.actions.ts index e06c2b93fe..c2462c1eab 100644 --- a/src/app/core/store/organization-management/budget/budget.actions.ts +++ b/projects/organization-management/src/app/store/budget/budget.actions.ts @@ -1,8 +1,9 @@ import { createAction } from '@ngrx/store'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { httpError, payload } from 'ish-core/utils/ngrx-creators'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + export const loadBudget = createAction('[Budget] Load Budget'); export const loadBudgetSuccess = createAction('[Budget API] Load Budget Success', payload<{ budget: UserBudget }>()); diff --git a/src/app/core/store/organization-management/budget/budget.effects.spec.ts b/projects/organization-management/src/app/store/budget/budget.effects.spec.ts similarity index 97% rename from src/app/core/store/organization-management/budget/budget.effects.spec.ts rename to projects/organization-management/src/app/store/budget/budget.effects.spec.ts index a931f633ac..c947ef79d7 100644 --- a/src/app/core/store/organization-management/budget/budget.effects.spec.ts +++ b/projects/organization-management/src/app/store/budget/budget.effects.spec.ts @@ -6,9 +6,10 @@ import { Observable, of, throwError } from 'rxjs'; import { instance, mock, verify, when } from 'ts-mockito'; import { Price } from 'ish-core/models/price/price.model'; -import { UsersService } from 'ish-core/services/users/users.service'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { UsersService } from '../../services/users/users.service'; + import { loadBudget, loadBudgetSuccess } from './budget.actions'; import { BudgetEffects } from './budget.effects'; diff --git a/src/app/core/store/organization-management/budget/budget.effects.ts b/projects/organization-management/src/app/store/budget/budget.effects.ts similarity index 91% rename from src/app/core/store/organization-management/budget/budget.effects.ts rename to projects/organization-management/src/app/store/budget/budget.effects.ts index 87db0f7333..3e38377edd 100644 --- a/src/app/core/store/organization-management/budget/budget.effects.ts +++ b/projects/organization-management/src/app/store/budget/budget.effects.ts @@ -2,9 +2,10 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { map, switchMap } from 'rxjs/operators'; -import { UsersService } from 'ish-core/services/users/users.service'; import { mapErrorToAction } from 'ish-core/utils/operators'; +import { UsersService } from '../../services/users/users.service'; + import { loadBudget, loadBudgetFail, loadBudgetSuccess } from './budget.actions'; @Injectable() diff --git a/src/app/core/store/organization-management/budget/budget.reducer.ts b/projects/organization-management/src/app/store/budget/budget.reducer.ts similarity index 91% rename from src/app/core/store/organization-management/budget/budget.reducer.ts rename to projects/organization-management/src/app/store/budget/budget.reducer.ts index a51ffb326d..83facf8c33 100644 --- a/src/app/core/store/organization-management/budget/budget.reducer.ts +++ b/projects/organization-management/src/app/store/budget/budget.reducer.ts @@ -1,9 +1,10 @@ import { createReducer, on } from '@ngrx/store'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { setErrorOn, setLoadingOn, unsetLoadingAndErrorOn } from 'ish-core/utils/ngrx-creators'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + import { loadBudget, loadBudgetFail, loadBudgetSuccess } from './budget.actions'; export interface BudgetState { diff --git a/src/app/core/store/organization-management/budget/budget.selectors.spec.ts b/projects/organization-management/src/app/store/budget/budget.selectors.spec.ts similarity index 94% rename from src/app/core/store/organization-management/budget/budget.selectors.spec.ts rename to projects/organization-management/src/app/store/budget/budget.selectors.spec.ts index 7adedf50cf..d2c6394f2d 100644 --- a/src/app/core/store/organization-management/budget/budget.selectors.spec.ts +++ b/projects/organization-management/src/app/store/budget/budget.selectors.spec.ts @@ -2,10 +2,11 @@ import { TestBed } from '@angular/core/testing'; import { Price } from 'ish-core/models/price/price.model'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; +import { OrganizationManagementStoreModule } from '../organization-management-store.module'; + import { loadBudget, loadBudgetFail, loadBudgetSuccess } from './budget.actions'; import { getCurrentUserBudget, getCurrentUserBudgetError, getCurrentUserBudgetLoading } from './budget.selectors'; diff --git a/src/app/core/store/organization-management/budget/budget.selectors.ts b/projects/organization-management/src/app/store/budget/budget.selectors.ts similarity index 78% rename from src/app/core/store/organization-management/budget/budget.selectors.ts rename to projects/organization-management/src/app/store/budget/budget.selectors.ts index bc7fd645e1..9f134d1322 100644 --- a/src/app/core/store/organization-management/budget/budget.selectors.ts +++ b/projects/organization-management/src/app/store/budget/budget.selectors.ts @@ -1,6 +1,6 @@ import { createSelector } from '@ngrx/store'; -import { getOrganizationManagementState } from 'ish-core/store/organization-management/organization-management-store'; +import { getOrganizationManagementState } from '../organization-management-store'; const getBudgetState = createSelector(getOrganizationManagementState, state => state.budget); diff --git a/src/app/core/store/organization-management/budget/index.ts b/projects/organization-management/src/app/store/budget/index.ts similarity index 100% rename from src/app/core/store/organization-management/budget/index.ts rename to projects/organization-management/src/app/store/budget/index.ts diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.actions.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.actions.ts similarity index 100% rename from src/app/core/store/organization-management/cost-centers/cost-centers.actions.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.actions.ts diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.effects.spec.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.effects.spec.ts similarity index 99% rename from src/app/core/store/organization-management/cost-centers/cost-centers.effects.spec.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.effects.spec.ts index 77f26d9a1f..d0a4cbbed1 100644 --- a/src/app/core/store/organization-management/cost-centers/cost-centers.effects.spec.ts +++ b/projects/organization-management/src/app/store/cost-centers/cost-centers.effects.spec.ts @@ -10,10 +10,11 @@ import { toArray } from 'rxjs/operators'; import { anyString, anything, instance, mock, verify, when } from 'ts-mockito'; import { CostCenter, CostCenterBase, CostCenterBuyer } from 'ish-core/models/cost-center/cost-center.model'; -import { CostCentersService } from 'ish-core/services/cost-centers/cost-centers.service'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { CostCentersService } from '../../services/cost-centers/cost-centers.service'; + import { addCostCenter, addCostCenterBuyers, diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.effects.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.effects.ts similarity index 98% rename from src/app/core/store/organization-management/cost-centers/cost-centers.effects.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.effects.ts index 167cff23c5..9140c425b4 100644 --- a/src/app/core/store/organization-management/cost-centers/cost-centers.effects.ts +++ b/projects/organization-management/src/app/store/cost-centers/cost-centers.effects.ts @@ -5,11 +5,12 @@ import { Store, select } from '@ngrx/store'; import { from } from 'rxjs'; import { concatMap, exhaustMap, map, mergeMap } from 'rxjs/operators'; -import { CostCentersService } from 'ish-core/services/cost-centers/cost-centers.service'; import { displaySuccessMessage } from 'ish-core/store/core/messages/messages.actions'; import { selectRouteParam } from 'ish-core/store/core/router'; import { mapErrorToAction, mapToPayload, mapToPayloadProperty, whenTruthy } from 'ish-core/utils/operators'; +import { CostCentersService } from '../../services/cost-centers/cost-centers.service'; + import { addCostCenter, addCostCenterBuyers, diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.reducer.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.reducer.ts similarity index 100% rename from src/app/core/store/organization-management/cost-centers/cost-centers.reducer.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.reducer.ts diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.selectors.spec.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.spec.ts similarity index 99% rename from src/app/core/store/organization-management/cost-centers/cost-centers.selectors.spec.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.spec.ts index ebab9c477c..37262b6914 100644 --- a/src/app/core/store/organization-management/cost-centers/cost-centers.selectors.spec.ts +++ b/projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.spec.ts @@ -4,10 +4,11 @@ import { RouterTestingModule } from '@angular/router/testing'; import { CostCenter, CostCenterBase, CostCenterBuyer } from 'ish-core/models/cost-center/cost-center.model'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; +import { OrganizationManagementStoreModule } from '../organization-management-store.module'; + import { addCostCenter, addCostCenterBuyers, diff --git a/src/app/core/store/organization-management/cost-centers/cost-centers.selectors.ts b/projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.ts similarity index 86% rename from src/app/core/store/organization-management/cost-centers/cost-centers.selectors.ts rename to projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.ts index c5af933401..d5650eb53d 100644 --- a/src/app/core/store/organization-management/cost-centers/cost-centers.selectors.ts +++ b/projects/organization-management/src/app/store/cost-centers/cost-centers.selectors.ts @@ -1,7 +1,8 @@ import { createSelector } from '@ngrx/store'; import { selectRouteParam } from 'ish-core/store/core/router'; -import { getOrganizationManagementState } from 'ish-core/store/organization-management/organization-management-store'; + +import { getOrganizationManagementState } from '../organization-management-store'; import { costCentersAdapter } from './cost-centers.reducer'; diff --git a/src/app/core/store/organization-management/cost-centers/index.ts b/projects/organization-management/src/app/store/cost-centers/index.ts similarity index 100% rename from src/app/core/store/organization-management/cost-centers/index.ts rename to projects/organization-management/src/app/store/cost-centers/index.ts diff --git a/src/app/core/store/organization-management/organization-management-store.module.ts b/projects/organization-management/src/app/store/organization-management-store.module.ts similarity index 100% rename from src/app/core/store/organization-management/organization-management-store.module.ts rename to projects/organization-management/src/app/store/organization-management-store.module.ts diff --git a/src/app/core/store/organization-management/organization-management-store.ts b/projects/organization-management/src/app/store/organization-management-store.ts similarity index 100% rename from src/app/core/store/organization-management/organization-management-store.ts rename to projects/organization-management/src/app/store/organization-management-store.ts diff --git a/src/app/core/store/organization-management/users/index.ts b/projects/organization-management/src/app/store/users/index.ts similarity index 100% rename from src/app/core/store/organization-management/users/index.ts rename to projects/organization-management/src/app/store/users/index.ts diff --git a/src/app/core/store/organization-management/users/users.actions.ts b/projects/organization-management/src/app/store/users/users.actions.ts similarity index 91% rename from src/app/core/store/organization-management/users/users.actions.ts rename to projects/organization-management/src/app/store/users/users.actions.ts index 79aa316995..5d1ad5cbdd 100644 --- a/src/app/core/store/organization-management/users/users.actions.ts +++ b/projects/organization-management/src/app/store/users/users.actions.ts @@ -1,10 +1,11 @@ import { createAction } from '@ngrx/store'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { httpError, payload } from 'ish-core/utils/ngrx-creators'; +import { B2bRole } from '../../models/b2b-role/b2b-role.model'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; +import { UserBudget } from '../../models/user-budget/user-budget.model'; + export const loadUsers = createAction('[Users] Load Users'); export const loadUsersFail = createAction('[Users API] Load Users Fail', httpError()); diff --git a/src/app/core/store/organization-management/users/users.effects.spec.ts b/projects/organization-management/src/app/store/users/users.effects.spec.ts similarity index 97% rename from src/app/core/store/organization-management/users/users.effects.spec.ts rename to projects/organization-management/src/app/store/users/users.effects.spec.ts index daa4309c2a..662f4e8818 100644 --- a/src/app/core/store/organization-management/users/users.effects.spec.ts +++ b/projects/organization-management/src/app/store/users/users.effects.spec.ts @@ -9,13 +9,14 @@ import { Observable, of, throwError } from 'rxjs'; import { toArray } from 'rxjs/operators'; import { anyString, anything, instance, mock, verify, when } from 'ts-mockito'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; -import { UsersService } from 'ish-core/services/users/users.service'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; import { displaySuccessMessage } from 'ish-core/store/core/messages'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; +import { UsersService } from '../../services/users/users.service'; +import { OrganizationManagementStoreModule } from '../organization-management-store.module'; + import { addUser, addUserFail, diff --git a/src/app/core/store/organization-management/users/users.effects.ts b/projects/organization-management/src/app/store/users/users.effects.ts similarity index 95% rename from src/app/core/store/organization-management/users/users.effects.ts rename to projects/organization-management/src/app/store/users/users.effects.ts index b8e68d9c3f..f30098b664 100644 --- a/src/app/core/store/organization-management/users/users.effects.ts +++ b/projects/organization-management/src/app/store/users/users.effects.ts @@ -5,13 +5,14 @@ import { Store, select } from '@ngrx/store'; import { from } from 'rxjs'; import { concatMap, exhaustMap, filter, map, mergeMap, switchMap } from 'rxjs/operators'; -import { UsersService } from 'ish-core/services/users/users.service'; import { displaySuccessMessage } from 'ish-core/store/core/messages'; import { selectPath, selectRouteParam } from 'ish-core/store/core/router'; import { loadRolesAndPermissions } from 'ish-core/store/customer/authorization'; -import { getLoggedInUser, loadCompanyUser, loadCompanyUserSuccess } from 'ish-core/store/customer/user'; +import { getLoggedInUser, loadCompanyUser } from 'ish-core/store/customer/user'; import { mapErrorToAction, mapToPayload, mapToPayloadProperty, whenTruthy } from 'ish-core/utils/operators'; +import { UsersService } from '../../services/users/users.service'; + import { addUser, addUserFail, @@ -46,13 +47,6 @@ export class UsersEffects { private router: Router ) {} - triggerLoading$ = createEffect(() => - this.actions$.pipe( - ofType(loadCompanyUserSuccess), - map(() => loadUsers()) - ) - ); - loadUsers$ = createEffect(() => this.actions$.pipe( ofType(loadUsers), diff --git a/src/app/core/store/organization-management/users/users.reducer.ts b/projects/organization-management/src/app/store/users/users.reducer.ts similarity index 95% rename from src/app/core/store/organization-management/users/users.reducer.ts rename to projects/organization-management/src/app/store/users/users.reducer.ts index 99bc669a52..58fa0e2b90 100644 --- a/src/app/core/store/organization-management/users/users.reducer.ts +++ b/projects/organization-management/src/app/store/users/users.reducer.ts @@ -1,11 +1,12 @@ import { EntityState, createEntityAdapter } from '@ngrx/entity'; import { createReducer, on } from '@ngrx/store'; -import { B2bRole } from 'ish-core/models/b2b-role/b2b-role.model'; -import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { setErrorOn, setLoadingOn, unsetLoadingAndErrorOn } from 'ish-core/utils/ngrx-creators'; +import { B2bRole } from '../../models/b2b-role/b2b-role.model'; +import { B2bUser } from '../../models/b2b-user/b2b-user.model'; + import { addUser, addUserFail, diff --git a/src/app/core/store/organization-management/users/users.selectors.spec.ts b/projects/organization-management/src/app/store/users/users.selectors.spec.ts similarity index 98% rename from src/app/core/store/organization-management/users/users.selectors.spec.ts rename to projects/organization-management/src/app/store/users/users.selectors.spec.ts index aba75779f7..8c1044f216 100644 --- a/src/app/core/store/organization-management/users/users.selectors.spec.ts +++ b/projects/organization-management/src/app/store/users/users.selectors.spec.ts @@ -4,10 +4,11 @@ import { RouterTestingModule } from '@angular/router/testing'; import { User } from 'ish-core/models/user/user.model'; import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { OrganizationManagementStoreModule } from 'ish-core/store/organization-management/organization-management-store.module'; import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; +import { OrganizationManagementStoreModule } from '../organization-management-store.module'; + import { loadSystemUserRolesSuccess, loadUsers, loadUsersFail, loadUsersSuccess } from './users.actions'; import { getCostCenterManagers, diff --git a/src/app/core/store/organization-management/users/users.selectors.ts b/projects/organization-management/src/app/store/users/users.selectors.ts similarity index 92% rename from src/app/core/store/organization-management/users/users.selectors.ts rename to projects/organization-management/src/app/store/users/users.selectors.ts index 3e7093d13e..db2df73a4a 100644 --- a/src/app/core/store/organization-management/users/users.selectors.ts +++ b/projects/organization-management/src/app/store/users/users.selectors.ts @@ -1,7 +1,8 @@ import { createSelector } from '@ngrx/store'; import { selectRouteParam } from 'ish-core/store/core/router'; -import { getOrganizationManagementState } from 'ish-core/store/organization-management/organization-management-store'; + +import { getOrganizationManagementState } from '../organization-management-store'; import { usersAdapter } from './users.reducer'; diff --git a/projects/requisition-management/src/app/models/requisition/requisition.model.ts b/projects/requisition-management/src/app/models/requisition/requisition.model.ts index 8518829671..8cbf85b392 100644 --- a/projects/requisition-management/src/app/models/requisition/requisition.model.ts +++ b/projects/requisition-management/src/app/models/requisition/requisition.model.ts @@ -1,9 +1,10 @@ +import { UserBudget } from 'organization-management'; + import { BasketApprover } from 'ish-core/models/basket-approval/basket-approval.model'; import { AbstractBasket } from 'ish-core/models/basket/basket.model'; import { CostCenter } from 'ish-core/models/cost-center/cost-center.model'; import { LineItem } from 'ish-core/models/line-item/line-item.model'; import { Price } from 'ish-core/models/price/price.model'; -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; export type RequisitionStatus = 'PENDING' | 'APPROVED' | 'REJECTED'; diff --git a/src/app/core/facades/account.facade.ts b/src/app/core/facades/account.facade.ts index 6b2bacff6c..f3d92a4160 100644 --- a/src/app/core/facades/account.facade.ts +++ b/src/app/core/facades/account.facade.ts @@ -74,7 +74,7 @@ import { updateUserPreferredPayment, userNewsletterActions, } from 'ish-core/store/customer/user'; -import { getUsers } from 'ish-core/store/organization-management/users'; +import { getUsers } from 'ish-core/store/customer/users'; import { whenTruthy } from 'ish-core/utils/operators'; /* eslint-disable @typescript-eslint/member-ordering */ diff --git a/src/app/core/models/b2b-user/b2b-user.interface.ts b/src/app/core/models/b2b-user/b2b-user.interface.ts index 3be3d2efcd..bf4795d6a8 100644 --- a/src/app/core/models/b2b-user/b2b-user.interface.ts +++ b/src/app/core/models/b2b-user/b2b-user.interface.ts @@ -1,6 +1,3 @@ import { Link } from 'ish-core/models/link/link.model'; -import { UserData } from 'ish-core/models/user/user.interface'; - -export type B2bUserData = UserData & { active: boolean }; export type B2bUserDataLink = Link & { login: string }; diff --git a/src/app/core/models/b2b-user/b2b-user.mapper.spec.ts b/src/app/core/models/b2b-user/b2b-user.mapper.spec.ts index 28a6436a67..073eed3c2c 100644 --- a/src/app/core/models/b2b-user/b2b-user.mapper.spec.ts +++ b/src/app/core/models/b2b-user/b2b-user.mapper.spec.ts @@ -1,48 +1,7 @@ -import { Address } from 'ish-core/models/address/address.model'; -import { PaymentInstrument } from 'ish-core/models/payment-instrument/payment-instrument.model'; -import { BasketMockData } from 'ish-core/utils/dev/basket-mock-data'; - -import { B2bUserData, B2bUserDataLink } from './b2b-user.interface'; +import { B2bUserDataLink } from './b2b-user.interface'; import { B2bUserMapper } from './b2b-user.mapper'; describe('B2b User Mapper', () => { - describe('fromData', () => { - it(`should return User when getting UserData`, () => { - const userData = { - firstName: 'Patricia', - lastName: 'Miller', - preferredInvoiceToAddress: BasketMockData.getAddress(), - preferredShipToAddress: { urn: 'urn:1234' } as Address, - preferredPaymentInstrument: { id: '1234' } as PaymentInstrument, - preferredLanguage: 'en_US', - active: true, - } as B2bUserData; - const user = B2bUserMapper.fromData(userData); - - expect(user).toMatchInlineSnapshot(` - { - "active": true, - "birthday": undefined, - "businessPartnerNo": undefined, - "department": undefined, - "email": undefined, - "fax": undefined, - "firstName": "Patricia", - "lastName": "Miller", - "login": undefined, - "phoneBusiness": undefined, - "phoneHome": undefined, - "phoneMobile": undefined, - "preferredInvoiceToAddressUrn": "urn:address:customer:JgEKAE8BA50AAAFgDtAd1LZU:ilMKAE8BlIUAAAFgEdAd1LZU", - "preferredLanguage": "en_US", - "preferredPaymentInstrumentId": "1234", - "preferredShipToAddressUrn": "urn:1234", - "title": undefined, - } - `); - }); - }); - describe('fromListData', () => { it(`should return User when getting UserListData`, () => { const userListData = [ @@ -78,25 +37,6 @@ describe('B2b User Mapper', () => { "APP_B2B_COSTCENTER_OWNER", "APP_B2B_BUYER", ], - "userBudget": { - "budget": { - "currency": "USD", - "value": 10000, - }, - "budgetPeriod": "monthly", - "orderSpentLimit": { - "currency": "USD", - "value": 500, - }, - "remainingBudget": { - "currency": "USD", - "value": 8000, - }, - "spentBudget": { - "currency": "USD", - "value": 2000, - }, - }, }, ] `); diff --git a/src/app/core/models/b2b-user/b2b-user.mapper.ts b/src/app/core/models/b2b-user/b2b-user.mapper.ts index 37e43afeda..5195d5e102 100644 --- a/src/app/core/models/b2b-user/b2b-user.mapper.ts +++ b/src/app/core/models/b2b-user/b2b-user.mapper.ts @@ -1,33 +1,18 @@ import { AttributeHelper } from 'ish-core/models/attribute/attribute.helper'; -import { UserMapper } from 'ish-core/models/user/user.mapper'; -import { B2bUserData, B2bUserDataLink } from './b2b-user.interface'; +import { B2bUserDataLink } from './b2b-user.interface'; import { B2bUser } from './b2b-user.model'; export class B2bUserMapper { - static fromData(user: B2bUserData): B2bUser { - return { ...UserMapper.fromData(user), active: user.active }; - } - static fromListData(data: B2bUserDataLink[]): B2bUser[] { if (data) { return data.map(e => ({ login: e.login, firstName: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'firstName'), lastName: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'lastName'), - roleIDs: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'roleIDs'), active: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'active'), + roleIDs: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'roleIDs'), businessPartnerNo: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'businessPartnerNo'), - userBudget: { - orderSpentLimit: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'orderSpentLimit'), - budget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budget'), - remainingBudget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'remainingBudget'), - budgetPeriod: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budgetPeriod'), - spentBudget: AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'spentBudget') || { - ...AttributeHelper.getAttributeValueByAttributeName(e.attributes, 'budget'), - value: 0, - }, - }, })); } else { throw new Error('data is required'); diff --git a/src/app/core/models/b2b-user/b2b-user.model.ts b/src/app/core/models/b2b-user/b2b-user.model.ts index 44102d4dc1..ccafb2d728 100644 --- a/src/app/core/models/b2b-user/b2b-user.model.ts +++ b/src/app/core/models/b2b-user/b2b-user.model.ts @@ -1,8 +1,6 @@ -import { UserBudget } from 'ish-core/models/user-budget/user-budget.model'; import { User } from 'ish-core/models/user/user.model'; export interface B2bUser extends Partial { - roleIDs?: string[]; active?: boolean; - userBudget?: UserBudget; + roleIDs?: string[]; } diff --git a/src/app/core/services/user/user.service.ts b/src/app/core/services/user/user.service.ts index dceaadebca..67c2f8be08 100644 --- a/src/app/core/services/user/user.service.ts +++ b/src/app/core/services/user/user.service.ts @@ -7,6 +7,8 @@ import { concatMap, first, map, switchMap, take, tap, withLatestFrom } from 'rxj import { AppFacade } from 'ish-core/facades/app.facade'; import { Address } from 'ish-core/models/address/address.model'; +import { B2bUserMapper } from 'ish-core/models/b2b-user/b2b-user.mapper'; +import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; import { CostCenter } from 'ish-core/models/cost-center/cost-center.model'; import { Credentials } from 'ish-core/models/credentials/credentials.model'; import { CustomerData, CustomerType } from 'ish-core/models/customer/customer.interface'; @@ -60,6 +62,8 @@ export class UserService { private tokenService: TokenService ) {} + private currentCustomer$ = this.store.pipe(select(getLoggedInCustomer), whenTruthy(), take(1)); + /** * Sign in an existing user with the given login credentials (login, password). * @@ -345,6 +349,21 @@ export class UserService { ); } + /** + * Get all users of a customer. The current user is expected to have user management permission. + * + * @returns All users of the customer. + */ + getUsers(): Observable { + return this.currentCustomer$.pipe( + switchMap(customer => + this.apiService + .get(`customers/${encodeResourceID(customer.customerNo)}/users`) + .pipe(unpackEnvelope(), map(B2bUserMapper.fromListData)) + ) + ); + } + /** * Get cost center data of a business customer for a given cost center id. The logged in user needs permission APP_B2B_VIEW_COSTCENTER. * diff --git a/src/app/core/state-management.module.ts b/src/app/core/state-management.module.ts index 0f518e90bb..07b610ffc4 100644 --- a/src/app/core/state-management.module.ts +++ b/src/app/core/state-management.module.ts @@ -8,7 +8,6 @@ import { CoreStoreModule } from './store/core/core-store.module'; import { CustomerStoreModule } from './store/customer/customer-store.module'; import { GeneralStoreModule } from './store/general/general-store.module'; import { HybridStoreModule } from './store/hybrid/hybrid-store.module'; -import { OrganizationManagementStoreModule } from './store/organization-management/organization-management-store.module'; import { ShoppingStoreModule } from './store/shopping/shopping-store.module'; import { storeDevtoolsModule } from './store/store-devtools.module'; @@ -19,7 +18,6 @@ import { storeDevtoolsModule } from './store/store-devtools.module'; CustomerStoreModule, GeneralStoreModule, HybridStoreModule, - OrganizationManagementStoreModule, ShoppingStoreModule, storeDevtoolsModule, // disable the Store Devtools in production (https://ngrx.io/guide/store-devtools/recipes/exclude) ], diff --git a/src/app/core/store/customer/customer-store.module.ts b/src/app/core/store/customer/customer-store.module.ts index f46ac2df8c..180704e46b 100644 --- a/src/app/core/store/customer/customer-store.module.ts +++ b/src/app/core/store/customer/customer-store.module.ts @@ -28,9 +28,12 @@ import { ssoRegistrationReducer } from './sso-registration/sso-registration.redu import { UserNewsletterEffects } from './user/user-newsletter.effects'; import { UserEffects } from './user/user.effects'; import { userReducer } from './user/user.reducer'; +import { UsersEffects } from './users/users.effects'; +import { usersReducer } from './users/users.reducer'; const customerReducers: ActionReducerMap = { user: userReducer, + users: usersReducer, addresses: addressesReducer, orders: ordersReducer, basket: basketReducer, @@ -49,6 +52,7 @@ const customerEffects = [ BasketValidationEffects, OrdersEffects, UserEffects, + UsersEffects, AuthorizationEffects, OrganizationManagementEffects, RequisitionManagementEffects, diff --git a/src/app/core/store/customer/customer-store.ts b/src/app/core/store/customer/customer-store.ts index 84c00b8663..550d30b48a 100644 --- a/src/app/core/store/customer/customer-store.ts +++ b/src/app/core/store/customer/customer-store.ts @@ -8,9 +8,11 @@ import { DataRequestsState } from './data-requests/data-requests.reducer'; import { OrdersState } from './orders/orders.reducer'; import { SsoRegistrationState } from './sso-registration/sso-registration.reducer'; import { UserState } from './user/user.reducer'; +import { UsersState } from './users/users.reducer'; export interface CustomerState { user: UserState; + users: UsersState; addresses: AddressesState; orders: OrdersState; basket: BasketState; diff --git a/src/app/core/store/customer/users/index.ts b/src/app/core/store/customer/users/index.ts new file mode 100644 index 0000000000..b1e5f4cd81 --- /dev/null +++ b/src/app/core/store/customer/users/index.ts @@ -0,0 +1,3 @@ +// API to access ngrx users state +export * from './users.actions'; +export * from './users.selectors'; diff --git a/src/app/core/store/customer/users/users.actions.ts b/src/app/core/store/customer/users/users.actions.ts new file mode 100644 index 0000000000..251050ffb0 --- /dev/null +++ b/src/app/core/store/customer/users/users.actions.ts @@ -0,0 +1,13 @@ +import { createAction } from '@ngrx/store'; + +import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; +import { httpError, payload } from 'ish-core/utils/ngrx-creators'; + +export const loadCustomerUsers = createAction('[Users Internal] Load Users of Customer'); + +export const loadCustomerUsersFail = createAction('[Users API] Load Users of Customer Fail', httpError()); + +export const loadCustomerUsersSuccess = createAction( + '[Users API] Load Users of Customer Success', + payload<{ users: B2bUser[] }>() +); diff --git a/src/app/core/store/customer/users/users.effects.spec.ts b/src/app/core/store/customer/users/users.effects.spec.ts new file mode 100644 index 0000000000..eccfe3019d --- /dev/null +++ b/src/app/core/store/customer/users/users.effects.spec.ts @@ -0,0 +1,86 @@ +import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { Action } from '@ngrx/store'; +import { cold, hot } from 'jasmine-marbles'; +import { Observable, of, throwError } from 'rxjs'; +import { instance, mock, verify, when } from 'ts-mockito'; + +import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; +import { UserService } from 'ish-core/services/user/user.service'; +import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; + +import { loadCustomerUsers, loadCustomerUsersFail } from './users.actions'; +import { UsersEffects } from './users.effects'; + +const users = [ + { + login: '1', + firstName: 'Patricia', + lastName: 'Miller', + name: 'Patricia Miller', + budget: { + budget: { value: 500, currency: 'USD' }, + orderSpentLimit: { value: 9000, currency: 'USD' }, + budgetPeriod: 'monthly', + }, + roleIDs: ['APP_USER_ROLE'], + }, + { login: '2' }, +] as B2bUser[]; + +describe('Users Effects', () => { + let actions$: Observable; + let effects: UsersEffects; + let userService: UserService; + + beforeEach(() => { + userService = mock(UserService); + when(userService.getUsers()).thenReturn(of(users)); + + TestBed.configureTestingModule({ + providers: [ + { provide: UserService, useFactory: () => instance(userService) }, + provideMockActions(() => actions$), + UsersEffects, + ], + }); + + effects = TestBed.inject(UsersEffects); + }); + + describe('loadUsers$', () => { + it('should call the service for retrieving users', done => { + actions$ = of(loadCustomerUsers()); + + effects.loadUsers$.subscribe(() => { + verify(userService.getUsers()).once(); + done(); + }); + }); + + it('should retrieve users when triggered', done => { + actions$ = of(loadCustomerUsers()); + + effects.loadUsers$.subscribe(action => { + expect(action).toMatchInlineSnapshot(` + [Users API] Load Users of Customer Success: + users: [{"login":"1","firstName":"Patricia","lastName":"Miller","na... + `); + done(); + }); + }); + + it('should dispatch a loadUsersFail action on failed users load', () => { + const error = makeHttpError({ status: 401, code: 'feld' }); + when(userService.getUsers()).thenReturn(throwError(() => error)); + + const action = loadCustomerUsers(); + const completion = loadCustomerUsersFail({ error }); + + actions$ = hot('-a', { a: action }); + const expected$ = cold('-b', { b: completion }); + + expect(effects.loadUsers$).toBeObservable(expected$); + }); + }); +}); diff --git a/src/app/core/store/customer/users/users.effects.ts b/src/app/core/store/customer/users/users.effects.ts new file mode 100644 index 0000000000..bb02dc737c --- /dev/null +++ b/src/app/core/store/customer/users/users.effects.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { exhaustMap, map } from 'rxjs/operators'; + +import { UserService } from 'ish-core/services/user/user.service'; +import { loadCompanyUserSuccess } from 'ish-core/store/customer/user/user.actions'; +import { mapErrorToAction } from 'ish-core/utils/operators'; + +import { loadCustomerUsers, loadCustomerUsersFail, loadCustomerUsersSuccess } from './users.actions'; + +@Injectable() +export class UsersEffects { + constructor(private actions$: Actions, private userService: UserService) {} + + triggerLoading$ = createEffect(() => + this.actions$.pipe( + ofType(loadCompanyUserSuccess), + map(() => loadCustomerUsers()) + ) + ); + + loadUsers$ = createEffect(() => + this.actions$.pipe( + ofType(loadCustomerUsers), + exhaustMap(() => + this.userService.getUsers().pipe( + map(users => loadCustomerUsersSuccess({ users })), + mapErrorToAction(loadCustomerUsersFail) + ) + ) + ) + ); +} diff --git a/src/app/core/store/customer/users/users.reducer.ts b/src/app/core/store/customer/users/users.reducer.ts new file mode 100644 index 0000000000..dee1a5c0c2 --- /dev/null +++ b/src/app/core/store/customer/users/users.reducer.ts @@ -0,0 +1,31 @@ +import { EntityState, createEntityAdapter } from '@ngrx/entity'; +import { createReducer, on } from '@ngrx/store'; + +import { B2bUser } from 'ish-core/models/b2b-user/b2b-user.model'; +import { setErrorOn, setLoadingOn, unsetLoadingAndErrorOn } from 'ish-core/utils/ngrx-creators'; + +import { loadCustomerUsers, loadCustomerUsersFail, loadCustomerUsersSuccess } from './users.actions'; + +export const usersAdapter = createEntityAdapter({ + selectId: user => user.login, +}); + +export type UsersState = EntityState; + +const initialState: UsersState = usersAdapter.getInitialState({}); + +export const usersReducer = createReducer( + initialState, + setLoadingOn(loadCustomerUsers), + unsetLoadingAndErrorOn(loadCustomerUsersSuccess), + setErrorOn(loadCustomerUsersFail), + on(loadCustomerUsersSuccess, (state, action) => { + const { users } = action.payload; + + return { + ...usersAdapter.upsertMany(users, state), + // preserve order from API + ids: users.map(u => u.login), + }; + }) +); diff --git a/src/app/core/store/customer/users/users.selectors.spec.ts b/src/app/core/store/customer/users/users.selectors.spec.ts new file mode 100644 index 0000000000..2fe8c5e7ba --- /dev/null +++ b/src/app/core/store/customer/users/users.selectors.spec.ts @@ -0,0 +1,69 @@ +import { TestBed } from '@angular/core/testing'; + +import { User } from 'ish-core/models/user/user.model'; +import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; +import { CustomerStoreModule } from 'ish-core/store/customer/customer-store.module'; +import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; + +import { loadCustomerUsers, loadCustomerUsersFail, loadCustomerUsersSuccess } from './users.actions'; +import { getUsers } from './users.selectors'; + +describe('Users Selectors', () => { + let store$: StoreWithSnapshots; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CoreStoreModule.forTesting(['serverConfig']), CustomerStoreModule.forTesting('users')], + providers: [provideStoreSnapshots()], + }); + + store$ = TestBed.inject(StoreWithSnapshots); + }); + + describe('initial state', () => { + it('should not have entities when in initial state', () => { + expect(getUsers(store$.state)).toBeEmpty(); + }); + }); + + describe('LoadUsers', () => { + const action = loadCustomerUsers(); + + beforeEach(() => { + store$.dispatch(action); + }); + + describe('LoadCustomerUsersSuccess', () => { + const users = [ + { login: '1' }, + { login: '2', roleIDs: ['APP_B2B_ACCOUNT_OWNER'] }, + { login: '3', roleIDs: ['APP_B2B_OCI_USER'] }, + { login: '3', roleIDs: ['APP_B2B_CXML_USER'] }, + { login: '4', roleIDs: ['APP_B2B_COSTCENTER_OWNER'] }, + ] as User[]; + const successAction = loadCustomerUsersSuccess({ users }); + + beforeEach(() => { + store$.dispatch(successAction); + }); + + it('should have entities when successfully loading', () => { + expect(getUsers(store$.state)).toHaveLength(3); + }); + }); + + describe('LoadCustomerUsersFail', () => { + const error = makeHttpError({ message: 'ERROR' }); + const failAction = loadCustomerUsersFail({ error }); + + beforeEach(() => { + store$.dispatch(failAction); + }); + + it('should not have entities when reducing error', () => { + expect(getUsers(store$.state)).toBeEmpty(); + }); + }); + }); +}); diff --git a/src/app/core/store/customer/users/users.selectors.ts b/src/app/core/store/customer/users/users.selectors.ts new file mode 100644 index 0000000000..a7c5eb7f39 --- /dev/null +++ b/src/app/core/store/customer/users/users.selectors.ts @@ -0,0 +1,13 @@ +import { createSelector } from '@ngrx/store'; + +import { getCustomerState } from 'ish-core/store/customer/customer-store'; + +import { usersAdapter } from './users.reducer'; + +const getUsersState = createSelector(getCustomerState, state => state.users); + +const { selectAll } = usersAdapter.getSelectors(getUsersState); + +export const getUsers = createSelector(selectAll, users => + users.filter(user => !user.roleIDs?.find(roleID => ['APP_B2B_OCI_USER', 'APP_B2B_CXML_USER'].includes(roleID))) +); diff --git a/src/app/pages/account-order-history/account-order-filters/account-order-filters.component.ts b/src/app/pages/account-order-history/account-order-filters/account-order-filters.component.ts index 753b2c8cbf..7f3f62049c 100644 --- a/src/app/pages/account-order-history/account-order-filters/account-order-filters.component.ts +++ b/src/app/pages/account-order-history/account-order-filters/account-order-filters.component.ts @@ -124,12 +124,11 @@ export class AccountOrderFiltersComponent implements OnInit, AfterViewInit { private destroyRef = inject(DestroyRef); - private buyers: SelectOption[] = [ - { - value: 'all', - label: 'account.order_history.filter.all_buyers', - }, - ]; + private allBuyersOption: SelectOption = { + value: 'all', + label: 'account.order_history.filter.all_buyers', + }; + private buyers: SelectOption[] = [this.allBuyersOption]; formIsCollapsed = true; private hideBuyerField = true;