diff --git a/src/handlers/list-xero-profit-and-loss.handler.ts b/src/handlers/list-xero-profit-and-loss.handler.ts index e19a7bfc..5a2484b5 100644 --- a/src/handlers/list-xero-profit-and-loss.handler.ts +++ b/src/handlers/list-xero-profit-and-loss.handler.ts @@ -1,35 +1,41 @@ import { xeroClient } from "../clients/xero-client.js"; import { XeroClientResponse } from "../types/tool-response.js"; +import { ListProfitAndLossParams } from "../types/list-profit-and-loss-params.js"; import { formatError } from "../helpers/format-error.js"; import { getClientHeaders } from "../helpers/get-client-headers.js"; import { ReportWithRow } from "xero-node"; -// Define the valid timeframe options -type TimeframeType = "MONTH" | "QUARTER" | "YEAR" | undefined; - /** * Internal function to fetch profit and loss data from Xero */ async function fetchProfitAndLoss( - fromDate?: string, - toDate?: string, - periods?: number, - timeframe?: TimeframeType, - standardLayout?: boolean, - paymentsOnly?: boolean, + params: ListProfitAndLossParams, ): Promise { await xeroClient.authenticate(); + const { + fromDate, + toDate, + periods, + timeframe, + trackingCategoryID, + trackingOptionID, + trackingCategoryID2, + trackingOptionID2, + standardLayout, + paymentsOnly, + } = params; + const response = await xeroClient.accountingApi.getReportProfitAndLoss( xeroClient.tenantId, fromDate, toDate, periods, timeframe, - undefined, // trackingCategoryID - undefined, // trackingOptionID - undefined, // trackingCategoryID2 - undefined, // trackingOptionID2 + trackingCategoryID, + trackingCategoryID2, + trackingOptionID, + trackingOptionID2, standardLayout, paymentsOnly, getClientHeaders(), @@ -40,33 +46,23 @@ async function fetchProfitAndLoss( /** * List profit and loss report from Xero - * @param fromDate Optional start date for the report (YYYY-MM-DD) - * @param toDate Optional end date for the report (YYYY-MM-DD) - * @param periods Optional number of periods for the report - * @param timeframe Optional timeframe for the report (MONTH, QUARTER, YEAR) - * @param trackingCategoryID Optional tracking category ID - * @param trackingOptionID Optional tracking option ID - * @param trackingCategoryID2 Optional second tracking category ID - * @param trackingOptionID2 Optional second tracking option ID - * @param standardLayout Optional boolean to use standard layout - * @param paymentsOnly Optional boolean to include only accounts with payments + * @param params Optional parameters for the report: + * - fromDate: Optional start date for the report (YYYY-MM-DD) + * - toDate: Optional end date for the report (YYYY-MM-DD) + * - periods: Optional number of periods for the report + * - timeframe: Optional timeframe for the report (MONTH, QUARTER, YEAR) + * - trackingCategoryID: Optional tracking category ID + * - trackingOptionID: Optional tracking option ID + * - trackingCategoryID2: Optional second tracking category ID + * - trackingOptionID2: Optional second tracking option ID + * - standardLayout: Optional boolean to use standard layout + * - paymentsOnly: Optional boolean to include only accounts with payments */ export async function listXeroProfitAndLoss( - fromDate?: string, - toDate?: string, - periods?: number, - timeframe?: TimeframeType, - standardLayout?: boolean, - paymentsOnly?: boolean, + params: ListProfitAndLossParams, ): Promise> { try { - const profitAndLoss = await fetchProfitAndLoss( - fromDate, - toDate, - periods, - timeframe, - paymentsOnly, - ); + const profitAndLoss = await fetchProfitAndLoss(params); if (!profitAndLoss) { return { @@ -88,4 +84,4 @@ export async function listXeroProfitAndLoss( error: formatError(error), }; } -} \ No newline at end of file +} diff --git a/src/tools/list/list-profit-and-loss.tool.ts b/src/tools/list/list-profit-and-loss.tool.ts index 72e6aba1..f5178139 100644 --- a/src/tools/list/list-profit-and-loss.tool.ts +++ b/src/tools/list/list-profit-and-loss.tool.ts @@ -10,18 +10,26 @@ const ListProfitAndLossTool = CreateXeroTool( toDate: z.string().optional().describe("Optional end date in YYYY-MM-DD format"), periods: z.number().optional().describe("Optional number of periods to compare"), timeframe: z.enum(["MONTH", "QUARTER", "YEAR"]).optional().describe("Optional timeframe for the report (MONTH, QUARTER, YEAR)"), + trackingCategoryID: z.string().optional().describe("Optional tracking category ID to scope the report to a tracking dimension. Obtain IDs from the list-tracking-categories tool. Supply this alone for a per-option breakdown (one column per option in the category); supply it together with trackingOptionID to filter the whole P&L to that single option."), + trackingOptionID: z.string().optional().describe("Optional tracking option ID. Obtain IDs from the list-tracking-categories tool. Must be supplied together with trackingCategoryID; it filters the whole P&L to that single option of that category."), + trackingCategoryID2: z.string().optional().describe("Optional SECOND tracking category ID for a cross-tab against a different category. Obtain IDs from the list-tracking-categories tool. This targets a second category (cross-tab), NOT a second option of the same category."), + trackingOptionID2: z.string().optional().describe("Optional second tracking option ID. Obtain IDs from the list-tracking-categories tool. Must be supplied together with trackingCategoryID2; it filters to that single option of the second category."), standardLayout: z.boolean().optional().describe("Optional flag to use standard layout"), paymentsOnly: z.boolean().optional().describe("Optional flag to include only accounts with payments"), }, async (args) => { - const response = await listXeroProfitAndLoss( - args?.fromDate, - args?.toDate, - args?.periods, - args?.timeframe, - args?.standardLayout, - args?.paymentsOnly, - ); + const response = await listXeroProfitAndLoss({ + fromDate: args?.fromDate, + toDate: args?.toDate, + periods: args?.periods, + timeframe: args?.timeframe, + trackingCategoryID: args?.trackingCategoryID, + trackingOptionID: args?.trackingOptionID, + trackingCategoryID2: args?.trackingCategoryID2, + trackingOptionID2: args?.trackingOptionID2, + standardLayout: args?.standardLayout, + paymentsOnly: args?.paymentsOnly, + }); if (response.error !== null) { return { diff --git a/src/types/list-profit-and-loss-params.ts b/src/types/list-profit-and-loss-params.ts new file mode 100644 index 00000000..3047b223 --- /dev/null +++ b/src/types/list-profit-and-loss-params.ts @@ -0,0 +1,15 @@ +import { timeframeType } from "./timeframeType.js"; + +// Define an interface for the profit and loss parameters +export interface ListProfitAndLossParams { + fromDate?: string; + toDate?: string; + periods?: number; + timeframe?: timeframeType; + trackingCategoryID?: string; + trackingOptionID?: string; + trackingCategoryID2?: string; + trackingOptionID2?: string; + standardLayout?: boolean; + paymentsOnly?: boolean; +}