Update giving reports

test
dan 2019-12-31 00:58:06 -07:00
parent 4b5a889efc
commit 27f9a5f3f3
6 changed files with 160 additions and 31 deletions

View File

@ -2236,6 +2236,37 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"chart.js": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.3.tgz",
"integrity": "sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==",
"requires": {
"chartjs-color": "^2.1.0",
"moment": "^2.10.2"
}
},
"chartjs-color": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
"integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
"requires": {
"chartjs-color-string": "^0.6.0",
"color-convert": "^1.9.3"
}
},
"chartjs-color-string": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
"integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
"requires": {
"color-name": "^1.0.0"
}
},
"chartjs-plugin-datalabels": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz",
"integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g=="
},
"chokidar": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
@ -2432,7 +2463,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
@ -2440,8 +2470,7 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"colors": {
"version": "1.1.2",
@ -6392,6 +6421,11 @@
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",

View File

@ -21,6 +21,8 @@
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~7.2.0",
"@angular/router": "~7.2.0",
"chart.js": "^2.9.3",
"chartjs-plugin-datalabels": "^0.7.0",
"core-js": "^2.5.4",
"hammerjs": "^2.0.8",
"rxjs": "~6.3.3",

View File

@ -16,17 +16,18 @@ export class ContributorAllReportsComponent implements OnInit {
constructor(private printService: PrintService, private userService: UserService, private transactionService: TransactionService) { }
ngOnInit() {
const query = forkJoin([this.userService.getAll(), this.transactionService.getByYear(2019)]);
const query = forkJoin([this.userService.getAll(), this.transactionService.getByYear(2019), this.transactionService.getByYear(2018)]);
query.subscribe(res => this.setup(res[0], res[1]));
query.subscribe(res => this.setup(res[0], res[1], res[2]));
this.printService.setPrinting(true);
}
private setup(contributorResult, transactionResult) {
private setup(contributorResult, transactionResult, priorYearTransactionResult) {
const contributors = contributorResult.users;
const transactions = transactionResult.transactions;
const priorYearTransactions = priorYearTransactionResult.transactions;
const contrib = {};
transactions.forEach(t => {
if (contrib.hasOwnProperty(t.contributorId)) {
@ -35,6 +36,7 @@ export class ContributorAllReportsComponent implements OnInit {
const con = contributors.find(c => c.id === t.contributorId);
if (con) {
contrib[con.id] = {contributor: con, transactions: [t]};
contrib[con.id].priorYearTransactions = priorYearTransactions.filter(t => t.contributorId === con.id);
this.contributors.push(contrib[con.id]);
} else {
console.error('coould not find contributor for', t);

View File

@ -29,12 +29,28 @@
display: flex;
}
.flex-direction-column {
flex-direction: column;
}
.flex-align-center {
align-items: center;
}
.flex-justify-space-between {
justify-content: space-between;
}
.flex-align-space-between {
align-content: space-between;
}
.flex-align-top {
align-items: baseline;
align-items: start;
}
.flex-align-stretch {
align-items: stretch;
}
.flex-justify-center {

View File

@ -3,13 +3,13 @@
<div class="h-100 flex flex-align-center flex-justify-center flex-direction-column">
<img src="../../../assets/images/original/logo_dark.png">
<p class="mt-5">
Old Fashion Baptist Church Contribution Report {{taxYear}} {{index}}
Old Fashion Baptist Church Contribution Report {{taxYear}}
</p>
<p class="mt-5">
{{contributorName}}
</p>
<p>{{contributorStreet}}</p>
<p>{{contributorCity}} {{contributorState}}, {{contributorZip}}</p>
<p *ngIf="contributorStreet && contributorCity && contributorState && contributorZip">{{contributorStreet}}</p>
<p *ngIf="contributorStreet && contributorCity && contributorState && contributorZip">{{contributorCity}} {{contributorState}}, {{contributorZip}}</p>
</div>
<div class="page-break-before">
@ -28,14 +28,13 @@
<hr class="hr mt-20">
<h2 class="text-center mt-20">Old Fashion Baptist Church Giving Statement {{taxYear}}</h2>
<hr class="mt-20">
<div class="flex flex-align-top flex-justify-space-between">
<div class="mt-20">
<p><b>Name: </b>{{contributorName}}</p>
<p><b>Tax Year: </b>{{taxYear}}</p>
<p><b>Registration Code: </b>{{registrationCode}}</p>
</div>
<div class="mt-20">
<table class="cell-padding-5 borders">
<div class="flex flex-align-stretch flex-justify-space-between">
<div class="mt-20 mb-20 flex flex-direction-column flex-justify-space-between">
<div class="mt-20">
<p><b>Name: </b>{{contributorName}}</p>
<p><b>Tax Year: </b>{{taxYear}}</p>
</div>
<table class="cell-padding-5 borders mt-20 w-100">
<thead>
<tr>
<th colspan="2">{{taxYear}} Giving Summary</th>
@ -57,16 +56,18 @@
</tbody>
</table>
</div>
<div class="mt-20">
<canvas #chart width="400" height="300"></canvas>
</div>
</div>
<div class="mt-20">
<div>
Thank you for your contribution. The information provided in this statement reflects
your contributions on record for tax year {{taxYear}}. The chart below provides current and
historical data (if available) for informational purposes only. The data on the following
pages includes a detail listing of contributions for {{taxYear}}.
your contributions on record for tax year {{taxYear}}.
No goods or services were provided in exchange for your contribution.
</div>
</div>
<table class="highlight-even cell-padding-5 w-100 borders page-break-before">
<table class="highlight-even cell-padding-5 w-100 borders mt-20">
<thead>
<tr>
<th class="text-left">Date</th>
@ -79,7 +80,7 @@
</thead>
<tbody>
<tr *ngFor="let t of transactions">
<td nowrap>{{t.date | date:'shortDate'}}</td>
<td nowrap>{{t.date | date:'MM-dd-yyyy'}}</td>
<td nowrap>{{t.type === 0 ? 'Cash' : 'Check'}}</td>
<td nowrap>{{t.checkNumber}}</td>
<td nowrap>{{t.fund === 0 ? 'General' : 'Missions'}}</td>

View File

@ -1,6 +1,8 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
import { PrintService } from '../../services/print-service';
import { Transaction } from '../add-transaction-page/transaction';
import Chart from 'chart.js';
import ChartDataLabels from 'chartjs-plugin-datalabels';
@Component({
selector: 'app-contributor-yearly-report',
@ -9,20 +11,34 @@ import { Transaction } from '../add-transaction-page/transaction';
})
export class ContributorYearlyReportComponent implements OnInit {
@ViewChild('chart') chartElement:ElementRef;
@Input() index: number;
@Input() contributorTransactions: {contributor: {}, transactions: {}};
@Input() contributorTransactions: {contributor: {}, transactions: {}, priorYearTransactions: {}};
public transactions: Transaction[] = [];
public contributorName: string = 'Bob and Jill Handerson';
public priorTransactions: Transaction[] = [];
public get contributorName(): string {
const first = (<any>this.contributorTransactions.contributor).firstName;
const last = (<any>this.contributorTransactions.contributor).lastName;
if (last && first) {
return last + ', ' + first;
} else if (last) {
return last;
} else if (first) {
return first;
} else {
return '';
}
}
public contributorStreet: string = '7878 Washington St';
public contributorCity: string = 'Butte';
public contributorState: string = 'MT';
public contributorZip: string = '59701';
public taxYear: number = 2019;
public registrationCode: string = 'HDIJDHDFD*#*@';
public rowsFirstPage: number = 13;
public rowsPerPage: number = 32;
public get pages(): number {
return Math.ceil(this.transactions.length / this.rowsPerPage) + 2;
return Math.ceil((this.transactions.length - this.rowsFirstPage) / this.rowsPerPage) + 2;
}
public get pagesOdd(): boolean {
return !(this.pages % 2 == 0)
@ -32,12 +48,12 @@ export class ContributorYearlyReportComponent implements OnInit {
ngOnInit() {
this.contributorCity = (<any>this.contributorTransactions.contributor).city;
this.contributorName = (<any>this.contributorTransactions.contributor).display;
this.contributorState = (<any>this.contributorTransactions.contributor).state;
this.contributorStreet = (<any>this.contributorTransactions.contributor).street;
this.contributorZip = (<any>this.contributorTransactions.contributor).zip;
this.transactions = <any>this.contributorTransactions.transactions;
this.priorTransactions = <any>this.contributorTransactions.priorYearTransactions;
this.renderChart();
}
public totalGeneral() {
@ -46,10 +62,68 @@ export class ContributorYearlyReportComponent implements OnInit {
return sum;
}
public priorGeneral() {
let sum = 0;
this.priorTransactions.filter(t => t.fundId === 1).forEach(t => sum += t.amount);
return sum;
}
public totalMissions() {
let sum = 0;
this.transactions.filter(t => t.fundId === 2).forEach(t => sum += t.amount);
return sum;
}
public priorMissions() {
let sum = 0;
this.priorTransactions.filter(t => t.fundId === 2).forEach(t => sum += t.amount);
return sum;
}
private renderChart() {
var myChart = new Chart(this.chartElement.nativeElement, {
plugins: [ChartDataLabels],
type: 'bar',
data: {
labels: ['2018', '2019'],
datasets: [{
label: 'General',
data: [this.priorGeneral(), this.totalGeneral()],
backgroundColor: 'rgba(54, 245, 162, 0.2)',
borderColor: 'rgba(54, 245, 162, 1)',
borderWidth: 1
}, {
label: 'Missions',
data: [this.priorMissions(), this.totalMissions()],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
},
options:{
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
},
plugins:{
datalabels:{
font:{
weight: 'bold'
},
formatter: function(value, context){
if (value === 0) {
return '';
}
return '$' + value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
}
}
}
}
});
}
}