Skip to content

Commit

Permalink
Merge pull request #5180 from ustaxcourt/opex-count-event-codes
Browse files Browse the repository at this point in the history
breaking out event-codes-by-year into -count-non-stricken-event-codes
  • Loading branch information
jimlerza committed Sep 9, 2024
2 parents 62ebe70 + bb07543 commit 4a1a246
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 16 deletions.
170 changes: 170 additions & 0 deletions scripts/reports/count-event-codes-by-year.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/usr/bin/env npx ts-node --transpile-only

// usage: scripts/reports/count-event-codes-by-year.ts m01,m02 feew [-y 2000-2020]

import { DateTime } from 'luxon';
import {
ServerApplicationContext,
createApplicationContext,
} from '@web-api/applicationContext';
import { count } from '@web-api/persistence/elasticsearch/searchClient';
import { parseArgs } from 'node:util';
import { parseIntsArg } from './reportUtils';
import { requireEnvVars } from '../../shared/admin-tools/util';
import { validateDateAndCreateISO } from '@shared/business/utilities/DateHandler';

requireEnvVars(['ENV', 'REGION']);

let positionals, values;

const config = {
allowPositionals: true,
options: {
stricken: {
default: false,
short: 's',
type: 'boolean',
},
verbose: {
default: false,
short: 'v',
type: 'boolean',
},
years: {
default: `${DateTime.now().toObject().year}`,
short: 'y',
type: 'string',
},
},
strict: true,
} as const;

function usage(warning: string | undefined) {
if (warning) {
console.log(warning);
}
console.log(`Usage: ${process.argv[1]} M071,m074 `);
console.log('Options:', JSON.stringify(config, null, 4));
}

const getCountDocketEntriesByEventCodesAndYears = async ({
applicationContext,
eventCodes,
onlyNonStricken,
years,
}: {
applicationContext: ServerApplicationContext;
eventCodes: string[];
onlyNonStricken: boolean;
years?: number[];
}): Promise<number> => {
const must: {}[] = [
{
bool: {
should: eventCodes.map(eventCode => {
return {
term: {
'eventCode.S': eventCode,
},
};
}),
},
},
];
if (onlyNonStricken) {
must.push({
term: {
'isStricken.BOOL': false,
},
});
}
if (years && years.length) {
if (years.length === 1) {
must.push({
range: {
'receivedAt.S': {
gte: validateDateAndCreateISO({
day: '1',
month: '1',
year: String(years[0]),
}),
lt: validateDateAndCreateISO({
day: '1',
month: '1',
year: String(years[0] + 1),
}),
},
},
});
} else {
must.push({
bool: {
should: years.map(year => {
return {
range: {
'receivedAt.S': {
gte: validateDateAndCreateISO({
day: '1',
month: '1',
year: String(year),
}),
lt: validateDateAndCreateISO({
day: '1',
month: '1',
year: String(year + 1),
}),
},
},
};
}),
},
});
}
}
const searchParameters = {
body: {
query: {
bool: {
must,
},
},
},
index: 'efcms-docket-entry',
};
// console.log('Effective Query:', JSON.stringify(searchParameters, null, 4));

const results = await count({
applicationContext,
searchParameters,
});
return results;
};

// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
try {
({ positionals, values } = parseArgs(config));
} catch (ex) {
usage(`Error: ${ex}`);
process.exit(1);
}
if (positionals.length === 0) {
usage('invalid input: expected event codes');
process.exit(1);
}
const eventCodes = positionals[0].split(',').map(s => s.toUpperCase());
const years: number[] = parseIntsArg(values.years);
const includeStricken = values.stricken;
const ret = await getCountDocketEntriesByEventCodesAndYears({
applicationContext: createApplicationContext({}),
eventCodes,
onlyNonStricken: !includeStricken,
years,
});
if (values.verbose) {
usage('Verbose output enabled');
console.log(`positionals: ${positionals}`);
console.log(`option values: ${values}`);
}
console.log(ret);
})();
55 changes: 39 additions & 16 deletions scripts/reports/event-codes-by-year.ts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// usage: npx ts-node --transpile-only scripts/reports/event-codes-by-year.ts M071,M074 2021-2022 > ~/Desktop/m071s-and-m074s-filed-2021-2022.csv
#!/usr/bin/env npx ts-node --transpile-only

// usage: scripts/reports/event-codes-by-year.ts M071,M074 [-y 2021-2022] > ~/Desktop/m071s-and-m074s-filed-2021-2022.csv

