mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
fix: adjust contact balance
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||
import { CustomerResponseDto } from './dtos/CustomerResponse.dto';
|
||||
import { GetCustomersQueryDto } from './dtos/GetCustomersQuery.dto';
|
||||
|
||||
@Controller('customers')
|
||||
@ApiTags('Customers')
|
||||
@@ -51,7 +52,7 @@ export class CustomersController {
|
||||
items: { $ref: getSchemaPath(CustomerResponseDto) },
|
||||
},
|
||||
})
|
||||
getCustomers(@Query() filterDTO: Partial<ICustomersFilter>) {
|
||||
getCustomers(@Query() filterDTO: GetCustomersQueryDto) {
|
||||
return this.customersApplication.getCustomers(filterDTO);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,14 @@ import { CreateCustomer } from './commands/CreateCustomer.service';
|
||||
import { EditCustomer } from './commands/EditCustomer.service';
|
||||
import { DeleteCustomer } from './commands/DeleteCustomer.service';
|
||||
import { EditOpeningBalanceCustomer } from './commands/EditOpeningBalanceCustomer.service';
|
||||
import { ICustomerOpeningBalanceEditDTO, ICustomersFilter } from './types/Customers.types';
|
||||
import {
|
||||
ICustomerOpeningBalanceEditDTO,
|
||||
ICustomersFilter,
|
||||
} from './types/Customers.types';
|
||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||
import { GetCustomers } from './queries/GetCustomers.service';
|
||||
import { GetCustomersQueryDto } from './dtos/GetCustomersQuery.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CustomersApplication {
|
||||
@@ -76,7 +80,7 @@ export class CustomersApplication {
|
||||
* Retrieve customers paginated list.
|
||||
* @param {ICustomersFilter} filter - Cusotmers filter.
|
||||
*/
|
||||
public getCustomers = (filterDTO: Partial<ICustomersFilter>) => {
|
||||
public getCustomers = (filterDTO: GetCustomersQueryDto) => {
|
||||
return this.getCustomersService.getCustomersList(filterDTO);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ import {
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
} from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { ContactAddressDto } from './ContactAddress.dto';
|
||||
import { IsOptional } from '@/common/decorators/Validators';
|
||||
|
||||
export class CreateCustomerDto extends ContactAddressDto {
|
||||
@ApiProperty({
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { IsInt, IsOptional, IsString, IsBoolean } from 'class-validator';
|
||||
import { ToNumber } from '@/common/decorators/Validators';
|
||||
import { DynamicFilterQueryDto } from '@/modules/DynamicListing/dtos/DynamicFilterQuery.dto';
|
||||
import { parseBoolean } from '@/utils/parse-boolean';
|
||||
import { Transform } from 'class-transformer';
|
||||
|
||||
export class GetCustomersQueryDto extends DynamicFilterQueryDto {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
stringifiedFilterRoles?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ToNumber()
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ToNumber()
|
||||
pageSize?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@Transform(({ value }) => parseBoolean(value, false))
|
||||
inactiveMode?: boolean;
|
||||
}
|
||||
@@ -1,8 +1,27 @@
|
||||
import { Model } from 'objection';
|
||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||
import { CustomerMeta } from './Customer.meta';
|
||||
import { InjectModelDefaultViews } from '@/modules/Views/decorators/InjectModelDefaultViews.decorator';
|
||||
import { CustomerDefaultViews } from '../constants';
|
||||
import { BaseQueryBuilder } from '@/models/Model';
|
||||
import { Knex } from 'knex';
|
||||
|
||||
export class CustomerQueryBuilder<
|
||||
M extends Model,
|
||||
R = M[],
|
||||
> extends BaseQueryBuilder<M, R> {
|
||||
constructor(...args) {
|
||||
// @ts-ignore
|
||||
super(...args);
|
||||
|
||||
this.onBuild((builder) => {
|
||||
if (builder.isFind() || builder.isDelete() || builder.isUpdate()) {
|
||||
builder.where('contact_service', 'customer');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@InjectModelMeta(CustomerMeta)
|
||||
@InjectModelDefaultViews(CustomerDefaultViews)
|
||||
@@ -54,9 +73,7 @@ export class Customer extends TenantBaseModel {
|
||||
/**
|
||||
* Query builder.
|
||||
*/
|
||||
// static get QueryBuilder() {
|
||||
// return CustomerQueryBuilder;
|
||||
// }
|
||||
static QueryBuilder = CustomerQueryBuilder;
|
||||
|
||||
/**
|
||||
* Table name
|
||||
@@ -152,6 +169,7 @@ export class Customer extends TenantBaseModel {
|
||||
);
|
||||
query.having('countOverdue', '>', 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters the unpaid customers.
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ICustomersFilter,
|
||||
} from '../types/Customers.types';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { GetCustomersQueryDto } from '../dtos/GetCustomersQuery.dto';
|
||||
|
||||
@Injectable()
|
||||
export class GetCustomers {
|
||||
@@ -29,12 +30,12 @@ export class GetCustomers {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve customers paginated list.
|
||||
* @param {ICustomersFilter} filter - Cusotmers filter.
|
||||
* Retrieves customers paginated list.
|
||||
* @param {GetCustomersQueryDto} filter - Cusotmers filter.
|
||||
* @returns {Promise<GetCustomersResponse>}
|
||||
*/
|
||||
public async getCustomersList(
|
||||
filterDto: Partial<ICustomersFilter>,
|
||||
filterDto: GetCustomersQueryDto,
|
||||
): Promise<GetCustomersResponse> {
|
||||
const _filterDto = {
|
||||
inactiveMode: false,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ToNumber } from '@/common/decorators/Validators';
|
||||
import { IsArray, IsEnum, IsInt, IsOptional, IsString } from 'class-validator';
|
||||
import { IsArray, IsOptional, IsString } from 'class-validator';
|
||||
import { IFilterRole, ISortOrder } from '../DynamicFilter/DynamicFilter.types';
|
||||
|
||||
export class DynamicFilterQueryDto {
|
||||
|
||||
@@ -85,7 +85,6 @@ export class LedgerContactsBalanceStorage {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} tenantId
|
||||
* @param {ILedger} ledger
|
||||
* @param {number} contactId
|
||||
* @returns {Promise<void>}
|
||||
@@ -130,11 +129,8 @@ export class LedgerContactsBalanceStorage {
|
||||
change: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// return this.contactModel.changeAmount(
|
||||
// { id: contactId },
|
||||
// 'balance',
|
||||
// change,
|
||||
// trx,
|
||||
// );
|
||||
return this.contactModel()
|
||||
.query(trx)
|
||||
.changeAmount({ id: contactId }, 'balance', change);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,11 +157,8 @@ export class LedegrAccountsStorage {
|
||||
.whereNull('amount')
|
||||
.patch({ amount: 0 });
|
||||
|
||||
// await this.accountModel.changeAmount(
|
||||
// { id: accountId },
|
||||
// 'amount',
|
||||
// change,
|
||||
// trx,
|
||||
// );
|
||||
await this.accountModel()
|
||||
.query(trx)
|
||||
.changeAmount({ id: accountId }, 'amount', change);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ import { IgnoreTenantInitializedRoute } from '../Tenancy/EnsureTenantIsInitializ
|
||||
import { IgnoreTenantSeededRoute } from '../Tenancy/EnsureTenantIsSeeded.guards';
|
||||
import { GetBuildOrganizationBuildJob } from './commands/GetBuildOrganizationJob.service';
|
||||
import { OrganizationBaseCurrencyLocking } from './Organization/OrganizationBaseCurrencyLocking.service';
|
||||
import {
|
||||
OrganizationBuildResponseExample,
|
||||
OrganizationBuiltResponseExample,
|
||||
} from './Organization.swagger';
|
||||
|
||||
@ApiTags('Organization')
|
||||
@Controller('organization')
|
||||
@@ -46,6 +50,11 @@ export class OrganizationController {
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The organization database has been initialized',
|
||||
example: OrganizationBuildResponseExample,
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 500,
|
||||
example: OrganizationBuiltResponseExample,
|
||||
})
|
||||
async build(@Body() buildDTO: BuildOrganizationDto) {
|
||||
const result = await this.buildOrganizationService.buildRunJob(buildDTO);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export const OrganizationBuildResponseExample = {
|
||||
type: 'success',
|
||||
code: 'ORGANIZATION.DATABASE.INITIALIZED',
|
||||
message: 'The organization database has been initialized.',
|
||||
data: {
|
||||
job_id: '1',
|
||||
},
|
||||
};
|
||||
|
||||
export const OrganizationBuiltResponseExample = {
|
||||
errors: [
|
||||
{
|
||||
statusCode: 500,
|
||||
type: 'TENANT_ALREADY_BUILT',
|
||||
message: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateVendorDto } from './dtos/CreateVendor.dto';
|
||||
import { EditVendorDto } from './dtos/EditVendor.dto';
|
||||
import { GetVendorsQueryDto } from './dtos/GetVendorsQuery.dto';
|
||||
|
||||
@Controller('vendors')
|
||||
@ApiTags('vendors')
|
||||
@@ -24,7 +25,7 @@ export class VendorsController {
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Retrieves the vendors.' })
|
||||
getVendors(@Query() filterDTO: Partial<IVendorsFilter>) {
|
||||
getVendors(@Query() filterDTO: GetVendorsQueryDto) {
|
||||
return this.vendorsApplication.getVendors(filterDTO);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { GetVendorsService } from './queries/GetVendors.service';
|
||||
import { CreateVendorDto } from './dtos/CreateVendor.dto';
|
||||
import { EditVendorDto } from './dtos/EditVendor.dto';
|
||||
import { GetVendorsQueryDto } from './dtos/GetVendorsQuery.dto';
|
||||
|
||||
@Injectable()
|
||||
export class VendorsApplication {
|
||||
@@ -82,7 +83,7 @@ export class VendorsApplication {
|
||||
* @param {Partial<IVendorsFilter>} filterDTO
|
||||
* @returns {Promise<{ vendors: Vendor[], pagination: IPaginationMeta, filterMeta: IFilterMeta }>>}
|
||||
*/
|
||||
public getVendors(filterDTO: Partial<IVendorsFilter>) {
|
||||
public getVendors(filterDTO: GetVendorsQueryDto) {
|
||||
return this.getVendorsService.getVendorsList(filterDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean, IsEmail, IsString } from 'class-validator';
|
||||
import {
|
||||
IsISO8601,
|
||||
IsInt,
|
||||
IsNumber,
|
||||
Min,
|
||||
IsBoolean,
|
||||
IsEmail,
|
||||
IsString,
|
||||
} from 'class-validator';
|
||||
import { ContactAddressDto } from '@/modules/Customers/dtos/ContactAddress.dto';
|
||||
import { IsInt, IsNumber } from 'class-validator';
|
||||
import { IsOptional, Min } from 'class-validator';
|
||||
import { IsISO8601 } from 'class-validator';
|
||||
import { IsOptional } from '@/common/decorators/Validators';
|
||||
|
||||
export class CreateVendorDto extends ContactAddressDto {
|
||||
@ApiProperty({ required: false, description: 'Vendor opening balance' })
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { ToNumber } from '@/common/decorators/Validators';
|
||||
import { DynamicFilterQueryDto } from '@/modules/DynamicListing/dtos/DynamicFilterQuery.dto';
|
||||
import { parseBoolean } from '@/utils/parse-boolean';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsInt, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class GetVendorsQueryDto extends DynamicFilterQueryDto {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
stringifiedFilterRoles?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ToNumber()
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@ToNumber()
|
||||
pageSize?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
@Transform(({ value }) => parseBoolean(value, false))
|
||||
inactiveMode?: boolean;
|
||||
}
|
||||
@@ -1,12 +1,5 @@
|
||||
import { Model, mixin } from 'objection';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import PaginationQueryBuilder from './Pagination';
|
||||
// import ModelSetting from './ModelSetting';
|
||||
// import VendorSettings from './Vendor.Settings';
|
||||
// import CustomViewBaseModel from './CustomViewBaseModel';
|
||||
// import { DEFAULT_VIEWS } from '@/services/Contacts/Vendors/constants';
|
||||
// import ModelSearchable from './ModelSearchable';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { Model } from 'objection';
|
||||
import { BaseQueryBuilder } from '@/models/Model';
|
||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ExportableModel } from '@/modules/Export/decorators/ExportableModel.decorator';
|
||||
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
|
||||
@@ -14,6 +7,22 @@ import { VendorMeta } from './Vendor.meta';
|
||||
import { InjectModelDefaultViews } from '@/modules/Views/decorators/InjectModelDefaultViews.decorator';
|
||||
import { VendorDefaultViews } from '../constants';
|
||||
|
||||
export class VendorQueryBuilder<
|
||||
M extends Model,
|
||||
R = M[],
|
||||
> extends BaseQueryBuilder<M, R> {
|
||||
constructor(...args) {
|
||||
// @ts-ignore
|
||||
super(...args);
|
||||
|
||||
this.onBuild((builder) => {
|
||||
if (builder.isFind() || builder.isDelete() || builder.isUpdate()) {
|
||||
builder.where('contact_service', 'vendor');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ExportableModel()
|
||||
@InjectModelMeta(VendorMeta)
|
||||
@InjectModelDefaultViews(VendorDefaultViews)
|
||||
@@ -64,9 +73,7 @@ export class Vendor extends TenantBaseModel {
|
||||
/**
|
||||
* Query builder.
|
||||
*/
|
||||
// static get QueryBuilder() {
|
||||
// return VendorQueryBuilder;
|
||||
// }
|
||||
static QueryBuilder = VendorQueryBuilder;
|
||||
|
||||
/**
|
||||
* Table name
|
||||
|
||||
@@ -6,6 +6,7 @@ import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectab
|
||||
import { VendorTransfromer } from './VendorTransformer';
|
||||
import { GetVendorsResponse, IVendorsFilter } from '../types/Vendors.types';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { GetVendorsQueryDto } from '../dtos/GetVendorsQuery.dto';
|
||||
|
||||
@Injectable()
|
||||
export class GetVendorsService {
|
||||
@@ -28,7 +29,7 @@ export class GetVendorsService {
|
||||
* @returns {Promise<GetVendorsResponse>}
|
||||
*/
|
||||
public async getVendorsList(
|
||||
filterDto: Partial<IVendorsFilter>,
|
||||
filterDto: GetVendorsQueryDto,
|
||||
): Promise<GetVendorsResponse> {
|
||||
const _filterDto = {
|
||||
inactiveMode: false,
|
||||
|
||||
@@ -76,15 +76,13 @@ export class WarehousesItemsQuantitySync {
|
||||
.first();
|
||||
|
||||
if (itemWarehouseQuantity) {
|
||||
// @ts-ignore
|
||||
await ItemWarehouseQuantity.changeAmount(
|
||||
await this.itemWarehouseQuantityModel().query(trx).changeAmount(
|
||||
{
|
||||
itemId: warehouseItemQuantity.itemId,
|
||||
warehouseId: warehouseItemQuantity.warehouseId,
|
||||
},
|
||||
'quantityOnHand',
|
||||
warehouseItemQuantity.amount,
|
||||
trx,
|
||||
);
|
||||
} else {
|
||||
await ItemWarehouseQuantity.query(trx).insert({
|
||||
@@ -96,7 +94,6 @@ export class WarehousesItemsQuantitySync {
|
||||
|
||||
/**
|
||||
* Mutates warehouses items quantity from inventory transactions.
|
||||
* @param {number} tenantId -
|
||||
* @param {IInventoryTransaction[]} inventoryTransactions -
|
||||
* @param {Knex.Transaction}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user