Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change FEMA filter logic to be inclusive, remove Unknown project type filter #1522

Merged
merged 2 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion client/app/templates/components/project-list-item.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
</span>
</a>
{{/if}}
<span class="label publicstatus-label">{{unless (eq project.dcpPublicstatusSimp 'Unknown') project.dcpPublicstatusSimp "Unknown Status"}}</span>
</div>
<div class="cell auto">
{{#if project.dcpLastmilestonedate}}
Expand Down
2 changes: 1 addition & 1 deletion client/app/templates/show-geography.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
filterTitle=(get-label-for 'filters.dcp_publicstatus')
tooltip='These checkboxes filter projects by their stage in the application process. "Noticed" refers to applications where notice has been given that an application will certify no sooner than 30 days per the City Charter requirement. In "Public Review” refers to applications that have graduated to the public review process. “Completed” refers to applications that have been Approved, Disapproved, Withdrawn or Terminated.'}}
<ul class="menu vertical medium-horizontal stage-checkboxes">
{{#each (array 'Filed' 'Noticed' 'In Public Review' 'Completed' 'Unknown') as |type|}}
{{#each (array 'Filed' 'Noticed' 'In Public Review' 'Completed') as |type|}}
<li {{action section.delegate-mutation (action 'mutateArray' 'dcp_publicstatus' type)}}
data-test-status-checkbox={{type}}
>
Expand Down
2 changes: 1 addition & 1 deletion client/mirage/factories/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default Factory.extend({
// Domain is ['Noticed', Filed', 'In Public Review', 'Completed']
dcpPublicstatus: 'Filed',

// Domain is ['Noticed', 'Filed', 'In Public Review', 'Completed', 'Unknown']
// Domain is ['Noticed', 'Filed', 'In Public Review', 'Completed']
// This field is derived from dcpPublicstatus.
// See https://github.com/NYCPlanning/zap-api/blob/develop/queries/projects/show.sql#L28
dcpPublicstatusSimp: 'Filed',
Expand Down
59 changes: 39 additions & 20 deletions server/src/crm/crm.utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function coerceToNumber(numericStrings) {
numericStrings
// filter out blank strings and undefined, which aren't meaningfully
// coercible in CRM
.filter(stringish => stringish !== "" && stringish !== undefined)
.filter(stringish => stringish !== '' && stringish !== undefined)
.map(stringish => {
// smelly; but let's prefer actual null
// coercing 'null' turns to 0, which we don't
Expand All @@ -21,7 +21,7 @@ export function coerceToNumber(numericStrings) {
// Coercing an empty string into a number returns
// NaN, which, although a number, is a Double in CRM
// which typically expects an Int
if (stringish === "") return stringish;
if (stringish === '') return stringish;

return Number(stringish);
})
Expand All @@ -39,25 +39,44 @@ export function mapInLookup(arrayOfStrings, lookupHash) {
}

export function all(...statements): string {
return statements.filter(Boolean).join(" and ");
const femaFloodZoneFilters = statements.filter(statement => {
if (statement.includes('femafloodzone') && statement.includes('true'))
return statement;
});
const filters = statements.filter(statement => {
if (!statement.includes('femafloodzone')) return statement;
});

if (femaFloodZoneFilters.length > 0) {
const femaFilterString = femaFloodZoneFilters.join(' and ');
const filterString = filters.filter(Boolean).join(' and ');

const allStatements = filterString.concat(
' and ',
`((${femaFilterString}))`
);
return allStatements;
}

return statements.filter(Boolean).join(' and ');
}

export function any(...statements): string {
return `(${statements.join(" or ")})`;
return `(${statements.join(' or ')})`;
}

export function comparisonOperator(propertyName, operator, value) {
let typeSafeValue = value;

if (typeof value === "string") {
if (value !== "false" && value !== "true") {
if (typeof value === 'string') {
if (value !== 'false' && value !== 'true') {
typeSafeValue = `'${value}'`;
}
}

// most likely means it's a date. we want the date formatting that
// json stringify provides.
if (typeof value === "object") {
if (typeof value === 'object') {
const stringyDate = JSON.stringify(value).replace(/"/g, "'");

typeSafeValue = `${stringyDate}`;
Expand All @@ -72,22 +91,22 @@ export function containsString(propertyName, string) {

export function equalsAnyOf(propertyName, strings = []) {
const querySegment = strings
.map(string => comparisonOperator(propertyName, "eq", string))
.join(" or ");
.map(string => comparisonOperator(propertyName, 'eq', string))
.join(' or ');

// Empty parenthases are invalid
return querySegment ? `(${querySegment})` : "";
return querySegment ? `(${querySegment})` : '';
}

export function containsAnyOf(propertyName, strings = [], options?) {
const { childEntity = "", comparisonStrategy = containsString, not = false } =
const { childEntity = '', comparisonStrategy = containsString, not = false } =
options || {};

const containsQuery = strings
.map((string, i) => {
// in odata syntax, this character o is a variable for scoping
// logic for related entities. it needs to only appear once.
const lambdaScope = childEntity && i === 0 ? `${childEntity}:` : "";
const lambdaScope = childEntity && i === 0 ? `${childEntity}:` : '';
const lambdaScopedProperty = childEntity
? `${childEntity}/${propertyName}`
: propertyName;
Expand All @@ -97,18 +116,18 @@ export function containsAnyOf(propertyName, strings = [], options?) {
string
)}`;
})
.join(" or ");
const lambdaQueryPrefix = childEntity ? `${childEntity}/any` : "";
.join(' or ');
const lambdaQueryPrefix = childEntity ? `${childEntity}/any` : '';

return `(${not ? "not " : ""}${lambdaQueryPrefix}(${containsQuery}))`;
return `(${not ? 'not ' : ''}${lambdaQueryPrefix}(${containsQuery}))`;
}

export const dateParser = function(key, value) {
if (typeof value === "string") {
if (typeof value === 'string') {
// YYYY-MM-DDTHH:mm:ss.sssZ => parsed as UTC
// YYYY-MM-DD => parsed as local date

if (value != "") {
if (value != '') {
const a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(
value
);
Expand Down Expand Up @@ -148,7 +167,7 @@ export const dateParser = function(key, value) {
return value;
};

const COMMUNITY_DISPLAY_TOKEN = "@OData.Community.Display.V1.FormattedValue";
const COMMUNITY_DISPLAY_TOKEN = '@OData.Community.Display.V1.FormattedValue';

// CRM provides numeric codes for picklist types
// for example, "yes" might appear as "1"
Expand All @@ -161,7 +180,7 @@ export function overwriteCodesWithLabels(records, targetFields) {
// parent record
Object.keys(record)
.filter(key => key.includes(COMMUNITY_DISPLAY_TOKEN))
.map(key => key.replace(COMMUNITY_DISPLAY_TOKEN, ""))
.map(key => key.replace(COMMUNITY_DISPLAY_TOKEN, ''))
.forEach(key => {
if (targetFields.includes(key)) {
newRecord[key] = record[`${key}${COMMUNITY_DISPLAY_TOKEN}`];
Expand All @@ -182,7 +201,7 @@ export function overwriteCodesWithLabels(records, targetFields) {

Object.keys(record)
.filter(key => key.includes(COMMUNITY_DISPLAY_TOKEN))
.map(key => key.replace(COMMUNITY_DISPLAY_TOKEN, ""))
.map(key => key.replace(COMMUNITY_DISPLAY_TOKEN, ''))
.forEach(key => {
if (targetFields.includes(key)) {
newRecord[key] = record[`${key}${COMMUNITY_DISPLAY_TOKEN}`];
Expand Down
3 changes: 1 addition & 2 deletions server/src/project/project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ export const PROJECT_STATUS_LOOKUP = {
Noticed: 717170005,
Filed: 717170000,
"In Public Review": 717170001,
Completed: 717170002,
Unknown: null
Completed: 717170002
};
export const PROJECT_VISIBILITY_LOOKUP = {
"Applicant Only": 717170002,
Expand Down
Loading