From d57f1f68840671fbcdd257e26d948519397c6eb1 Mon Sep 17 00:00:00 2001 From: Sasha Dresden Date: Tue, 15 Oct 2024 11:36:12 -0400 Subject: [PATCH 01/68] Commenting out dead links --- .../header-links/header-links.component.html | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/front-end/src/app/layout/header/header-links/header-links.component.html b/front-end/src/app/layout/header/header-links/header-links.component.html index c4526beff..125fc6cb7 100644 --- a/front-end/src/app/layout/header/header-links/header-links.component.html +++ b/front-end/src/app/layout/header/header-links/header-links.component.html @@ -6,11 +6,11 @@ - @@ -28,19 +28,19 @@ - + --> From 73b7afd6e98d56d757c2ff13b0c819c17db1a62a Mon Sep 17 00:00:00 2001 From: Sasha Dresden Date: Wed, 16 Oct 2024 17:16:29 -0400 Subject: [PATCH 02/68] Fix issues with page overflow when sidebar screens --- front-end/src/app/layout/layout.component.html | 6 ++---- front-end/src/app/layout/layout.component.scss | 7 +++++-- .../transaction-list/transaction-list.component.html | 2 +- front-end/src/assets/styles/theme.css | 1 + 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/front-end/src/app/layout/layout.component.html b/front-end/src/app/layout/layout.component.html index 93cb98318..4b220fa2f 100644 --- a/front-end/src/app/layout/layout.component.html +++ b/front-end/src/app/layout/layout.component.html @@ -17,10 +17,8 @@ -
-
- -
+
+
diff --git a/front-end/src/app/layout/layout.component.scss b/front-end/src/app/layout/layout.component.scss index 63958a662..98e50a56c 100644 --- a/front-end/src/app/layout/layout.component.scss +++ b/front-end/src/app/layout/layout.component.scss @@ -1,5 +1,8 @@ #sidebar-container { min-height: calc(100vh - 2rem); + width: 250px; + min-width: 250px; + max-width: 250px; } .main-content { @@ -11,7 +14,7 @@ .sidebar-content-container > .main-content { margin-left: 32px; margin-right: 0; - width: 100%; + width: calc(100% - 64px); } .header-container { @@ -38,7 +41,7 @@ app-footer { .sidebar-content-container { min-height: calc(100vh - 2rem); - width: 100%; + width: calc(100% - 250px); display: flex; flex-direction: column; } diff --git a/front-end/src/app/reports/transactions/transaction-list/transaction-list.component.html b/front-end/src/app/reports/transactions/transaction-list/transaction-list.component.html index 34b3f9867..2d363b036 100644 --- a/front-end/src/app/reports/transactions/transaction-list/transaction-list.component.html +++ b/front-end/src/app/reports/transactions/transaction-list/transaction-list.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/front-end/src/assets/styles/theme.css b/front-end/src/assets/styles/theme.css index 2a5b3b098..2fdd6c6a1 100644 --- a/front-end/src/assets/styles/theme.css +++ b/front-end/src/assets/styles/theme.css @@ -3827,6 +3827,7 @@ p-treeselect.p-treeselect-clearable .p-treeselect-clear-icon { .p-paginator { background: #ffffff; color: #112e51; + min-width: 167px; } .p-paginator .p-paginator-first, From 9ebb947a3bc746c77d30e2f49ab5b8ab9dc88ad4 Mon Sep 17 00:00:00 2001 From: Sasha Dresden Date: Wed, 16 Oct 2024 17:37:27 -0400 Subject: [PATCH 03/68] Make dates validate on change instead of blur --- .../f3x/create-workflow/cash-on-hand.component.ts | 4 +++- .../double-transaction-type-base.component.ts | 4 +++- .../reatt-redes-transaction-type-base.component.ts | 9 ++++++--- .../triple-transaction-type-base.component.ts | 4 +++- front-end/src/app/shared/utils/schema.utils.ts | 6 +++++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/front-end/src/app/reports/f3x/create-workflow/cash-on-hand.component.ts b/front-end/src/app/reports/f3x/create-workflow/cash-on-hand.component.ts index c4586da72..79a0278ff 100644 --- a/front-end/src/app/reports/f3x/create-workflow/cash-on-hand.component.ts +++ b/front-end/src/app/reports/f3x/create-workflow/cash-on-hand.component.ts @@ -21,7 +21,9 @@ export class CashOnHandComponent extends DestroyerComponent implements OnInit { formProperties: string[] = ['L6a_cash_on_hand_jan_1_ytd', 'cash_on_hand_date']; report: Form3X | undefined; formSubmitted = false; - form: FormGroup = this.fb.group(SchemaUtils.getFormGroupFields(this.formProperties), { updateOn: 'blur' }); + form: FormGroup = this.fb.group(SchemaUtils.getFormGroupFieldsNoBlur(this.formProperties, this.fb), { + updateOn: 'blur', + }); constructor( public router: Router, diff --git a/front-end/src/app/shared/components/transaction-type-base/double-transaction-type-base.component.ts b/front-end/src/app/shared/components/transaction-type-base/double-transaction-type-base.component.ts index 6eaa152c4..e94811206 100644 --- a/front-end/src/app/shared/components/transaction-type-base/double-transaction-type-base.component.ts +++ b/front-end/src/app/shared/components/transaction-type-base/double-transaction-type-base.component.ts @@ -65,7 +65,9 @@ export abstract class DoubleTransactionTypeBaseComponent this.childTemplateMap = this.childTransactionType.templateMap; this.childContactTypeOptions = getContactTypeOptions(this.childTransactionType.contactTypeOptions ?? []); this.childFormProperties = this.childTransactionType.getFormControlNames(); - this.childForm = this.fb.group(SchemaUtils.getFormGroupFields(this.childFormProperties), { updateOn: 'blur' }); + this.childForm = this.fb.group(SchemaUtils.getFormGroupFieldsNoBlur(this.childFormProperties, this.fb), { + updateOn: 'blur', + }); if ( this.childTransactionType diff --git a/front-end/src/app/shared/components/transaction-type-base/reatt-redes-transaction-type-base.component.ts b/front-end/src/app/shared/components/transaction-type-base/reatt-redes-transaction-type-base.component.ts index 9e0108e39..b5d9368a2 100644 --- a/front-end/src/app/shared/components/transaction-type-base/reatt-redes-transaction-type-base.component.ts +++ b/front-end/src/app/shared/components/transaction-type-base/reatt-redes-transaction-type-base.component.ts @@ -104,9 +104,12 @@ export abstract class ReattRedesTransactionTypeBaseComponent reatRedes.transactionType.contactTypeOptions ?? [], ); - this.reattributedData.form = this.fb.group(SchemaUtils.getFormGroupFields(this.reattributedData.formProperties), { - updateOn: 'blur', - }); + this.reattributedData.form = this.fb.group( + SchemaUtils.getFormGroupFieldsNoBlur(this.reattributedData.formProperties, this.fb), + { + updateOn: 'blur', + }, + ); this.reattributedData.contactIdMap = {}; this.reattributedData.memoCodeCheckboxLabel$ = this.getMemoCodeCheckboxLabel$( this.reattributedData.form, diff --git a/front-end/src/app/shared/components/transaction-type-base/triple-transaction-type-base.component.ts b/front-end/src/app/shared/components/transaction-type-base/triple-transaction-type-base.component.ts index 2671c8b95..a46bb8112 100644 --- a/front-end/src/app/shared/components/transaction-type-base/triple-transaction-type-base.component.ts +++ b/front-end/src/app/shared/components/transaction-type-base/triple-transaction-type-base.component.ts @@ -65,7 +65,9 @@ export abstract class TripleTransactionTypeBaseComponent this.childTemplateMap_2 = this.childTransactionType_2.templateMap; this.childContactTypeOptions_2 = getContactTypeOptions(this.childTransactionType_2.contactTypeOptions ?? []); this.childFormProperties_2 = this.childTransactionType_2.getFormControlNames(); - this.childForm_2 = this.fb.group(SchemaUtils.getFormGroupFields(this.childFormProperties_2), { updateOn: 'blur' }); + this.childForm_2 = this.fb.group(SchemaUtils.getFormGroupFieldsNoBlur(this.childFormProperties_2, this.fb), { + updateOn: 'blur', + }); if ( this.childTransactionType_2 diff --git a/front-end/src/app/shared/utils/schema.utils.ts b/front-end/src/app/shared/utils/schema.utils.ts index bb8e72f1a..9234a673b 100644 --- a/front-end/src/app/shared/utils/schema.utils.ts +++ b/front-end/src/app/shared/utils/schema.utils.ts @@ -41,12 +41,16 @@ export class SchemaUtils { static getFormGroupFieldsNoBlur(properties: string[], fb: FormBuilder) { const group: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any properties.forEach((property) => { - group[property] = fb.control('', SchemaUtils.noBlur.includes(property) ? { updateOn: 'change' } : {}); + group[property] = fb.control('', SchemaUtils.isNoBlur(property) ? { updateOn: 'change' } : {}); }); return group; } + private static isNoBlur(property: string) { + return property.includes('date') || SchemaUtils.noBlur.includes(property); + } + /** * * @param {FormGroup} form From d3fd7b6fb286a7fbeea1231292c529f4c33587e5 Mon Sep 17 00:00:00 2001 From: David Heitzer Date: Thu, 17 Oct 2024 00:22:42 -0400 Subject: [PATCH 04/68] 1118 add update coh page --- .../cash-on-hand-override.component.html | 65 +++++++++++++++++++ .../cash-on-hand-override.component.scss | 0 .../cash-on-hand-override.component.spec.ts | 33 ++++++++++ .../cash-on-hand-override.component.ts | 55 ++++++++++++++++ .../shared/services/form-3x.service.spec.ts | 13 ++++ .../app/shared/services/form-3x.service.ts | 27 +++++++- 6 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html create mode 100644 front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.scss create mode 100644 front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts create mode 100644 front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html new file mode 100644 index 000000000..77a294c05 --- /dev/null +++ b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html @@ -0,0 +1,65 @@ +

