refactor(nestjs): wip

This commit is contained in:
Ahmed Bouhuolia
2025-05-27 15:42:27 +02:00
parent 83c9392b74
commit b7a3c42074
33 changed files with 186 additions and 72 deletions

View File

@@ -0,0 +1,32 @@
import { Transform } from 'class-transformer';
import { ValidateIf, ValidationOptions } from 'class-validator';
/**
* Decorator that converts the property value to a number.
* @returns PropertyDecorator
*/
export function ToNumber() {
return Transform(({ value, key }) => {
const defaultValue = null;
if (typeof value === 'number') {
return value;
}
// If value is an empty string or undefined/null, return it as-is (wont pass validation)
if (value === '' || value === null || value === undefined) {
return defaultValue;
}
const parsed = Number(value);
return !isNaN(parsed) ? parsed : value;
});
}
/**
* Validates if the property is not empty.
* @returns PropertyDecorator
*/
export function IsOptional(validationOptions?: ValidationOptions) {
return ValidateIf((_obj, value) => {
return value !== null && value !== undefined && value !== '';
}, validationOptions);
}

View File

@@ -0,0 +1,4 @@
{
"primary_warehouse": "Primary Warehouse"
}

View File

@@ -76,8 +76,13 @@ export class BranchesController {
status: 200, status: 200,
description: 'The branches feature has been successfully activated.', description: 'The branches feature has been successfully activated.',
}) })
activateBranches() { async activateBranches() {
return this.branchesApplication.activateBranches(); await this.branchesApplication.activateBranches();
return {
code: 200,
message: 'The branches activated successfully.',
};
} }
@Put(':id/mark-as-primary') @Put(':id/mark-as-primary')

View File

