Skip to content

Commit

Permalink
Merge pull request #374 from Enterprise-CMCS/val
Browse files Browse the repository at this point in the history
Release to production
  • Loading branch information
mdial89f authored Feb 13, 2024
2 parents bcc4114 + fbb0f1f commit 2c81828
Show file tree
Hide file tree
Showing 60 changed files with 4,852 additions and 1,587 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:
- deploy
env:
baseurl: ${{ needs.deploy.outputs.app-url }}
if: ${{ github.ref != 'refs/heads/production' && github.ref != 'refs/heads/val' }}
if: ${{ github.ref != 'refs/heads/production' }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
86 changes: 86 additions & 0 deletions docs/docs/team-norms/code-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
layout: default
title: Code Style Cheatsheet
parent: Team Norms
nav_order: 2
---

# Code Style

### What is it?

A set of rules or guidelines used when writing the source code for a computer program.

### Why is it?

It keeps the code looking neat and tidy, so anyone on the team can jump in and not
get lost in a jungle of curly braces and indentation levels. It's like everyone speaking
the same slang in a super cool secret club. Plus, it saves time from arguing over trivial
stuff, like whether tabs are better than spaces, so there's more time for the fun
stuff—coding and creating!

# OneMAC Style Norms

## Cheatsheet

TL;DR? No worries, here's a cheatsheet of the concepts outlined below:

- [DO NOT destructure](#object-access) so we maintain object context for methods and properties used in code

### Object Access

When integrating with complex objects, consider maintaining the object's integrity rather
than opting for destructuring. This approach ensures that the object's context is
preserved, enhancing readability and maintainability.

#### Nomenclature simplification

For instance, rather than breaking
down the object into individual variables, which can lead to verbose and confusing naming
conventions, maintain the object as a whole.

```typescript jsx
const {
setModalOpen,
setContent: setModalContent,
setOnAccept: setModalOnAccept,
} = useModalContext();
const {
setContent: setBannerContent,
setBannerShow,
setBannerDisplayOn,
} = useAlertContext();

// vs

const modal = useModalContext();
const alert = useAlertContext();
```

#### Usage implication

This method simplifies reference to its properties and methods, providing a clearer and
more direct understanding of its usage within the code. This strategy is particularly
beneficial in scenarios where the object's structure and context significantly contribute
to its functionality and meaning in the application.

```typescript jsx
<form
onSubmit={form.handleSubmit(async (data) => {
try {
await submit({
//...
});
alert.setContent({
header: "RAI response submitted",
body: `The RAI response for ${item._source.id} has been submitted.`,
});
alert.setBannerShow(true);
alert.setBannerDisplayOn("/dashboard");
navigate({ path: "/dashboard" });
} catch (e) {
//...
}
})}
>
```
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "macpro-om-template",
"name": "macpro-mako",
"type": "module",
"description": "TBD.",
"version": "0.0.0-managed-by-semantic-release",
Expand All @@ -21,18 +21,20 @@
"test-gui": "vitest --ui",
"test-tsc": "tsc --skipLibCheck --noEmit"
},
"repository": "https://github.com/Enterprise-CMCS/macpro-om-template",
"repository": "https://github.com/Enterprise-CMCS/macpro-mako",
"workspaces": [
"src/services/*",
"src/libs",
"src/cli",
"src/packages/*"
],
"license": "CC0-1.0",
"homepage": "https://github.com/Enterprise-CMCS/macpro-om-template#readme",
"homepage": "https://github.com/Enterprise-CMCS/macpro-mako#readme",
"devDependencies": {
"@enterprise-cmcs/macpro-serverless-running-stages": "^1.0.4",
"@enterprise-cmcs/serverless-waf-plugin": "^1.3.0",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@serverless/compose": "^1.3.0",
"@stratiformdigital/serverless-iam-helper": "^3.2.0",
"@stratiformdigital/serverless-online": "^3.1.0",
Expand All @@ -45,7 +47,7 @@
"aws-sdk-client-mock": "^2.0.1",
"esbuild": "^0.19.3",
"prettier": "2.7.1",
"semantic-release": "^19.0.5",
"semantic-release": "^21.0.1",
"serverless": "^3.38.0",
"serverless-disable-functions": "^1.0.0",
"serverless-esbuild": "^1.47.0",
Expand All @@ -64,8 +66,7 @@
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github",
"@semantic-release/npm"
"@semantic-release/github"
]
},
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/packages/shared-types/action-types/new-submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { attachmentSchema } from "../attachments";
// This is the event schema for ne submissions from our system
export const onemacSchema = z.object({
authority: z.string(),
seaActionType: z.string().optional(), // Used by waivers.
origin: z.string(),
additionalInformation: z.string().nullable().default(null),
submitterName: z.string(),
Expand Down
10 changes: 10 additions & 0 deletions src/packages/shared-types/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ export const attachmentTitleMap: Record<string, string> = {
other: "Other",
// RAI WITHDRAW
supportingDocumentation: "Supporting Documentation",
bCapWaiverApplication:
"1915(b) Comprehensive (Capitated) Waiver Application Pre-print",
bCapCostSpreadsheets:
"1915(b) Comprehensive (Capitated) Waiver Cost Effectiveness Spreadsheets",
bCapIndependentAssessment:
"1915(b) Comprehensive (Capitated) Waiver Independent Assessment (first two renewals only)",
b4WaiverApplication:
"1915(b)(4) FFS Selective Contracting (Streamlined) Waiver Application Pre-print",
b4IndependentAssessment:
"1915(b)(4) FFS Selective Contracting (Streamlined) Independent Assessment (first two renewals only)",
};
export type AttachmentKey = keyof typeof attachmentTitleMap;
export type AttachmentTitle = typeof attachmentTitleMap[AttachmentKey];
Expand Down
3 changes: 3 additions & 0 deletions src/packages/shared-types/planType.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export enum PlanType {
MED_SPA = "medicaid spa",
CHIP_SPA = "chip spa",
WAIVER = "waiver",
"1915b" = "1915(b)",
"1915c" = "1915(c)",
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export const getAvailableActions = (
result: opensearch.main.Document
) => {
const checks = PackageCheck(result);
return checks.isSpa
? rules.filter((r) => r.check(checks, user)).map((r) => r.action)
: [];
return [
...((checks.isWaiver || checks.isSpa)
? rules.filter((r) => r.check(checks, user)).map((r) => r.action)
: []),
];
};
14 changes: 13 additions & 1 deletion src/packages/shared-utils/package-actions/rules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Action,
ActionRule,
PlanType,
SEATOOL_STATUS,
finalDispositionStatuses,
} from "../../shared-types";
Expand All @@ -10,7 +11,18 @@ const arIssueRai: ActionRule = {
action: Action.ISSUE_RAI,
check: (checker, user) =>
checker.isInActivePendingStatus &&
(!checker.hasLatestRai || checker.hasRequestedRai) &&
(
// Doesn't have any RAIs
!checker.hasLatestRai ||
(
// The latest RAI is complete
checker.hasCompletedRai &&
// The package is not a medicaid spa (med spas only get 1 rai)
!checker.planTypeIs([PlanType.MED_SPA]) &&
// The package does not have RAI Response Withdraw enabled
!checker.hasEnabledRaiWithdraw
)
) &&
isCmsWriteUser(user),
};

Expand Down
8 changes: 7 additions & 1 deletion src/packages/shared-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@
"version": "0.0.0",
"private": true,
"license": "MIT",
"devDependencies": {}
"scripts": {
"test": "vitest"
},
"devDependencies": {},
"dependencies": {
"@18f/us-federal-holidays": "^4.0.0"
}
}
12 changes: 7 additions & 5 deletions src/packages/shared-utils/packageCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const PackageCheck = ({
}: opensearch.main.Document) => {
const planChecks = {
isSpa: checkPlan(planType, [PlanType.MED_SPA, PlanType.CHIP_SPA]),
isWaiver: checkPlan(planType, []),
isWaiver: checkPlan(planType, [PlanType["1915b"]]),
/** Keep excess methods to a minimum with `is` **/
planTypeIs: (validPlanTypes: PlanType[]) =>
checkPlan(planType, validPlanTypes),
Expand All @@ -52,12 +52,14 @@ export const PackageCheck = ({
checkStatus(seatoolStatus, authorizedStatuses),
};
const raiChecks = {
/** Latest RAI is requested and status is Pending-RAI **/
hasRequestedRai: !!raiRequestedDate && !raiReceivedDate && !raiWithdrawnDate,
/** Latest RAI is not null **/
/** There is an RAI and it does not have a response **/
hasRequestedRai: !!raiRequestedDate && !raiReceivedDate,
/** There is an RAI **/
hasLatestRai: !!raiRequestedDate,
/** Latest RAI has been responded to **/
/** There is an RAI, it has a response, and it has not been withdrawn **/
hasRaiResponse: !!raiRequestedDate && !!raiReceivedDate && !raiWithdrawnDate,
/** Latest RAI has a response and/or has been withdrawn **/
hasCompletedRai: !!raiRequestedDate && !!raiReceivedDate,
/** RAI Withdraw has been enabled **/
hasEnabledRaiWithdraw: raiWithdrawEnabled,
};
Expand Down
26 changes: 26 additions & 0 deletions src/packages/shared-utils/seatool-date-helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import moment from "moment-timezone";
import * as fedHolidays from '@18f/us-federal-holidays';


// This manually accounts for the offset between the client's timezone and UTC.
export const offsetForUtc = (date: Date): Date => {
Expand All @@ -18,4 +20,28 @@ export const seaToolFriendlyTimestamp = (date?: Date): number => {
// This takes an epoch string and converts it to a standard format for display
export const formatSeatoolDate = (date: string): string => {
return moment(date).tz("UTC").format("MM/DD/yyyy")
}

export const getNextBusinessDayTimestamp = (date: Date = new Date()): number => {
let localeStringDate = date.toLocaleString("en-US", { timeZone: "America/New_York", dateStyle: "short" });
let localeStringHours24 = date.toLocaleString("en-US", { timeZone: "America/New_York", hour: 'numeric', hour12: false });
let localeDate = new Date(localeStringDate);

console.log(`Evaluating ${localeStringDate} at ${localeStringHours24}`);

const after5pmEST = parseInt(localeStringHours24,10) >= 17
const isHoliday = fedHolidays.isAHoliday(localeDate)
const isWeekend = !(localeDate.getDay() % 6)
if(after5pmEST || isHoliday || isWeekend) {
let nextDate = localeDate;
nextDate.setDate(nextDate.getDate() + 1);
nextDate.setHours(12,0,0,0)
console.log("Current date is not valid. Will try " + nextDate)
return getNextBusinessDayTimestamp(nextDate)
}

// Return the next business day's epoch for midnight UTC
let ret = offsetForUtc(localeDate).getTime();
console.log('Current date is a valid business date. Will return ' + ret);
return ret;
}
42 changes: 42 additions & 0 deletions src/packages/shared-utils/tests/seatool-date-helper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { it, describe, expect } from "vitest";
import { getNextBusinessDayTimestamp } from "../seatool-date-helper";

describe("The getNextBusinessDayTimestamp function", () => {
it("identifies weekenends", () => {
let testDate = new Date(2024, 0, 27, 12, 0, 0); // Saturday, noon, utc
let nextDate = getNextBusinessDayTimestamp(testDate);
expect(nextDate).toEqual(Date.UTC(2024, 0, 29)); // Monday, midnight, utc
});

it("identifies holidays", () => {
let testDate = new Date(2024, 0, 15, 12, 0, 0); // MLK Day, a Monday
let nextDate = getNextBusinessDayTimestamp(testDate);
expect(nextDate).toEqual(Date.UTC(2024, 0, 16)); // Tuesday, midnight, utc
});

it("identifies submissions after 5pm eastern", () => {
let testDate = new Date(2024, 0, 17, 23, 0, 0); // Wednesday 11pm utc, Wednesday 6pm eastern
let nextDate = getNextBusinessDayTimestamp(testDate);
expect(nextDate).toEqual(Date.UTC(2024, 0, 18)); // Thursday, midnight, utc
});

it("identifies submissions before 5pm eastern", () => {
let testDate = new Date(2024, 0, 17, 10, 0, 0); // Wednesday 10am utc, Wednesday 5am eastern
let nextDate = getNextBusinessDayTimestamp(testDate);
expect(nextDate).toEqual(Date.UTC(2024, 0, 17)); // Wednesday, midnight, utc
});

it("handles combinations of rule violations", () => {
let testDate = new Date(2024, 0, 12, 23, 0, 0); // Friday 11pm utc, Friday 6pm eastern
let nextDate = getNextBusinessDayTimestamp(testDate);
// Submission is after 5pm, Saturday is a weekend, Sunday is a weekend, and Monday is MLK Day
expect(nextDate).toEqual(Date.UTC(2024, 0, 16)); // Tuesday, midnight utc
});

it("identifies valid business days", () => {
let testDate = new Date(2024, 0, 9, 15, 0, 0); // Tuesday 3pm utc, Tuesday 8am eastern
let nextDate = getNextBusinessDayTimestamp(testDate);
expect(nextDate).toEqual(Date.UTC(2024, 0, 9)); // Tuesday, midnight utc
});

});
Loading

0 comments on commit 2c81828

Please sign in to comment.