refactor(nestjs): export module

This commit is contained in:
Ahmed Bouhuolia
2025-04-10 23:34:42 +02:00
parent ab49113d5a
commit c953c48c39
23 changed files with 176 additions and 68 deletions

View File

@@ -6,9 +6,6 @@ import {
ACCOUNT_TYPES, ACCOUNT_TYPES,
getAccountsSupportsMultiCurrency, getAccountsSupportsMultiCurrency,
} from '@/constants/accounts'; } from '@/constants/accounts';
// import { SearchableModel } from '@/modules/Search/SearchableMdel';
// import { CustomViewBaseModel } from '@/modules/CustomViews/CustomViewBaseModel';
// import { ModelSettings } from '@/modules/Settings/ModelSettings';
import { AccountTypesUtils } from '@/libs/accounts-utils/AccountTypesUtils'; import { AccountTypesUtils } from '@/libs/accounts-utils/AccountTypesUtils';
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem'; import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel'; import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
@@ -16,9 +13,6 @@ import { flatToNestedArray } from '@/utils/flat-to-nested-array';
import { ExportableModel } from '../../Export/decorators/ExportableModel.decorator'; import { ExportableModel } from '../../Export/decorators/ExportableModel.decorator';
import { AccountMeta } from './Account.meta'; import { AccountMeta } from './Account.meta';
import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator'; import { InjectModelMeta } from '@/modules/Tenancy/TenancyModels/decorators/InjectModelMeta.decorator';
// import AccountSettings from './Account.Settings';
// import { DEFAULT_VIEWS } from '@/modules/Accounts/constants';
// import { buildFilterQuery, buildSortColumnQuery } from '@/lib/ViewRolesBuilder';
@ExportableModel() @ExportableModel()
@InjectModelMeta(AccountMeta) @InjectModelMeta(AccountMeta)

View File

@@ -27,6 +27,7 @@ import { GetBillsService } from './queries/GetBills.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module'; import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module'; import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
import { BillsExportable } from './commands/BillsExportable'; import { BillsExportable } from './commands/BillsExportable';
import { BillsImportable } from './commands/BillsImportable';
@Module({ @Module({
imports: [ imports: [
@@ -58,8 +59,10 @@ import { BillsExportable } from './commands/BillsExportable';
BillGLEntriesSubscriber, BillGLEntriesSubscriber,
BillInventoryTransactions, BillInventoryTransactions,
BillWriteInventoryTransactionsSubscriber, BillWriteInventoryTransactionsSubscriber,
BillsExportable BillsExportable,
BillsImportable
], ],
controllers: [BillsController], controllers: [BillsController],
exports: [BillsExportable, BillsImportable],
}) })
export class BillsModule {} export class BillsModule {}

View File

@@ -4,8 +4,11 @@ import { Injectable } from '@nestjs/common';
import { Exportable } from '@/modules/Export/Exportable'; import { Exportable } from '@/modules/Export/Exportable';
import { IBillsFilter } from '../Bills.types'; import { IBillsFilter } from '../Bills.types';
import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants'; import { EXPORT_SIZE_LIMIT } from '@/modules/Export/constants';
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
import { Bill } from '../models/Bill';
@Injectable() @Injectable()
@ExportableService({ name: Bill.name })
export class BillsExportable extends Exportable { export class BillsExportable extends Exportable {
constructor(private readonly billsApplication: BillsApplication) { constructor(private readonly billsApplication: BillsApplication) {
super(); super();

View File

@@ -37,7 +37,7 @@ import { CreditNotesExportable } from './commands/CreditNotesExportable';
AutoIncrementOrdersModule, AutoIncrementOrdersModule,
LedgerModule, LedgerModule,
AccountsModule, AccountsModule,
DynamicListModule DynamicListModule,
], ],
providers: [ providers: [
CreateCreditNoteService, CreateCreditNoteService,
@@ -54,7 +54,7 @@ import { CreditNotesExportable } from './commands/CreditNotesExportable';
CreditNoteBrandingTemplate, CreditNoteBrandingTemplate,
CreditNoteGLEntries, CreditNoteGLEntries,
CreditNoteGLEntriesSubscriber, CreditNoteGLEntriesSubscriber,
CreditNotesExportable CreditNotesExportable,
], ],
exports: [ exports: [
CreateCreditNoteService, CreateCreditNoteService,
@@ -68,6 +68,7 @@ import { CreditNotesExportable } from './commands/CreditNotesExportable';
GetCreditNoteState, GetCreditNoteState,
CreditNoteApplication, CreditNoteApplication,
CreditNoteBrandingTemplate, CreditNoteBrandingTemplate,
CreditNotesExportable,
], ],
controllers: [CreditNotesController], controllers: [CreditNotesController],
}) })