@@ -17,6 +17,8 @@ export class BranchesSettingsService {
const settingsStore = await this.settingsStore(); const settingsStore = await this.settingsStore();
settingsStore.set({ group: 'features', key: Features.BRANCHES, value: 1 }); settingsStore.set({ group: 'features', key: Features.BRANCHES, value: 1 });
await settingsStore.save();
}; };
/** /**

View File

@@ -1,9 +1,9 @@
import { IsOptional } from '@/common/decorators/Validators';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { import {
IsBoolean, IsBoolean,
IsEmail, IsEmail,
IsNotEmpty, IsNotEmpty,
IsOptional,
IsString, IsString,
IsUrl, IsUrl,
} from 'class-validator'; } from 'class-validator';

View File

@@ -37,15 +37,15 @@ export class CurrenciesController {
return this.currenciesApp.createCurrency(dto); return this.currenciesApp.createCurrency(dto);
} }
@Put(':code') @Put(':id')
@ApiOperation({ summary: 'Edit an existing currency' }) @ApiOperation({ summary: 'Edit an existing currency' })
@ApiParam({ name: 'id', type: Number, description: 'Currency ID' }) @ApiParam({ name: 'id', type: Number, description: 'Currency ID' })
@ApiBody({ type: EditCurrencyDto }) @ApiBody({ type: EditCurrencyDto })
@ApiOkResponse({ description: 'The currency has been successfully updated.' }) @ApiOkResponse({ description: 'The currency has been successfully updated.' })
@ApiNotFoundResponse({ description: 'Currency not found.' }) @ApiNotFoundResponse({ description: 'Currency not found.' })
@ApiBadRequestResponse({ description: 'Invalid input data.' }) @ApiBadRequestResponse({ description: 'Invalid input data.' })
edit(@Param('code') code: string, @Body() dto: EditCurrencyDto) { edit(@Param('id') id: number, @Body() dto: EditCurrencyDto) {
return this.currenciesApp.editCurrency(code, dto); return this.currenciesApp.editCurrency(id, dto);
} }
@Delete(':code') @Delete(':code')

View File

@@ -27,8 +27,8 @@ export class CurrenciesApplication {
/** /**
* Edits an existing currency. * Edits an existing currency.
*/ */
public editCurrency(currencyCode: string, currencyDTO: EditCurrencyDto) { public editCurrency(currencyId: number, currencyDTO: EditCurrencyDto) {
return this.editCurrencyService.editCurrency(currencyCode, currencyDTO); return this.editCurrencyService.editCurrency(currencyId, currencyDTO);
} }
/** /**

View File

@@ -12,21 +12,22 @@ export class EditCurrencyService {
/** /**
* Edit details of the given currency. * Edit details of the given currency.
* @param {number} currencyCode - Currency code. * @param {number} currencyId - Currency ID.
* @param {ICurrencyDTO} currencyDTO - Edit currency dto. * @param {ICurrencyDTO} currencyDTO - Edit currency dto.
*/ */
public async editCurrency( public async editCurrency(
currencyCode: string, currencyId: number,
currencyDTO: EditCurrencyDto, currencyDTO: EditCurrencyDto,
): Promise<Currency> { ): Promise<Currency> {
const foundCurrency = await this.currencyModel() const foundCurrency = this.currencyModel()
.query() .query()
.findOne('currencyCode', currencyCode) .findById(currencyId)
.throwIfNotFound(); .throwIfNotFound();
// Directly use the provided ID to update the currency
const currency = await this.currencyModel() const currency = await this.currencyModel()
.query() .query()
.patchAndFetchById(foundCurrency.id, { .patchAndFetchById(currencyId, {
...currencyDTO, ...currencyDTO,
}); });
return currency; return currency;

View File

@@ -1,12 +1,16 @@
import { IsString } from 'class-validator'; import { IsNotEmpty } from "class-validator";
import { IsString } from "class-validator";
export class CreateCurrencyDto { export class CreateCurrencyDto {
@IsString() @IsString()
@IsNotEmpty()
currencyName: string; currencyName: string;
@IsString() @IsString()
@IsNotEmpty()
currencyCode: string; currencyCode: string;
@IsString() @IsString()
@IsNotEmpty()
currencySign: string; currencySign: string;
} }

View File

@@ -1,9 +1,12 @@
import { IsString } from 'class-validator'; import { IsNotEmpty } from "class-validator";
import { IsString } from "class-validator";
export class EditCurrencyDto { export class EditCurrencyDto {
@IsString() @IsString()
@IsNotEmpty()
currencyName: string; currencyName: string;
@IsString() @IsString()
@IsNotEmpty()
currencySign: string; currencySign: string;
} }

View File

@@ -1,7 +1,6 @@
import { import {
IsString, IsString,
IsIn, IsIn,
IsOptional,
IsBoolean, IsBoolean,
IsNumber, IsNumber,
IsInt, IsInt,
@@ -9,11 +8,10 @@ import {
ValidateIf, ValidateIf,
MaxLength, MaxLength,
Min, Min,
Max,
IsNotEmpty, IsNotEmpty,
} from 'class-validator'; } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, ToNumber } from '@/common/decorators/Validators';
export class CommandItemDto { export class CommandItemDto {
@IsString() @IsString()
@@ -23,6 +21,7 @@ export class CommandItemDto {
name: string; name: string;
@IsString() @IsString()
@IsNotEmpty()
@IsIn(['service', 'non-inventory', 'inventory']) @IsIn(['service', 'non-inventory', 'inventory'])
@ApiProperty({ @ApiProperty({
description: 'Item type', description: 'Item type',
@@ -52,6 +51,7 @@ export class CommandItemDto {
purchasable?: boolean; purchasable?: boolean;
@IsOptional() @IsOptional()
@ToNumber()
@IsNumber({ maxDecimalPlaces: 3 }) @IsNumber({ maxDecimalPlaces: 3 })
@Min(0) @Min(0)
@ValidateIf((o) => o.purchasable === true) @ValidateIf((o) => o.purchasable === true)
@@ -64,6 +64,7 @@ export class CommandItemDto {
costPrice?: number; costPrice?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@Min(0) @Min(0)
@ValidateIf((o) => o.purchasable === true) @ValidateIf((o) => o.purchasable === true)
@@ -86,6 +87,7 @@ export class CommandItemDto {
sellable?: boolean; sellable?: boolean;
@IsOptional() @IsOptional()
@ToNumber()
@IsNumber({ maxDecimalPlaces: 3 }) @IsNumber({ maxDecimalPlaces: 3 })
@Min(0) @Min(0)
@ValidateIf((o) => o.sellable === true) @ValidateIf((o) => o.sellable === true)
@@ -98,6 +100,7 @@ export class CommandItemDto {
sellPrice?: number; sellPrice?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@Min(0) @Min(0)
@ValidateIf((o) => o.sellable === true) @ValidateIf((o) => o.sellable === true)
@@ -110,6 +113,7 @@ export class CommandItemDto {
sellAccountId?: number; sellAccountId?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@Min(0) @Min(0)
@ValidateIf((o) => o.type === 'inventory') @ValidateIf((o) => o.type === 'inventory')
@@ -140,6 +144,7 @@ export class CommandItemDto {
purchaseDescription?: string; purchaseDescription?: string;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@ApiProperty({ @ApiProperty({
description: 'ID of the tax rate applied to sales', description: 'ID of the tax rate applied to sales',
@@ -149,6 +154,7 @@ export class CommandItemDto {
sellTaxRateId?: number; sellTaxRateId?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@ApiProperty({ @ApiProperty({
description: 'ID of the tax rate applied to purchases', description: 'ID of the tax rate applied to purchases',
@@ -158,6 +164,7 @@ export class CommandItemDto {
purchaseTaxRateId?: number; purchaseTaxRateId?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
@Min(0) @Min(0)
@ApiProperty({ @ApiProperty({
@@ -189,7 +196,6 @@ export class CommandItemDto {
@IsOptional() @IsOptional()
@IsArray() @IsArray()
@Type(() => Number)
@IsInt({ each: true }) @IsInt({ each: true })
@ApiProperty({ @ApiProperty({
description: 'IDs of media files associated with the item', description: 'IDs of media files associated with the item',

View File

@@ -4,6 +4,7 @@ import { DeleteRoleService } from './commands/DeleteRole.service';
import { EditRoleService } from './commands/EditRole.service'; import { EditRoleService } from './commands/EditRole.service';
import { GetRoleService } from './queries/GetRole.service'; import { GetRoleService } from './queries/GetRole.service';
import { GetRolesService } from './queries/GetRoles.service'; import { GetRolesService } from './queries/GetRoles.service';
import { RolePermissionsSchema } from './queries/RolePermissionsSchema';
@Injectable() @Injectable()
export class RolesApplication { export class RolesApplication {
@@ -13,6 +14,7 @@ export class RolesApplication {
private readonly deleteRoleService: DeleteRoleService, private readonly deleteRoleService: DeleteRoleService,
private readonly getRoleService: GetRoleService, private readonly getRoleService: GetRoleService,
private readonly getRolesService: GetRolesService, private readonly getRolesService: GetRolesService,
private readonly getRolePermissionsSchemaService: RolePermissionsSchema,
) {} ) {}
/** /**
@@ -59,4 +61,12 @@ export class RolesApplication {
async getRoles() { async getRoles() {
return this.getRolesService.getRoles(); return this.getRolesService.getRoles();
} }
/**
* Gets the role permissions schema.
* @returns The role permissions schema.
*/
async getRolePermissionsSchema() {
return this.getRolePermissionsSchemaService.getRolePermissionsSchema();
}
} }

View File

@@ -72,9 +72,7 @@ export class RolesController {
status: HttpStatus.OK, status: HttpStatus.OK,
description: 'Role deleted successfully', description: 'Role deleted successfully',
}) })
async deleteRole( async deleteRole(@Param('id', ParseIntPipe) roleId: number) {
@Param('id', ParseIntPipe) roleId: number,
) {
await this.rolesApp.deleteRole(roleId); await this.rolesApp.deleteRole(roleId);
return { return {
@@ -83,24 +81,34 @@ export class RolesController {
}; };
} }
@Get('permissions/schema')
@ApiOperation({ summary: 'Get role permissions schema' })
@ApiResponse({
status: HttpStatus.OK,
description: 'Role permissions schema',
})
async getRolePermissionsSchema() {
const schema = await this.rolesApp.getRolePermissionsSchema();
return schema;
}
@Get() @Get()
@ApiOperation({ summary: 'Get all roles' }) @ApiOperation({ summary: 'Get all roles' })
@ApiResponse({ status: HttpStatus.OK, description: 'List of all roles' }) @ApiResponse({ status: HttpStatus.OK, description: 'List of all roles' })
async getRoles() { async getRoles() {
const roles = await this.rolesApp.getRoles(); const roles = await this.rolesApp.getRoles();
return { roles }; return roles;
} }
@Get(':id') @Get(':id')
@ApiOperation({ summary: 'Get a specific role by ID' }) @ApiOperation({ summary: 'Get a specific role by ID' })
@ApiParam({ name: 'id', description: 'Role ID' }) @ApiParam({ name: 'id', description: 'Role ID' })
@ApiResponse({ status: HttpStatus.OK, description: 'Role details' }) @ApiResponse({ status: HttpStatus.OK, description: 'Role details' })
async getRole( async getRole(@Param('id', ParseIntPipe) roleId: number) {
@Param('id', ParseIntPipe) roleId: number,
) {
const role = await this.rolesApp.getRole(roleId); const role = await this.rolesApp.getRole(roleId);
return { role }; return role;
} }
} }

View File

@@ -9,6 +9,7 @@ import { Role } from './models/Role.model';
import { RolePermission } from './models/RolePermission.model'; import { RolePermission } from './models/RolePermission.model';
import { RolesController } from './Roles.controller'; import { RolesController } from './Roles.controller';
import { RolesApplication } from './Roles.application'; import { RolesApplication } from './Roles.application';
import { RolePermissionsSchema } from './queries/RolePermissionsSchema';
const models = [ const models = [
RegisterTenancyModel(Role), RegisterTenancyModel(Role),
@@ -24,6 +25,7 @@ const models = [
GetRoleService, GetRoleService,
GetRolesService, GetRolesService,
RolesApplication, RolesApplication,
RolePermissionsSchema
], ],
controllers: [RolesController], controllers: [RolesController],
exports: [...models], exports: [...models],

View File

@@ -1,12 +1,12 @@
import { Knex } from 'knex'; import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { IRoleCreatedPayload } from '../Roles.types'; import { IRoleCreatedPayload } from '../Roles.types';
import { Role } from './../models/Role.model'; import { Role } from './../models/Role.model';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service'; import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { CreateRoleDto } from '../dtos/Role.dto'; import { CreateRoleDto } from '../dtos/Role.dto';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { Inject, Injectable } from '@nestjs/common';
import { validateInvalidPermissions } from '../utils'; import { validateInvalidPermissions } from '../utils';
@Injectable() @Injectable()

View File

@@ -1,12 +1,42 @@
import { AbilitySchema } from '../AbilitySchema'; import { AbilitySchema } from '../AbilitySchema';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { I18nService } from 'nestjs-i18n';
import { cloneDeep } from 'lodash';
import { ISubjectAbilitiesSchema } from '../Roles.types';
@Injectable() @Injectable()
export class RolePermissionsSchema { export class RolePermissionsSchema {
constructor(private readonly i18nService: I18nService) {}
/** /**
* Retrieve the role permissions schema. * Retrieve the role permissions schema with translated labels.
* @returns {ISubjectAbilitiesSchema[]}
*/ */
getRolePermissionsSchema() { getRolePermissionsSchema(): ISubjectAbilitiesSchema[] {
return AbilitySchema; // Clone the schema to avoid modifying the original
const schema = cloneDeep(AbilitySchema);
// Apply translations to each subject and its abilities
return schema.map((subject: ISubjectAbilitiesSchema) => {
// Translate subject label
subject.subjectLabel = this.i18nService.t(subject.subjectLabel);
// Translate abilities labels
if (subject.abilities) {
subject.abilities = subject.abilities.map((ability) => ({
...ability,
label: this.i18nService.t(ability.label),
}));
}
// Translate extra abilities labels if they exist
if (subject.extraAbilities) {
subject.extraAbilities = subject.extraAbilities.map((ability) => ({
...ability,
label: this.i18nService.t(ability.label),
}));
}
return subject;
});
} }
} }

View File

@@ -6,6 +6,9 @@ import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.dec
import { ImportableModel } from '@/modules/Import/decorators/Import.decorator'; import { ImportableModel } from '@/modules/Import/decorators/Import.decorator';
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator'; import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
import { SaleEstimateMeta } from './SaleEstimate.meta'; import { SaleEstimateMeta } from './SaleEstimate.meta';
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
import { Customer } from '@/modules/Customers/models/Customer';
@ExportableModel() @ExportableModel()
@ImportableModel() @ImportableModel()
@@ -40,6 +43,10 @@ export class SaleEstimate extends TenantBaseModel {
branchId?: number; branchId?: number;
warehouseId?: number; warehouseId?: number;
public entries!: ItemEntry[];
public attachments!: Document[];
public customer!: Customer;
/** /**
* Table name * Table name
*/ */

View File

@@ -1,10 +1,7 @@
// import { Transformer } from '@/lib/Transformer/Transformer';
// import { ItemEntryTransformer } from '../Invoices/ItemEntryTransformer';
// import { AttachmentTransformer } from '@/services/Attachments/AttachmentTransformer';
import { Transformer } from '@/modules/Transformer/Transformer'; import { Transformer } from '@/modules/Transformer/Transformer';
import { SaleEstimate } from '../models/SaleEstimate'; import { SaleEstimate } from '../models/SaleEstimate';
import { ItemEntryTransformer } from '@/modules/TransactionItemEntry/ItemEntry.transformer'; import { ItemEntryTransformer } from '@/modules/TransactionItemEntry/ItemEntry.transformer';
import { AttachmentTransformer } from '@/modules/Attachments/Attachment.transformer';
export class SaleEstimateTransfromer extends Transformer { export class SaleEstimateTransfromer extends Transformer {
/** /**
@@ -106,9 +103,9 @@ export class SaleEstimateTransfromer extends Transformer {
* @returns {} * @returns {}
*/ */
protected entries = (estimate: SaleEstimate) => { protected entries = (estimate: SaleEstimate) => {
// return this.item(estimate.entries, new ItemEntryTransformer(), { return this.item(estimate.entries, new ItemEntryTransformer(), {
// currencyCode: estimate.currencyCode, currencyCode: estimate.currencyCode,
// }); });
}; };
/** /**
@@ -117,6 +114,6 @@ export class SaleEstimateTransfromer extends Transformer {
* @returns * @returns
*/ */
protected attachments = (estimate: SaleEstimate) => { protected attachments = (estimate: SaleEstimate) => {
// return this.item(estimate.attachments, new AttachmentTransformer()); return this.item(estimate.attachments, new AttachmentTransformer());
}; };
} }

View File

@@ -57,7 +57,7 @@ export class WarehousesController {
return this.warehousesApplication.activateWarehouses(); return this.warehousesApplication.activateWarehouses();
} }
@Post(':id/mark-primary') @Put(':id/mark-primary')
@ApiOperation({ summary: 'Mark a warehouse as primary' }) @ApiOperation({ summary: 'Mark a warehouse as primary' })
markWarehousePrimary(@Param('id') warehouseId: string) { markWarehousePrimary(@Param('id') warehouseId: string) {
return this.warehousesApplication.markWarehousePrimary(Number(warehouseId)); return this.warehousesApplication.markWarehousePrimary(Number(warehouseId));

View File

@@ -17,6 +17,8 @@ export class WarehousesSettings {
const settings = await this.settingsStore(); const settings = await this.settingsStore();
settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 }); settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 });
await settings.save();
}; };
/** /**

View File

@@ -1,16 +1,16 @@
import { CreateWarehouse } from './CreateWarehouse.service'; import { CreateWarehouse } from './CreateWarehouse.service';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { I18nContext } from 'nestjs-i18n'; import { I18nService } from 'nestjs-i18n';
@Injectable() @Injectable()
export class CreateInitialWarehouse { export class CreateInitialWarehouse {
/** /**
* @param {CreateWarehouse} createWarehouse - Create warehouse service. * @param {CreateWarehouse} createWarehouse - Create warehouse service.
* @param {I18nContext} i18n - I18n context. * @param {I18nService} i18n - I18n service.
*/ */
constructor( constructor(
private readonly createWarehouse: CreateWarehouse, private readonly createWarehouse: CreateWarehouse,
private readonly i18n: I18nContext, private readonly i18n: I18nService,
) {} ) {}
/** /**

View File

@@ -1,5 +1,6 @@
import { IsOptional } from "@/common/decorators/Validators";
import { ApiProperty } from "@nestjs/swagger"; import { ApiProperty } from "@nestjs/swagger";
import { IsBoolean, IsEmail, IsOptional, IsUrl } from "class-validator"; import { IsBoolean, IsEmail, IsUrl } from "class-validator";
import { IsNotEmpty } from "class-validator"; import { IsNotEmpty } from "class-validator";
import { IsString } from "class-validator"; import { IsString } from "class-validator";

View File

@@ -38,7 +38,7 @@ export function useEditBranch(props) {
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useMutation( return useMutation(
([id, values]) => apiRequest.post(`branches/${id}`, values), ([id, values]) => apiRequest.put(`branches/${id}`, values),
{ {
onSuccess: (res, [id, values]) => { onSuccess: (res, [id, values]) => {
// Invalidate specific branch. // Invalidate specific branch.
@@ -79,7 +79,7 @@ export function useBranches(query, props) {
[t.BRANCHES, query], [t.BRANCHES, query],
{ method: 'get', url: 'branches', params: query }, { method: 'get', url: 'branches', params: query },
{ {
select: (res) => res.data.branches, select: (res) => res.data,
defaultData: [], defaultData: [],
...props, ...props,
}, },
@@ -95,7 +95,7 @@ export function useBranch(id, props, requestProps) {
[t.BRANCH, id], [t.BRANCH, id],
{ method: 'get', url: `branches/${id}`, ...requestProps }, { method: 'get', url: `branches/${id}`, ...requestProps },
{ {
select: (res) => res.data.branch, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -21,15 +21,15 @@ export function useCreateCurrency(props) {
} }
/** /**
* Edits the given currency code. * Edits the given currency by ID.
*/ */
export function useEditCurrency(props) { export function useEditCurrency(props) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useMutation( return useMutation(
([currencyCode, values]) => ([currencyId, values]) =>
apiRequest.post(`currencies/${currencyCode}`, values), apiRequest.put(`currencies/${currencyId}`, values),
{ {
onSuccess: () => { onSuccess: () => {
// Invalidate currencies. // Invalidate currencies.

View File

@@ -76,7 +76,7 @@ export function useExpense(id, props) {
url: `expenses/${id}`, url: `expenses/${id}`,
}, },
{ {
select: (res) => res.data.expense, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -101,7 +101,7 @@ export function useItemCategory(id, props) {
[t.ITEM_CATEGORY, id], [t.ITEM_CATEGORY, id],
{ method: 'get', url: `item-categories/${id}` }, { method: 'get', url: `item-categories/${id}` },
{ {
select: (res) => res.data.category, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -139,7 +139,7 @@ export function useJournal(id, props) {
[t.MANUAL_JOURNAL, id], [t.MANUAL_JOURNAL, id],
{ method: 'get', url: `manual-journals/${id}` }, { method: 'get', url: `manual-journals/${id}` },
{ {
select: (res) => res.data.manual_journal, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -185,7 +185,7 @@ export function usePaymentMade(id, props) {
[t.PAYMENT_MADE, id], [t.PAYMENT_MADE, id],
{ method: 'get', url: `bill-payments/${id}` }, { method: 'get', url: `bill-payments/${id}` },
{ {
select: (res) => res.data.bill_payment, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -159,7 +159,7 @@ export function useReceipt(id, props) {
['SALE_RECEIPT', id], ['SALE_RECEIPT', id],
{ method: 'get', url: `sale-receipts/${id}` }, { method: 'get', url: `sale-receipts/${id}` },
{ {
select: (res) => res.data.sale_receipt, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -211,7 +211,7 @@ export function useReceiptSMSDetail(receiptId, props, requestProps) {
...requestProps, ...requestProps,
}, },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -304,7 +304,7 @@ export function useSaleReceiptMailState(
() => () =>
apiRequest apiRequest
.get(`sale-receipts/${receiptId}/mail`) .get(`sale-receipts/${receiptId}/mail`)
.then((res) => transformToCamelCase(res.data.data)), .then((res) => transformToCamelCase(res.data)),
); );
} }
@@ -322,7 +322,7 @@ export function useGetReceiptState(
() => () =>
apiRequest apiRequest
.get(`/sale-receipts/state`) .get(`/sale-receipts/state`)
.then((res) => transformToCamelCase(res.data?.data)), .then((res) => transformToCamelCase(res.data)),
{ ...options }, { ...options },
); );
} }

View File

@@ -69,7 +69,7 @@ export function usePermissionsSchema(query, props) {
[t.ROLES_PERMISSIONS_SCHEMA, query], [t.ROLES_PERMISSIONS_SCHEMA, query],
{ method: 'get', url: 'roles/permissions/schema', params: query }, { method: 'get', url: 'roles/permissions/schema', params: query },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: { defaultData: {
roles: [], roles: [],
}, },
@@ -87,7 +87,7 @@ export function useRolePermission(role_id, props, requestProps) {
[t.ROLE, role_id], [t.ROLE, role_id],
{ method: 'get', url: `roles/${role_id}`, ...requestProps }, { method: 'get', url: `roles/${role_id}`, ...requestProps },
{ {
select: (res) => res.data.role, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -102,7 +102,7 @@ export function useRoles(props, query) {
[t.ROLES, query], [t.ROLES, query],
{ method: 'get', url: `roles`, params: query }, { method: 'get', url: `roles`, params: query },
{ {
select: (res) => res.data.roles, select: (res) => res.data,
defaultData: [], defaultData: [],
...props, ...props,
}, },

View File

@@ -13,7 +13,7 @@ export function useSaveSettings(props) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useMutation((settings) => apiRequest.post('settings', settings), { return useMutation((settings) => apiRequest.put('settings', settings), {
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries(t.SETTING); queryClient.invalidateQueries(t.SETTING);
}, },

View File

@@ -156,7 +156,7 @@ export function useVendorCredit(id, props, requestProps) {
[t.VENDOR_CREDIT, id], [t.VENDOR_CREDIT, id],
{ method: 'get', url: `vendor-credits/${id}`, ...requestProps }, { method: 'get', url: `vendor-credits/${id}`, ...requestProps },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -232,7 +232,7 @@ export function useRefundVendorCredit(id, props, requestProps) {
...requestProps, ...requestProps,
}, },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -298,7 +298,7 @@ export function useReconcileVendorCredit(id, props, requestProps) {
...requestProps, ...requestProps,
}, },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: [], defaultData: [],
...props, ...props,
}, },
@@ -317,7 +317,7 @@ export function useReconcileVendorCredits(id, props, requestProps) {
...requestProps, ...requestProps,
}, },
{ {
select: (res) => res.data.data, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -359,7 +359,7 @@ export function useRefundVendorCreditTransaction(id, props, requestProps) {
...requestProps, ...requestProps,
}, },
{ {
select: (res) => res.data.refund_credit, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },

View File

@@ -41,7 +41,7 @@ export function useEditWarehouse(props) {
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useMutation( return useMutation(
([id, values]) => apiRequest.post(`warehouses/${id}`, values), ([id, values]) => apiRequest.put(`warehouses/${id}`, values),
{ {
onSuccess: (res, [id, values]) => { onSuccess: (res, [id, values]) => {
// Invalidate specific sale invoice. // Invalidate specific sale invoice.
@@ -82,7 +82,7 @@ export function useWarehouses(query, props) {
[t.WAREHOUSES, query], [t.WAREHOUSES, query],
{ method: 'get', url: 'warehouses', params: query }, { method: 'get', url: 'warehouses', params: query },
{ {
select: (res) => res.data.warehouses, select: (res) => res.data,
defaultData: [], defaultData: [],
...props, ...props,
}, },
@@ -98,7 +98,7 @@ export function useWarehouse(id, props, requestProps) {
[t.WAREHOUSE, id], [t.WAREHOUSE, id],
{ method: 'get', url: `warehouses/${id}`, ...requestProps }, { method: 'get', url: `warehouses/${id}`, ...requestProps },
{ {
select: (res) => res.data.warehouse, select: (res) => res.data,
defaultData: {}, defaultData: {},
...props, ...props,
}, },
@@ -128,7 +128,7 @@ export function useMarkWarehouseAsPrimary(props) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const apiRequest = useApiRequest(); const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`warehouses/${id}/mark-primary`), { return useMutation((id) => apiRequest.put(`warehouses/${id}/mark-primary`), {
onSuccess: (res, id) => { onSuccess: (res, id) => {
// Invalidate specific inventory adjustment. // Invalidate specific inventory adjustment.
queryClient.invalidateQueries([t.WAREHOUSE, id]); queryClient.invalidateQueries([t.WAREHOUSE, id]);