import { DateTime } from 'luxon';
import { createApplicationContext } from '@web-api/applicationContext';
import { parseArgs } from 'node:util';
import { parseIntsArg } from './reportUtils';
import { requireEnvVars } from '../../shared/admin-tools/util';
import {
search,
Expand All @@ -9,6 +14,27 @@ import {
import { validateDateAndCreateISO } from '@shared/business/utilities/DateHandler';

requireEnvVars(['ENV', 'REGION']);
let positionals, values;

const config = {
allowPositionals: true,
options: {
years: {
default: `${DateTime.now().toObject().year}`,
short: 'y',
type: 'string',
},
},
strict: true,
} as const;

function usage(warning: string | undefined) {
if (warning) {
console.log(warning);
}
console.log(`Usage: ${process.argv[1]} M071,m074 [-y 2023,2024]`);
console.log('Options:', JSON.stringify(config, null, 4));
}

const cachedCases: { [key: string]: RawCase } = {};

Expand Down Expand Up @@ -132,22 +158,19 @@ const getDocketEntriesByEventCodesAndYears = async ({

// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
const applicationContext = createApplicationContext({});

const eventCodes = process.argv[2].split(',');
const years: number[] = [];
const yearArg = process.argv[3];
if (yearArg.includes('-')) {
const [lower, upper] = yearArg.split('-');
for (let i = Number(lower); i <= Number(upper); i++) {
years.push(Number(i));
}
} else {
const yearStrings = yearArg.split(',');
for (const year of yearStrings) {
years.push(Number(year));
}
try {
({ positionals, values } = parseArgs(config));
} catch (ex) {
usage(`Error: ${ex}`);
process.exit(1);
}
if (positionals.length === 0) {
usage('invalid input: expected event codes');
process.exit(1);
}
const eventCodes = positionals[0].split(',').map(s => s.toUpperCase());
const years: number[] = parseIntsArg(values.years);
const applicationContext = createApplicationContext({});

const docketEntries = await getDocketEntriesByEventCodesAndYears({
applicationContext,
Expand Down
55 changes: 55 additions & 0 deletions scripts/reports/reportUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { parseIntRange, parseInts, parseIntsArg } from './reportUtils';

describe('parseIntsRange', () => {
it('returns array when given valid ranges', () => {
expect(parseIntRange('1-2')).toEqual([1, 2]);
expect(parseIntRange('3-1')).toEqual([1, 2, 3]);
expect(parseIntRange('1-3')).toEqual([1, 2, 3]);
expect(parseIntRange('0-0')).toEqual([0]); // hoot!
expect(parseIntRange('')).toEqual([]);
});

it('returns single item array when given single number', () => {
expect(parseIntRange('1')).toEqual([1]);
});

it('returns empty array when given no valid input', () => {
expect(parseIntRange('')).toEqual([]);
});
});

describe('parseInts', () => {
it('should return empty array when given empty input', () => {
expect(parseInts('')).toEqual([]);
});
it('should ignore trailing comma', () => {
expect(parseInts('1,')).toEqual([1]);
});
it('should return an array when given comma-delimited list', () => {
expect(parseInts('1,2,3')).toEqual([1, 2, 3]);
});
it('should return an array when given tab-delimited list', () => {
expect(parseInts('1\t2\t3', '\t')).toEqual([1, 2, 3]);
});

it('should return array of ints', () => {
let ints = parseInts('1,2,3');
expect(ints).toEqual([1, 2, 3]);
ints.forEach(n => {
expect(typeof n).toBe('number');
});
});
});

describe('parseIntsArg', () => {
it('returns empty array when given empty input', () => {
expect(parseIntsArg('')).toEqual([]);
});
it('handles int ranges', () => {
expect(parseIntsArg('1-3')).toEqual([1, 2, 3]);
});

it('handles int lists', () => {
expect(parseIntsArg('1,2,3')).toEqual([1, 2, 3]);
});
});
35 changes: 35 additions & 0 deletions scripts/reports/reportUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export function parseInts(ints: string, delimiter = ','): number[] {
let nums = ints
.split(delimiter)
.filter(s => s.length)
.map(s => parseInt(s));
return nums;
}

export function parseIntRange(intRange: string): number[] {
const ints = intRange
.split('-')
.filter(s => s.length)
.map(s => parseInt(s));
const min = Math.min(...ints);
const max = Math.max(...ints);
let rangeNums: number[] = [];
for (let i = min; i <= max; i++) {
rangeNums.push(i);
}
return rangeNums;
}

// eslint-disable-next-line spellcheck/spell-checker
/**
*
* @param intstr a string containing an int (e.g. '1'), list of ints(e.g. '1,2,3'), or inclusive int range (e.g. '1-3')
* @returns an array of one or more integers
*/
export function parseIntsArg(intstr: string): number[] {
if (intstr.indexOf('-') > 0) {
return parseIntRange(intstr);
} else {
return parseInts(intstr);
}
}

0 comments on commit 4a1a246

Please sign in to comment.