Line 6a override

+
+
+
+ WHAT IS A LINE 6A OVERRIDE? +

+ When there is a discrepancy between the reported (FECFile-calculated) cash on hand and the correct + (committee-calculated) cash on hand, committees filing a Form 3X can override the reported cash on hand by + manually entering an amount for Line 6(a). If your committee overrides Line 6(a), it will adjust the cash on hand + for any reports in that calendar year (submitted or in-progress) and amendments may need to be submitted. Further, + if the cash on hand is overridden on a report from a prior year, reports in subsequent years will also be adjusted + and amendments may be needed. +

+ NEED HELP? +

+ If you’re unsure whether an override is the right choice for your committee, please reach out to your assigned campaign finance analyst for guidance. +

+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+
diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.scss b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts new file mode 100644 index 000000000..344164091 --- /dev/null +++ b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts @@ -0,0 +1,33 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { provideMockStore } from '@ngrx/store/testing'; +import { testMockStore } from 'app/shared/utils/unit-test.utils'; +import { SharedModule } from 'primeng/api'; +import { DividerModule } from 'primeng/divider'; +import { DropdownModule } from 'primeng/dropdown'; +import { CashOnHandOverrideComponent } from './cash-on-hand-override.component'; + +describe('CashOnHandOverrideComponent', () => { + let component: CashOnHandOverrideComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + providers: [provideMockStore(testMockStore)], + declarations: [CashOnHandOverrideComponent], + imports: [DividerModule, DropdownModule, HttpClientTestingModule, FormsModule, ReactiveFormsModule, SharedModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CashOnHandOverrideComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + +}); diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts new file mode 100644 index 000000000..547b24595 --- /dev/null +++ b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { DestroyerComponent } from 'app/shared/components/app-destroyer.component'; +import { Form3XService } from 'app/shared/services/form-3x.service'; +import { takeUntil } from 'rxjs'; + +@Component({ + selector: 'app-cash-on-hand-override', + templateUrl: './cash-on-hand-override.component.html', + styleUrls: ['./cash-on-hand-override.component.scss'], +}) +export class CashOnHandOverrideComponent extends DestroyerComponent implements OnInit { + yearFormControl = new FormControl(null, Validators.required); + currentAmountFormControl = new FormControl(null, Validators.required); + newAmountFormControl = new FormControl(null, Validators.required); + yearOptions: number[] = []; + numberOfYearOptions = 25 + + form: FormGroup = new FormGroup({ + year: this.yearFormControl, + currentAmount: this.currentAmountFormControl, + newAmount: this.newAmountFormControl, + }); + + constructor( + private form3XService: Form3XService, + ) { + super(); + } + + ngOnInit(): void { + this.yearFormControl.valueChanges.pipe(takeUntil(this.destroy$)) + .subscribe((year) => { + if (year) { + this.form3XService.getJan1CashOnHand(year).then(cashOnHandForYear => { + this.currentAmountFormControl.setValue(cashOnHandForYear); + }); + } + }); + + const currentYear = new Date().getFullYear(); + this.yearOptions = Array.from( + { length: this.numberOfYearOptions }, + (value, index) => currentYear - this.numberOfYearOptions + index + ); + this.yearFormControl.setValue(this.yearOptions[this.yearOptions.length - 1]); + } + + updateLine6a(): void { + if (this.form.valid) { + this.form3XService.updateJan1CashOnHand(this.form.get('year')?.value, + this.form.get('amount')?.value).then(() => { }); + } + } +} diff --git a/front-end/src/app/shared/services/form-3x.service.spec.ts b/front-end/src/app/shared/services/form-3x.service.spec.ts index 84f34c1c5..fd1cccc42 100644 --- a/front-end/src/app/shared/services/form-3x.service.spec.ts +++ b/front-end/src/app/shared/services/form-3x.service.spec.ts @@ -65,6 +65,19 @@ describe('Form3XService', () => { httpTestingController.verify(); }); + it('#delete() should DELETE a record2', () => { + const form3X: Form3X = Form3X.fromJSON({ id: '999' }); + + service.delete(form3X).subscribe((response: null) => { + expect(response).toBeTrue(); + }); + + const req = httpTestingController.expectOne(`${environment.apiUrl}/reports/form-3x/999`); + expect(req.request.method).toEqual('DELETE'); + req.flush(null); + httpTestingController.verify(); + }); + describe('getFutureReports', () => { it('should return a list of Form3X reports whose coverage through is after the submitted value', () => { service.getFutureReports('2024-01-20').subscribe((reports) => { diff --git a/front-end/src/app/shared/services/form-3x.service.ts b/front-end/src/app/shared/services/form-3x.service.ts index a1c7989dc..378a0cb60 100644 --- a/front-end/src/app/shared/services/form-3x.service.ts +++ b/front-end/src/app/shared/services/form-3x.service.ts @@ -4,10 +4,10 @@ import { BehaviorSubject, Observable, firstValueFrom } from 'rxjs'; import { map } from 'rxjs/operators'; import { CommitteeAccount } from '../models/committee-account.model'; import { F3xCoverageDates, Form3X } from '../models/form-3x.model'; -import { ApiService } from './api.service'; -import { ReportService } from './report.service'; import { Report } from '../models/report.model'; import { F3xReportCodes } from '../utils/report-code.utils'; +import { ApiService } from './api.service'; +import { ReportService } from './report.service'; @Injectable({ providedIn: 'root', @@ -51,6 +51,29 @@ export class Form3XService extends ReportService { .pipe(map((response) => response.map((r) => Form3X.fromJSON(r)))); } + public getJan1CashOnHand(year: number): Promise { + return firstValueFrom( + this.apiService + .get(`${this.apiEndpoint}/jan1_cash_on_hand?year=${year}`) + .pipe( + map((response) => response), + ), + ); + } + + public updateJan1CashOnHand(year: number, amount: number): Promise { + return firstValueFrom( + this.apiService + .put(`${this.apiEndpoint}/jan1_cash_on_hand`, { + "year": year, + "amount": amount, + }) + .pipe( + map((response) => response), + ), + ); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public isQualifiedCommittee(committeeAccount?: CommitteeAccount) { return true; From f8cdb6b23f9ca9f636cc0ac5f8432964afbcda16 Mon Sep 17 00:00:00 2001 From: David Heitzer Date: Thu, 17 Oct 2024 20:47:02 -0400 Subject: [PATCH 05/68] 1118 local testing --- .../header-links/header-links.component.html | 2 +- .../cash-on-hand-override.component.spec.ts | 33 ------------ .../cash-on-hand-override.component.html | 6 +-- .../cash-on-hand-override.component.scss | 0 .../cash-on-hand-override.component.spec.ts | 52 +++++++++++++++++++ .../cash-on-hand-override.component.ts | 4 +- .../src/app/tools/tools-routing.module.ts | 15 ++++-- front-end/src/app/tools/tools.module.ts | 22 ++++++-- 8 files changed, 88 insertions(+), 46 deletions(-) delete mode 100644 front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts rename front-end/src/app/{reports/f3x => tools}/cash-on-hand-override/cash-on-hand-override.component.html (94%) rename front-end/src/app/{reports/f3x => tools}/cash-on-hand-override/cash-on-hand-override.component.scss (100%) create mode 100644 front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts rename front-end/src/app/{reports/f3x => tools}/cash-on-hand-override/cash-on-hand-override.component.ts (97%) diff --git a/front-end/src/app/layout/header/header-links/header-links.component.html b/front-end/src/app/layout/header/header-links/header-links.component.html index c4526beff..aab6dfb64 100644 --- a/front-end/src/app/layout/header/header-links/header-links.component.html +++ b/front-end/src/app/layout/header/header-links/header-links.component.html @@ -30,7 +30,7 @@ Import Export - Update cash on hand + Update cash on hand FECFile Help diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts b/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts deleted file mode 100644 index 344164091..000000000 --- a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { provideMockStore } from '@ngrx/store/testing'; -import { testMockStore } from 'app/shared/utils/unit-test.utils'; -import { SharedModule } from 'primeng/api'; -import { DividerModule } from 'primeng/divider'; -import { DropdownModule } from 'primeng/dropdown'; -import { CashOnHandOverrideComponent } from './cash-on-hand-override.component'; - -describe('CashOnHandOverrideComponent', () => { - let component: CashOnHandOverrideComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - providers: [provideMockStore(testMockStore)], - declarations: [CashOnHandOverrideComponent], - imports: [DividerModule, DropdownModule, HttpClientTestingModule, FormsModule, ReactiveFormsModule, SharedModule], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(CashOnHandOverrideComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - -}); diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html similarity index 94% rename from front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html rename to front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html index 77a294c05..bf163a4ce 100644 --- a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.html +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html @@ -1,6 +1,6 @@

Line 6a override


-
+
WHAT IS A LINE 6A OVERRIDE?

@@ -31,7 +31,7 @@

Line 6a override

@@ -42,7 +42,7 @@

Line 6a override

diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.scss b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.scss similarity index 100% rename from front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.scss rename to front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.scss diff --git a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts new file mode 100644 index 000000000..c88616c58 --- /dev/null +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts @@ -0,0 +1,52 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Router } from '@angular/router'; +import { provideMockStore } from '@ngrx/store/testing'; +import { ReportsModule } from 'app/reports/reports.module'; +import { Form3XService } from 'app/shared/services/form-3x.service'; +import { testMockStore } from 'app/shared/utils/unit-test.utils'; +import { CashOnHandOverrideComponent } from './cash-on-hand-override.component'; + +describe('CashOnHandOverrideComponent', () => { + let component: CashOnHandOverrideComponent; + let router: Router; + let fixture: ComponentFixture; + let form3XService: Form3XService; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CashOnHandOverrideComponent], + imports: [ + HttpClientTestingModule, + ReportsModule, + ], + providers: [Form3XService, provideMockStore(testMockStore)], + }).compileComponents(); + }); + + beforeEach(() => { + router = TestBed.inject(Router); + form3XService = TestBed.inject(Form3XService); + fixture = TestBed.createComponent(CashOnHandOverrideComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + expect(router).toBeTruthy(); + expect(form3XService).toBeTruthy(); + }); + + it('should call updateJan1CashOnHand', () => { + spyOn(component.form3XService, 'updateJan1CashOnHand').and.resolveTo(); + component.yearFormControl.setValue(2024); + component.currentAmountFormControl.setValue(0.00); + component.newAmountFormControl.setValue(25.00); + + component.updateLine6a(); + + expect(component.form3XService.updateJan1CashOnHand).toHaveBeenCalledTimes(1); + }); + +}); diff --git a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts similarity index 97% rename from front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts rename to front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts index 547b24595..1b630d260 100644 --- a/front-end/src/app/reports/f3x/cash-on-hand-override/cash-on-hand-override.component.ts +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts @@ -23,7 +23,7 @@ export class CashOnHandOverrideComponent extends DestroyerComponent implements O }); constructor( - private form3XService: Form3XService, + public form3XService: Form3XService, ) { super(); } @@ -41,7 +41,7 @@ export class CashOnHandOverrideComponent extends DestroyerComponent implements O const currentYear = new Date().getFullYear(); this.yearOptions = Array.from( { length: this.numberOfYearOptions }, - (value, index) => currentYear - this.numberOfYearOptions + index + (value, index) => currentYear - this.numberOfYearOptions + index + 1, ); this.yearFormControl.setValue(this.yearOptions[this.yearOptions.length - 1]); } diff --git a/front-end/src/app/tools/tools-routing.module.ts b/front-end/src/app/tools/tools-routing.module.ts index 89bcbe571..1dbba5e9d 100644 --- a/front-end/src/app/tools/tools-routing.module.ts +++ b/front-end/src/app/tools/tools-routing.module.ts @@ -1,10 +1,19 @@ import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; +import { RouterModule, Routes } from '@angular/router'; +import { CashOnHandOverrideComponent } from './cash-on-hand-override/cash-on-hand-override.component'; -const routes: Routes = [{ path: '**', redirectTo: '' }]; +const routes: Routes = [ + { + path: 'update-cash-on-hand', + component: CashOnHandOverrideComponent, + title: 'Update cash on hand', + pathMatch: 'full', + }, + { path: '**', redirectTo: '' }, +]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) -export class ToolsRoutingModule {} +export class ToolsRoutingModule { } diff --git a/front-end/src/app/tools/tools.module.ts b/front-end/src/app/tools/tools.module.ts index 137ae6613..751e79fc9 100644 --- a/front-end/src/app/tools/tools.module.ts +++ b/front-end/src/app/tools/tools.module.ts @@ -1,8 +1,22 @@ -import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { SharedModule } from 'app/shared/shared.module'; +import { DropdownModule } from 'primeng/dropdown'; +import { CashOnHandOverrideComponent } from './cash-on-hand-override/cash-on-hand-override.component'; +import { ToolsRoutingModule } from './tools-routing.module'; @NgModule({ - declarations: [], - imports: [CommonModule], + declarations: [ + CashOnHandOverrideComponent, + ], + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule, + DropdownModule, + SharedModule, + ToolsRoutingModule, + ], }) -export class ToolsModule {} +export class ToolsModule { } From b21e65e777ff22ce164b29dc8ea54886d6357cc8 Mon Sep 17 00:00:00 2001 From: David Heitzer Date: Fri, 18 Oct 2024 01:00:44 -0400 Subject: [PATCH 06/68] 1118 local testing --- .../app/shared/services/form-3x.service.ts | 14 +- .../cash-on-hand-override.component.html | 121 +++++++++--------- .../cash-on-hand-override.component.spec.ts | 10 +- .../cash-on-hand-override.component.ts | 28 ++-- .../src/app/tools/tools-routing.module.ts | 2 +- front-end/src/app/tools/tools.module.ts | 10 +- 6 files changed, 92 insertions(+), 93 deletions(-) diff --git a/front-end/src/app/shared/services/form-3x.service.ts b/front-end/src/app/shared/services/form-3x.service.ts index 378a0cb60..d45e45d1a 100644 --- a/front-end/src/app/shared/services/form-3x.service.ts +++ b/front-end/src/app/shared/services/form-3x.service.ts @@ -55,22 +55,18 @@ export class Form3XService extends ReportService { return firstValueFrom( this.apiService .get(`${this.apiEndpoint}/jan1_cash_on_hand?year=${year}`) - .pipe( - map((response) => response), - ), + .pipe(map((response) => response)), ); } public updateJan1CashOnHand(year: number, amount: number): Promise { return firstValueFrom( this.apiService - .put(`${this.apiEndpoint}/jan1_cash_on_hand`, { - "year": year, - "amount": amount, + .put(`${this.apiEndpoint}/jan1_cash_on_hand/`, { + year: year, + amount: amount, }) - .pipe( - map((response) => response), - ), + .pipe(map((response) => response)), ); } diff --git a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html index bf163a4ce..5f30a6af1 100644 --- a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.html @@ -1,65 +1,70 @@ -

Line 6a override

-
- -
- WHAT IS A LINE 6A OVERRIDE? -

- When there is a discrepancy between the reported (FECFile-calculated) cash on hand and the correct - (committee-calculated) cash on hand, committees filing a Form 3X can override the reported cash on hand by - manually entering an amount for Line 6(a). If your committee overrides Line 6(a), it will adjust the cash on hand - for any reports in that calendar year (submitted or in-progress) and amendments may need to be submitted. Further, - if the cash on hand is overridden on a report from a prior year, reports in subsequent years will also be adjusted - and amendments may be needed. -

- NEED HELP? -

- If you’re unsure whether an override is the right choice for your committee, please reach out to your assigned campaign finance analyst for guidance. -

-
-
-
-
-
- - -
-
+
+

Line 6a override

+
+ +
+ WHAT IS A LINE 6A OVERRIDE? +

+ When there is a discrepancy between the reported (FECFile-calculated) cash on hand and the correct + (committee-calculated) cash on hand, committees filing a Form 3X can override the reported cash on hand by + manually entering an amount for Line 6(a). If your committee overrides Line 6(a), it will adjust the cash on + hand for any reports in that calendar year (submitted or in-progress) and amendments may need to be submitted. + Further, if the cash on hand is overridden on a report from a prior year, reports in subsequent years will also + be adjusted and amendments may be needed. +

+ NEED HELP? +

+ If you’re unsure whether an override is the right choice for your committee, please reach out to your assigned + campaign finance analyst for guidance. +

-
-
-
- - +
+
+
+
+ + +
-
-
- - +
+
+
+ + +
+
+
+
+ + +
-
-
-
- +
+
+ +
-
-
- +
+ +
diff --git a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts index c88616c58..3b26e93ec 100644 --- a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.spec.ts @@ -16,10 +16,7 @@ describe('CashOnHandOverrideComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [CashOnHandOverrideComponent], - imports: [ - HttpClientTestingModule, - ReportsModule, - ], + imports: [HttpClientTestingModule, ReportsModule], providers: [Form3XService, provideMockStore(testMockStore)], }).compileComponents(); }); @@ -41,12 +38,11 @@ describe('CashOnHandOverrideComponent', () => { it('should call updateJan1CashOnHand', () => { spyOn(component.form3XService, 'updateJan1CashOnHand').and.resolveTo(); component.yearFormControl.setValue(2024); - component.currentAmountFormControl.setValue(0.00); - component.newAmountFormControl.setValue(25.00); + component.currentAmountFormControl.setValue(0.0); + component.newAmountFormControl.setValue(25.0); component.updateLine6a(); expect(component.form3XService.updateJan1CashOnHand).toHaveBeenCalledTimes(1); }); - }); diff --git a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts index 1b630d260..a15f151a5 100644 --- a/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts +++ b/front-end/src/app/tools/cash-on-hand-override/cash-on-hand-override.component.ts @@ -14,7 +14,7 @@ export class CashOnHandOverrideComponent extends DestroyerComponent implements O currentAmountFormControl = new FormControl(null, Validators.required); newAmountFormControl = new FormControl(null, Validators.required); yearOptions: number[] = []; - numberOfYearOptions = 25 + numberOfYearOptions = 25; form: FormGroup = new FormGroup({ year: this.yearFormControl, @@ -22,21 +22,18 @@ export class CashOnHandOverrideComponent extends DestroyerComponent implements O newAmount: this.newAmountFormControl, }); - constructor( - public form3XService: Form3XService, - ) { + constructor(public form3XService: Form3XService) { super(); } ngOnInit(): void { - this.yearFormControl.valueChanges.pipe(takeUntil(this.destroy$)) - .subscribe((year) => { - if (year) { - this.form3XService.getJan1CashOnHand(year).then(cashOnHandForYear => { - this.currentAmountFormControl.setValue(cashOnHandForYear); - }); - } - }); + this.yearFormControl.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((year) => { + if (year) { + this.form3XService.getJan1CashOnHand(year).then((cashOnHandForYear) => { + this.currentAmountFormControl.setValue(cashOnHandForYear); + }); + } + }); const currentYear = new Date().getFullYear(); this.yearOptions = Array.from( @@ -48,8 +45,11 @@ export class CashOnHandOverrideComponent extends DestroyerComponent implements O updateLine6a(): void { if (this.form.valid) { - this.form3XService.updateJan1CashOnHand(this.form.get('year')?.value, - this.form.get('amount')?.value).then(() => { }); + if (this.yearFormControl.value && this.newAmountFormControl.value) { + this.form3XService + .updateJan1CashOnHand(this.yearFormControl.value, this.newAmountFormControl.value) + .then(() => {}); + } } } } diff --git a/front-end/src/app/tools/tools-routing.module.ts b/front-end/src/app/tools/tools-routing.module.ts index 1dbba5e9d..4526a7259 100644 --- a/front-end/src/app/tools/tools-routing.module.ts +++ b/front-end/src/app/tools/tools-routing.module.ts @@ -16,4 +16,4 @@ const routes: Routes = [ imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) -export class ToolsRoutingModule { } +export class ToolsRoutingModule {} diff --git a/front-end/src/app/tools/tools.module.ts b/front-end/src/app/tools/tools.module.ts index 751e79fc9..ba159f8e7 100644 --- a/front-end/src/app/tools/tools.module.ts +++ b/front-end/src/app/tools/tools.module.ts @@ -5,11 +5,11 @@ import { SharedModule } from 'app/shared/shared.module'; import { DropdownModule } from 'primeng/dropdown'; import { CashOnHandOverrideComponent } from './cash-on-hand-override/cash-on-hand-override.component'; import { ToolsRoutingModule } from './tools-routing.module'; +import { CardModule } from 'primeng/card'; +import { ButtonModule } from 'primeng/button'; @NgModule({ - declarations: [ - CashOnHandOverrideComponent, - ], + declarations: [CashOnHandOverrideComponent], imports: [ CommonModule, FormsModule, @@ -17,6 +17,8 @@ import { ToolsRoutingModule } from './tools-routing.module'; DropdownModule, SharedModule, ToolsRoutingModule, + CardModule, + ButtonModule, ], }) -export class ToolsModule { } +export class ToolsModule {} From 2e6486574527c020cdfa48ecad562de97df4f405 Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Fri, 18 Oct 2024 15:15:48 -0400 Subject: [PATCH 07/68] Fixes the login process by removing the fixture that was being used to stub out the real response --- front-end/cypress/e2e/pages/loginPage.ts | 8 +- .../fixtures/FEC_Get_Committee_Account.json | 87 ------------------- 2 files changed, 2 insertions(+), 93 deletions(-) delete mode 100644 front-end/cypress/fixtures/FEC_Get_Committee_Account.json diff --git a/front-end/cypress/e2e/pages/loginPage.ts b/front-end/cypress/e2e/pages/loginPage.ts index a5236f7b3..ee1effe94 100644 --- a/front-end/cypress/e2e/pages/loginPage.ts +++ b/front-end/cypress/e2e/pages/loginPage.ts @@ -56,12 +56,8 @@ function getLoginIntervalString(sessionDur: number): string { } function loginDotGovLogin() { - const committeeID = Cypress.env('COMMITTEE_ID'); - cy.intercept('GET', 'http://localhost:8080/api/v1/oidc/login-redirect').as('GetLoggedIn'); - cy.intercept('GET', `http://localhost:8080/api/v1/openfec/${committeeID}/committee/?check_can_create=false`, { - fixture: 'FEC_Get_Committee_Account', - }).as('GetCommitteeAccounts'); + cy.intercept('GET', 'http://localhost:8080/api/v1/committees/').as('GetCommitteeAccounts'); cy.intercept('POST', 'http://localhost:8080/api/v1/committees/*/activate/').as('ActivateCommittee'); cy.visit('/'); @@ -74,7 +70,7 @@ function loginDotGovLogin() { cy.wait('@GetCommitteeAccounts'); cy.get('.committee-list .committee-info').first().click(); cy.wait('@ActivateCommittee'); - cy.visit('/dashboard'); + //cy.visit('/dashboard'); } function retrieveAuthToken() { diff --git a/front-end/cypress/fixtures/FEC_Get_Committee_Account.json b/front-end/cypress/fixtures/FEC_Get_Committee_Account.json deleted file mode 100644 index 1d72b943b..000000000 --- a/front-end/cypress/fixtures/FEC_Get_Committee_Account.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "api_version":"1.0", - "results":[ - { - "custodian_name_2":null, - "custodian_name_middle":null, - "last_file_date":"2017-01-25", - "treasurer_phone":null, - "treasurer_name_title":null, - "treasurer_name":"Test McTest", - "party_type_full":null, - "designation":"U", - "custodian_street_1":null, - "custodian_state":null, - "treasurer_zip":"12345", - "custodian_name_title":null, - "party":null, - "treasurer_city":"Testville", - "committee_id":"C99999999", - "lobbyist_registrant_pac":null, - "treasurer_state":null, - "leadership_pac":null, - "first_file_date":"1992-10-22", - "affiliated_committee_name":null, - "sponsor_candidate_ids":null, - "treasurer_street_1":"123 Test Ln", - "custodian_phone":null, - "state":"MO", - "filing_frequency":"A", - "custodian_city":null, - "name":"PAC Your Bags", - "last_f1_date":"2012-12-21", - "email":"test@pacyourbags.csv", - "party_type":null, - "custodian_street_2":null, - "party_full":null, - "treasurer_name_suffix":"III", - "state_full":"Missouri", - "treasurer_name_prefix":"Mr.", - "designation_full":"Unauthorized", - "first_f1_date":"1992-10-22", - "committee_type_full":"PAC - Nonqualified", - "fax":null, - "street_2":null, - "organization_type":null, - "city":"KANSAS CITY", - "treasurer_name_1":"Test", - "treasurer_name_middle":"Thomas", - "custodian_name_full":null, - "custodian_zip":null, - "organization_type_full":null, - "website":null, - "street_1":"920 TEST STREET SUITE 300", - "treasurer_name_2":"McTest", - "committee_type":"N", - "zip":"64105", - "form_type":"F1", - "treasurer_street_2":null, - "cycles":[ - 1992, - 1994, - 1996, - 1998, - 2000, - 2002, - 2004, - 2006, - 2008, - 2010, - 2012, - 2014, - 2016, - 2018 - ], - "custodian_name_1":null, - "candidate_ids":[], - "custodian_name_suffix":null, - "custodian_name_prefix":null - } - ], - "pagination":{ - "page":1, - "per_page":20, - "pages":1, - "count":1 - } -} \ No newline at end of file From b867df6a3a6ed782eb6c90413677058f5392e8a0 Mon Sep 17 00:00:00 2001 From: Sasha Dresden Date: Mon, 21 Oct 2024 11:19:17 -0400 Subject: [PATCH 08/68] Delete commented out code --- .../header-links/header-links.component.html | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/front-end/src/app/layout/header/header-links/header-links.component.html b/front-end/src/app/layout/header/header-links/header-links.component.html index 125fc6cb7..2a3bf2c6e 100644 --- a/front-end/src/app/layout/header/header-links/header-links.component.html +++ b/front-end/src/app/layout/header/header-links/header-links.component.html @@ -6,11 +6,6 @@ - @@ -27,28 +22,9 @@ Tools - - - From 9addd241111a0dc4766b36ca7906591ab72cd40b Mon Sep 17 00:00:00 2001 From: Sasha Dresden Date: Mon, 21 Oct 2024 14:41:38 -0400 Subject: [PATCH 09/68] Add the missing /login/ to fix the back to select committee link --- .../committee/create-committee/create-committee.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/src/app/committee/create-committee/create-committee.component.html b/front-end/src/app/committee/create-committee/create-committee.component.html index 62a42ccdb..788888235 100644 --- a/front-end/src/app/committee/create-committee/create-committee.component.html +++ b/front-end/src/app/committee/create-committee/create-committee.component.html @@ -7,7 +7,7 @@

Create an account