mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
refactor(nestjs): contacts module
This commit is contained in:
@@ -88,6 +88,7 @@ import { ViewsModule } from '../Views/Views.module';
|
|||||||
import { CurrenciesModule } from '../Currencies/Currencies.module';
|
import { CurrenciesModule } from '../Currencies/Currencies.module';
|
||||||
import { MiscellaneousModule } from '../Miscellaneous/Miscellaneous.module';
|
import { MiscellaneousModule } from '../Miscellaneous/Miscellaneous.module';
|
||||||
import { UsersModule } from '../UsersModule/Users.module';
|
import { UsersModule } from '../UsersModule/Users.module';
|
||||||
|
import { ContactsModule } from '../Contacts/Contacts.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -210,7 +211,8 @@ import { UsersModule } from '../UsersModule/Users.module';
|
|||||||
ViewsModule,
|
ViewsModule,
|
||||||
CurrenciesModule,
|
CurrenciesModule,
|
||||||
MiscellaneousModule,
|
MiscellaneousModule,
|
||||||
UsersModule
|
UsersModule,
|
||||||
|
ContactsModule
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export const ERRORS = {
|
||||||
|
CONTACT_ALREADY_ACTIVE: 'CONTACT_ALREADY_ACTIVE',
|
||||||
|
CONTACT_ALREADY_INACTIVE: 'CONTACT_ALREADY_INACTIVE'
|
||||||
|
}
|
||||||
45
packages/server/src/modules/Contacts/Contacts.controller.ts
Normal file
45
packages/server/src/modules/Contacts/Contacts.controller.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Query,
|
||||||
|
Param,
|
||||||
|
Post,
|
||||||
|
ParseIntPipe,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation, ApiParam } from '@nestjs/swagger';
|
||||||
|
import { GetContactsAutoCompleteQuery } from './dtos/GetContactsAutoCompleteQuery.dto';
|
||||||
|
import { GetAutoCompleteContactsService } from './queries/GetAutoCompleteContacts.service';
|
||||||
|
import { ActivateContactService } from './commands/ActivateContact.service';
|
||||||
|
import { InactivateContactService } from './commands/InactivateContact.service';
|
||||||
|
|
||||||
|
@Controller('contacts')
|
||||||
|
@ApiTags('contacts')
|
||||||
|
export class ContactsController {
|
||||||
|
constructor(
|
||||||
|
private readonly getAutoCompleteService: GetAutoCompleteContactsService,
|
||||||
|
private readonly activateContactService: ActivateContactService,
|
||||||
|
private readonly inactivateContactService: InactivateContactService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
@Get('auto-complete')
|
||||||
|
@ApiOperation({ summary: 'Get the auto-complete contacts' })
|
||||||
|
getAutoComplete(@Query() query: GetContactsAutoCompleteQuery) {
|
||||||
|
return this.getAutoCompleteService.autocompleteContacts(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/activate')
|
||||||
|
@ApiOperation({ summary: 'Activate a contact' })
|
||||||
|
@ApiParam({ name: 'id', type: 'number', description: 'Contact ID' })
|
||||||
|
async activateContact(@Param('id', ParseIntPipe) contactId: number) {
|
||||||
|
await this.activateContactService.activateContact(contactId);
|
||||||
|
return { id: contactId, activated: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post(':id/inactivate')
|
||||||
|
@ApiOperation({ summary: 'Inactivate a contact' })
|
||||||
|
@ApiParam({ name: 'id', type: 'number', description: 'Contact ID' })
|
||||||
|
async inactivateContact(@Param('id', ParseIntPipe) contactId: number) {
|
||||||
|
await this.inactivateContactService.inactivateContact(contactId);
|
||||||
|
return { id: contactId, inactivated: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
15
packages/server/src/modules/Contacts/Contacts.module.ts
Normal file
15
packages/server/src/modules/Contacts/Contacts.module.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { GetAutoCompleteContactsService } from './queries/GetAutoCompleteContacts.service';
|
||||||
|
import { ContactsController } from './Contacts.controller';
|
||||||
|
import { ActivateContactService } from './commands/ActivateContact.service';
|
||||||
|
import { InactivateContactService } from './commands/InactivateContact.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
GetAutoCompleteContactsService,
|
||||||
|
ActivateContactService,
|
||||||
|
InactivateContactService,
|
||||||
|
],
|
||||||
|
controllers: [ContactsController],
|
||||||
|
})
|
||||||
|
export class ContactsModule {}
|
||||||
14
packages/server/src/modules/Contacts/Contacts.types.ts
Normal file
14
packages/server/src/modules/Contacts/Contacts.types.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { IFilterRole } from '../DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||||
|
|
||||||
|
export interface IContactsAutoCompleteFilter {
|
||||||
|
limit: number;
|
||||||
|
keyword: string;
|
||||||
|
filterRoles?: IFilterRole[];
|
||||||
|
columnSortBy: string;
|
||||||
|
sortOrder: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IContactAutoCompleteItem {
|
||||||
|
displayName: string;
|
||||||
|
contactService: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
import { Contact } from '../models/Contact';
|
||||||
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ERRORS } from '../Contacts.constants';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ActivateContactService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Contact.name)
|
||||||
|
private readonly contactModel: TenantModelProxy<typeof Contact>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async activateContact(contactId: number) {
|
||||||
|
const contact = await this.contactModel()
|
||||||
|
.query()
|
||||||
|
.findById(contactId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
if (contact.active) {
|
||||||
|
throw new ServiceError(ERRORS.CONTACT_ALREADY_ACTIVE);
|
||||||
|
}
|
||||||
|
await this.contactModel()
|
||||||
|
.query()
|
||||||
|
.findById(contactId)
|
||||||
|
.update({ active: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||||
|
import { Contact } from '../models/Contact';
|
||||||
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ERRORS } from '../Contacts.constants';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class InactivateContactService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Contact.name)
|
||||||
|
private readonly contactModel: TenantModelProxy<typeof Contact>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async inactivateContact(contactId: number) {
|
||||||
|
const contact = await this.contactModel()
|
||||||
|
.query()
|
||||||
|
.findById(contactId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
if (!contact.active) {
|
||||||
|
throw new ServiceError(ERRORS.CONTACT_ALREADY_INACTIVE);
|
||||||
|
}
|
||||||
|
await this.contactModel()
|
||||||
|
.query()
|
||||||
|
.findById(contactId)
|
||||||
|
.update({ active: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { IsNumber, IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class GetContactsAutoCompleteQuery {
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
limit: number;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
keyword: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { Contact } from '../models/Contact';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { IContactsAutoCompleteFilter } from '../Contacts.types';
|
||||||
|
import { GetContactsAutoCompleteQuery } from '../dtos/GetContactsAutoCompleteQuery.dto';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GetAutoCompleteContactsService {
|
||||||
|
constructor(
|
||||||
|
@Inject(Contact.name)
|
||||||
|
private readonly contactModel: TenantModelProxy<typeof Contact>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve auto-complete contacts list.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @param {IContactsAutoCompleteFilter} contactsFilter -
|
||||||
|
* @return {IContactAutoCompleteItem}
|
||||||
|
*/
|
||||||
|
async autocompleteContacts(queryDto: GetContactsAutoCompleteQuery) {
|
||||||
|
const _queryDto = {
|
||||||
|
filterRoles: [],
|
||||||
|
sortOrder: 'asc',
|
||||||
|
columnSortBy: 'display_name',
|
||||||
|
limit: 10,
|
||||||
|
...queryDto,
|
||||||
|
};
|
||||||
|
// Retrieve contacts list by the given query.
|
||||||
|
const contacts = await this.contactModel()
|
||||||
|
.query()
|
||||||
|
.onBuild((builder) => {
|
||||||
|
if (_queryDto.keyword) {
|
||||||
|
builder.where('display_name', 'LIKE', `%${_queryDto.keyword}%`);
|
||||||
|
}
|
||||||
|
builder.limit(_queryDto.limit);
|
||||||
|
});
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,6 @@ function DisconnectBankAccountDialogContent({
|
|||||||
values: DisconnectFormValues,
|
values: DisconnectFormValues,
|
||||||
{ setErrors, setSubmitting }: FormikHelpers<DisconnectFormValues>,
|
{ setErrors, setSubmitting }: FormikHelpers<DisconnectFormValues>,
|
||||||
) => {
|
) => {
|
||||||
debugger;
|
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
|
|
||||||
if (values.label !== 'DISCONNECT ACCOUNT') {
|
if (values.label !== 'DISCONNECT ACCOUNT') {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function useAutoCompleteContacts(props) {
|
|||||||
['CONTACTS', 'AUTO-COMPLETE'],
|
['CONTACTS', 'AUTO-COMPLETE'],
|
||||||
() => apiRequest.get('contacts/auto-complete'),
|
() => apiRequest.get('contacts/auto-complete'),
|
||||||
{
|
{
|
||||||
select: (res) => res.data.contacts,
|
select: (res) => res.data,
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export function useCurrencies(props) {
|
|||||||
[t.CURRENCIES],
|
[t.CURRENCIES],
|
||||||
{ method: 'get', url: 'currencies' },
|
{ method: 'get', url: 'currencies' },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.currencies,
|
select: (res) => res.data,
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const useResendInvitation = (props) => {
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
(userId) => apiRequest.post(`invite/resend/${userId}`),
|
(userId) => apiRequest.post(`invite/users/${userId}/resend`),
|
||||||
props
|
props
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ export function useUpdateOrganization(props = {}) {
|
|||||||
export function useOrgBaseCurrencyMutateAbilities(props) {
|
export function useOrgBaseCurrencyMutateAbilities(props) {
|
||||||
return useRequestQuery(
|
return useRequestQuery(
|
||||||
[t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES],
|
[t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES],
|
||||||
{ method: 'get', url: `organization/base_currency_mutate` },
|
{ method: 'get', url: `organization/base-currency-mutate` },
|
||||||
{
|
{
|
||||||
select: (res) => res.data.abilities,
|
select: (res) => res.data.abilities,
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function useUsers(props) {
|
|||||||
url: 'users',
|
url: 'users',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
select: (res) => res.data.users,
|
select: (res) => res.data,
|
||||||
defaultData: [],
|
defaultData: [],
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
@@ -123,7 +123,7 @@ export function useUser(id, props) {
|
|||||||
url: `users/${id}`,
|
url: `users/${id}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
select: (response) => response.data.user,
|
select: (response) => response.data,
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
@@ -143,7 +143,6 @@ export function useAuthenticatedAccount(props) {
|
|||||||
select: (response) => response.data,
|
select: (response) => response.data,
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
debugger;
|
|
||||||
setEmailConfirmed(data.verified, data.email);
|
setEmailConfirmed(data.verified, data.email);
|
||||||
},
|
},
|
||||||
...props,
|
...props,
|
||||||
|
|||||||
Reference in New Issue
Block a user