View File

@@ -2,8 +2,11 @@ import { Exportable } from '@/modules/Export/Exportable';
import { CreditNoteApplication } from '../CreditNoteApplication.service'; import { CreditNoteApplication } from '../CreditNoteApplication.service';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { ICreditNotesQueryDTO } from '../types/CreditNotes.types'; import { ICreditNotesQueryDTO } from '../types/CreditNotes.types';
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
import { CreditNote } from '../models/CreditNote';
@Injectable() @Injectable()
@ExportableService({ name: CreditNote.name })
export class CreditNotesExportable extends Exportable { export class CreditNotesExportable extends Exportable {
constructor(private readonly creditNotesApp: CreditNoteApplication) { constructor(private readonly creditNotesApp: CreditNoteApplication) {
super(); super();

View File

@@ -1,3 +1,4 @@
import { Inject, Injectable } from '@nestjs/common';
import * as R from 'ramda'; import * as R from 'ramda';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service'; import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service'; import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
@@ -7,8 +8,6 @@ import {
} from '../types/CreditNotes.types'; } from '../types/CreditNotes.types';
import { CreditNote } from '../models/CreditNote'; import { CreditNote } from '../models/CreditNote';
import { CreditNoteTransformer } from './CreditNoteTransformer'; import { CreditNoteTransformer } from './CreditNoteTransformer';
import { Inject } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable() @Injectable()

View File

@@ -23,7 +23,7 @@ import { ExpensesImportable } from './ExpensesImportable';
@Module({ @Module({
imports: [LedgerModule, BranchesModule, DynamicListModule], imports: [LedgerModule, BranchesModule, DynamicListModule],
controllers: [ExpensesController], controllers: [ExpensesController],
exports: [CreateExpense], exports: [CreateExpense, ExpensesExportable, ExpensesImportable],
providers: [ providers: [
CreateExpense, CreateExpense,
ExpenseDTOTransformer, ExpenseDTOTransformer,
@@ -40,7 +40,7 @@ import { ExpensesImportable } from './ExpensesImportable';
ExpenseGLEntriesService, ExpenseGLEntriesService,
GetExpensesService, GetExpensesService,
ExpensesExportable, ExpensesExportable,
ExpensesImportable ExpensesImportable,
], ],
}) })
export class ExpensesModule {} export class ExpensesModule {}

View File

@@ -17,6 +17,7 @@ export class ExpensesExportable extends Exportable {
/** /**
* Retrieves the accounts data to exportable sheet. * Retrieves the accounts data to exportable sheet.
* @param {IExpensesFilter}
*/ */
public exportable(query: IExpensesFilter) { public exportable(query: IExpensesFilter) {
const filterQuery = (query) => { const filterQuery = (query) => {

View File

@@ -7,7 +7,6 @@ import { ExportApplication } from './ExportApplication';
import { ResourceModule } from '../Resource/Resource.module'; import { ResourceModule } from '../Resource/Resource.module';
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module'; import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
import { ImportModel } from '../Import/models/Import'; import { ImportModel } from '../Import/models/Import';
import { ExportableResources } from './ExportResources';
import { ExportableRegistry } from './ExportRegistery'; import { ExportableRegistry } from './ExportRegistery';
import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectable.module'; import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectable.module';
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module'; import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
@@ -28,7 +27,6 @@ const models = [RegisterTenancyModel(ImportModel)];
ExportPdf, ExportPdf,
ExportAls, ExportAls,
ExportApplication, ExportApplication,
ExportableResources,
ExportableRegistry ExportableRegistry
], ],
exports: [...models], exports: [...models],

View File

@@ -3,7 +3,6 @@ import * as xlsx from 'xlsx';
import * as R from 'ramda'; import * as R from 'ramda';
import { get } from 'lodash'; import { get } from 'lodash';
import { sanitizeResourceName } from '../Import/_utils'; import { sanitizeResourceName } from '../Import/_utils';
import { ExportableResources } from './ExportResources';
import { Errors, ExportFormat } from './common'; import { Errors, ExportFormat } from './common';
import { flatDataCollections, getDataAccessor } from './utils'; import { flatDataCollections, getDataAccessor } from './utils';
import { ExportPdf } from './ExportPdf'; import { ExportPdf } from './ExportPdf';
@@ -19,7 +18,6 @@ export class ExportResourceService {
constructor( constructor(
private readonly exportAls: ExportAls, private readonly exportAls: ExportAls,
private readonly exportPdf: ExportPdf, private readonly exportPdf: ExportPdf,
private readonly exportableResources: ExportableResources,
private readonly resourceService: ResourceService, private readonly resourceService: ResourceService,
private readonly moduleRef: ModuleRef, private readonly moduleRef: ModuleRef,
) {} ) {}

View File

@@ -1,3 +1,5 @@
import { Global } from "@nestjs/common";
const exportableModels = new Map<string, boolean>(); const exportableModels = new Map<string, boolean>();
const exportableService = new Map<string, any>() const exportableService = new Map<string, any>()
@@ -15,6 +17,9 @@ export function ExportableModel() {
export function ExportableService({ name }: { name: string }) { export function ExportableService({ name }: { name: string }) {
return function (target: any) { return function (target: any) {
exportableService.set(name, target); exportableService.set(name, target);
// Apply the @Global() decorator to make the service globally available
Global()(target);
}; };
} }

View File

@@ -25,10 +25,14 @@ import { ItemCategoriesImportable } from './ItemCategoriesImportable';
DeleteItemCategoryService, DeleteItemCategoryService,
ItemCategoryApplication, ItemCategoryApplication,
CommandItemCategoryValidatorService, CommandItemCategoryValidatorService,
ItemCategoriesExportable,
TransformerInjectable, TransformerInjectable,
TenancyContext, TenancyContext,
ItemCategoriesImportable ItemCategoriesExportable,
ItemCategoriesImportable,
],
exports: [
ItemCategoriesExportable,
ItemCategoriesImportable,
], ],
}) })
export class ItemCategoryModule {} export class ItemCategoryModule {}

View File

@@ -16,6 +16,7 @@ import { ItemsEntriesService } from './ItemsEntries.service';
import { GetItemsService } from './GetItems.service'; import { GetItemsService } from './GetItems.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module'; import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdjustments.module'; import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdjustments.module';
import { ItemsExportable } from './ItemsExportable.service';
@Module({ @Module({
imports: [ imports: [
@@ -38,7 +39,8 @@ import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdju
TenancyContext, TenancyContext,
TransformerInjectable, TransformerInjectable,
ItemsEntriesService, ItemsEntriesService,
ItemsExportable,
], ],
exports: [ItemsEntriesService], exports: [ItemsEntriesService, ItemsExportable],
}) })
export class ItemsModule {} export class ItemsModule {}

View File

@@ -0,0 +1,36 @@
import { Global, Injectable } from '@nestjs/common';
import { Exportable } from '../Export/Exportable';
import { EXPORT_SIZE_LIMIT } from '../Export/constants';
import { ItemsApplicationService } from './ItemsApplication.service';
import { IItemsFilter } from './types/Items.types';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { Item } from './models/Item';
@Injectable()
@ExportableService({ name: Item.name })
@Global()
export class ItemsExportable extends Exportable {
constructor(
private readonly itemsApplication: ItemsApplicationService,
) {
super();
}
/**
* Retrieves the accounts data to exportable sheet.
* @param {IItemsFilter} query - Items export query.
*/
public exportable(query: IItemsFilter) {
const parsedQuery = {
sortOrder: 'DESC',
columnSortBy: 'created_at',
page: 1,
...query,
pageSize: EXPORT_SIZE_LIMIT,
} as IItemsFilter;
return this.itemsApplication
.getItems(parsedQuery)
.then((output) => output.items);
}
}

View File

@@ -0,0 +1,36 @@
import { Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import { Importable } from '../Import/Importable';
import { CreateItemService } from './CreateItem.service';
import { CreateItemDto } from './dtos/Item.dto';
import { ItemsSampleData } from './Items.constants';
@Injectable()
export class ItemsImportable extends Importable {
constructor(
private readonly createItemService: CreateItemService,
) {
super();
}
/**
* Mapps the imported data to create a new item service.
* @param {number} tenantId
* @param {ICustomerNewDTO} createDTO
* @param {Knex.Transaction} trx
* @returns {Promise<void>}
*/
public async importable(
createDTO: CreateItemDto,
trx?: Knex.Transaction<any, any[]>
): Promise<void> {
await this.createItemService.createItem(createDTO, trx);
}
/**
* Retrieves the sample data of customers used to download sample sheet.
*/
public sampleData(): any[] {
return ItemsSampleData;
}
}

View File

@@ -53,6 +53,13 @@ export class Item extends TenantBaseModel {
} }
return q; return q;
}, },
/**
* Inactive/Active mode.
*/
inactiveMode(query, active = false) {
query.where('items.active', !active);
},
}; };
} }

View File

@@ -40,7 +40,8 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
ManualJournalGLEntries, ManualJournalGLEntries,
ManualJournalWriteGLSubscriber, ManualJournalWriteGLSubscriber,
ManualJournalsExportable, ManualJournalsExportable,
ManualJournalImportable ManualJournalImportable,
], ],
exports: [ManualJournalsExportable, ManualJournalImportable],
}) })
export class ManualJournalsModule {} export class ManualJournalsModule {}

View File

@@ -3,8 +3,11 @@ import { EXPORT_SIZE_LIMIT } from '../../Export/constants';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { IManualJournalsFilter } from '../types/ManualJournals.types'; import { IManualJournalsFilter } from '../types/ManualJournals.types';
import { ManualJournalsApplication } from '../ManualJournalsApplication.service'; import { ManualJournalsApplication } from '../ManualJournalsApplication.service';
import { ExportableService } from '@/modules/Export/decorators/ExportableModel.decorator';
import { ManualJournal } from '../models/ManualJournal';
@Injectable() @Injectable()
@ExportableService({ name: ManualJournal.name })
export class ManualJournalsExportable extends Exportable { export class ManualJournalsExportable extends Exportable {
constructor( constructor(
private readonly manualJournalsApplication: ManualJournalsApplication, private readonly manualJournalsApplication: ManualJournalsApplication,
@@ -14,6 +17,7 @@ export class ManualJournalsExportable extends Exportable {
/** /**
* Retrieves the manual journals data to exportable sheet. * Retrieves the manual journals data to exportable sheet.
* @param {IManualJournalsFilter} query -
*/ */
public exportable(query: IManualJournalsFilter) { public exportable(query: IManualJournalsFilter) {
const parsedQuery = { const parsedQuery = {

View File

@@ -80,5 +80,9 @@ import { SaleEstimatesImportable } from './SaleEstimatesImportable';
SaleEstimatesExportable, SaleEstimatesExportable,
SaleEstimatesImportable SaleEstimatesImportable
], ],
exports: [
SaleEstimatesExportable,
SaleEstimatesImportable
]
}) })
export class SaleEstimatesModule {} export class SaleEstimatesModule {}

View File

@@ -4,8 +4,11 @@ import { Exportable } from '../Export/Exportable';
import { ISalesInvoicesFilter } from '../SaleInvoices/SaleInvoice.types'; import { ISalesInvoicesFilter } from '../SaleInvoices/SaleInvoice.types';
import { SaleEstimatesApplication } from './SaleEstimates.application'; import { SaleEstimatesApplication } from './SaleEstimates.application';
import { ISalesEstimatesFilter } from './types/SaleEstimates.types'; import { ISalesEstimatesFilter } from './types/SaleEstimates.types';
import { ExportableService } from '../Export/decorators/ExportableModel.decorator';
import { SaleEstimate } from './models/SaleEstimate';
@Injectable() @Injectable()
@ExportableService({ name: SaleEstimate.name })
export class SaleEstimatesExportable extends Exportable { export class SaleEstimatesExportable extends Exportable {
constructor( constructor(
private readonly saleEstimatesApplication: SaleEstimatesApplication, private readonly saleEstimatesApplication: SaleEstimatesApplication,

View File

@@ -57,6 +57,7 @@ import { InvoicePaymentsGLEntriesRewrite } from './InvoicePaymentsGLRewrite';
import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module'; import { PaymentsReceivedModule } from '../PaymentReceived/PaymentsReceived.module';
import { SaleInvoicesCost } from './SalesInvoicesCost'; import { SaleInvoicesCost } from './SalesInvoicesCost';
import { SaleInvoicesExportable } from './commands/SaleInvoicesExportable'; import { SaleInvoicesExportable } from './commands/SaleInvoicesExportable';
import { SaleInvoicesImportable } from './commands/SaleInvoicesImportable';
@Module({ @Module({
imports: [ imports: [
@@ -119,8 +120,15 @@ import { SaleInvoicesExportable } from './commands/SaleInvoicesExportable';
SaleInvoiceWriteInventoryTransactionsSubscriber, SaleInvoiceWriteInventoryTransactionsSubscriber,
InvoicePaymentsGLEntriesRewrite, InvoicePaymentsGLEntriesRewrite,
SaleInvoicesCost, SaleInvoicesCost,
SaleInvoicesExportable SaleInvoicesExportable,
SaleInvoicesImportable,
],
exports: [
GetSaleInvoice,
SaleInvoicesCost,
SaleInvoicePdf,
SaleInvoicesExportable,
SaleInvoicesImportable,
], ],
exports: [GetSaleInvoice, SaleInvoicesCost, SaleInvoicePdf],
}) })
export class SaleInvoicesModule {} export class SaleInvoicesModule {}

View File

@@ -1,46 +1,39 @@
// import { Inject, Service } from 'typedi'; import { Injectable } from '@nestjs/common';
// import { Knex } from 'knex'; import { Knex } from 'knex';
// import { ISaleInvoiceCreateDTO } from '@/interfaces'; import { CreateSaleInvoice } from './CreateSaleInvoice.service';
// import { CreateSaleInvoice } from './commands/CreateSaleInvoice.service'; import { Importable } from '@/modules/Import/Importable';
// import { Importable } from '@/services/Import/Importable'; import { CreateSaleInvoiceDto } from '../dtos/SaleInvoice.dto';
// import { SaleInvoicesSampleData } from './constants'; import { SaleInvoicesSampleData } from '../constants';
// @Service() @Injectable()
// export class SaleInvoicesImportable extends Importable { export class SaleInvoicesImportable extends Importable {
// @Inject() constructor(private readonly createInvoiceService: CreateSaleInvoice) {
// private createInvoiceService: CreateSaleInvoice; super();
}
// /** /**
// * Importing to account service. * Importing to account service.
// * @param {number} tenantId * @param {CreateSaleInvoiceDto} createAccountDTO
// * @param {IAccountCreateDTO} createAccountDTO */
// * @returns public importable(
// */ createAccountDTO: CreateSaleInvoiceDto,
// public importable( trx?: Knex.Transaction,
// tenantId: number, ) {
// createAccountDTO: ISaleInvoiceCreateDTO, return this.createInvoiceService.createSaleInvoice(createAccountDTO, trx);
// trx?: Knex.Transaction }
// ) {
// return this.createInvoiceService.createSaleInvoice(
// tenantId,
// createAccountDTO,
// {},
// trx
// );
// }
// /** /**
// * Concurrrency controlling of the importing process. * Concurrrency controlling of the importing process.
// * @returns {number} * @returns {number}
// */ */
// public get concurrency() { public get concurrency() {
// return 1; return 1;
// } }
// /** /**
// * Retrieves the sample data that used to download accounts sample sheet. * Retrieves the sample data that used to download accounts sample sheet.
// */ */
// public sampleData(): any[] { public sampleData(): any[] {
// return SaleInvoicesSampleData; return SaleInvoicesSampleData;
// } }
// } }

View File

@@ -1,18 +1,22 @@
import * as R from 'ramda'; import * as R from 'ramda';
import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common';
import { SaleInvoiceTransformer } from './SaleInvoice.transformer'; import { SaleInvoiceTransformer } from './SaleInvoice.transformer';
import { Injectable } from '@nestjs/common';
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service'; import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service'; import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model'; import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
import { SaleInvoice } from '../models/SaleInvoice'; import { SaleInvoice } from '../models/SaleInvoice';
import { ISalesInvoicesFilter } from '../SaleInvoice.types'; import { ISalesInvoicesFilter } from '../SaleInvoice.types';
import { Knex } from 'knex'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable() @Injectable()
export class GetSaleInvoicesService { export class GetSaleInvoicesService {
constructor( constructor(
private readonly dynamicListService: DynamicListService, private readonly dynamicListService: DynamicListService,
private readonly transformer: TransformerInjectable, private readonly transformer: TransformerInjectable,
@Inject(SaleInvoice.name)
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
) {} ) {}
/** /**
@@ -33,7 +37,8 @@ export class GetSaleInvoicesService {
SaleInvoice, SaleInvoice,
filter, filter,
); );
const { results, pagination } = await SaleInvoice.query() const { results, pagination } = await this.saleInvoiceModel()
.query()
.onBuild((builder) => { .onBuild((builder) => {
builder.withGraphFetched('entries.item'); builder.withGraphFetched('entries.item');
builder.withGraphFetched('customer'); builder.withGraphFetched('customer');